df: fix "df /"
[oweals/busybox.git] / libbb / find_mount_point.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * Utility routines.
4  *
5  * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
6  *
7  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
8  */
9
10 #include "libbb.h"
11 #include <mntent.h>
12
13 /*
14  * Given a block device, find the mount table entry if that block device
15  * is mounted.
16  *
17  * Given any other file (or directory), find the mount table entry for its
18  * filesystem.
19  */
20 struct mntent* FAST_FUNC find_mount_point(const char *name)
21 {
22         struct stat s;
23         dev_t mountDevice;
24         FILE *mountTable;
25         struct mntent *mountEntry;
26
27         if (stat(name, &s) != 0)
28                 return NULL;
29
30         if (S_ISBLK(s.st_mode))
31                 mountDevice = s.st_rdev;
32         else
33                 mountDevice = s.st_dev;
34
35
36         mountTable = setmntent(bb_path_mtab_file, "r");
37         if (!mountTable)
38                 return 0;
39
40         while ((mountEntry = getmntent(mountTable)) != NULL) {
41                 /* rootfs mount in Linux 2.6 exists always,
42                  * and it makes sense to always ignore it.
43                  * Otherwise people can't reference their "real" root! */
44                 if (strcmp(mountEntry->mnt_fsname, "rootfs") == 0)
45                         continue;
46
47                 if (strcmp(name, mountEntry->mnt_dir) == 0
48                  || strcmp(name, mountEntry->mnt_fsname) == 0
49                 ) { /* String match. */
50                         break;
51                 }
52                 /* Match the device. */
53                 if (stat(mountEntry->mnt_fsname, &s) == 0 && s.st_rdev == mountDevice)
54                         break;
55                 /* Match the directory's mount point. */
56                 if (stat(mountEntry->mnt_dir, &s) == 0 && s.st_dev == mountDevice)
57                         break;
58         }
59         endmntent(mountTable);
60         return mountEntry;
61 }