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