]>
git.ipfire.org Git - thirdparty/util-linux.git/blob - lib/ismounted.c
2 * ismounted.c --- Check to see if the filesystem was mounted
4 * Copyright (C) 1995,1996,1997,1998,1999,2000,2008 Theodore Ts'o.
6 * This file may be redistributed under the terms of the GNU Public
20 #include <sys/param.h>
22 #include <sys/ucred.h>
23 #include <sys/mount.h>
26 #include "pathnames.h"
27 #include "ismounted.h"
37 * Helper function which checks a file in /etc/mtab format to see if a
38 * filesystem is mounted. Returns an error if the file doesn't exist
41 static int check_mntent_file(const char *mtab_file
, const char *file
,
42 int *mount_flags
, char *mtpt
, int mtlen
)
47 dev_t file_dev
=0, file_rdev
=0;
53 if ((f
= setmntent (mtab_file
, "r")) == NULL
)
56 if (stat(file
, &st_buf
) == 0) {
57 if (S_ISBLK(st_buf
.st_mode
)) {
58 #ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
59 file_rdev
= st_buf
.st_rdev
;
62 file_dev
= st_buf
.st_dev
;
63 file_ino
= st_buf
.st_ino
;
67 while ((mnt
= getmntent (f
)) != NULL
) {
68 if (mnt
->mnt_fsname
[0] != '/')
70 if (strcmp(file
, mnt
->mnt_fsname
) == 0)
72 if (stat(mnt
->mnt_fsname
, &st_buf
) != 0)
75 if (S_ISBLK(st_buf
.st_mode
)) {
77 if (file_rdev
&& file_rdev
== st_buf
.st_rdev
)
80 /* maybe the file is loopdev backing file */
82 && major(st_buf
.st_rdev
) == LOOPDEV_MAJOR
83 && loopdev_is_used(mnt
->mnt_fsname
, file
, 0, 0))
85 #endif /* __linux__ */
88 if (file_dev
&& ((file_dev
== st_buf
.st_dev
) &&
89 (file_ino
== st_buf
.st_ino
)))
95 #ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
97 * Do an extra check to see if this is the root device. We
98 * can't trust /etc/mtab, and /proc/mounts will only list
99 * /dev/root for the root filesystem. Argh. Instead we
100 * check if the given device has the same major/minor number
101 * as the device that the root directory is on.
103 if (file_rdev
&& stat("/", &st_buf
) == 0 &&
104 st_buf
.st_dev
== file_rdev
) {
105 *mount_flags
= MF_MOUNTED
;
107 strncpy(mtpt
, "/", mtlen
);
113 #ifndef __GNU__ /* The GNU hurd is deficient; what else is new? */
114 /* Validate the entry in case /etc/mtab is out of date */
116 * We need to be paranoid, because some broken distributions
117 * (read: Slackware) don't initialize /etc/mtab before checking
118 * all of the non-root filesystems on the disk.
120 if (stat(mnt
->mnt_dir
, &st_buf
) < 0) {
122 if (retval
== ENOENT
) {
124 printf("Bogus entry in %s! (%s does not exist)\n",
125 mtab_file
, mnt
->mnt_dir
);
131 if (file_rdev
&& (st_buf
.st_dev
!= file_rdev
)) {
133 printf("Bogus entry in %s! (%s not mounted on %s)\n",
134 mtab_file
, file
, mnt
->mnt_dir
);
139 *mount_flags
= MF_MOUNTED
;
142 /* Check to see if the ro option is set */
143 if (hasmntopt(mnt
, MNTOPT_RO
))
144 *mount_flags
|= MF_READONLY
;
148 strncpy(mtpt
, mnt
->mnt_dir
, mtlen
);
150 * Check to see if we're referring to the root filesystem.
151 * If so, do a manual check to see if we can open /etc/mtab
152 * read/write, since if the root is mounted read/only, the
153 * contents of /etc/mtab may not be accurate.
155 if (!strcmp(mnt
->mnt_dir
, "/")) {
157 #define TEST_FILE "/.ismount-test-file"
158 *mount_flags
|= MF_ISROOT
;
159 fd
= open(TEST_FILE
, O_RDWR
|O_CREAT
, 0600);
162 *mount_flags
|= MF_READONLY
;
165 (void) unlink(TEST_FILE
);
173 static int check_mntent(const char *file
, int *mount_flags
,
174 char *mtpt
, int mtlen
)
179 retval
= check_mntent_file("/tmp/mtab", file
, mount_flags
,
185 retval
= check_mntent_file("/proc/mounts", file
, mount_flags
,
187 if (retval
== 0 && (*mount_flags
!= 0))
189 if (access("/proc/mounts", R_OK
) == 0) {
193 #endif /* __linux__ */
194 #if defined(MOUNTED) || defined(_PATH_MOUNTED)
196 #define MOUNTED _PATH_MOUNTED
198 retval
= check_mntent_file(MOUNTED
, file
, mount_flags
, mtpt
, mtlen
);
203 #endif /* defined(MOUNTED) || defined(_PATH_MOUNTED) */
207 #if defined(HAVE_GETMNTINFO)
209 static int check_getmntinfo(const char *file
, int *mount_flags
,
210 char *mtpt
, int mtlen
)
217 n
= getmntinfo(&mp
, MNT_NOWAIT
);
221 len
= sizeof(_PATH_DEV
) - 1;
223 if (strncmp(_PATH_DEV
, s1
, len
) == 0)
228 s2
= mp
->f_mntfromname
;
229 if (strncmp(_PATH_DEV
, s2
, len
) == 0) {
233 if (strcmp(s1
, s2
) == 0 || strcmp(s1
, &s2
[1]) == 0) {
234 *mount_flags
= MF_MOUNTED
;
240 strncpy(mtpt
, mp
->f_mntonname
, mtlen
);
243 #endif /* HAVE_GETMNTINFO */
244 #endif /* HAVE_MNTENT_H */
247 * Check to see if we're dealing with the swap device.
249 static int is_swap_device(const char *file
)
258 #ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
259 if ((stat(file
, &st_buf
) == 0) &&
260 S_ISBLK(st_buf
.st_mode
))
261 file_dev
= st_buf
.st_rdev
;
264 if (!(f
= fopen("/proc/swaps", "r")))
266 /* Skip the first line */
267 if (!fgets(buf
, sizeof(buf
), f
))
269 if (*buf
&& strncmp(buf
, "Filename\t", 9))
270 /* Linux <=2.6.19 contained a bug in the /proc/swaps
271 * code where the header would not be displayed
273 goto valid_first_line
;
275 while (fgets(buf
, sizeof(buf
), f
)) {
277 if ((cp
= strchr(buf
, ' ')) != NULL
)
279 if ((cp
= strchr(buf
, '\t')) != NULL
)
281 if (strcmp(buf
, file
) == 0) {
286 if (file_dev
&& (stat(buf
, &st_buf
) == 0) &&
287 S_ISBLK(st_buf
.st_mode
) &&
288 file_dev
== st_buf
.st_rdev
) {
302 * check_mount_point() fills determines if the device is mounted or otherwise
303 * busy, and fills in mount_flags with one or more of the following flags:
304 * MF_MOUNTED, MF_ISROOT, MF_READONLY, MF_SWAP, and MF_BUSY. If mtpt is
305 * non-NULL, the directory where the device is mounted is copied to where mtpt
306 * is pointing, up to mtlen characters.
311 int check_mount_point(const char *device
, int *mount_flags
,
312 char *mtpt
, int mtlen
)
318 if (is_swap_device(device
)) {
319 *mount_flags
= MF_MOUNTED
| MF_SWAP
;
320 strncpy(mtpt
, "<swap>", mtlen
);
323 retval
= check_mntent(device
, mount_flags
, mtpt
, mtlen
);
325 #ifdef HAVE_GETMNTINFO
326 retval
= check_getmntinfo(device
, mount_flags
, mtpt
, mtlen
);
329 #warning "Can't use getmntent or getmntinfo to check for mounted filesystems!"
332 #endif /* HAVE_GETMNTINFO */
333 #endif /* HAVE_MNTENT_H */
338 #ifdef __linux__ /* This only works on Linux 2.6+ systems */
339 if ((stat(device
, &st_buf
) != 0) ||
340 !S_ISBLK(st_buf
.st_mode
))
342 fd
= open(device
, O_RDONLY
| O_EXCL
);
345 *mount_flags
|= MF_BUSY
;
353 int is_mounted(const char *file
)
358 retval
= check_mount_point(file
, &mount_flags
, NULL
, 0);
361 return mount_flags
& MF_MOUNTED
;
365 int main(int argc
, char **argv
)
368 char devname
[PATH_MAX
];
371 fprintf(stderr
, "Usage: %s device\n", argv
[0]);
375 if (check_mount_point(argv
[1], &flags
, devname
, sizeof(devname
)) == 0 &&
376 (flags
& MF_MOUNTED
)) {
378 printf("used swap device\n");
380 printf("mounted on %s\n", devname
);
384 printf("not mounted\n");