]>
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>
23 # ifdef HAVE_SYS_UCRED_H
24 # include <sys/ucred.h>
26 # ifdef HAVE_SYS_MOUNT_H
27 # include <sys/mount.h>
31 #include "pathnames.h"
33 #include "ismounted.h"
43 * Helper function which checks a file in /etc/mtab format to see if a
44 * filesystem is mounted. Returns an error if the file doesn't exist
47 static int check_mntent_file(const char *mtab_file
, const char *file
,
48 int *mount_flags
, char *mtpt
, int mtlen
)
53 dev_t file_dev
=0, file_rdev
=0;
59 if ((f
= setmntent (mtab_file
, "r")) == NULL
)
62 if (stat(file
, &st_buf
) == 0) {
63 if (S_ISBLK(st_buf
.st_mode
)) {
64 #ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
65 file_rdev
= st_buf
.st_rdev
;
68 file_dev
= st_buf
.st_dev
;
69 file_ino
= st_buf
.st_ino
;
73 while ((mnt
= getmntent (f
)) != NULL
) {
74 if (mnt
->mnt_fsname
[0] != '/')
76 if (strcmp(file
, mnt
->mnt_fsname
) == 0)
78 if (stat(mnt
->mnt_fsname
, &st_buf
) != 0)
81 if (S_ISBLK(st_buf
.st_mode
)) {
83 if (file_rdev
&& file_rdev
== st_buf
.st_rdev
)
86 /* maybe the file is loopdev backing file */
88 && major(st_buf
.st_rdev
) == LOOPDEV_MAJOR
89 && loopdev_is_used(mnt
->mnt_fsname
, file
, 0, 0, 0))
91 #endif /* __linux__ */
94 if (file_dev
&& ((file_dev
== st_buf
.st_dev
) &&
95 (file_ino
== st_buf
.st_ino
)))
101 #ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
103 * Do an extra check to see if this is the root device. We
104 * can't trust /etc/mtab, and /proc/mounts will only list
105 * /dev/root for the root filesystem. Argh. Instead we
106 * check if the given device has the same major/minor number
107 * as the device that the root directory is on.
109 if (file_rdev
&& stat("/", &st_buf
) == 0 &&
110 st_buf
.st_dev
== file_rdev
) {
111 *mount_flags
= MF_MOUNTED
;
113 xstrncpy(mtpt
, "/", mtlen
);
119 #ifndef __GNU__ /* The GNU hurd is deficient; what else is new? */
120 /* Validate the entry in case /etc/mtab is out of date */
122 * We need to be paranoid, because some broken distributions
123 * (read: Slackware) don't initialize /etc/mtab before checking
124 * all of the non-root filesystems on the disk.
126 if (stat(mnt
->mnt_dir
, &st_buf
) < 0) {
128 if (retval
== ENOENT
) {
130 printf("Bogus entry in %s! (%s does not exist)\n",
131 mtab_file
, mnt
->mnt_dir
);
137 if (file_rdev
&& (st_buf
.st_dev
!= file_rdev
)) {
139 printf("Bogus entry in %s! (%s not mounted on %s)\n",
140 mtab_file
, file
, mnt
->mnt_dir
);
145 *mount_flags
= MF_MOUNTED
;
148 /* Check to see if the ro option is set */
149 if (hasmntopt(mnt
, MNTOPT_RO
))
150 *mount_flags
|= MF_READONLY
;
154 xstrncpy(mtpt
, mnt
->mnt_dir
, mtlen
);
156 * Check to see if we're referring to the root filesystem.
157 * If so, do a manual check to see if we can open /etc/mtab
158 * read/write, since if the root is mounted read/only, the
159 * contents of /etc/mtab may not be accurate.
161 if (!strcmp(mnt
->mnt_dir
, "/")) {
163 #define TEST_FILE "/.ismount-test-file"
164 *mount_flags
|= MF_ISROOT
;
165 fd
= open(TEST_FILE
, O_RDWR
|O_CREAT
|O_CLOEXEC
, 0600);
168 *mount_flags
|= MF_READONLY
;
171 (void) unlink(TEST_FILE
);
179 static int check_mntent(const char *file
, int *mount_flags
,
180 char *mtpt
, int mtlen
)
185 retval
= check_mntent_file("/tmp/mtab", file
, mount_flags
,
191 retval
= check_mntent_file("/proc/mounts", file
, mount_flags
,
193 if (retval
== 0 && (*mount_flags
!= 0))
195 if (access("/proc/mounts", R_OK
) == 0) {
199 #endif /* __linux__ */
200 #if defined(MOUNTED) || defined(_PATH_MOUNTED)
202 #define MOUNTED _PATH_MOUNTED
204 retval
= check_mntent_file(MOUNTED
, file
, mount_flags
, mtpt
, mtlen
);
209 #endif /* defined(MOUNTED) || defined(_PATH_MOUNTED) */
213 #if defined(HAVE_GETMNTINFO)
215 static int check_getmntinfo(const char *file
, int *mount_flags
,
216 char *mtpt
, int mtlen
)
223 n
= getmntinfo(&mp
, MNT_NOWAIT
);
227 len
= sizeof(_PATH_DEV
) - 1;
229 if (strncmp(_PATH_DEV
, s1
, len
) == 0)
234 s2
= mp
->f_mntfromname
;
235 if (strncmp(_PATH_DEV
, s2
, len
) == 0) {
239 if (strcmp(s1
, s2
) == 0 || strcmp(s1
, &s2
[1]) == 0) {
240 *mount_flags
= MF_MOUNTED
;
246 xstrncpy(mtpt
, mp
->f_mntonname
, mtlen
);
249 #endif /* HAVE_GETMNTINFO */
250 #endif /* HAVE_MNTENT_H */
253 * Check to see if we're dealing with the swap device.
255 static int is_swap_device(const char *file
)
264 #ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
265 if ((stat(file
, &st_buf
) == 0) &&
266 S_ISBLK(st_buf
.st_mode
))
267 file_dev
= st_buf
.st_rdev
;
270 if (!(f
= fopen("/proc/swaps", "r" UL_CLOEXECSTR
)))
272 /* Skip the first line */
273 if (!fgets(buf
, sizeof(buf
), f
))
275 if (*buf
&& strncmp(buf
, "Filename\t", 9) != 0)
276 /* Linux <=2.6.19 contained a bug in the /proc/swaps
277 * code where the header would not be displayed
279 goto valid_first_line
;
281 while (fgets(buf
, sizeof(buf
), f
)) {
283 if ((cp
= strchr(buf
, ' ')) != NULL
)
285 if ((cp
= strchr(buf
, '\t')) != NULL
)
287 if (strcmp(buf
, file
) == 0) {
292 if (file_dev
&& (stat(buf
, &st_buf
) == 0) &&
293 S_ISBLK(st_buf
.st_mode
) &&
294 file_dev
== st_buf
.st_rdev
) {
308 * check_mount_point() determines if the device is mounted or otherwise
309 * busy, and fills in mount_flags with one or more of the following flags:
310 * MF_MOUNTED, MF_ISROOT, MF_READONLY, MF_SWAP, and MF_BUSY. If mtpt is
311 * non-NULL, the directory where the device is mounted is copied to where mtpt
312 * is pointing, up to mtlen characters.
317 int check_mount_point(const char *device
, int *mount_flags
,
318 char *mtpt
, int mtlen
)
322 if (is_swap_device(device
)) {
323 *mount_flags
= MF_MOUNTED
| MF_SWAP
;
325 xstrncpy(mtpt
, "[SWAP]", mtlen
);
328 retval
= check_mntent(device
, mount_flags
, mtpt
, mtlen
);
330 #ifdef HAVE_GETMNTINFO
331 retval
= check_getmntinfo(device
, mount_flags
, mtpt
, mtlen
);
334 #warning "Can't use getmntent or getmntinfo to check for mounted filesystems!"
337 #endif /* HAVE_GETMNTINFO */
338 #endif /* HAVE_MNTENT_H */
343 #ifdef __linux__ /* This only works on Linux 2.6+ systems */
347 if ((stat(device
, &st_buf
) != 0) ||
348 !S_ISBLK(st_buf
.st_mode
))
350 fd
= open(device
, O_RDONLY
|O_EXCL
|O_CLOEXEC
|O_NONBLOCK
);
353 *mount_flags
|= MF_BUSY
;
362 int is_mounted(const char *file
)
367 retval
= check_mount_point(file
, &mount_flags
, NULL
, 0);
370 return mount_flags
& MF_MOUNTED
;
373 #ifdef TEST_PROGRAM_ISMOUNTED
374 int main(int argc
, char **argv
)
377 char devname
[PATH_MAX
];
380 fprintf(stderr
, "Usage: %s device\n", argv
[0]);
384 if (check_mount_point(argv
[1], &flags
, devname
, sizeof(devname
)) == 0 &&
385 (flags
& MF_MOUNTED
)) {
387 printf("used swap device\n");
389 printf("mounted on %s\n", devname
);
393 printf("not mounted\n");