]> git.ipfire.org Git - thirdparty/e2fsprogs.git/blame - lib/ext2fs/ismounted.c
Remove trailing whitespace for the entire source tree
[thirdparty/e2fsprogs.git] / lib / ext2fs / ismounted.c
CommitLineData
50e1e10f 1/*
19c78dc0 2 * ismounted.c --- Check to see if the filesystem was mounted
efc6f628 3 *
cc86017b 4 * Copyright (C) 1995,1996,1997,1998,1999,2000 Theodore Ts'o.
19c78dc0
TT
5 *
6 * %Begin-Header%
7 * This file may be redistributed under the terms of the GNU Public
8 * License.
9 * %End-Header%
50e1e10f
TT
10 */
11
12#include <stdio.h>
13#if HAVE_UNISTD_H
14#include <unistd.h>
15#endif
c4e749ab
TT
16#if HAVE_ERRNO_H
17#include <errno.h>
18#endif
50e1e10f 19#include <fcntl.h>
50e1e10f
TT
20#ifdef HAVE_LINUX_FD_H
21#include <linux/fd.h>
22#endif
23#ifdef HAVE_MNTENT_H
24#include <mntent.h>
25#endif
26#ifdef HAVE_GETMNTINFO
27#include <paths.h>
28#include <sys/param.h>
29#include <sys/mount.h>
30#endif /* HAVE_GETMNTINFO */
31dbecd4 31#include <string.h>
cc86017b 32#include <sys/stat.h>
50e1e10f 33
b5abe6fa 34#include "ext2_fs.h"
50e1e10f
TT
35#include "ext2fs.h"
36
37#ifdef HAVE_MNTENT_H
38/*
52db0b41
TT
39 * Helper function which checks a file in /etc/mtab format to see if a
40 * filesystem is mounted. Returns an error if the file doesn't exist
efc6f628 41 * or can't be opened.
50e1e10f 42 */
efc6f628 43static errcode_t check_mntent_file(const char *mtab_file, const char *file,
52db0b41 44 int *mount_flags, char *mtpt, int mtlen)
50e1e10f 45{
2038b636 46 struct mntent *mnt;
a8fd6e36 47 struct stat st_buf;
2038b636 48 errcode_t retval = 0;
3a42fe22
TT
49 dev_t file_dev=0, file_rdev=0;
50 ino_t file_ino=0;
2038b636
TT
51 FILE *f;
52 int fd;
50e1e10f
TT
53
54 *mount_flags = 0;
52db0b41 55 if ((f = setmntent (mtab_file, "r")) == NULL)
50e1e10f 56 return errno;
3a42fe22
TT
57 if (stat(file, &st_buf) == 0) {
58 if (S_ISBLK(st_buf.st_mode)) {
a8fd6e36 59#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
3a42fe22 60 file_rdev = st_buf.st_rdev;
f0efd297 61#endif /* __GNU__ */
3a42fe22
TT
62 } else {
63 file_dev = st_buf.st_dev;
64 file_ino = st_buf.st_ino;
65 }
66 }
a8fd6e36 67 while ((mnt = getmntent (f)) != NULL) {
50e1e10f
TT
68 if (strcmp(file, mnt->mnt_fsname) == 0)
69 break;
3a42fe22
TT
70 if (stat(mnt->mnt_fsname, &st_buf) == 0) {
71 if (S_ISBLK(st_buf.st_mode)) {
a8fd6e36 72#ifndef __GNU__
3a42fe22
TT
73 if (file_rdev && (file_rdev == st_buf.st_rdev))
74 break;
f0efd297 75#endif /* __GNU__ */
3a42fe22
TT
76 } else {
77 if (file_dev && ((file_dev == st_buf.st_dev) &&
78 (file_ino == st_buf.st_ino)))
79 break;
80 }
81 }
a8fd6e36 82 }
cc86017b
TT
83
84 if (mnt == 0) {
66a46146 85#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
cc86017b
TT
86 /*
87 * Do an extra check to see if this is the root device. We
2038b636 88 * can't trust /etc/mtab, and /proc/mounts will only list
cc86017b
TT
89 * /dev/root for the root filesystem. Argh. Instead we
90 * check if the given device has the same major/minor number
91 * as the device that the root directory is on.
92 */
3a42fe22
TT
93 if (file_rdev && stat("/", &st_buf) == 0) {
94 if (st_buf.st_dev == file_rdev) {
cc86017b
TT
95 *mount_flags = EXT2_MF_MOUNTED;
96 if (mtpt)
d5f858dd 97 strncpy(mtpt, "/", mtlen);
cc86017b
TT
98 goto is_root;
99 }
100 }
f0efd297 101#endif /* __GNU__ */
48e6e813 102 goto errout;
2038b636
TT
103 }
104#ifndef __GNU__ /* The GNU hurd is deficient; what else is new? */
105 /* Validate the entry in case /etc/mtab is out of date */
efc6f628 106 /*
2038b636
TT
107 * We need to be paranoid, because some broken distributions
108 * (read: Slackware) don't initialize /etc/mtab before checking
109 * all of the non-root filesystems on the disk.
110 */
a8fd6e36 111 if (stat(mnt->mnt_dir, &st_buf) < 0) {
2038b636
TT
112 retval = errno;
113 if (retval == ENOENT) {
114#ifdef DEBUG
115 printf("Bogus entry in %s! (%s does not exist)\n",
116 mtab_file, mnt->mnt_dir);
f0efd297 117#endif /* DEBUG */
2038b636
TT
118 retval = 0;
119 }
48e6e813 120 goto errout;
2038b636 121 }
3a42fe22 122 if (file_rdev && (st_buf.st_dev != file_rdev)) {
2038b636 123#ifdef DEBUG
a8fd6e36
TT
124 printf("Bogus entry in %s! (%s not mounted on %s)\n",
125 mtab_file, file, mnt->mnt_dir);
f0efd297 126#endif /* DEBUG */
48e6e813 127 goto errout;
cc86017b 128 }
f0efd297 129#endif /* __GNU__ */
50e1e10f 130 *mount_flags = EXT2_MF_MOUNTED;
efc6f628 131
fff45483 132#ifdef MNTOPT_RO
52db0b41
TT
133 /* Check to see if the ro option is set */
134 if (hasmntopt(mnt, MNTOPT_RO))
135 *mount_flags |= EXT2_MF_READONLY;
fff45483 136#endif
52db0b41 137
cc86017b
TT
138 if (mtpt)
139 strncpy(mtpt, mnt->mnt_dir, mtlen);
52db0b41
TT
140 /*
141 * Check to see if we're referring to the root filesystem.
142 * If so, do a manual check to see if we can open /etc/mtab
cc86017b
TT
143 * read/write, since if the root is mounted read/only, the
144 * contents of /etc/mtab may not be accurate.
52db0b41 145 */
50e1e10f 146 if (!strcmp(mnt->mnt_dir, "/")) {
cc86017b 147is_root:
efc6f628 148#define TEST_FILE "/.ismount-test-file"
50e1e10f 149 *mount_flags |= EXT2_MF_ISROOT;
8cdd6a6f 150 fd = open(TEST_FILE, O_RDWR|O_CREAT, 0600);
50e1e10f
TT
151 if (fd < 0) {
152 if (errno == EROFS)
153 *mount_flags |= EXT2_MF_READONLY;
154 } else
155 close(fd);
997b820e 156 (void) unlink(TEST_FILE);
50e1e10f 157 }
2038b636 158 retval = 0;
48e6e813 159errout:
cc86017b 160 endmntent (f);
2038b636 161 return retval;
50e1e10f 162}
52db0b41
TT
163
164static errcode_t check_mntent(const char *file, int *mount_flags,
165 char *mtpt, int mtlen)
166{
167 errcode_t retval;
168
2038b636
TT
169#ifdef DEBUG
170 retval = check_mntent_file("/tmp/mtab", file, mount_flags,
171 mtpt, mtlen);
172 if (retval == 0)
173 return 0;
f0efd297 174#endif /* DEBUG */
52db0b41
TT
175#ifdef __linux__
176 retval = check_mntent_file("/proc/mounts", file, mount_flags,
177 mtpt, mtlen);
3a42fe22 178 if (retval == 0 && (*mount_flags != 0))
52db0b41 179 return 0;
f0efd297 180#endif /* __linux__ */
5818d678
TT
181#if defined(MOUNTED) || defined(_PATH_MOUNTED)
182#ifndef MOUNTED
183#define MOUNTED _PATH_MOUNTED
184#endif /* MOUNTED */
52db0b41
TT
185 retval = check_mntent_file(MOUNTED, file, mount_flags, mtpt, mtlen);
186 return retval;
efc6f628 187#else
5818d678
TT
188 *mount_flags = 0;
189 return 0;
190#endif /* defined(MOUNTED) || defined(_PATH_MOUNTED) */
52db0b41
TT
191}
192
48e6e813
TT
193#else
194#if defined(HAVE_GETMNTINFO)
50e1e10f 195
43ec8734
TT
196static errcode_t check_getmntinfo(const char *file, int *mount_flags,
197 char *mtpt, int mtlen)
50e1e10f
TT
198{
199 struct statfs *mp;
200 int len, n;
201 const char *s1;
202 char *s2;
203
204 n = getmntinfo(&mp, MNT_NOWAIT);
205 if (n == 0)
206 return errno;
207
208 len = sizeof(_PATH_DEV) - 1;
209 s1 = file;
210 if (strncmp(_PATH_DEV, s1, len) == 0)
211 s1 += len;
efc6f628 212
50e1e10f
TT
213 *mount_flags = 0;
214 while (--n >= 0) {
215 s2 = mp->f_mntfromname;
216 if (strncmp(_PATH_DEV, s2, len) == 0) {
217 s2 += len - 1;
218 *s2 = 'r';
219 }
220 if (strcmp(s1, s2) == 0 || strcmp(s1, &s2[1]) == 0) {
221 *mount_flags = EXT2_MF_MOUNTED;
222 break;
223 }
224 ++mp;
225 }
43ec8734
TT
226 if (mtpt)
227 strncpy(mtpt, mp->f_mntonname, mtlen);
50e1e10f
TT
228 return 0;
229}
230#endif /* HAVE_GETMNTINFO */
48e6e813 231#endif /* HAVE_MNTENT_H */
50e1e10f 232
f0efd297
TT
233/*
234 * Check to see if we're dealing with the swap device.
235 */
236static int is_swap_device(const char *file)
237{
238 FILE *f;
239 char buf[1024], *cp;
240 dev_t file_dev;
241 struct stat st_buf;
242 int ret = 0;
243
244 file_dev = 0;
245#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
246 if ((stat(file, &st_buf) == 0) &&
247 S_ISBLK(st_buf.st_mode))
248 file_dev = st_buf.st_rdev;
249#endif /* __GNU__ */
250
251 if (!(f = fopen("/proc/swaps", "r")))
252 return 0;
253 /* Skip the first line */
d9039ae0
DL
254 if (fgets(buf, sizeof(buf), f))
255 while (fgets(buf, sizeof(buf), f)) {
f0efd297
TT
256 if ((cp = strchr(buf, ' ')) != NULL)
257 *cp = 0;
258 if ((cp = strchr(buf, '\t')) != NULL)
259 *cp = 0;
260 if (strcmp(buf, file) == 0) {
261 ret++;
262 break;
263 }
264#ifndef __GNU__
265 if (file_dev && (stat(buf, &st_buf) == 0) &&
266 S_ISBLK(st_buf.st_mode) &&
267 file_dev == st_buf.st_rdev) {
268 ret++;
269 break;
270 }
271#endif /* __GNU__ */
272 }
273 fclose(f);
274 return ret;
275}
276
277
50e1e10f 278/*
2fa8f37f
TT
279 * ext2fs_check_mount_point() fills determines if the device is
280 * mounted or otherwise busy, and fills in mount_flags with one or
281 * more of the following flags: EXT2_MF_MOUNTED, EXT2_MF_ISROOT,
282 * EXT2_MF_READONLY, EXT2_MF_SWAP, and EXT2_MF_BUSY. If mtpt is
283 * non-NULL, the directory where the device is mounted is copied to
284 * where mtpt is pointing, up to mtlen characters.
43ec8734
TT
285 */
286#ifdef __TURBOC__
31dbecd4 287 #pragma argsused
43ec8734
TT
288#endif
289errcode_t ext2fs_check_mount_point(const char *device, int *mount_flags,
290 char *mtpt, int mtlen)
291{
2fa8f37f
TT
292 struct stat st_buf;
293 errcode_t retval = 0;
294 int fd;
295
07cefe7a
TT
296 if (is_swap_device(device)) {
297 *mount_flags = EXT2_MF_MOUNTED | EXT2_MF_SWAP;
298 strncpy(mtpt, "<swap>", mtlen);
2fa8f37f 299 } else {
43ec8734 300#ifdef HAVE_MNTENT_H
2fa8f37f 301 retval = check_mntent(device, mount_flags, mtpt, mtlen);
efc6f628 302#else
43ec8734 303#ifdef HAVE_GETMNTINFO
2fa8f37f 304 retval = check_getmntinfo(device, mount_flags, mtpt, mtlen);
43ec8734 305#else
ed78c021 306#ifdef __GNUC__
48e6e813 307 #warning "Can't use getmntent or getmntinfo to check for mounted filesystems!"
ed78c021 308#endif
2fa8f37f 309 *mount_flags = 0;
43ec8734
TT
310#endif /* HAVE_GETMNTINFO */
311#endif /* HAVE_MNTENT_H */
2fa8f37f
TT
312 }
313 if (retval)
314 return retval;
315
316#ifdef __linux__ /* This only works on Linux 2.6+ systems */
317 if ((stat(device, &st_buf) != 0) ||
318 !S_ISBLK(st_buf.st_mode))
319 return 0;
320 fd = open(device, O_RDONLY | O_EXCL);
321 if (fd < 0) {
322 if (errno == EBUSY)
323 *mount_flags |= EXT2_MF_BUSY;
324 } else
325 close(fd);
406ba674 326#endif
2fa8f37f
TT
327
328 return 0;
43ec8734
TT
329}
330
331/*
6bd13480 332 * ext2fs_check_if_mounted() sets the mount_flags EXT2_MF_MOUNTED,
d5f858dd 333 * EXT2_MF_READONLY, and EXT2_MF_ROOT
efc6f628 334 *
50e1e10f
TT
335 */
336errcode_t ext2fs_check_if_mounted(const char *file, int *mount_flags)
337{
d5f858dd 338 return ext2fs_check_mount_point(file, mount_flags, NULL, 0);
50e1e10f 339}
52db0b41
TT
340
341#ifdef DEBUG
342int main(int argc, char **argv)
343{
52db0b41 344 int retval, mount_flags;
a8fd6e36 345 char mntpt[80];
efc6f628 346
52db0b41
TT
347 if (argc < 2) {
348 fprintf(stderr, "Usage: %s device\n", argv[0]);
349 exit(1);
350 }
351
a8fd6e36
TT
352 mntpt[0] = 0;
353 retval = ext2fs_check_mount_point(argv[1], &mount_flags,
354 mntpt, sizeof(mntpt));
52db0b41
TT
355 if (retval) {
356 com_err(argv[0], retval,
357 "while calling ext2fs_check_if_mounted");
358 exit(1);
359 }
360 printf("Device %s reports flags %02x\n", argv[1], mount_flags);
2fa8f37f
TT
361 if (mount_flags & EXT2_MF_BUSY)
362 printf("\t%s is apparently in use.\n", argv[1]);
52db0b41 363 if (mount_flags & EXT2_MF_MOUNTED)
cc86017b 364 printf("\t%s is mounted.\n", argv[1]);
07cefe7a
TT
365 if (mount_flags & EXT2_MF_SWAP)
366 printf("\t%s is a swap device.\n", argv[1]);
52db0b41 367 if (mount_flags & EXT2_MF_READONLY)
cc86017b 368 printf("\t%s is read-only.\n", argv[1]);
52db0b41 369 if (mount_flags & EXT2_MF_ISROOT)
cc86017b 370 printf("\t%s is the root filesystem.\n", argv[1]);
a8fd6e36
TT
371 if (mntpt[0])
372 printf("\t%s is mounted on %s.\n", argv[1], mntpt);
52db0b41
TT
373 exit(0);
374}
f0efd297 375#endif /* DEBUG */