150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o/*
219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * ismounted.c --- Check to see if the filesystem was mounted
3efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o *
4cc86017b593ddfbd4d7a12ed8695e62998f30944Theodore Ts'o * Copyright (C) 1995,1996,1997,1998,1999,2000 Theodore Ts'o.
519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o *
619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * %Begin-Header%
7543547a52a20cb7e69d74921b2f691078fd55d83Theodore Ts'o * This file may be redistributed under the terms of the GNU Library
8543547a52a20cb7e69d74921b2f691078fd55d83Theodore Ts'o * General Public License, version 2.
919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * %End-Header%
1050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o */
1150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
128f6f8602dc1037fb8fc2051fb062c0209f8baa2aTheodore Ts'o/* define BSD_SOURCE to make sure we get the major() macro */
138f6f8602dc1037fb8fc2051fb062c0209f8baa2aTheodore Ts'o#ifndef _BSD_SOURCE
148f6f8602dc1037fb8fc2051fb062c0209f8baa2aTheodore Ts'o#define _BSD_SOURCE
158f6f8602dc1037fb8fc2051fb062c0209f8baa2aTheodore Ts'o#endif
168f6f8602dc1037fb8fc2051fb062c0209f8baa2aTheodore Ts'o#ifndef _DEFAULT_SOURCE
178f6f8602dc1037fb8fc2051fb062c0209f8baa2aTheodore Ts'o#define _DEFAULT_SOURCE	/* since glibc 2.20 _SVID_SOURCE is deprecated */
188f6f8602dc1037fb8fc2051fb062c0209f8baa2aTheodore Ts'o#endif
198f6f8602dc1037fb8fc2051fb062c0209f8baa2aTheodore Ts'o
20d1154eb460efe588eaed3d439c1caaca149fa362Theodore Ts'o#include "config.h"
2150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#include <stdio.h>
2250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#if HAVE_UNISTD_H
2350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#include <unistd.h>
2450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#endif
25c4e749abd8451f02418fe552b2af14f226f7bd1eTheodore Ts'o#if HAVE_ERRNO_H
26c4e749abd8451f02418fe552b2af14f226f7bd1eTheodore Ts'o#include <errno.h>
27c4e749abd8451f02418fe552b2af14f226f7bd1eTheodore Ts'o#endif
2850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#include <fcntl.h>
2950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#ifdef HAVE_LINUX_FD_H
3050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#include <linux/fd.h>
3150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#endif
32fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio#ifdef HAVE_LINUX_LOOP_H
33fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio#include <linux/loop.h>
34fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio#include <sys/ioctl.h>
35fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio#ifdef HAVE_LINUX_MAJOR_H
36fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio#include <linux/major.h>
37fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio#endif /* HAVE_LINUX_MAJOR_H */
38fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio#endif /* HAVE_LINUX_LOOP_H */
3950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#ifdef HAVE_MNTENT_H
4050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#include <mntent.h>
4150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#endif
4250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#ifdef HAVE_GETMNTINFO
4350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#include <paths.h>
4450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#include <sys/param.h>
4550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#include <sys/mount.h>
4650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#endif /* HAVE_GETMNTINFO */
4731dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o#include <string.h>
48cc86017b593ddfbd4d7a12ed8695e62998f30944Theodore Ts'o#include <sys/stat.h>
498f6f8602dc1037fb8fc2051fb062c0209f8baa2aTheodore Ts'o#if HAVE_SYS_TYPES_H
508f6f8602dc1037fb8fc2051fb062c0209f8baa2aTheodore Ts'o#include <sys/types.h>
518f6f8602dc1037fb8fc2051fb062c0209f8baa2aTheodore Ts'o#endif
5250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
53b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o#include "ext2_fs.h"
5450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#include "ext2fs.h"
5550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
56aee40b870cd70a884fd98a56d9c956945584b429Theodore Ts'o#ifdef HAVE_SETMNTENT
57fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio/*
58fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio * Check to see if a regular file is mounted.
59fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio * If /etc/mtab/ is a symlink of /proc/mounts, you will need the following check
60fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio * because the name in /proc/mounts is a loopback device not a regular file.
61fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio */
62fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Miostatic int check_loop_mounted(const char *mnt_fsname, dev_t mnt_rdev,
63fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio				dev_t file_dev, ino_t file_ino)
64fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio{
65fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio#if defined(HAVE_LINUX_LOOP_H) && defined(HAVE_LINUX_MAJOR_H)
66fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio	struct loop_info64 loopinfo;
67fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio	int loop_fd, ret;
68fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio
69fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio	if (major(mnt_rdev) == LOOP_MAJOR) {
70fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio		loop_fd = open(mnt_fsname, O_RDONLY);
71fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio		if (loop_fd < 0)
72fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio			return -1;
73fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio
74fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio		ret = ioctl(loop_fd, LOOP_GET_STATUS64, &loopinfo);
75fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio		close(loop_fd);
76fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio		if (ret < 0)
77fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio			return -1;
78fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio
79fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio		if (file_dev == loopinfo.lo_device &&
80fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio				file_ino == loopinfo.lo_inode)
81fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio			return 1;
82fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio	}
83fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio#endif /* defined(HAVE_LINUX_LOOP_H) && defined(HAVE_LINUX_MAJOR_H) */
84fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio	return 0;
85fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio}
86fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio
8750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o/*
8852db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o * Helper function which checks a file in /etc/mtab format to see if a
8952db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o * filesystem is mounted.  Returns an error if the file doesn't exist
90efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * or can't be opened.
9150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o */
92efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'ostatic errcode_t check_mntent_file(const char *mtab_file, const char *file,
9352db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o				   int *mount_flags, char *mtpt, int mtlen)
9450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o{
952038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o	struct mntent 	*mnt;
96a8fd6e36b866f2cf14edaa19d452fa64bd0fba40Theodore Ts'o	struct stat	st_buf;
972038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o	errcode_t	retval = 0;
983a42fe220c301c8b9a8df595938c9a923cf5c494Theodore Ts'o	dev_t		file_dev=0, file_rdev=0;
993a42fe220c301c8b9a8df595938c9a923cf5c494Theodore Ts'o	ino_t		file_ino=0;
1002038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o	FILE 		*f;
1012038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o	int		fd;
10250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
10350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	*mount_flags = 0;
1042b8772f522be1c82c92e7e0401126808431d06a2Darrick J. Wong
10542b61c50e5af99a10fc56975ecd08ab71e4f00e8Theodore Ts'o	if ((f = setmntent (mtab_file, "r")) == NULL) {
10642b61c50e5af99a10fc56975ecd08ab71e4f00e8Theodore Ts'o		if (errno == ENOENT) {
10742b61c50e5af99a10fc56975ecd08ab71e4f00e8Theodore Ts'o			if (getenv("EXT2FS_NO_MTAB_OK"))
10842b61c50e5af99a10fc56975ecd08ab71e4f00e8Theodore Ts'o				return 0;
10942b61c50e5af99a10fc56975ecd08ab71e4f00e8Theodore Ts'o			else
1108ab395524b95875818505a497428cab73e80c0d5Zheng Liu				return EXT2_ET_NO_MTAB_FILE;
11142b61c50e5af99a10fc56975ecd08ab71e4f00e8Theodore Ts'o		}
11242b61c50e5af99a10fc56975ecd08ab71e4f00e8Theodore Ts'o		return errno;
11342b61c50e5af99a10fc56975ecd08ab71e4f00e8Theodore Ts'o	}
1143a42fe220c301c8b9a8df595938c9a923cf5c494Theodore Ts'o	if (stat(file, &st_buf) == 0) {
1153a42fe220c301c8b9a8df595938c9a923cf5c494Theodore Ts'o		if (S_ISBLK(st_buf.st_mode)) {
116a8fd6e36b866f2cf14edaa19d452fa64bd0fba40Theodore Ts'o#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
1173a42fe220c301c8b9a8df595938c9a923cf5c494Theodore Ts'o			file_rdev = st_buf.st_rdev;
118f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o#endif	/* __GNU__ */
1193a42fe220c301c8b9a8df595938c9a923cf5c494Theodore Ts'o		} else {
1203a42fe220c301c8b9a8df595938c9a923cf5c494Theodore Ts'o			file_dev = st_buf.st_dev;
1213a42fe220c301c8b9a8df595938c9a923cf5c494Theodore Ts'o			file_ino = st_buf.st_ino;
1223a42fe220c301c8b9a8df595938c9a923cf5c494Theodore Ts'o		}
1233a42fe220c301c8b9a8df595938c9a923cf5c494Theodore Ts'o	}
124a8fd6e36b866f2cf14edaa19d452fa64bd0fba40Theodore Ts'o	while ((mnt = getmntent (f)) != NULL) {
125f9110f4480eade2d849c4cc08efa49bf0f7f5148Theodore Ts'o		if (mnt->mnt_fsname[0] != '/')
126f9110f4480eade2d849c4cc08efa49bf0f7f5148Theodore Ts'o			continue;
12750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o		if (strcmp(file, mnt->mnt_fsname) == 0)
12850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o			break;
1293a42fe220c301c8b9a8df595938c9a923cf5c494Theodore Ts'o		if (stat(mnt->mnt_fsname, &st_buf) == 0) {
1303a42fe220c301c8b9a8df595938c9a923cf5c494Theodore Ts'o			if (S_ISBLK(st_buf.st_mode)) {
131a8fd6e36b866f2cf14edaa19d452fa64bd0fba40Theodore Ts'o#ifndef __GNU__
1323a42fe220c301c8b9a8df595938c9a923cf5c494Theodore Ts'o				if (file_rdev && (file_rdev == st_buf.st_rdev))
1333a42fe220c301c8b9a8df595938c9a923cf5c494Theodore Ts'o					break;
134fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio				if (check_loop_mounted(mnt->mnt_fsname,
135fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio						st_buf.st_rdev, file_dev,
136fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio						file_ino) == 1)
137fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio					break;
138f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o#endif	/* __GNU__ */
1393a42fe220c301c8b9a8df595938c9a923cf5c494Theodore Ts'o			} else {
1403a42fe220c301c8b9a8df595938c9a923cf5c494Theodore Ts'o				if (file_dev && ((file_dev == st_buf.st_dev) &&
1413a42fe220c301c8b9a8df595938c9a923cf5c494Theodore Ts'o						 (file_ino == st_buf.st_ino)))
1423a42fe220c301c8b9a8df595938c9a923cf5c494Theodore Ts'o					break;
1433a42fe220c301c8b9a8df595938c9a923cf5c494Theodore Ts'o			}
1443a42fe220c301c8b9a8df595938c9a923cf5c494Theodore Ts'o		}
145a8fd6e36b866f2cf14edaa19d452fa64bd0fba40Theodore Ts'o	}
146cc86017b593ddfbd4d7a12ed8695e62998f30944Theodore Ts'o
147cc86017b593ddfbd4d7a12ed8695e62998f30944Theodore Ts'o	if (mnt == 0) {
14866a461469ccafd7aad2a824b0ab66fd9096d6e94Theodore Ts'o#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
149cc86017b593ddfbd4d7a12ed8695e62998f30944Theodore Ts'o		/*
150cc86017b593ddfbd4d7a12ed8695e62998f30944Theodore Ts'o		 * Do an extra check to see if this is the root device.  We
1512038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o		 * can't trust /etc/mtab, and /proc/mounts will only list
152cc86017b593ddfbd4d7a12ed8695e62998f30944Theodore Ts'o		 * /dev/root for the root filesystem.  Argh.  Instead we
153cc86017b593ddfbd4d7a12ed8695e62998f30944Theodore Ts'o		 * check if the given device has the same major/minor number
154cc86017b593ddfbd4d7a12ed8695e62998f30944Theodore Ts'o		 * as the device that the root directory is on.
155cc86017b593ddfbd4d7a12ed8695e62998f30944Theodore Ts'o		 */
1563a42fe220c301c8b9a8df595938c9a923cf5c494Theodore Ts'o		if (file_rdev && stat("/", &st_buf) == 0) {
1573a42fe220c301c8b9a8df595938c9a923cf5c494Theodore Ts'o			if (st_buf.st_dev == file_rdev) {
158cc86017b593ddfbd4d7a12ed8695e62998f30944Theodore Ts'o				*mount_flags = EXT2_MF_MOUNTED;
159cc86017b593ddfbd4d7a12ed8695e62998f30944Theodore Ts'o				if (mtpt)
160d5f858dd7f02532ad90e4121537c358e86d0eecfTheodore Ts'o					strncpy(mtpt, "/", mtlen);
161cc86017b593ddfbd4d7a12ed8695e62998f30944Theodore Ts'o				goto is_root;
162cc86017b593ddfbd4d7a12ed8695e62998f30944Theodore Ts'o			}
163cc86017b593ddfbd4d7a12ed8695e62998f30944Theodore Ts'o		}
164f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o#endif	/* __GNU__ */
16548e6e81362f264aee4f3945c14928efaf71a06c9Theodore Ts'o		goto errout;
1662038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o	}
1672038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o#ifndef __GNU__ /* The GNU hurd is deficient; what else is new? */
1682038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o	/* Validate the entry in case /etc/mtab is out of date */
169efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	/*
1702038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o	 * We need to be paranoid, because some broken distributions
1712038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o	 * (read: Slackware) don't initialize /etc/mtab before checking
1722038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o	 * all of the non-root filesystems on the disk.
1732038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o	 */
174a8fd6e36b866f2cf14edaa19d452fa64bd0fba40Theodore Ts'o	if (stat(mnt->mnt_dir, &st_buf) < 0) {
1752038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o		retval = errno;
1762038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o		if (retval == ENOENT) {
1772038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o#ifdef DEBUG
1782038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o			printf("Bogus entry in %s!  (%s does not exist)\n",
1792038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o			       mtab_file, mnt->mnt_dir);
180f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o#endif /* DEBUG */
1812038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o			retval = 0;
1822038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o		}
18348e6e81362f264aee4f3945c14928efaf71a06c9Theodore Ts'o		goto errout;
1842038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o	}
1853a42fe220c301c8b9a8df595938c9a923cf5c494Theodore Ts'o	if (file_rdev && (st_buf.st_dev != file_rdev)) {
1862038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o#ifdef DEBUG
187a8fd6e36b866f2cf14edaa19d452fa64bd0fba40Theodore Ts'o		printf("Bogus entry in %s!  (%s not mounted on %s)\n",
188a8fd6e36b866f2cf14edaa19d452fa64bd0fba40Theodore Ts'o		       mtab_file, file, mnt->mnt_dir);
189f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o#endif /* DEBUG */
19048e6e81362f264aee4f3945c14928efaf71a06c9Theodore Ts'o		goto errout;
191cc86017b593ddfbd4d7a12ed8695e62998f30944Theodore Ts'o	}
192f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o#endif /* __GNU__ */
19350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	*mount_flags = EXT2_MF_MOUNTED;
194efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
195fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o#ifdef MNTOPT_RO
19652db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o	/* Check to see if the ro option is set */
19752db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o	if (hasmntopt(mnt, MNTOPT_RO))
19852db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o		*mount_flags |= EXT2_MF_READONLY;
199fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o#endif
20052db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o
201cc86017b593ddfbd4d7a12ed8695e62998f30944Theodore Ts'o	if (mtpt)
202cc86017b593ddfbd4d7a12ed8695e62998f30944Theodore Ts'o		strncpy(mtpt, mnt->mnt_dir, mtlen);
20352db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o	/*
20452db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o	 * Check to see if we're referring to the root filesystem.
20552db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o	 * If so, do a manual check to see if we can open /etc/mtab
206cc86017b593ddfbd4d7a12ed8695e62998f30944Theodore Ts'o	 * read/write, since if the root is mounted read/only, the
207cc86017b593ddfbd4d7a12ed8695e62998f30944Theodore Ts'o	 * contents of /etc/mtab may not be accurate.
20852db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o	 */
20950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	if (!strcmp(mnt->mnt_dir, "/")) {
210cc86017b593ddfbd4d7a12ed8695e62998f30944Theodore Ts'ois_root:
211efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o#define TEST_FILE "/.ismount-test-file"
21250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o		*mount_flags |= EXT2_MF_ISROOT;
2138cdd6a6f34a66806fb200f2a55c8fa4142d79511Andreas Dilger		fd = open(TEST_FILE, O_RDWR|O_CREAT, 0600);
21450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o		if (fd < 0) {
21550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o			if (errno == EROFS)
21650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o				*mount_flags |= EXT2_MF_READONLY;
21750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o		} else
21850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o			close(fd);
219997b820e94468aeb3fb1a6fd38bc52e34af6f9e6Theodore Ts'o		(void) unlink(TEST_FILE);
22050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	}
2212038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o	retval = 0;
22248e6e81362f264aee4f3945c14928efaf71a06c9Theodore Ts'oerrout:
223cc86017b593ddfbd4d7a12ed8695e62998f30944Theodore Ts'o	endmntent (f);
2242038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o	return retval;
22550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o}
22652db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o
22752db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'ostatic errcode_t check_mntent(const char *file, int *mount_flags,
22852db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o			      char *mtpt, int mtlen)
22952db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o{
23052db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o	errcode_t	retval;
23152db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o
2322038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o#ifdef DEBUG
2332038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o	retval = check_mntent_file("/tmp/mtab", file, mount_flags,
2342038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o				   mtpt, mtlen);
2352038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o	if (retval == 0)
2362038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o		return 0;
237f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o#endif /* DEBUG */
23852db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o#ifdef __linux__
23952db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o	retval = check_mntent_file("/proc/mounts", file, mount_flags,
24052db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o				   mtpt, mtlen);
2413a42fe220c301c8b9a8df595938c9a923cf5c494Theodore Ts'o	if (retval == 0 && (*mount_flags != 0))
24252db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o		return 0;
243f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o#endif /* __linux__ */
2445818d6789aaa795aeee1fdb0f7d812a1cabe3d1dTheodore Ts'o#if defined(MOUNTED) || defined(_PATH_MOUNTED)
2455818d6789aaa795aeee1fdb0f7d812a1cabe3d1dTheodore Ts'o#ifndef MOUNTED
2465818d6789aaa795aeee1fdb0f7d812a1cabe3d1dTheodore Ts'o#define MOUNTED _PATH_MOUNTED
2475818d6789aaa795aeee1fdb0f7d812a1cabe3d1dTheodore Ts'o#endif /* MOUNTED */
24852db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o	retval = check_mntent_file(MOUNTED, file, mount_flags, mtpt, mtlen);
24952db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o	return retval;
250efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o#else
2515818d6789aaa795aeee1fdb0f7d812a1cabe3d1dTheodore Ts'o	*mount_flags = 0;
2525818d6789aaa795aeee1fdb0f7d812a1cabe3d1dTheodore Ts'o	return 0;
2535818d6789aaa795aeee1fdb0f7d812a1cabe3d1dTheodore Ts'o#endif /* defined(MOUNTED) || defined(_PATH_MOUNTED) */
25452db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o}
25552db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o
25648e6e81362f264aee4f3945c14928efaf71a06c9Theodore Ts'o#else
25748e6e81362f264aee4f3945c14928efaf71a06c9Theodore Ts'o#if defined(HAVE_GETMNTINFO)
25850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
25943ec8734f2ecd0a345e831f45fd3dfb077426811Theodore Ts'ostatic errcode_t check_getmntinfo(const char *file, int *mount_flags,
26043ec8734f2ecd0a345e831f45fd3dfb077426811Theodore Ts'o				  char *mtpt, int mtlen)
26150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o{
26250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	struct statfs *mp;
26350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o        int    len, n;
26450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o        const  char   *s1;
26550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	char	*s2;
26650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
26750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o        n = getmntinfo(&mp, MNT_NOWAIT);
26850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o        if (n == 0)
26950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o		return errno;
27050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
27150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o        len = sizeof(_PATH_DEV) - 1;
27250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o        s1 = file;
27350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o        if (strncmp(_PATH_DEV, s1, len) == 0)
27450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o                s1 += len;
275efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
27650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	*mount_flags = 0;
27750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o        while (--n >= 0) {
27850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o                s2 = mp->f_mntfromname;
27950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o                if (strncmp(_PATH_DEV, s2, len) == 0) {
28050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o                        s2 += len - 1;
28150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o                        *s2 = 'r';
28250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o                }
28350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o                if (strcmp(s1, s2) == 0 || strcmp(s1, &s2[1]) == 0) {
28450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o			*mount_flags = EXT2_MF_MOUNTED;
28550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o			break;
28650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o		}
28750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o                ++mp;
28850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	}
28943ec8734f2ecd0a345e831f45fd3dfb077426811Theodore Ts'o	if (mtpt)
29043ec8734f2ecd0a345e831f45fd3dfb077426811Theodore Ts'o		strncpy(mtpt, mp->f_mntonname, mtlen);
29150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	return 0;
29250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o}
29350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#endif /* HAVE_GETMNTINFO */
294b24efa218794b567c27ad99db319b4bd5d696958Theodore Ts'o#endif /* HAVE_SETMNTENT */
29550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
29650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o/*
297f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o * Check to see if we're dealing with the swap device.
298f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o */
299f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'ostatic int is_swap_device(const char *file)
300f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o{
301f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o	FILE		*f;
302f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o	char		buf[1024], *cp;
303f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o	dev_t		file_dev;
304f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o	struct stat	st_buf;
305f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o	int		ret = 0;
306f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o
307f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o	file_dev = 0;
308f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
309f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o	if ((stat(file, &st_buf) == 0) &&
310f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o	    S_ISBLK(st_buf.st_mode))
311f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o		file_dev = st_buf.st_rdev;
312f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o#endif	/* __GNU__ */
313f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o
314f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o	if (!(f = fopen("/proc/swaps", "r")))
315f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o		return 0;
316f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o	/* Skip the first line */
3175f91561ae7e08d79b6a5feca167259fd7634713fKarel Zak	if (!fgets(buf, sizeof(buf), f))
3185f91561ae7e08d79b6a5feca167259fd7634713fKarel Zak		goto leave;
3195f91561ae7e08d79b6a5feca167259fd7634713fKarel Zak	if (*buf && strncmp(buf, "Filename\t", 9))
3205f91561ae7e08d79b6a5feca167259fd7634713fKarel Zak		/* Linux <=2.6.19 contained a bug in the /proc/swaps
3215f91561ae7e08d79b6a5feca167259fd7634713fKarel Zak		 * code where the header would not be displayed
3225f91561ae7e08d79b6a5feca167259fd7634713fKarel Zak		 */
3235f91561ae7e08d79b6a5feca167259fd7634713fKarel Zak		goto valid_first_line;
3245f91561ae7e08d79b6a5feca167259fd7634713fKarel Zak
325d9039ae0ff3f7929ede576058b3ad3e9c62a47c4Dmitry V. Levin	while (fgets(buf, sizeof(buf), f)) {
3265f91561ae7e08d79b6a5feca167259fd7634713fKarel Zakvalid_first_line:
327f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o		if ((cp = strchr(buf, ' ')) != NULL)
328f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o			*cp = 0;
329f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o		if ((cp = strchr(buf, '\t')) != NULL)
330f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o			*cp = 0;
331f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o		if (strcmp(buf, file) == 0) {
332f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o			ret++;
333f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o			break;
334f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o		}
335f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o#ifndef __GNU__
336f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o		if (file_dev && (stat(buf, &st_buf) == 0) &&
337f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o		    S_ISBLK(st_buf.st_mode) &&
338f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o		    file_dev == st_buf.st_rdev) {
339f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o			ret++;
340f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o			break;
341f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o		}
342f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o#endif 	/* __GNU__ */
343f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o	}
3445f91561ae7e08d79b6a5feca167259fd7634713fKarel Zak
3455f91561ae7e08d79b6a5feca167259fd7634713fKarel Zakleave:
346f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o	fclose(f);
347f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o	return ret;
348f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o}
349f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o
350f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o
351f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o/*
3522fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o * ext2fs_check_mount_point() fills determines if the device is
3532fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o * mounted or otherwise busy, and fills in mount_flags with one or
3542fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o * more of the following flags: EXT2_MF_MOUNTED, EXT2_MF_ISROOT,
3552fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o * EXT2_MF_READONLY, EXT2_MF_SWAP, and EXT2_MF_BUSY.  If mtpt is
3562fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o * non-NULL, the directory where the device is mounted is copied to
3572fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o * where mtpt is pointing, up to mtlen characters.
35843ec8734f2ecd0a345e831f45fd3dfb077426811Theodore Ts'o */
35943ec8734f2ecd0a345e831f45fd3dfb077426811Theodore Ts'o#ifdef __TURBOC__
36031dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o #pragma argsused
36143ec8734f2ecd0a345e831f45fd3dfb077426811Theodore Ts'o#endif
36243ec8734f2ecd0a345e831f45fd3dfb077426811Theodore Ts'oerrcode_t ext2fs_check_mount_point(const char *device, int *mount_flags,
36343ec8734f2ecd0a345e831f45fd3dfb077426811Theodore Ts'o				  char *mtpt, int mtlen)
36443ec8734f2ecd0a345e831f45fd3dfb077426811Theodore Ts'o{
3652fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o	errcode_t	retval = 0;
3662fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o
36743b7b054cd3165645c9b22977247674f9465e0e1Theodore Ts'o	if (getenv("EXT2FS_PRETEND_RO_MOUNT")) {
36843b7b054cd3165645c9b22977247674f9465e0e1Theodore Ts'o		*mount_flags = EXT2_MF_MOUNTED | EXT2_MF_READONLY;
36943b7b054cd3165645c9b22977247674f9465e0e1Theodore Ts'o		if (getenv("EXT2FS_PRETEND_ROOTFS"))
37043b7b054cd3165645c9b22977247674f9465e0e1Theodore Ts'o			*mount_flags = EXT2_MF_ISROOT;
37143b7b054cd3165645c9b22977247674f9465e0e1Theodore Ts'o		return 0;
37243b7b054cd3165645c9b22977247674f9465e0e1Theodore Ts'o	}
37343b7b054cd3165645c9b22977247674f9465e0e1Theodore Ts'o	if (getenv("EXT2FS_PRETEND_RW_MOUNT")) {
37443b7b054cd3165645c9b22977247674f9465e0e1Theodore Ts'o		*mount_flags = EXT2_MF_MOUNTED;
37543b7b054cd3165645c9b22977247674f9465e0e1Theodore Ts'o		if (getenv("EXT2FS_PRETEND_ROOTFS"))
37643b7b054cd3165645c9b22977247674f9465e0e1Theodore Ts'o			*mount_flags = EXT2_MF_ISROOT;
37743b7b054cd3165645c9b22977247674f9465e0e1Theodore Ts'o		return 0;
37843b7b054cd3165645c9b22977247674f9465e0e1Theodore Ts'o	}
37943b7b054cd3165645c9b22977247674f9465e0e1Theodore Ts'o
38007cefe7a7051e32f14b93d9003a6dbb308597bd3Theodore Ts'o	if (is_swap_device(device)) {
38107cefe7a7051e32f14b93d9003a6dbb308597bd3Theodore Ts'o		*mount_flags = EXT2_MF_MOUNTED | EXT2_MF_SWAP;
38207cefe7a7051e32f14b93d9003a6dbb308597bd3Theodore Ts'o		strncpy(mtpt, "<swap>", mtlen);
3832fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o	} else {
384b24efa218794b567c27ad99db319b4bd5d696958Theodore Ts'o#ifdef HAVE_SETMNTENT
3852fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o		retval = check_mntent(device, mount_flags, mtpt, mtlen);
386efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o#else
38743ec8734f2ecd0a345e831f45fd3dfb077426811Theodore Ts'o#ifdef HAVE_GETMNTINFO
3882fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o		retval = check_getmntinfo(device, mount_flags, mtpt, mtlen);
38943ec8734f2ecd0a345e831f45fd3dfb077426811Theodore Ts'o#else
390ed78c021c3b111d8ab9a51aef5d5156e3004083fTheodore Ts'o#ifdef __GNUC__
39148e6e81362f264aee4f3945c14928efaf71a06c9Theodore Ts'o #warning "Can't use getmntent or getmntinfo to check for mounted filesystems!"
392ed78c021c3b111d8ab9a51aef5d5156e3004083fTheodore Ts'o#endif
3932fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o		*mount_flags = 0;
39443ec8734f2ecd0a345e831f45fd3dfb077426811Theodore Ts'o#endif /* HAVE_GETMNTINFO */
395b24efa218794b567c27ad99db319b4bd5d696958Theodore Ts'o#endif /* HAVE_SETMNTENT */
3962fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o	}
3972fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o	if (retval)
3982fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o		return retval;
3992fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o
4002fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o#ifdef __linux__ /* This only works on Linux 2.6+ systems */
4011d6fd6d0c3766a8165e69284c75812574a29c804Andreas Dilger	{
4021d6fd6d0c3766a8165e69284c75812574a29c804Andreas Dilger		struct stat st_buf;
4031d6fd6d0c3766a8165e69284c75812574a29c804Andreas Dilger
4041d6fd6d0c3766a8165e69284c75812574a29c804Andreas Dilger		if (stat(device, &st_buf) == 0 && S_ISBLK(st_buf.st_mode)) {
4051d6fd6d0c3766a8165e69284c75812574a29c804Andreas Dilger			int fd = open(device, O_RDONLY | O_EXCL);
4061d6fd6d0c3766a8165e69284c75812574a29c804Andreas Dilger
4071d6fd6d0c3766a8165e69284c75812574a29c804Andreas Dilger			if (fd >= 0)
4081d6fd6d0c3766a8165e69284c75812574a29c804Andreas Dilger				close(fd);
4091d6fd6d0c3766a8165e69284c75812574a29c804Andreas Dilger			else if (errno == EBUSY)
4101d6fd6d0c3766a8165e69284c75812574a29c804Andreas Dilger				*mount_flags |= EXT2_MF_BUSY;
4111d6fd6d0c3766a8165e69284c75812574a29c804Andreas Dilger		}
4121d6fd6d0c3766a8165e69284c75812574a29c804Andreas Dilger	}
413406ba674fe33469c600a4dd7ed5853cac34ca4e7Matthias Andree#endif
4142fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o
4152fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o	return 0;
41643ec8734f2ecd0a345e831f45fd3dfb077426811Theodore Ts'o}
41743ec8734f2ecd0a345e831f45fd3dfb077426811Theodore Ts'o
41843ec8734f2ecd0a345e831f45fd3dfb077426811Theodore Ts'o/*
4196bd134809ca75741941f41c11fa2b24fbc5ecfacTheodore Ts'o * ext2fs_check_if_mounted() sets the mount_flags EXT2_MF_MOUNTED,
420d5f858dd7f02532ad90e4121537c358e86d0eecfTheodore Ts'o * EXT2_MF_READONLY, and EXT2_MF_ROOT
421efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o *
42250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o */
42350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'oerrcode_t ext2fs_check_if_mounted(const char *file, int *mount_flags)
42450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o{
425d5f858dd7f02532ad90e4121537c358e86d0eecfTheodore Ts'o	return ext2fs_check_mount_point(file, mount_flags, NULL, 0);
42650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o}
42752db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o
42852db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o#ifdef DEBUG
42952db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'oint main(int argc, char **argv)
43052db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o{
43152db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o	int	retval, mount_flags;
432a8fd6e36b866f2cf14edaa19d452fa64bd0fba40Theodore Ts'o	char	mntpt[80];
433efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
43452db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o	if (argc < 2) {
43552db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o		fprintf(stderr, "Usage: %s device\n", argv[0]);
43652db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o		exit(1);
43752db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o	}
43852db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o
43904f13d6685b57c29974e4ce2d9074679123bf8a9Theodore Ts'o	add_error_table(&et_ext2_error_table);
440a8fd6e36b866f2cf14edaa19d452fa64bd0fba40Theodore Ts'o	mntpt[0] = 0;
441a8fd6e36b866f2cf14edaa19d452fa64bd0fba40Theodore Ts'o	retval = ext2fs_check_mount_point(argv[1], &mount_flags,
442a8fd6e36b866f2cf14edaa19d452fa64bd0fba40Theodore Ts'o					  mntpt, sizeof(mntpt));
44352db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o	if (retval) {
44452db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o		com_err(argv[0], retval,
44552db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o			"while calling ext2fs_check_if_mounted");
44652db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o		exit(1);
44752db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o	}
44852db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o	printf("Device %s reports flags %02x\n", argv[1], mount_flags);
4492fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o	if (mount_flags & EXT2_MF_BUSY)
4502fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o		printf("\t%s is apparently in use.\n", argv[1]);
45152db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o	if (mount_flags & EXT2_MF_MOUNTED)
452cc86017b593ddfbd4d7a12ed8695e62998f30944Theodore Ts'o		printf("\t%s is mounted.\n", argv[1]);
45307cefe7a7051e32f14b93d9003a6dbb308597bd3Theodore Ts'o	if (mount_flags & EXT2_MF_SWAP)
45407cefe7a7051e32f14b93d9003a6dbb308597bd3Theodore Ts'o		printf("\t%s is a swap device.\n", argv[1]);
45552db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o	if (mount_flags & EXT2_MF_READONLY)
456cc86017b593ddfbd4d7a12ed8695e62998f30944Theodore Ts'o		printf("\t%s is read-only.\n", argv[1]);
45752db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o	if (mount_flags & EXT2_MF_ISROOT)
458cc86017b593ddfbd4d7a12ed8695e62998f30944Theodore Ts'o		printf("\t%s is the root filesystem.\n", argv[1]);
459a8fd6e36b866f2cf14edaa19d452fa64bd0fba40Theodore Ts'o	if (mntpt[0])
460a8fd6e36b866f2cf14edaa19d452fa64bd0fba40Theodore Ts'o		printf("\t%s is mounted on %s.\n", argv[1], mntpt);
46152db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o	exit(0);
46252db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o}
463f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o#endif /* DEBUG */
464