]> git.ipfire.org Git - thirdparty/util-linux.git/blob - lib/ismounted.c
lib: add test_ismounted for regression test
[thirdparty/util-linux.git] / lib / ismounted.c
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 * This file may be redistributed under the terms of the GNU Public
7 * License.
8 */
9 #include <stdio.h>
10 #include <unistd.h>
11 #include <stdlib.h>
12 #include <errno.h>
13 #include <fcntl.h>
14 #include <linux/fd.h>
15 #include <mntent.h>
16 #include <string.h>
17 #include <sys/stat.h>
18 #include <ctype.h>
19
20 #include "pathnames.h"
21 #include "ismounted.h"
22
23 /*
24 * ext2fs_check_if_mounted flags
25 */
26 #define MF_MOUNTED 1
27
28 static char *skip_over_blank(char *cp)
29 {
30 while (*cp && isspace(*cp))
31 cp++;
32 return cp;
33 }
34
35 static char *skip_over_word(char *cp)
36 {
37 while (*cp && !isspace(*cp))
38 cp++;
39 return cp;
40 }
41
42 static char *parse_word(char **buf)
43 {
44 char *word, *next;
45
46 word = *buf;
47 if (*word == 0)
48 return 0;
49
50 word = skip_over_blank(word);
51 next = skip_over_word(word);
52 if (*next)
53 *next++ = 0;
54 *buf = next;
55 return word;
56 }
57
58 /*
59 * Helper function which checks a file in /etc/mtab format to see if a
60 * filesystem is mounted. Returns an error if the file doesn't exist
61 * or can't be opened.
62 */
63 static int check_mntent_file(const char *mtab_file, const char *file,
64 int *mount_flags)
65 {
66 struct stat st_buf;
67 int retval = 0;
68 dev_t file_dev=0, file_rdev=0;
69 ino_t file_ino=0;
70 FILE *f;
71 char buf[1024], *device = 0, *mnt_dir = 0, *cp;
72
73 *mount_flags = 0;
74 if ((f = fopen(mtab_file, "r")) == NULL)
75 return errno;
76
77 if ((f = setmntent (mtab_file, "r")) == NULL)
78 return errno;
79 if (stat(file, &st_buf) == 0) {
80 if (S_ISBLK(st_buf.st_mode)) {
81 #ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
82 file_rdev = st_buf.st_rdev;
83 #endif /* __GNU__ */
84 } else {
85 file_dev = st_buf.st_dev;
86 file_ino = st_buf.st_ino;
87 }
88 }
89 while (1) {
90 if (!fgets(buf, sizeof(buf), f)) {
91 device = mnt_dir = 0;
92 break;
93 }
94 buf[sizeof(buf)-1] = 0;
95
96 cp = buf;
97 device = parse_word(&cp);
98 if (!device || *device == '#')
99 return 0; /* Ignore blank lines and comments */
100 mnt_dir = parse_word(&cp);
101
102 if (device[0] != '/')
103 continue;
104
105 if (strcmp(file, device) == 0)
106 break;
107 if (stat(device, &st_buf) == 0) {
108 if (S_ISBLK(st_buf.st_mode)) {
109 #ifndef __GNU__
110 if (file_rdev && (file_rdev == st_buf.st_rdev))
111 break;
112 #endif /* __GNU__ */
113 } else {
114 if (file_dev && ((file_dev == st_buf.st_dev) &&
115 (file_ino == st_buf.st_ino)))
116 break;
117 }
118 }
119 }
120
121 if (mnt_dir == 0) {
122 #ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
123 /*
124 * Do an extra check to see if this is the root device. We
125 * can't trust /etc/mtab, and /proc/mounts will only list
126 * /dev/root for the root filesystem. Argh. Instead we
127 * check if the given device has the same major/minor number
128 * as the device that the root directory is on.
129 */
130 if (file_rdev && (stat("/", &st_buf) == 0) &&
131 (st_buf.st_dev == file_rdev))
132 *mount_flags = MF_MOUNTED;
133 #endif /* __GNU__ */
134 goto errout;
135 }
136 #ifndef __GNU__ /* The GNU hurd is deficient; what else is new? */
137 /* Validate the entry in case /etc/mtab is out of date */
138 /*
139 * We need to be paranoid, because some broken distributions
140 * (read: Slackware) don't initialize /etc/mtab before checking
141 * all of the non-root filesystems on the disk.
142 */
143 if (stat(mnt_dir, &st_buf) < 0) {
144 retval = errno;
145 if (retval == ENOENT) {
146 #ifdef DEBUG
147 printf("Bogus entry in %s! (%s does not exist)\n",
148 mtab_file, mnt_dir);
149 #endif /* DEBUG */
150 retval = 0;
151 }
152 goto errout;
153 }
154 if (file_rdev && (st_buf.st_dev != file_rdev)) {
155 #ifdef DEBUG
156 printf("Bogus entry in %s! (%s not mounted on %s)\n",
157 mtab_file, file, mnt_dir);
158 #endif /* DEBUG */
159 goto errout;
160 }
161 #endif /* __GNU__ */
162 *mount_flags = MF_MOUNTED;
163
164 retval = 0;
165 errout:
166 endmntent (f);
167 return retval;
168 }
169
170 int is_mounted(const char *file)
171 {
172 int retval;
173 int mount_flags = 0;
174
175 #ifdef __linux__
176 retval = check_mntent_file(_PATH_PROC_MOUNTS, file, &mount_flags);
177 if (retval)
178 return 0;
179 if (mount_flags)
180 return 1;
181 #endif /* __linux__ */
182 retval = check_mntent_file(_PATH_MOUNTED, file, &mount_flags);
183 if (retval)
184 return 0;
185 return mount_flags;
186 }
187
188 #ifdef TEST_PROGRAM
189 int main(int argc, char **argv)
190 {
191 if (argc < 2) {
192 fprintf(stderr, "Usage: %s device\n", argv[0]);
193 exit(1);
194 }
195
196 if (is_mounted(argv[1]))
197 printf("\t%s is mounted.\n", argv[1]);
198 exit(0);
199 }
200 #endif /* DEBUG */