ismounted.c revision 1d6fd6d0c3766a8165e69284c75812574a29c804
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 44static char *skip_over_blank(char *cp) 45{ 46 while (*cp && isspace(*cp)) 47 cp++; 48 return cp; 49} 50 51static char *skip_over_word(char *cp) 52{ 53 while (*cp && !isspace(*cp)) 54 cp++; 55 return cp; 56} 57 58static 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 */ 80static 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; 180errout: 181 endmntent (f); 182 return retval; 183#else /* !HAVE_SETMNTENT */ 184 return 0; 185#endif /* HAVE_MNTENT_H */ 186} 187 188int 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 207int 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