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