1 /* 2 * ismounted.c --- Check to see if the filesystem was mounted 3 * 4 * Copyright (C) 1995,1996,1997,1998,1999,2000,2008 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 12 #include <stdio.h> 13 #if HAVE_UNISTD_H 14 #include <unistd.h> 15 #endif 16 #ifdef HAVE_STDLIB_H 17 #include <stdlib.h> 18 #endif 19 #if HAVE_ERRNO_H 20 #include <errno.h> 21 #endif 22 #include <fcntl.h> 23 #ifdef HAVE_LINUX_FD_H 24 #include <linux/fd.h> 25 #endif 26 #ifdef HAVE_MNTENT_H 27 #include <mntent.h> 28 #endif 29 #include <string.h> 30 #include <sys/stat.h> 31 32 /* 33 * ext2fs_check_if_mounted flags 34 */ 35 #define MF_MOUNTED 1 36 37 #include "et/com_err.h" 38 39 static char *skip_over_blank(char *cp) 40 { 41 while (*cp && isspace(*cp)) 42 cp++; 43 return cp; 44 } 45 46 static char *skip_over_word(char *cp) 47 { 48 while (*cp && !isspace(*cp)) 49 cp++; 50 return cp; 51 } 52 53 static char *parse_word(char **buf) 54 { 55 char *word, *next; 56 57 word = *buf; 58 if (*word == 0) 59 return 0; 60 61 word = skip_over_blank(word); 62 next = skip_over_word(word); 63 if (*next) 64 *next++ = 0; 65 *buf = next; 66 return word; 67 } 68 69 /* 70 * Helper function which checks a file in /etc/mtab format to see if a 71 * filesystem is mounted. Returns an error if the file doesn't exist 72 * or can't be opened. 73 */ 74 static errcode_t check_mntent_file(const char *mtab_file, const char *file, 75 int *mount_flags) 76 { 77 struct stat st_buf; 78 errcode_t retval = 0; 79 dev_t file_dev=0, file_rdev=0; 80 ino_t file_ino=0; 81 FILE *f; 82 char buf[1024], *device = 0, *mnt_dir = 0, *cp; 83 int fd; 84 85 *mount_flags = 0; 86 if ((f = fopen(mtab_file, "r")) == NULL) 87 return errno; 88 89 if ((f = setmntent (mtab_file, "r")) == NULL) 90 return errno; 91 if (stat(file, &st_buf) == 0) { 92 if (S_ISBLK(st_buf.st_mode)) { 93 #ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */ 94 file_rdev = st_buf.st_rdev; 95 #endif /* __GNU__ */ 96 } else { 97 file_dev = st_buf.st_dev; 98 file_ino = st_buf.st_ino; 99 } 100 } 101 while (1) { 102 if (!fgets(buf, sizeof(buf), f)) { 103 device = mnt_dir = 0; 104 break; 105 } 106 buf[sizeof(buf)-1] = 0; 107 108 cp = buf; 109 device = parse_word(&cp); 110 if (!device || *device == '#') 111 return 0; /* Ignore blank lines and comments */ 112 mnt_dir = parse_word(&cp); 113 114 if (device[0] != '/') 115 continue; 116 117 if (strcmp(file, device) == 0) 118 break; 119 if (stat(device, &st_buf) == 0) { 120 if (S_ISBLK(st_buf.st_mode)) { 121 #ifndef __GNU__ 122 if (file_rdev && (file_rdev == st_buf.st_rdev)) 123 break; 124 #endif /* __GNU__ */ 125 } else { 126 if (file_dev && ((file_dev == st_buf.st_dev) && 127 (file_ino == st_buf.st_ino))) 128 break; 129 } 130 } 131 } 132 133 if (mnt_dir == 0) { 134 #ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */ 135 /* 136 * Do an extra check to see if this is the root device. We 137 * can't trust /etc/mtab, and /proc/mounts will only list 138 * /dev/root for the root filesystem. Argh. Instead we 139 * check if the given device has the same major/minor number 140 * as the device that the root directory is on. 141 */ 142 if (file_rdev && (stat("/", &st_buf) == 0) && 143 (st_buf.st_dev == file_rdev)) 144 *mount_flags = MF_MOUNTED; 145 #endif /* __GNU__ */ 146 goto errout; 147 } 148 #ifndef __GNU__ /* The GNU hurd is deficient; what else is new? */ 149 /* Validate the entry in case /etc/mtab is out of date */ 150 /* 151 * We need to be paranoid, because some broken distributions 152 * (read: Slackware) don't initialize /etc/mtab before checking 153 * all of the non-root filesystems on the disk. 154 */ 155 if (stat(mnt_dir, &st_buf) < 0) { 156 retval = errno; 157 if (retval == ENOENT) { 158 #ifdef DEBUG 159 printf("Bogus entry in %s! (%s does not exist)\n", 160 mtab_file, mnt_dir); 161 #endif /* DEBUG */ 162 retval = 0; 163 } 164 goto errout; 165 } 166 if (file_rdev && (st_buf.st_dev != file_rdev)) { 167 #ifdef DEBUG 168 printf("Bogus entry in %s! (%s not mounted on %s)\n", 169 mtab_file, file, mnt_dir); 170 #endif /* DEBUG */ 171 goto errout; 172 } 173 #endif /* __GNU__ */ 174 *mount_flags = MF_MOUNTED; 175 176 retval = 0; 177 errout: 178 endmntent (f); 179 return retval; 180 } 181 182 int is_mounted(const char *file) 183 { 184 errcode_t retval; 185 int mount_flags = 0; 186 187 #ifdef __linux__ 188 retval = check_mntent_file("/proc/mounts", file, &mount_flags); 189 if (retval) 190 return 0; 191 if (mount_flags) 192 return 1; 193 #endif /* __linux__ */ 194 retval = check_mntent_file("/etc/mtab", file, &mount_flags); 195 if (retval) 196 return 0; 197 return (mount_flags); 198 } 199 200 #ifdef DEBUG 201 int main(int argc, char **argv) 202 { 203 if (argc < 2) { 204 fprintf(stderr, "Usage: %s device\n", argv[0]); 205 exit(1); 206 } 207 208 if (is_mounted(argv[1])) 209 printf("\t%s is mounted.\n", argv[1]); 210 exit(0); 211 } 212 #endif /* DEBUG */ 213