ismounted.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. /*
  2. * ismounted.c --- Check to see if the filesystem was mounted
  3. *
  4. * Copyright (C) 1995,1996,1997,1998,1999,2000 Theodore Ts'o.
  5. *
  6. * %Begin-Header%
  7. * This file may be redistributed under the terms of the GNU Public
  8. * License.
  9. * %End-Header%
  10. */
  11. #include <stdio.h>
  12. #if HAVE_UNISTD_H
  13. #include <unistd.h>
  14. #endif
  15. #if HAVE_ERRNO_H
  16. #include <errno.h>
  17. #endif
  18. #include <fcntl.h>
  19. #ifdef HAVE_LINUX_FD_H
  20. #include <linux/fd.h>
  21. #endif
  22. #ifdef HAVE_MNTENT_H
  23. #include <mntent.h>
  24. #endif
  25. #ifdef HAVE_GETMNTINFO
  26. #include <paths.h>
  27. #include <sys/param.h>
  28. #include <sys/mount.h>
  29. #endif /* HAVE_GETMNTINFO */
  30. #include <string.h>
  31. #include <sys/stat.h>
  32. #include "ext2_fs.h"
  33. #include "ext2fs.h"
  34. #ifdef HAVE_MNTENT_H
  35. /*
  36. * Helper function which checks a file in /etc/mtab format to see if a
  37. * filesystem is mounted. Returns an error if the file doesn't exist
  38. * or can't be opened.
  39. */
  40. static errcode_t check_mntent_file(const char *mtab_file, const char *file,
  41. int *mount_flags, char *mtpt, int mtlen)
  42. {
  43. struct mntent *mnt;
  44. struct stat st_buf;
  45. errcode_t retval = 0;
  46. dev_t file_dev=0, file_rdev=0;
  47. ino_t file_ino=0;
  48. FILE *f;
  49. int fd;
  50. *mount_flags = 0;
  51. if ((f = setmntent (mtab_file, "r")) == NULL)
  52. return errno;
  53. if (stat(file, &st_buf) == 0) {
  54. if (S_ISBLK(st_buf.st_mode)) {
  55. #ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
  56. file_rdev = st_buf.st_rdev;
  57. #endif /* __GNU__ */
  58. } else {
  59. file_dev = st_buf.st_dev;
  60. file_ino = st_buf.st_ino;
  61. }
  62. }
  63. while ((mnt = getmntent (f)) != NULL) {
  64. if (strcmp(file, mnt->mnt_fsname) == 0)
  65. break;
  66. if (stat(mnt->mnt_fsname, &st_buf) == 0) {
  67. if (S_ISBLK(st_buf.st_mode)) {
  68. #ifndef __GNU__
  69. if (file_rdev && (file_rdev == st_buf.st_rdev))
  70. break;
  71. #endif /* __GNU__ */
  72. } else {
  73. if (file_dev && ((file_dev == st_buf.st_dev) &&
  74. (file_ino == st_buf.st_ino)))
  75. break;
  76. }
  77. }
  78. }
  79. if (mnt == 0) {
  80. #ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
  81. /*
  82. * Do an extra check to see if this is the root device. We
  83. * can't trust /etc/mtab, and /proc/mounts will only list
  84. * /dev/root for the root filesystem. Argh. Instead we
  85. * check if the given device has the same major/minor number
  86. * as the device that the root directory is on.
  87. */
  88. if (file_rdev && stat("/", &st_buf) == 0) {
  89. if (st_buf.st_dev == file_rdev) {
  90. *mount_flags = EXT2_MF_MOUNTED;
  91. if (mtpt)
  92. strncpy(mtpt, "/", mtlen);
  93. goto is_root;
  94. }
  95. }
  96. #endif /* __GNU__ */
  97. goto errout;
  98. }
  99. #ifndef __GNU__ /* The GNU hurd is deficient; what else is new? */
  100. /* Validate the entry in case /etc/mtab is out of date */
  101. /*
  102. * We need to be paranoid, because some broken distributions
  103. * (read: Slackware) don't initialize /etc/mtab before checking
  104. * all of the non-root filesystems on the disk.
  105. */
  106. if (stat(mnt->mnt_dir, &st_buf) < 0) {
  107. retval = errno;
  108. if (retval == ENOENT) {
  109. #ifdef DEBUG
  110. printf("Bogus entry in %s! (%s does not exist)\n",
  111. mtab_file, mnt->mnt_dir);
  112. #endif /* DEBUG */
  113. retval = 0;
  114. }
  115. goto errout;
  116. }
  117. if (file_rdev && (st_buf.st_dev != file_rdev)) {
  118. #ifdef DEBUG
  119. printf("Bogus entry in %s! (%s not mounted on %s)\n",
  120. mtab_file, file, mnt->mnt_dir);
  121. #endif /* DEBUG */
  122. goto errout;
  123. }
  124. #endif /* __GNU__ */
  125. *mount_flags = EXT2_MF_MOUNTED;
  126. #ifdef MNTOPT_RO
  127. /* Check to see if the ro option is set */
  128. if (hasmntopt(mnt, MNTOPT_RO))
  129. *mount_flags |= EXT2_MF_READONLY;
  130. #endif
  131. if (mtpt)
  132. strncpy(mtpt, mnt->mnt_dir, mtlen);
  133. /*
  134. * Check to see if we're referring to the root filesystem.
  135. * If so, do a manual check to see if we can open /etc/mtab
  136. * read/write, since if the root is mounted read/only, the
  137. * contents of /etc/mtab may not be accurate.
  138. */
  139. if (!strcmp(mnt->mnt_dir, "/")) {
  140. is_root:
  141. #define TEST_FILE "/.ismount-test-file"
  142. *mount_flags |= EXT2_MF_ISROOT;
  143. fd = open(TEST_FILE, O_RDWR|O_CREAT);
  144. if (fd < 0) {
  145. if (errno == EROFS)
  146. *mount_flags |= EXT2_MF_READONLY;
  147. } else
  148. close(fd);
  149. (void) unlink(TEST_FILE);
  150. }
  151. retval = 0;
  152. errout:
  153. endmntent (f);
  154. return retval;
  155. }
  156. static errcode_t check_mntent(const char *file, int *mount_flags,
  157. char *mtpt, int mtlen)
  158. {
  159. errcode_t retval;
  160. #ifdef DEBUG
  161. retval = check_mntent_file("/tmp/mtab", file, mount_flags,
  162. mtpt, mtlen);
  163. if (retval == 0)
  164. return 0;
  165. #endif /* DEBUG */
  166. #ifdef __linux__
  167. retval = check_mntent_file("/proc/mounts", file, mount_flags,
  168. mtpt, mtlen);
  169. if (retval == 0 && (*mount_flags != 0))
  170. return 0;
  171. #endif /* __linux__ */
  172. #if defined(MOUNTED) || defined(_PATH_MOUNTED)
  173. #ifndef MOUNTED
  174. #define MOUNTED _PATH_MOUNTED
  175. #endif /* MOUNTED */
  176. retval = check_mntent_file(MOUNTED, file, mount_flags, mtpt, mtlen);
  177. return retval;
  178. #else
  179. *mount_flags = 0;
  180. return 0;
  181. #endif /* defined(MOUNTED) || defined(_PATH_MOUNTED) */
  182. }
  183. #else
  184. #if defined(HAVE_GETMNTINFO)
  185. static errcode_t check_getmntinfo(const char *file, int *mount_flags,
  186. char *mtpt, int mtlen)
  187. {
  188. struct statfs *mp;
  189. int len, n;
  190. const char *s1;
  191. char *s2;
  192. n = getmntinfo(&mp, MNT_NOWAIT);
  193. if (n == 0)
  194. return errno;
  195. len = sizeof(_PATH_DEV) - 1;
  196. s1 = file;
  197. if (strncmp(_PATH_DEV, s1, len) == 0)
  198. s1 += len;
  199. *mount_flags = 0;
  200. while (--n >= 0) {
  201. s2 = mp->f_mntfromname;
  202. if (strncmp(_PATH_DEV, s2, len) == 0) {
  203. s2 += len - 1;
  204. *s2 = 'r';
  205. }
  206. if (strcmp(s1, s2) == 0 || strcmp(s1, &s2[1]) == 0) {
  207. *mount_flags = EXT2_MF_MOUNTED;
  208. break;
  209. }
  210. ++mp;
  211. }
  212. if (mtpt)
  213. strncpy(mtpt, mp->f_mntonname, mtlen);
  214. return 0;
  215. }
  216. #endif /* HAVE_GETMNTINFO */
  217. #endif /* HAVE_MNTENT_H */
  218. /*
  219. * Check to see if we're dealing with the swap device.
  220. */
  221. static int is_swap_device(const char *file)
  222. {
  223. FILE *f;
  224. char buf[1024], *cp;
  225. dev_t file_dev;
  226. struct stat st_buf;
  227. int ret = 0;
  228. file_dev = 0;
  229. #ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
  230. if ((stat(file, &st_buf) == 0) &&
  231. S_ISBLK(st_buf.st_mode))
  232. file_dev = st_buf.st_rdev;
  233. #endif /* __GNU__ */
  234. if (!(f = fopen("/proc/swaps", "r")))
  235. return 0;
  236. /* Skip the first line */
  237. fgets(buf, sizeof(buf), f);
  238. while (!feof(f)) {
  239. if (!fgets(buf, sizeof(buf), f))
  240. break;
  241. if ((cp = strchr(buf, ' ')) != NULL)
  242. *cp = 0;
  243. if ((cp = strchr(buf, '\t')) != NULL)
  244. *cp = 0;
  245. if (strcmp(buf, file) == 0) {
  246. ret++;
  247. break;
  248. }
  249. #ifndef __GNU__
  250. if (file_dev && (stat(buf, &st_buf) == 0) &&
  251. S_ISBLK(st_buf.st_mode) &&
  252. file_dev == st_buf.st_rdev) {
  253. ret++;
  254. break;
  255. }
  256. #endif /* __GNU__ */
  257. }
  258. fclose(f);
  259. return ret;
  260. }
  261. /*
  262. * ext2fs_check_mount_point() returns 1 if the device is mounted, 0
  263. * otherwise. If mtpt is non-NULL, the directory where the device is
  264. * mounted is copied to where mtpt is pointing, up to mtlen
  265. * characters.
  266. */
  267. #ifdef __TURBOC__
  268. #pragma argsused
  269. #endif
  270. errcode_t ext2fs_check_mount_point(const char *device, int *mount_flags,
  271. char *mtpt, int mtlen)
  272. {
  273. if (is_swap_device(device)) {
  274. *mount_flags = EXT2_MF_MOUNTED | EXT2_MF_SWAP;
  275. strncpy(mtpt, "<swap>", mtlen);
  276. return 0;
  277. }
  278. #ifdef HAVE_MNTENT_H
  279. return check_mntent(device, mount_flags, mtpt, mtlen);
  280. #else
  281. #ifdef HAVE_GETMNTINFO
  282. return check_getmntinfo(device, mount_flags, mtpt, mtlen);
  283. #else
  284. #ifdef __GNUC__
  285. #warning "Can't use getmntent or getmntinfo to check for mounted filesystems!"
  286. #endif
  287. *mount_flags = 0;
  288. return 0;
  289. #endif /* HAVE_GETMNTINFO */
  290. #endif /* HAVE_MNTENT_H */
  291. }
  292. /*
  293. * ext2fs_check_if_mounted() sets the mount_flags EXT2_MF_MOUNTED,
  294. * EXT2_MF_READONLY, and EXT2_MF_ROOT
  295. *
  296. */
  297. errcode_t ext2fs_check_if_mounted(const char *file, int *mount_flags)
  298. {
  299. return ext2fs_check_mount_point(file, mount_flags, NULL, 0);
  300. }
  301. #ifdef DEBUG
  302. int main(int argc, char **argv)
  303. {
  304. int retval, mount_flags;
  305. char mntpt[80];
  306. if (argc < 2) {
  307. fprintf(stderr, "Usage: %s device\n", argv[0]);
  308. exit(1);
  309. }
  310. mntpt[0] = 0;
  311. retval = ext2fs_check_mount_point(argv[1], &mount_flags,
  312. mntpt, sizeof(mntpt));
  313. if (retval) {
  314. com_err(argv[0], retval,
  315. "while calling ext2fs_check_if_mounted");
  316. exit(1);
  317. }
  318. printf("Device %s reports flags %02x\n", argv[1], mount_flags);
  319. if (mount_flags & EXT2_MF_MOUNTED)
  320. printf("\t%s is mounted.\n", argv[1]);
  321. if (mount_flags & EXT2_MF_SWAP)
  322. printf("\t%s is a swap device.\n", argv[1]);
  323. if (mount_flags & EXT2_MF_READONLY)
  324. printf("\t%s is read-only.\n", argv[1]);
  325. if (mount_flags & EXT2_MF_ISROOT)
  326. printf("\t%s is the root filesystem.\n", argv[1]);
  327. if (mntpt[0])
  328. printf("\t%s is mounted on %s.\n", argv[1], mntpt);
  329. exit(0);
  330. }
  331. #endif /* DEBUG */