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 
     32 /*
     33  * ext2fs_check_if_mounted flags
     34  */
     35 #define MF_MOUNTED		1
     36 
     37 #include "et/com_err.h"
     38 
     39 static char *skip_over_blank(char *cp)
     40 {
     41 	while (*cp && isspace(*cp))
     42 		cp++;
     43 	return cp;
     44 }
     45 
     46 static char *skip_over_word(char *cp)
     47 {
     48 	while (*cp && !isspace(*cp))
     49 		cp++;
     50 	return cp;
     51 }
     52 
     53 static 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  */
     74 static errcode_t check_mntent_file(const char *mtab_file, const char *file,
     75 				   int *mount_flags)
     76 {
     77 	struct stat	st_buf;
     78 	errcode_t	retval = 0;
     79 	dev_t		file_dev=0, file_rdev=0;
     80 	ino_t		file_ino=0;
     81 	FILE 		*f;
     82 	char		buf[1024], *device = 0, *mnt_dir = 0, *cp;
     83 	int		fd;
     84 
     85 	*mount_flags = 0;
     86 	if ((f = fopen(mtab_file, "r")) == NULL)
     87 		return errno;
     88 
     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 }
    181 
    182 int is_mounted(const char *file)
    183 {
    184 	errcode_t	retval;
    185 	int		mount_flags = 0;
    186 
    187 #ifdef __linux__
    188 	retval = check_mntent_file("/proc/mounts", file, &mount_flags);
    189 	if (retval)
    190 		return 0;
    191 	if (mount_flags)
    192 		return 1;
    193 #endif /* __linux__ */
    194 	retval = check_mntent_file("/etc/mtab", file, &mount_flags);
    195 	if (retval)
    196 		return 0;
    197 	return (mount_flags);
    198 }
    199 
    200 #ifdef DEBUG
    201 int main(int argc, char **argv)
    202 {
    203 	if (argc < 2) {
    204 		fprintf(stderr, "Usage: %s device\n", argv[0]);
    205 		exit(1);
    206 	}
    207 
    208 	if (is_mounted(argv[1]))
    209 		printf("\t%s is mounted.\n", argv[1]);
    210 	exit(0);
    211 }
    212 #endif /* DEBUG */
    213