Home | History | Annotate | Download | only in misc
      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