source: MondoRescue/branches/stable/mindi-busybox/e2fsprogs/ext2fs/ismounted.c @ 821

Last change on this file since 821 was 821, checked in by Bruno Cornec, 13 years ago

Addition of busybox 1.2.1 as a mindi-busybox new package
This should avoid delivering binary files in mindi not built there (Fedora and Debian are quite serious about that)

File size: 8.4 KB
Line 
1/*
2 * ismounted.c --- Check to see if the filesystem was mounted
3 *
4 * Copyright (C) 1995,1996,1997,1998,1999,2000 Theodore Ts'o.
5 *
6 * %Begin-Header%
7 * This file may be redistributed under the terms of the GNU Public
8 * License.
9 * %End-Header%
10 */
11
12#include <stdio.h>
13#if HAVE_UNISTD_H
14#include <unistd.h>
15#endif
16#if HAVE_ERRNO_H
17#include <errno.h>
18#endif
19#include <fcntl.h>
20#ifdef HAVE_LINUX_FD_H
21#include <linux/fd.h>
22#endif
23#ifdef HAVE_MNTENT_H
24#include <mntent.h>
25#endif
26#ifdef HAVE_GETMNTINFO
27#include <paths.h>
28#include <sys/param.h>
29#include <sys/mount.h>
30#endif /* HAVE_GETMNTINFO */
31#include <string.h>
32#include <sys/stat.h>
33
34#include "ext2_fs.h"
35#include "ext2fs.h"
36
37#ifdef HAVE_MNTENT_H
38/*
39 * Helper function which checks a file in /etc/mtab format to see if a
40 * filesystem is mounted.  Returns an error if the file doesn't exist
41 * or can't be opened.
42 */
43static errcode_t check_mntent_file(const char *mtab_file, const char *file,
44                   int *mount_flags, char *mtpt, int mtlen)
45{
46    struct mntent   *mnt;
47    struct stat st_buf;
48    errcode_t   retval = 0;
49    dev_t       file_dev=0, file_rdev=0;
50    ino_t       file_ino=0;
51    FILE        *f;
52    int     fd;
53
54    *mount_flags = 0;
55    if ((f = setmntent (mtab_file, "r")) == NULL)
56        return errno;
57    if (stat(file, &st_buf) == 0) {
58        if (S_ISBLK(st_buf.st_mode)) {
59#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
60            file_rdev = st_buf.st_rdev;
61#endif  /* __GNU__ */
62        } else {
63            file_dev = st_buf.st_dev;
64            file_ino = st_buf.st_ino;
65        }
66    }
67    while ((mnt = getmntent (f)) != NULL) {
68        if (strcmp(file, mnt->mnt_fsname) == 0)
69            break;
70        if (stat(mnt->mnt_fsname, &st_buf) == 0) {
71            if (S_ISBLK(st_buf.st_mode)) {
72#ifndef __GNU__
73                if (file_rdev && (file_rdev == st_buf.st_rdev))
74                    break;
75#endif  /* __GNU__ */
76            } else {
77                if (file_dev && ((file_dev == st_buf.st_dev) &&
78                         (file_ino == st_buf.st_ino)))
79                    break;
80            }
81        }
82    }
83
84    if (mnt == 0) {
85#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
86        /*
87         * Do an extra check to see if this is the root device.  We
88         * can't trust /etc/mtab, and /proc/mounts will only list
89         * /dev/root for the root filesystem.  Argh.  Instead we
90         * check if the given device has the same major/minor number
91         * as the device that the root directory is on.
92         */
93        if (file_rdev && stat("/", &st_buf) == 0) {
94            if (st_buf.st_dev == file_rdev) {
95                *mount_flags = EXT2_MF_MOUNTED;
96                if (mtpt)
97                    strncpy(mtpt, "/", mtlen);
98                goto is_root;
99            }
100        }
101#endif  /* __GNU__ */
102        goto errout;
103    }
104#ifndef __GNU__ /* The GNU hurd is deficient; what else is new? */
105    /* Validate the entry in case /etc/mtab is out of date */
106    /*
107     * We need to be paranoid, because some broken distributions
108     * (read: Slackware) don't initialize /etc/mtab before checking
109     * all of the non-root filesystems on the disk.
110     */
111    if (stat(mnt->mnt_dir, &st_buf) < 0) {
112        retval = errno;
113        if (retval == ENOENT) {
114#ifdef DEBUG
115            printf("Bogus entry in %s!  (%s does not exist)\n",
116                   mtab_file, mnt->mnt_dir);
117#endif /* DEBUG */
118            retval = 0;
119        }
120        goto errout;
121    }
122    if (file_rdev && (st_buf.st_dev != file_rdev)) {
123#ifdef DEBUG
124        printf("Bogus entry in %s!  (%s not mounted on %s)\n",
125               mtab_file, file, mnt->mnt_dir);
126#endif /* DEBUG */
127        goto errout;
128    }
129#endif /* __GNU__ */
130    *mount_flags = EXT2_MF_MOUNTED;
131
132#ifdef MNTOPT_RO
133    /* Check to see if the ro option is set */
134    if (hasmntopt(mnt, MNTOPT_RO))
135        *mount_flags |= EXT2_MF_READONLY;
136#endif
137
138    if (mtpt)
139        strncpy(mtpt, mnt->mnt_dir, mtlen);
140    /*
141     * Check to see if we're referring to the root filesystem.
142     * If so, do a manual check to see if we can open /etc/mtab
143     * read/write, since if the root is mounted read/only, the
144     * contents of /etc/mtab may not be accurate.
145     */
146    if (!strcmp(mnt->mnt_dir, "/")) {
147is_root:
148#define TEST_FILE "/.ismount-test-file"
149        *mount_flags |= EXT2_MF_ISROOT;
150        fd = open(TEST_FILE, O_RDWR|O_CREAT);
151        if (fd < 0) {
152            if (errno == EROFS)
153                *mount_flags |= EXT2_MF_READONLY;
154        } else
155            close(fd);
156        (void) unlink(TEST_FILE);
157    }
158    retval = 0;
159errout:
160    endmntent (f);
161    return retval;
162}
163
164static errcode_t check_mntent(const char *file, int *mount_flags,
165                  char *mtpt, int mtlen)
166{
167    errcode_t   retval;
168
169#ifdef DEBUG
170    retval = check_mntent_file("/tmp/mtab", file, mount_flags,
171                   mtpt, mtlen);
172    if (retval == 0)
173        return 0;
174#endif /* DEBUG */
175#ifdef __linux__
176    retval = check_mntent_file("/proc/mounts", file, mount_flags,
177                   mtpt, mtlen);
178    if (retval == 0 && (*mount_flags != 0))
179        return 0;
180#endif /* __linux__ */
181#if defined(MOUNTED) || defined(_PATH_MOUNTED)
182#ifndef MOUNTED
183#define MOUNTED _PATH_MOUNTED
184#endif /* MOUNTED */
185    retval = check_mntent_file(MOUNTED, file, mount_flags, mtpt, mtlen);
186    return retval;
187#else
188    *mount_flags = 0;
189    return 0;
190#endif /* defined(MOUNTED) || defined(_PATH_MOUNTED) */
191}
192
193#else
194#if defined(HAVE_GETMNTINFO)
195
196static errcode_t check_getmntinfo(const char *file, int *mount_flags,
197                  char *mtpt, int mtlen)
198{
199    struct statfs *mp;
200    int    len, n;
201    const  char   *s1;
202    char    *s2;
203
204    n = getmntinfo(&mp, MNT_NOWAIT);
205    if (n == 0)
206        return errno;
207
208    len = sizeof(_PATH_DEV) - 1;
209    s1 = file;
210    if (strncmp(_PATH_DEV, s1, len) == 0)
211        s1 += len;
212
213    *mount_flags = 0;
214    while (--n >= 0) {
215        s2 = mp->f_mntfromname;
216        if (strncmp(_PATH_DEV, s2, len) == 0) {
217            s2 += len - 1;
218            *s2 = 'r';
219        }
220        if (strcmp(s1, s2) == 0 || strcmp(s1, &s2[1]) == 0) {
221            *mount_flags = EXT2_MF_MOUNTED;
222            break;
223        }
224        ++mp;
225    }
226    if (mtpt)
227        strncpy(mtpt, mp->f_mntonname, mtlen);
228    return 0;
229}
230#endif /* HAVE_GETMNTINFO */
231#endif /* HAVE_MNTENT_H */
232
233/*
234 * Check to see if we're dealing with the swap device.
235 */
236static int is_swap_device(const char *file)
237{
238    FILE        *f;
239    char        buf[1024], *cp;
240    dev_t       file_dev;
241    struct stat st_buf;
242    int     ret = 0;
243
244    file_dev = 0;
245#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
246    if ((stat(file, &st_buf) == 0) &&
247        S_ISBLK(st_buf.st_mode))
248        file_dev = st_buf.st_rdev;
249#endif  /* __GNU__ */
250
251    if (!(f = fopen("/proc/swaps", "r")))
252        return 0;
253    /* Skip the first line */
254    fgets(buf, sizeof(buf), f);
255    while (!feof(f)) {
256        if (!fgets(buf, sizeof(buf), f))
257            break;
258        if ((cp = strchr(buf, ' ')) != NULL)
259            *cp = 0;
260        if ((cp = strchr(buf, '\t')) != NULL)
261            *cp = 0;
262        if (strcmp(buf, file) == 0) {
263            ret++;
264            break;
265        }
266#ifndef __GNU__
267        if (file_dev && (stat(buf, &st_buf) == 0) &&
268            S_ISBLK(st_buf.st_mode) &&
269            file_dev == st_buf.st_rdev) {
270            ret++;
271            break;
272        }
273#endif  /* __GNU__ */
274    }
275    fclose(f);
276    return ret;
277}
278
279
280/*
281 * ext2fs_check_mount_point() returns 1 if the device is mounted, 0
282 * otherwise.  If mtpt is non-NULL, the directory where the device is
283 * mounted is copied to where mtpt is pointing, up to mtlen
284 * characters.
285 */
286#ifdef __TURBOC__
287# pragma argsused
288#endif
289errcode_t ext2fs_check_mount_point(const char *device, int *mount_flags,
290                  char *mtpt, int mtlen)
291{
292    if (is_swap_device(device)) {
293        *mount_flags = EXT2_MF_MOUNTED | EXT2_MF_SWAP;
294        strncpy(mtpt, "<swap>", mtlen);
295        return 0;
296    }
297#ifdef HAVE_MNTENT_H
298    return check_mntent(device, mount_flags, mtpt, mtlen);
299#else
300#ifdef HAVE_GETMNTINFO
301    return check_getmntinfo(device, mount_flags, mtpt, mtlen);
302#else
303#ifdef __GNUC__
304 #warning "Can't use getmntent or getmntinfo to check for mounted filesystems!"
305#endif
306    *mount_flags = 0;
307    return 0;
308#endif /* HAVE_GETMNTINFO */
309#endif /* HAVE_MNTENT_H */
310}
311
312/*
313 * ext2fs_check_if_mounted() sets the mount_flags EXT2_MF_MOUNTED,
314 * EXT2_MF_READONLY, and EXT2_MF_ROOT
315 *
316 */
317errcode_t ext2fs_check_if_mounted(const char *file, int *mount_flags)
318{
319    return ext2fs_check_mount_point(file, mount_flags, NULL, 0);
320}
321
322#ifdef DEBUG
323int main(int argc, char **argv)
324{
325    int retval, mount_flags;
326    char    mntpt[80];
327
328    if (argc < 2) {
329        fprintf(stderr, "Usage: %s device\n", argv[0]);
330        exit(1);
331    }
332
333    mntpt[0] = 0;
334    retval = ext2fs_check_mount_point(argv[1], &mount_flags,
335                      mntpt, sizeof(mntpt));
336    if (retval) {
337        com_err(argv[0], retval,
338            "while calling ext2fs_check_if_mounted");
339        exit(1);
340    }
341    printf("Device %s reports flags %02x\n", argv[1], mount_flags);
342    if (mount_flags & EXT2_MF_BUSY)
343        printf("\t%s is apparently in use.\n", argv[1]);
344    if (mount_flags & EXT2_MF_MOUNTED)
345        printf("\t%s is mounted.\n", argv[1]);
346    if (mount_flags & EXT2_MF_SWAP)
347        printf("\t%s is a swap device.\n", argv[1]);
348    if (mount_flags & EXT2_MF_READONLY)
349        printf("\t%s is read-only.\n", argv[1]);
350    if (mount_flags & EXT2_MF_ISROOT)
351        printf("\t%s is the root filesystem.\n", argv[1]);
352    if (mntpt[0])
353        printf("\t%s is mounted on %s.\n", argv[1], mntpt);
354    exit(0);
355}
356#endif /* DEBUG */
Note: See TracBrowser for help on using the repository browser.