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 #include <ctype.h> 32 33 #include "fsck.h" 34 35 /* 36 * ext2fs_check_if_mounted flags 37 */ 38 #define MF_MOUNTED 1 39 40 #include "et/com_err.h" 41 42 static char *skip_over_blank(char *cp) 43 { 44 while (*cp && isspace(*cp)) 45 cp++; 46 return cp; 47 } 48 49 static char *skip_over_word(char *cp) 50 { 51 while (*cp && !isspace(*cp)) 52 cp++; 53 return cp; 54 } 55 56 static char *parse_word(char **buf) 57 { 58 char *word, *next; 59 60 word = *buf; 61 if (*word == 0) 62 return 0; 63 64 word = skip_over_blank(word); 65 next = skip_over_word(word); 66 if (*next) 67 *next++ = 0; 68 *buf = next; 69 return word; 70 } 71 72 /* 73 * Helper function which checks a file in /etc/mtab format to see if a 74 * filesystem is mounted. Returns an error if the file doesn't exist 75 * or can't be opened. 76 */ 77 static errcode_t check_mntent_file(const char *mtab_file, const char *file, 78 int *mount_flags) 79 { 80 #ifdef HAVE_MNTENT_H 81 struct stat st_buf; 82 errcode_t retval = 0; 83 dev_t file_dev=0, file_rdev=0; 84 ino_t file_ino=0; 85 FILE *f; 86 char buf[1024], *device = 0, *mnt_dir = 0, *cp; 87 88 *mount_flags = 0; 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 #else /* !HAVE_MNTENT_H */ 181 return 0; 182 #endif /* HAVE_MNTENT_H */ 183 } 184 185 int is_mounted(const char *file) 186 { 187 errcode_t retval; 188 int mount_flags = 0; 189 190 #ifdef __linux__ 191 retval = check_mntent_file("/proc/mounts", file, &mount_flags); 192 if (retval) 193 return 0; 194 if (mount_flags) 195 return 1; 196 #endif /* __linux__ */ 197 retval = check_mntent_file("/etc/mtab", file, &mount_flags); 198 if (retval) 199 return 0; 200 return (mount_flags); 201 } 202 203 #ifdef DEBUG 204 int main(int argc, char **argv) 205 { 206 if (argc < 2) { 207 fprintf(stderr, "Usage: %s device\n", argv[0]); 208 exit(1); 209 } 210 211 if (is_mounted(argv[1])) 212 printf("\t%s is mounted.\n", argv[1]); 213 exit(0); 214 } 215 #endif /* DEBUG */ 216