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