/* * Written by Igor Pashev * * The author has placed this work in the Public Domain, * thereby relinquishing all copyrights. Everyone is free * to use, modify, republish, sell or give away this work * without prior consent from anybody. * */ #include #include #include #include #include #include #include #include #ifndef PATH_MAX #define PATH_MAX 1024 #endif static int flag_q = 0; static int flag_d = 0; static int flag_x = 0; static int rc; static struct stat st, st_up; static const char *path; static char path_up[PATH_MAX]; static void usage (void) { fprintf (stderr, "Usage: mountpoint [-q] [-d] [-x] path\n"); exit (1); } static void xstat (const char *p, struct stat *s) { if (flag_x) rc = lstat (p, s); else rc = stat (p, s); if (rc != 0) { if (!flag_q) fprintf (stderr, "mountpoint: %s: %s\n", path, strerror (errno)); exit (1); } } int main (int argc, char *argv[]) { while ((rc = getopt (argc, argv, "qdx")) != EOF) switch (rc) { case 'q': flag_q++; break; case 'd': flag_d++; break; case 'x': flag_x++; break; default: usage (); break; } if (optind != argc - 1) usage (); path = argv[optind]; xstat (path, &st); if (flag_x) { if (S_ISBLK (st.st_mode) || S_ISCHR (st.st_mode)) { printf ("%u:%u\n", major (st.st_rdev), minor (st.st_rdev)); return 0; } if (!flag_q) fprintf (stderr, "mountpoint: %s: not a block device\n", path); return 1; } if (!S_ISDIR (st.st_mode)) { if (!flag_q) fprintf (stderr, "mountpoint: %s: not a directory\n", path); return 1; } rc = snprintf (path_up, sizeof (path_up), "%s/..", path); if ((size_t) rc >= sizeof (path_up)) { if (!flag_q) fprintf (stderr, "mountpoint: internal error: path is too long: %s\n", path); return 1; } xstat (path_up, &st_up); rc = (st.st_dev != st_up.st_dev) || (st.st_dev == st_up.st_dev && st.st_ino == st_up.st_ino); if (flag_d) printf ("%u:%u\n", major (st.st_dev), minor (st.st_dev)); else if (!flag_q) printf ("%s is %sa mountpoint\n", path, rc ? "" : "not "); return rc ? 0 : 1; }