]>
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"
32 #include "ismounted.h"
42 * Helper function which checks a file in /etc/mtab format to see if a
43 * filesystem is mounted. Returns an error if the file doesn't exist
46 static int check_mntent_file(const char *mtab_file
, const char *file
,
47 int *mount_flags
, char *mtpt
, int mtlen
)
52 dev_t file_dev
=0, file_rdev
=0;
58 if ((f
= setmntent (mtab_file
, "r")) == NULL
)
61 if (stat(file
, &st_buf
) == 0) {
62 if (S_ISBLK(st_buf
.st_mode
)) {
63 #ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
64 file_rdev
= st_buf
.st_rdev
;
67 file_dev
= st_buf
.st_dev
;
68 file_ino
= st_buf
.st_ino
;
72 while ((mnt
= getmntent (f
)) != NULL
) {
73 if (mnt
->mnt_fsname
[0] != '/')
75 if (strcmp(file
, mnt
->mnt_fsname
) == 0)
77 if (stat(mnt
->mnt_fsname
, &st_buf
) != 0)
80 if (S_ISBLK(st_buf
.st_mode
)) {
82 if (file_rdev
&& file_rdev
== st_buf
.st_rdev
)
85 /* maybe the file is loopdev backing file */
87 && major(st_buf
.st_rdev
) == LOOPDEV_MAJOR
88 && loopdev_is_used(mnt
->mnt_fsname
, file
, 0, 0, 0))
90 #endif /* __linux__ */
93 if (file_dev
&& ((file_dev
== st_buf
.st_dev
) &&
94 (file_ino
== st_buf
.st_ino
)))
100 #ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
102 * Do an extra check to see if this is the root device. We
103 * can't trust /etc/mtab, and /proc/mounts will only list
104 * /dev/root for the root filesystem. Argh. Instead we
105 * check if the given device has the same major/minor number
106 * as the device that the root directory is on.
108 if (file_rdev
&& stat("/", &st_buf
) == 0 &&
109 st_buf
.st_dev
== file_rdev
) {
110 *mount_flags
= MF_MOUNTED
;
112 strncpy(mtpt
, "/", mtlen
);
118 #ifndef __GNU__ /* The GNU hurd is deficient; what else is new? */
119 /* Validate the entry in case /etc/mtab is out of date */
121 * We need to be paranoid, because some broken distributions
122 * (read: Slackware) don't initialize /etc/mtab before checking
123 * all of the non-root filesystems on the disk.
125 if (stat(mnt
->mnt_dir
, &st_buf
) < 0) {
127 if (retval
== ENOENT
) {
129 printf("Bogus entry in %s! (%s does not exist)\n",
130 mtab_file
, mnt
->mnt_dir
);
136 if (file_rdev
&& (st_buf
.st_dev
!= file_rdev
)) {
138 printf("Bogus entry in %s! (%s not mounted on %s)\n",
139 mtab_file
, file
, mnt
->mnt_dir
);
144 *mount_flags
= MF_MOUNTED
;
147 /* Check to see if the ro option is set */
148 if (hasmntopt(mnt
, MNTOPT_RO
))
149 *mount_flags
|= MF_READONLY
;
153 strncpy(mtpt
, mnt
->mnt_dir
, mtlen
);
155 * Check to see if we're referring to the root filesystem.
156 * If so, do a manual check to see if we can open /etc/mtab
157 * read/write, since if the root is mounted read/only, the
158 * contents of /etc/mtab may not be accurate.
160 if (!strcmp(mnt
->mnt_dir
, "/")) {
162 #define TEST_FILE "/.ismount-test-file"
163 *mount_flags
|= MF_ISROOT
;
164 fd
= open(TEST_FILE
, O_RDWR
|O_CREAT
|O_CLOEXEC
, 0600);
167 *mount_flags
|= MF_READONLY
;
170 (void) unlink(TEST_FILE
);
178 static int check_mntent(const char *file
, int *mount_flags
,
179 char *mtpt
, int mtlen
)
184 retval
= check_mntent_file("/tmp/mtab", file
, mount_flags
,
190 retval
= check_mntent_file("/proc/mounts", file
, mount_flags
,
192 if (retval
== 0 && (*mount_flags
!= 0))
194 if (access("/proc/mounts", R_OK
) == 0) {
198 #endif /* __linux__ */
199 #if defined(MOUNTED) || defined(_PATH_MOUNTED)
201 #define MOUNTED _PATH_MOUNTED
203 retval
= check_mntent_file(MOUNTED
, file
, mount_flags
, mtpt
, mtlen
);
208 #endif /* defined(MOUNTED) || defined(_PATH_MOUNTED) */
212 #if defined(HAVE_GETMNTINFO)
214 static int check_getmntinfo(const char *file
, int *mount_flags
,
215 char *mtpt
, int mtlen
)
222 n
= getmntinfo(&mp
, MNT_NOWAIT
);
226 len
= sizeof(_PATH_DEV
) - 1;
228 if (strncmp(_PATH_DEV
, s1
, len
) == 0)
233 s2
= mp
->f_mntfromname
;
234 if (strncmp(_PATH_DEV
, s2
, len
) == 0) {
238 if (strcmp(s1
, s2
) == 0 || strcmp(s1
, &s2
[1]) == 0) {
239 *mount_flags
= MF_MOUNTED
;
245 strncpy(mtpt
, mp
->f_mntonname
, mtlen
);
248 #endif /* HAVE_GETMNTINFO */
249 #endif /* HAVE_MNTENT_H */
252 * Check to see if we're dealing with the swap device.
254 static int is_swap_device(const char *file
)
263 #ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
264 if ((stat(file
, &st_buf
) == 0) &&
265 S_ISBLK(st_buf
.st_mode
))
266 file_dev
= st_buf
.st_rdev
;
269 if (!(f
= fopen("/proc/swaps", "r" UL_CLOEXECSTR
)))
271 /* Skip the first line */
272 if (!fgets(buf
, sizeof(buf
), f
))
274 if (*buf
&& strncmp(buf
, "Filename\t", 9))
275 /* Linux <=2.6.19 contained a bug in the /proc/swaps
276 * code where the header would not be displayed
278 goto valid_first_line
;
280 while (fgets(buf
, sizeof(buf
), f
)) {
282 if ((cp
= strchr(buf
, ' ')) != NULL
)
284 if ((cp
= strchr(buf
, '\t')) != NULL
)
286 if (strcmp(buf
, file
) == 0) {
291 if (file_dev
&& (stat(buf
, &st_buf
) == 0) &&
292 S_ISBLK(st_buf
.st_mode
) &&
293 file_dev
== st_buf
.st_rdev
) {
307 * check_mount_point() fills determines if the device is mounted or otherwise
308 * busy, and fills in mount_flags with one or more of the following flags:
309 * MF_MOUNTED, MF_ISROOT, MF_READONLY, MF_SWAP, and MF_BUSY. If mtpt is
310 * non-NULL, the directory where the device is mounted is copied to where mtpt
311 * is pointing, up to mtlen characters.
316 int check_mount_point(const char *device
, int *mount_flags
,
317 char *mtpt
, int mtlen
)
321 if (is_swap_device(device
)) {
322 *mount_flags
= MF_MOUNTED
| MF_SWAP
;
324 strncpy(mtpt
, "[SWAP]", mtlen
);
327 retval
= check_mntent(device
, mount_flags
, mtpt
, mtlen
);
329 #ifdef HAVE_GETMNTINFO
330 retval
= check_getmntinfo(device
, mount_flags
, mtpt
, mtlen
);
333 #warning "Can't use getmntent or getmntinfo to check for mounted filesystems!"
336 #endif /* HAVE_GETMNTINFO */
337 #endif /* HAVE_MNTENT_H */
342 #ifdef __linux__ /* This only works on Linux 2.6+ systems */
346 if ((stat(device
, &st_buf
) != 0) ||
347 !S_ISBLK(st_buf
.st_mode
))
349 fd
= open(device
, O_RDONLY
|O_EXCL
|O_CLOEXEC
);
352 *mount_flags
|= MF_BUSY
;
361 int is_mounted(const char *file
)
366 retval
= check_mount_point(file
, &mount_flags
, NULL
, 0);
369 return mount_flags
& MF_MOUNTED
;
373 int main(int argc
, char **argv
)
376 char devname
[PATH_MAX
];
379 fprintf(stderr
, "Usage: %s device\n", argv
[0]);
383 if (check_mount_point(argv
[1], &flags
, devname
, sizeof(devname
)) == 0 &&
384 (flags
& MF_MOUNTED
)) {
386 printf("used swap device\n");
388 printf("mounted on %s\n", devname
);
392 printf("not mounted\n");