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
5295e97131a0e96ad2c30c67d1c167dc586619486bMike Frysinger#ifdef HAVE_SYS_SYSMACROS_H
5395e97131a0e96ad2c30c67d1c167dc586619486bMike Frysinger#include <sys/sysmacros.h>
5495e97131a0e96ad2c30c67d1c167dc586619486bMike Frysinger#endif
5550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
56b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o#include "ext2_fs.h"
5750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#include "ext2fs.h"
5850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
59aee40b870cd70a884fd98a56d9c956945584b429Theodore Ts'o#ifdef HAVE_SETMNTENT
60fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio/*
61fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio * Check to see if a regular file is mounted.
62fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio * If /etc/mtab/ is a symlink of /proc/mounts, you will need the following check
63fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio * because the name in /proc/mounts is a loopback device not a regular file.
64fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio */
65fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Miostatic int check_loop_mounted(const char *mnt_fsname, dev_t mnt_rdev,
66fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio				dev_t file_dev, ino_t file_ino)
67fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio{
68fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio#if defined(HAVE_LINUX_LOOP_H) && defined(HAVE_LINUX_MAJOR_H)
69fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio	struct loop_info64 loopinfo;
70fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio	int loop_fd, ret;
71fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio
72fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio	if (major(mnt_rdev) == LOOP_MAJOR) {
73fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio		loop_fd = open(mnt_fsname, O_RDONLY);
74fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio		if (loop_fd < 0)
75fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio			return -1;
76fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio
77fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio		ret = ioctl(loop_fd, LOOP_GET_STATUS64, &loopinfo);
78fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio		close(loop_fd);
79fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio		if (ret < 0)
80fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio			return -1;
81fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio
82fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio		if (file_dev == loopinfo.lo_device &&
83fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio				file_ino == loopinfo.lo_inode)
84fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio			return 1;
85fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio	}
86fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio#endif /* defined(HAVE_LINUX_LOOP_H) && defined(HAVE_LINUX_MAJOR_H) */
87fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio	return 0;
88fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio}
89fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio
9050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o/*
9152db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o * Helper function which checks a file in /etc/mtab format to see if a
9252db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o * filesystem is mounted.  Returns an error if the file doesn't exist
93efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * or can't be opened.
9450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o */
95efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'ostatic errcode_t check_mntent_file(const char *mtab_file, const char *file,
9652db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o				   int *mount_flags, char *mtpt, int mtlen)
9750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o{
982038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o	struct mntent 	*mnt;
99a8fd6e36b866f2cf14edaa19d452fa64bd0fba40Theodore Ts'o	struct stat	st_buf;
1002038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o	errcode_t	retval = 0;
1013a42fe220c301c8b9a8df595938c9a923cf5c494Theodore Ts'o	dev_t		file_dev=0, file_rdev=0;
1023a42fe220c301c8b9a8df595938c9a923cf5c494Theodore Ts'o	ino_t		file_ino=0;
1032038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o	FILE 		*f;
1042038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o	int		fd;
10550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
10650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	*mount_flags = 0;
1072b8772f522be1c82c92e7e0401126808431d06a2Darrick J. Wong
10842b61c50e5af99a10fc56975ecd08ab71e4f00e8Theodore Ts'o	if ((f = setmntent (mtab_file, "r")) == NULL) {
10942b61c50e5af99a10fc56975ecd08ab71e4f00e8Theodore Ts'o		if (errno == ENOENT) {
11042b61c50e5af99a10fc56975ecd08ab71e4f00e8Theodore Ts'o			if (getenv("EXT2FS_NO_MTAB_OK"))
11142b61c50e5af99a10fc56975ecd08ab71e4f00e8Theodore Ts'o				return 0;
11242b61c50e5af99a10fc56975ecd08ab71e4f00e8Theodore Ts'o			else
1138ab395524b95875818505a497428cab73e80c0d5Zheng Liu				return EXT2_ET_NO_MTAB_FILE;
11442b61c50e5af99a10fc56975ecd08ab71e4f00e8Theodore Ts'o		}
11542b61c50e5af99a10fc56975ecd08ab71e4f00e8Theodore Ts'o		return errno;
11642b61c50e5af99a10fc56975ecd08ab71e4f00e8Theodore Ts'o	}
1173a42fe220c301c8b9a8df595938c9a923cf5c494Theodore Ts'o	if (stat(file, &st_buf) == 0) {
1183a42fe220c301c8b9a8df595938c9a923cf5c494Theodore Ts'o		if (S_ISBLK(st_buf.st_mode)) {
119a8fd6e36b866f2cf14edaa19d452fa64bd0fba40Theodore Ts'o#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
1203a42fe220c301c8b9a8df595938c9a923cf5c494Theodore Ts'o			file_rdev = st_buf.st_rdev;
121f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o#endif	/* __GNU__ */
1223a42fe220c301c8b9a8df595938c9a923cf5c494Theodore Ts'o		} else {
1233a42fe220c301c8b9a8df595938c9a923cf5c494Theodore Ts'o			file_dev = st_buf.st_dev;
1243a42fe220c301c8b9a8df595938c9a923cf5c494Theodore Ts'o			file_ino = st_buf.st_ino;
1253a42fe220c301c8b9a8df595938c9a923cf5c494Theodore Ts'o		}
1263a42fe220c301c8b9a8df595938c9a923cf5c494Theodore Ts'o	}
127a8fd6e36b866f2cf14edaa19d452fa64bd0fba40Theodore Ts'o	while ((mnt = getmntent (f)) != NULL) {
128f9110f4480eade2d849c4cc08efa49bf0f7f5148Theodore Ts'o		if (mnt->mnt_fsname[0] != '/')
129f9110f4480eade2d849c4cc08efa49bf0f7f5148Theodore Ts'o			continue;
13050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o		if (strcmp(file, mnt->mnt_fsname) == 0)
13150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o			break;
1323a42fe220c301c8b9a8df595938c9a923cf5c494Theodore Ts'o		if (stat(mnt->mnt_fsname, &st_buf) == 0) {
1333a42fe220c301c8b9a8df595938c9a923cf5c494Theodore Ts'o			if (S_ISBLK(st_buf.st_mode)) {
134a8fd6e36b866f2cf14edaa19d452fa64bd0fba40Theodore Ts'o#ifndef __GNU__
1353a42fe220c301c8b9a8df595938c9a923cf5c494Theodore Ts'o				if (file_rdev && (file_rdev == st_buf.st_rdev))
1363a42fe220c301c8b9a8df595938c9a923cf5c494Theodore Ts'o					break;
137fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio				if (check_loop_mounted(mnt->mnt_fsname,
138fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio						st_buf.st_rdev, file_dev,
139fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio						file_ino) == 1)
140fbabd5c44c2303501ad79b0e0386fe6436e0e147Kazuya Mio					break;
141f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o#endif	/* __GNU__ */
1423a42fe220c301c8b9a8df595938c9a923cf5c494Theodore Ts'o			} else {
1433a42fe220c301c8b9a8df595938c9a923cf5c494Theodore Ts'o				if (file_dev && ((file_dev == st_buf.st_dev) &&
1443a42fe220c301c8b9a8df595938c9a923cf5c494Theodore Ts'o						 (file_ino == st_buf.st_ino)))
1453a42fe220c301c8b9a8df595938c9a923cf5c494Theodore Ts'o					break;
1463a42fe220c301c8b9a8df595938c9a923cf5c494Theodore Ts'o			}
1473a42fe220c301c8b9a8df595938c9a923cf5c494Theodore Ts'o		}
148a8fd6e36b866f2cf14edaa19d452fa64bd0fba40Theodore Ts'o	}
149cc86017b593ddfbd4d7a12ed8695e62998f30944Theodore Ts'o
150cc86017b593ddfbd4d7a12ed8695e62998f30944Theodore Ts'o	if (mnt == 0) {
15166a461469ccafd7aad2a824b0ab66fd9096d6e94Theodore Ts'o#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
152cc86017b593ddfbd4d7a12ed8695e62998f30944Theodore Ts'o		/*
153cc86017b593ddfbd4d7a12ed8695e62998f30944Theodore Ts'o		 * Do an extra check to see if this is the root device.  We
1542038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o		 * can't trust /etc/mtab, and /proc/mounts will only list
155cc86017b593ddfbd4d7a12ed8695e62998f30944Theodore Ts'o		 * /dev/root for the root filesystem.  Argh.  Instead we
156cc86017b593ddfbd4d7a12ed8695e62998f30944Theodore Ts'o		 * check if the given device has the same major/minor number
157cc86017b593ddfbd4d7a12ed8695e62998f30944Theodore Ts'o		 * as the device that the root directory is on.
158cc86017b593ddfbd4d7a12ed8695e62998f30944Theodore Ts'o		 */
1593a42fe220c301c8b9a8df595938c9a923cf5c494Theodore Ts'o		if (file_rdev && stat("/", &st_buf) == 0) {
1603a42fe220c301c8b9a8df595938c9a923cf5c494Theodore Ts'o			if (st_buf.st_dev == file_rdev) {
161cc86017b593ddfbd4d7a12ed8695e62998f30944Theodore Ts'o				*mount_flags = EXT2_MF_MOUNTED;
162cc86017b593ddfbd4d7a12ed8695e62998f30944Theodore Ts'o				if (mtpt)
163d5f858dd7f02532ad90e4121537c358e86d0eecfTheodore Ts'o					strncpy(mtpt, "/", mtlen);
164cc86017b593ddfbd4d7a12ed8695e62998f30944Theodore Ts'o				goto is_root;
165cc86017b593ddfbd4d7a12ed8695e62998f30944Theodore Ts'o			}
166cc86017b593ddfbd4d7a12ed8695e62998f30944Theodore Ts'o		}
167f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o#endif	/* __GNU__ */
16848e6e81362f264aee4f3945c14928efaf71a06c9Theodore Ts'o		goto errout;
1692038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o	}
1702038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o#ifndef __GNU__ /* The GNU hurd is deficient; what else is new? */
1712038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o	/* Validate the entry in case /etc/mtab is out of date */
172efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	/*
1732038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o	 * We need to be paranoid, because some broken distributions
1742038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o	 * (read: Slackware) don't initialize /etc/mtab before checking
1752038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o	 * all of the non-root filesystems on the disk.
1762038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o	 */
177a8fd6e36b866f2cf14edaa19d452fa64bd0fba40Theodore Ts'o	if (stat(mnt->mnt_dir, &st_buf) < 0) {
1782038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o		retval = errno;
1792038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o		if (retval == ENOENT) {
1802038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o#ifdef DEBUG
1812038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o			printf("Bogus entry in %s!  (%s does not exist)\n",
1822038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o			       mtab_file, mnt->mnt_dir);
183f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o#endif /* DEBUG */
1842038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o			retval = 0;
1852038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o		}
18648e6e81362f264aee4f3945c14928efaf71a06c9Theodore Ts'o		goto errout;
1872038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o	}
1883a42fe220c301c8b9a8df595938c9a923cf5c494Theodore Ts'o	if (file_rdev && (st_buf.st_dev != file_rdev)) {
1892038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o#ifdef DEBUG
190a8fd6e36b866f2cf14edaa19d452fa64bd0fba40Theodore Ts'o		printf("Bogus entry in %s!  (%s not mounted on %s)\n",
191a8fd6e36b866f2cf14edaa19d452fa64bd0fba40Theodore Ts'o		       mtab_file, file, mnt->mnt_dir);
192f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o#endif /* DEBUG */
19348e6e81362f264aee4f3945c14928efaf71a06c9Theodore Ts'o		goto errout;
194cc86017b593ddfbd4d7a12ed8695e62998f30944Theodore Ts'o	}
195f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o#endif /* __GNU__ */
19650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	*mount_flags = EXT2_MF_MOUNTED;
197efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
198fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o#ifdef MNTOPT_RO
19952db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o	/* Check to see if the ro option is set */
20052db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o	if (hasmntopt(mnt, MNTOPT_RO))
20152db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o		*mount_flags |= EXT2_MF_READONLY;
202fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o#endif
20352db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o
204cc86017b593ddfbd4d7a12ed8695e62998f30944Theodore Ts'o	if (mtpt)
205cc86017b593ddfbd4d7a12ed8695e62998f30944Theodore Ts'o		strncpy(mtpt, mnt->mnt_dir, mtlen);
20652db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o	/*
20752db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o	 * Check to see if we're referring to the root filesystem.
20852db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o	 * If so, do a manual check to see if we can open /etc/mtab
209cc86017b593ddfbd4d7a12ed8695e62998f30944Theodore Ts'o	 * read/write, since if the root is mounted read/only, the
210cc86017b593ddfbd4d7a12ed8695e62998f30944Theodore Ts'o	 * contents of /etc/mtab may not be accurate.
21152db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o	 */
21250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	if (!strcmp(mnt->mnt_dir, "/")) {
213cc86017b593ddfbd4d7a12ed8695e62998f30944Theodore Ts'ois_root:
214efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o#define TEST_FILE "/.ismount-test-file"
21550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o		*mount_flags |= EXT2_MF_ISROOT;
2168cdd6a6f34a66806fb200f2a55c8fa4142d79511Andreas Dilger		fd = open(TEST_FILE, O_RDWR|O_CREAT, 0600);
21750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o		if (fd < 0) {
21850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o			if (errno == EROFS)
21950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o				*mount_flags |= EXT2_MF_READONLY;
22050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o		} else
22150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o			close(fd);
222997b820e94468aeb3fb1a6fd38bc52e34af6f9e6Theodore Ts'o		(void) unlink(TEST_FILE);
22350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	}
2242038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o	retval = 0;
22548e6e81362f264aee4f3945c14928efaf71a06c9Theodore Ts'oerrout:
226cc86017b593ddfbd4d7a12ed8695e62998f30944Theodore Ts'o	endmntent (f);
2272038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o	return retval;
22850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o}
22952db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o
23052db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'ostatic errcode_t check_mntent(const char *file, int *mount_flags,
23152db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o			      char *mtpt, int mtlen)
23252db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o{
23352db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o	errcode_t	retval;
23452db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o
2352038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o#ifdef DEBUG
2362038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o	retval = check_mntent_file("/tmp/mtab", file, mount_flags,
2372038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o				   mtpt, mtlen);
2382038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o	if (retval == 0)
2392038b636b2a72d997b7a6b4123e50d7f8dcb7108Theodore Ts'o		return 0;
240f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o#endif /* DEBUG */
24152db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o#ifdef __linux__
24252db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o	retval = check_mntent_file("/proc/mounts", file, mount_flags,
24352db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o				   mtpt, mtlen);
2443a42fe220c301c8b9a8df595938c9a923cf5c494Theodore Ts'o	if (retval == 0 && (*mount_flags != 0))
24552db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o		return 0;
246f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o#endif /* __linux__ */
2475818d6789aaa795aeee1fdb0f7d812a1cabe3d1dTheodore Ts'o#if defined(MOUNTED) || defined(_PATH_MOUNTED)
2485818d6789aaa795aeee1fdb0f7d812a1cabe3d1dTheodore Ts'o#ifndef MOUNTED
2495818d6789aaa795aeee1fdb0f7d812a1cabe3d1dTheodore Ts'o#define MOUNTED _PATH_MOUNTED
2505818d6789aaa795aeee1fdb0f7d812a1cabe3d1dTheodore Ts'o#endif /* MOUNTED */
25152db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o	retval = check_mntent_file(MOUNTED, file, mount_flags, mtpt, mtlen);
25252db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o	return retval;
253efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o#else
2545818d6789aaa795aeee1fdb0f7d812a1cabe3d1dTheodore Ts'o	*mount_flags = 0;
2555818d6789aaa795aeee1fdb0f7d812a1cabe3d1dTheodore Ts'o	return 0;
2565818d6789aaa795aeee1fdb0f7d812a1cabe3d1dTheodore Ts'o#endif /* defined(MOUNTED) || defined(_PATH_MOUNTED) */
25752db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o}
25852db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o
25948e6e81362f264aee4f3945c14928efaf71a06c9Theodore Ts'o#else
26048e6e81362f264aee4f3945c14928efaf71a06c9Theodore Ts'o#if defined(HAVE_GETMNTINFO)
26150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
26243ec8734f2ecd0a345e831f45fd3dfb077426811Theodore Ts'ostatic errcode_t check_getmntinfo(const char *file, int *mount_flags,
26343ec8734f2ecd0a345e831f45fd3dfb077426811Theodore Ts'o				  char *mtpt, int mtlen)
26450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o{
26550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	struct statfs *mp;
26650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o        int    len, n;
26750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o        const  char   *s1;
26850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	char	*s2;
26950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
27050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o        n = getmntinfo(&mp, MNT_NOWAIT);
27150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o        if (n == 0)
27250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o		return errno;
27350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
27450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o        len = sizeof(_PATH_DEV) - 1;
27550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o        s1 = file;
27650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o        if (strncmp(_PATH_DEV, s1, len) == 0)
27750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o                s1 += len;
278efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
27950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	*mount_flags = 0;
28050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o        while (--n >= 0) {
28150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o                s2 = mp->f_mntfromname;
28250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o                if (strncmp(_PATH_DEV, s2, len) == 0) {
28350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o                        s2 += len - 1;
28450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o                        *s2 = 'r';
28550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o                }
28650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o                if (strcmp(s1, s2) == 0 || strcmp(s1, &s2[1]) == 0) {
28750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o			*mount_flags = EXT2_MF_MOUNTED;
28850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o			break;
28950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o		}
29050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o                ++mp;
29150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	}
29243ec8734f2ecd0a345e831f45fd3dfb077426811Theodore Ts'o	if (mtpt)
29343ec8734f2ecd0a345e831f45fd3dfb077426811Theodore Ts'o		strncpy(mtpt, mp->f_mntonname, mtlen);
29450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	return 0;
29550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o}
29650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#endif /* HAVE_GETMNTINFO */
297b24efa218794b567c27ad99db319b4bd5d696958Theodore Ts'o#endif /* HAVE_SETMNTENT */
29850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
29950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o/*
300f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o * Check to see if we're dealing with the swap device.
301f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o */
302f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'ostatic int is_swap_device(const char *file)
303f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o{
304f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o	FILE		*f;
305f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o	char		buf[1024], *cp;
306f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o	dev_t		file_dev;
307f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o	struct stat	st_buf;
308f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o	int		ret = 0;
309f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o
310f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o	file_dev = 0;
311f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
312f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o	if ((stat(file, &st_buf) == 0) &&
313f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o	    S_ISBLK(st_buf.st_mode))
314f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o		file_dev = st_buf.st_rdev;
315f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o#endif	/* __GNU__ */
316f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o
317f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o	if (!(f = fopen("/proc/swaps", "r")))
318f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o		return 0;
319f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o	/* Skip the first line */
3205f91561ae7e08d79b6a5feca167259fd7634713fKarel Zak	if (!fgets(buf, sizeof(buf), f))
3215f91561ae7e08d79b6a5feca167259fd7634713fKarel Zak		goto leave;
3225f91561ae7e08d79b6a5feca167259fd7634713fKarel Zak	if (*buf && strncmp(buf, "Filename\t", 9))
3235f91561ae7e08d79b6a5feca167259fd7634713fKarel Zak		/* Linux <=2.6.19 contained a bug in the /proc/swaps
3245f91561ae7e08d79b6a5feca167259fd7634713fKarel Zak		 * code where the header would not be displayed
3255f91561ae7e08d79b6a5feca167259fd7634713fKarel Zak		 */
3265f91561ae7e08d79b6a5feca167259fd7634713fKarel Zak		goto valid_first_line;
3275f91561ae7e08d79b6a5feca167259fd7634713fKarel Zak
328d9039ae0ff3f7929ede576058b3ad3e9c62a47c4Dmitry V. Levin	while (fgets(buf, sizeof(buf), f)) {
3295f91561ae7e08d79b6a5feca167259fd7634713fKarel Zakvalid_first_line:
330f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o		if ((cp = strchr(buf, ' ')) != NULL)
331f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o			*cp = 0;
332f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o		if ((cp = strchr(buf, '\t')) != NULL)
333f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o			*cp = 0;
334f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o		if (strcmp(buf, file) == 0) {
335f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o			ret++;
336f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o			break;
337f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o		}
338f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o#ifndef __GNU__
339f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o		if (file_dev && (stat(buf, &st_buf) == 0) &&
340f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o		    S_ISBLK(st_buf.st_mode) &&
341f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o		    file_dev == st_buf.st_rdev) {
342f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o			ret++;
343f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o			break;
344f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o		}
345f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o#endif 	/* __GNU__ */
346f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o	}
3475f91561ae7e08d79b6a5feca167259fd7634713fKarel Zak
3485f91561ae7e08d79b6a5feca167259fd7634713fKarel Zakleave:
349f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o	fclose(f);
350f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o	return ret;
351f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o}
352f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o
353f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o
354f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o/*
3552fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o * ext2fs_check_mount_point() fills determines if the device is
3562fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o * mounted or otherwise busy, and fills in mount_flags with one or
3572fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o * more of the following flags: EXT2_MF_MOUNTED, EXT2_MF_ISROOT,
3582fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o * EXT2_MF_READONLY, EXT2_MF_SWAP, and EXT2_MF_BUSY.  If mtpt is
3592fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o * non-NULL, the directory where the device is mounted is copied to
3602fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o * where mtpt is pointing, up to mtlen characters.
36143ec8734f2ecd0a345e831f45fd3dfb077426811Theodore Ts'o */
36243ec8734f2ecd0a345e831f45fd3dfb077426811Theodore Ts'o#ifdef __TURBOC__
36331dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o #pragma argsused
36443ec8734f2ecd0a345e831f45fd3dfb077426811Theodore Ts'o#endif
36543ec8734f2ecd0a345e831f45fd3dfb077426811Theodore Ts'oerrcode_t ext2fs_check_mount_point(const char *device, int *mount_flags,
36643ec8734f2ecd0a345e831f45fd3dfb077426811Theodore Ts'o				  char *mtpt, int mtlen)
36743ec8734f2ecd0a345e831f45fd3dfb077426811Theodore Ts'o{
3682fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o	errcode_t	retval = 0;
3692fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o
37043b7b054cd3165645c9b22977247674f9465e0e1Theodore Ts'o	if (getenv("EXT2FS_PRETEND_RO_MOUNT")) {
37143b7b054cd3165645c9b22977247674f9465e0e1Theodore Ts'o		*mount_flags = EXT2_MF_MOUNTED | EXT2_MF_READONLY;
37243b7b054cd3165645c9b22977247674f9465e0e1Theodore Ts'o		if (getenv("EXT2FS_PRETEND_ROOTFS"))
37343b7b054cd3165645c9b22977247674f9465e0e1Theodore Ts'o			*mount_flags = EXT2_MF_ISROOT;
37443b7b054cd3165645c9b22977247674f9465e0e1Theodore Ts'o		return 0;
37543b7b054cd3165645c9b22977247674f9465e0e1Theodore Ts'o	}
37643b7b054cd3165645c9b22977247674f9465e0e1Theodore Ts'o	if (getenv("EXT2FS_PRETEND_RW_MOUNT")) {
37743b7b054cd3165645c9b22977247674f9465e0e1Theodore Ts'o		*mount_flags = EXT2_MF_MOUNTED;
37843b7b054cd3165645c9b22977247674f9465e0e1Theodore Ts'o		if (getenv("EXT2FS_PRETEND_ROOTFS"))
37943b7b054cd3165645c9b22977247674f9465e0e1Theodore Ts'o			*mount_flags = EXT2_MF_ISROOT;
38043b7b054cd3165645c9b22977247674f9465e0e1Theodore Ts'o		return 0;
38143b7b054cd3165645c9b22977247674f9465e0e1Theodore Ts'o	}
38243b7b054cd3165645c9b22977247674f9465e0e1Theodore Ts'o
38307cefe7a7051e32f14b93d9003a6dbb308597bd3Theodore Ts'o	if (is_swap_device(device)) {
38407cefe7a7051e32f14b93d9003a6dbb308597bd3Theodore Ts'o		*mount_flags = EXT2_MF_MOUNTED | EXT2_MF_SWAP;
38507cefe7a7051e32f14b93d9003a6dbb308597bd3Theodore Ts'o		strncpy(mtpt, "<swap>", mtlen);
3862fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o	} else {
387b24efa218794b567c27ad99db319b4bd5d696958Theodore Ts'o#ifdef HAVE_SETMNTENT
3882fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o		retval = check_mntent(device, mount_flags, mtpt, mtlen);
389efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o#else
39043ec8734f2ecd0a345e831f45fd3dfb077426811Theodore Ts'o#ifdef HAVE_GETMNTINFO
3912fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o		retval = check_getmntinfo(device, mount_flags, mtpt, mtlen);
39243ec8734f2ecd0a345e831f45fd3dfb077426811Theodore Ts'o#else
393ed78c021c3b111d8ab9a51aef5d5156e3004083fTheodore Ts'o#ifdef __GNUC__
39448e6e81362f264aee4f3945c14928efaf71a06c9Theodore Ts'o #warning "Can't use getmntent or getmntinfo to check for mounted filesystems!"
395ed78c021c3b111d8ab9a51aef5d5156e3004083fTheodore Ts'o#endif
3962fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o		*mount_flags = 0;
39743ec8734f2ecd0a345e831f45fd3dfb077426811Theodore Ts'o#endif /* HAVE_GETMNTINFO */
398b24efa218794b567c27ad99db319b4bd5d696958Theodore Ts'o#endif /* HAVE_SETMNTENT */
3992fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o	}
4002fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o	if (retval)
4012fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o		return retval;
4022fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o
4032fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o#ifdef __linux__ /* This only works on Linux 2.6+ systems */
4041d6fd6d0c3766a8165e69284c75812574a29c804Andreas Dilger	{
4051d6fd6d0c3766a8165e69284c75812574a29c804Andreas Dilger		struct stat st_buf;
4061d6fd6d0c3766a8165e69284c75812574a29c804Andreas Dilger
4071d6fd6d0c3766a8165e69284c75812574a29c804Andreas Dilger		if (stat(device, &st_buf) == 0 && S_ISBLK(st_buf.st_mode)) {
4081d6fd6d0c3766a8165e69284c75812574a29c804Andreas Dilger			int fd = open(device, O_RDONLY | O_EXCL);
4091d6fd6d0c3766a8165e69284c75812574a29c804Andreas Dilger
4101d6fd6d0c3766a8165e69284c75812574a29c804Andreas Dilger			if (fd >= 0)
4111d6fd6d0c3766a8165e69284c75812574a29c804Andreas Dilger				close(fd);
4121d6fd6d0c3766a8165e69284c75812574a29c804Andreas Dilger			else if (errno == EBUSY)
4131d6fd6d0c3766a8165e69284c75812574a29c804Andreas Dilger				*mount_flags |= EXT2_MF_BUSY;
4141d6fd6d0c3766a8165e69284c75812574a29c804Andreas Dilger		}
4151d6fd6d0c3766a8165e69284c75812574a29c804Andreas Dilger	}
416406ba674fe33469c600a4dd7ed5853cac34ca4e7Matthias Andree#endif
4172fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o
4182fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o	return 0;
41943ec8734f2ecd0a345e831f45fd3dfb077426811Theodore Ts'o}
42043ec8734f2ecd0a345e831f45fd3dfb077426811Theodore Ts'o
42143ec8734f2ecd0a345e831f45fd3dfb077426811Theodore Ts'o/*
4226bd134809ca75741941f41c11fa2b24fbc5ecfacTheodore Ts'o * ext2fs_check_if_mounted() sets the mount_flags EXT2_MF_MOUNTED,
423d5f858dd7f02532ad90e4121537c358e86d0eecfTheodore Ts'o * EXT2_MF_READONLY, and EXT2_MF_ROOT
424efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o *
42550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o */
42650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'oerrcode_t ext2fs_check_if_mounted(const char *file, int *mount_flags)
42750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o{
428d5f858dd7f02532ad90e4121537c358e86d0eecfTheodore Ts'o	return ext2fs_check_mount_point(file, mount_flags, NULL, 0);
42950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o}
43052db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o
43152db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o#ifdef DEBUG
43252db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'oint main(int argc, char **argv)
43352db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o{
43452db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o	int	retval, mount_flags;
435a8fd6e36b866f2cf14edaa19d452fa64bd0fba40Theodore Ts'o	char	mntpt[80];
436efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
43752db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o	if (argc < 2) {
43852db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o		fprintf(stderr, "Usage: %s device\n", argv[0]);
43952db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o		exit(1);
44052db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o	}
44152db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o
44204f13d6685b57c29974e4ce2d9074679123bf8a9Theodore Ts'o	add_error_table(&et_ext2_error_table);
443a8fd6e36b866f2cf14edaa19d452fa64bd0fba40Theodore Ts'o	mntpt[0] = 0;
444a8fd6e36b866f2cf14edaa19d452fa64bd0fba40Theodore Ts'o	retval = ext2fs_check_mount_point(argv[1], &mount_flags,
445a8fd6e36b866f2cf14edaa19d452fa64bd0fba40Theodore Ts'o					  mntpt, sizeof(mntpt));
44652db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o	if (retval) {
44752db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o		com_err(argv[0], retval,
44852db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o			"while calling ext2fs_check_if_mounted");
44952db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o		exit(1);
45052db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o	}
45152db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o	printf("Device %s reports flags %02x\n", argv[1], mount_flags);
4522fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o	if (mount_flags & EXT2_MF_BUSY)
4532fa8f37ffff4687228d9f204062f2d27b0e5b919Theodore Ts'o		printf("\t%s is apparently in use.\n", argv[1]);
45452db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o	if (mount_flags & EXT2_MF_MOUNTED)
455cc86017b593ddfbd4d7a12ed8695e62998f30944Theodore Ts'o		printf("\t%s is mounted.\n", argv[1]);
45607cefe7a7051e32f14b93d9003a6dbb308597bd3Theodore Ts'o	if (mount_flags & EXT2_MF_SWAP)
45707cefe7a7051e32f14b93d9003a6dbb308597bd3Theodore Ts'o		printf("\t%s is a swap device.\n", argv[1]);
45852db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o	if (mount_flags & EXT2_MF_READONLY)
459cc86017b593ddfbd4d7a12ed8695e62998f30944Theodore Ts'o		printf("\t%s is read-only.\n", argv[1]);
46052db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o	if (mount_flags & EXT2_MF_ISROOT)
461cc86017b593ddfbd4d7a12ed8695e62998f30944Theodore Ts'o		printf("\t%s is the root filesystem.\n", argv[1]);
462a8fd6e36b866f2cf14edaa19d452fa64bd0fba40Theodore Ts'o	if (mntpt[0])
463a8fd6e36b866f2cf14edaa19d452fa64bd0fba40Theodore Ts'o		printf("\t%s is mounted on %s.\n", argv[1], mntpt);
46452db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o	exit(0);
46552db0b4178553318aac08bb9cdc1d42743e6beebTheodore Ts'o}
466f0efd2976b69d31b752b5e5ce4f5e8341a130c45Theodore Ts'o#endif /* DEBUG */
467