ismounted.c revision 2a6b60488feb819bae7e506281ebe37e6091b5d6
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 39static char *skip_over_blank(char *cp) 40{ 41 while (*cp && isspace(*cp)) 42 cp++; 43 return cp; 44} 45 46static char *skip_over_word(char *cp) 47{ 48 while (*cp && !isspace(*cp)) 49 cp++; 50 return cp; 51} 52 53static 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 */ 74static errcode_t check_mntent_file(const char *mtab_file, const char *file, 75 int *mount_flags) 76{ 77#ifdef HAVE_MNTENT_H 78 struct stat st_buf; 79 errcode_t retval = 0; 80 dev_t file_dev=0, file_rdev=0; 81 ino_t file_ino=0; 82 FILE *f; 83 char buf[1024], *device = 0, *mnt_dir = 0, *cp; 84 int fd; 85 86 *mount_flags = 0; 87 if ((f = fopen(mtab_file, "r")) == NULL) 88 return errno; 89 90 if ((f = setmntent (mtab_file, "r")) == NULL) 91 return errno; 92 if (stat(file, &st_buf) == 0) { 93 if (S_ISBLK(st_buf.st_mode)) { 94#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */ 95 file_rdev = st_buf.st_rdev; 96#endif /* __GNU__ */ 97 } else { 98 file_dev = st_buf.st_dev; 99 file_ino = st_buf.st_ino; 100 } 101 } 102 while (1) { 103 if (!fgets(buf, sizeof(buf), f)) { 104 device = mnt_dir = 0; 105 break; 106 } 107 buf[sizeof(buf)-1] = 0; 108 109 cp = buf; 110 device = parse_word(&cp); 111 if (!device || *device == '#') 112 return 0; /* Ignore blank lines and comments */ 113 mnt_dir = parse_word(&cp); 114 115 if (device[0] != '/') 116 continue; 117 118 if (strcmp(file, device) == 0) 119 break; 120 if (stat(device, &st_buf) == 0) { 121 if (S_ISBLK(st_buf.st_mode)) { 122#ifndef __GNU__ 123 if (file_rdev && (file_rdev == st_buf.st_rdev)) 124 break; 125#endif /* __GNU__ */ 126 } else { 127 if (file_dev && ((file_dev == st_buf.st_dev) && 128 (file_ino == st_buf.st_ino))) 129 break; 130 } 131 } 132 } 133 134 if (mnt_dir == 0) { 135#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */ 136 /* 137 * Do an extra check to see if this is the root device. We 138 * can't trust /etc/mtab, and /proc/mounts will only list 139 * /dev/root for the root filesystem. Argh. Instead we 140 * check if the given device has the same major/minor number 141 * as the device that the root directory is on. 142 */ 143 if (file_rdev && (stat("/", &st_buf) == 0) && 144 (st_buf.st_dev == file_rdev)) 145 *mount_flags = MF_MOUNTED; 146#endif /* __GNU__ */ 147 goto errout; 148 } 149#ifndef __GNU__ /* The GNU hurd is deficient; what else is new? */ 150 /* Validate the entry in case /etc/mtab is out of date */ 151 /* 152 * We need to be paranoid, because some broken distributions 153 * (read: Slackware) don't initialize /etc/mtab before checking 154 * all of the non-root filesystems on the disk. 155 */ 156 if (stat(mnt_dir, &st_buf) < 0) { 157 retval = errno; 158 if (retval == ENOENT) { 159#ifdef DEBUG 160 printf("Bogus entry in %s! (%s does not exist)\n", 161 mtab_file, mnt_dir); 162#endif /* DEBUG */ 163 retval = 0; 164 } 165 goto errout; 166 } 167 if (file_rdev && (st_buf.st_dev != file_rdev)) { 168#ifdef DEBUG 169 printf("Bogus entry in %s! (%s not mounted on %s)\n", 170 mtab_file, file, mnt_dir); 171#endif /* DEBUG */ 172 goto errout; 173 } 174#endif /* __GNU__ */ 175 *mount_flags = MF_MOUNTED; 176 177 retval = 0; 178errout: 179 endmntent (f); 180 return retval; 181#else /* !HAVE_MNTENT_H */ 182 return 0; 183#endif /* HAVE_MNTENT_H */ 184} 185 186int is_mounted(const char *file) 187{ 188 errcode_t retval; 189 int mount_flags = 0; 190 191#ifdef __linux__ 192 retval = check_mntent_file("/proc/mounts", file, &mount_flags); 193 if (retval) 194 return 0; 195 if (mount_flags) 196 return 1; 197#endif /* __linux__ */ 198 retval = check_mntent_file("/etc/mtab", file, &mount_flags); 199 if (retval) 200 return 0; 201 return (mount_flags); 202} 203 204#ifdef DEBUG 205int main(int argc, char **argv) 206{ 207 if (argc < 2) { 208 fprintf(stderr, "Usage: %s device\n", argv[0]); 209 exit(1); 210 } 211 212 if (is_mounted(argv[1])) 213 printf("\t%s is mounted.\n", argv[1]); 214 exit(0); 215} 216#endif /* DEBUG */ 217