blob: bcb18effe5650af4bfb30888589341e4feb74f6f [file] [log] [blame]
Eric Andersenaad1a882001-03-16 22:47:14 +00001/* vi: set sw=4 ts=4: */
2/*
3 * Utility routines.
4 *
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
Eric Andersenaad1a882001-03-16 22:47:14 +00006 *
Bernhard Reutner-Fischerb1629b12006-05-19 19:29:19 +00007 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
Eric Andersenaad1a882001-03-16 22:47:14 +00008 */
9
Eric Andersenaad1a882001-03-16 22:47:14 +000010#include "libbb.h"
Eric Andersenaad1a882001-03-16 22:47:14 +000011#include <mntent.h>
Denis Vlasenkoc6ce8732006-11-29 18:15:52 +000012
Eric Andersenaad1a882001-03-16 22:47:14 +000013/*
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 */
Denys Vlasenko6ae64262009-07-18 16:22:26 +020020struct mntent* FAST_FUNC find_mount_point(const char *name, int subdir_too)
Eric Andersenaad1a882001-03-16 22:47:14 +000021{
22 struct stat s;
Denys Vlasenko6ae64262009-07-18 16:22:26 +020023 FILE *mtab_fp;
Eric Andersenaad1a882001-03-16 22:47:14 +000024 struct mntent *mountEntry;
Denys Vlasenko6ae64262009-07-18 16:22:26 +020025 dev_t devno_of_name;
26 bool block_dev;
Eric Andersenaad1a882001-03-16 22:47:14 +000027
28 if (stat(name, &s) != 0)
Denys Vlasenko09e63bb2009-07-05 04:50:36 +020029 return NULL;
Eric Andersenaad1a882001-03-16 22:47:14 +000030
Denys Vlasenko6ae64262009-07-18 16:22:26 +020031 devno_of_name = s.st_dev;
32 block_dev = 0;
33 if (S_ISBLK(s.st_mode)) {
34 devno_of_name = s.st_rdev;
35 block_dev = 1;
36 }
Eric Andersenaad1a882001-03-16 22:47:14 +000037
Denys Vlasenko6ae64262009-07-18 16:22:26 +020038 mtab_fp = setmntent(bb_path_mtab_file, "r");
39 if (!mtab_fp)
40 return NULL;
Eric Andersenaad1a882001-03-16 22:47:14 +000041
Denys Vlasenko6ae64262009-07-18 16:22:26 +020042 while ((mountEntry = getmntent(mtab_fp)) != NULL) {
Denys Vlasenko09e63bb2009-07-05 04:50:36 +020043 /* rootfs mount in Linux 2.6 exists always,
44 * and it makes sense to always ignore it.
45 * Otherwise people can't reference their "real" root! */
46 if (strcmp(mountEntry->mnt_fsname, "rootfs") == 0)
47 continue;
48
Denis Vlasenkoc6ce8732006-11-29 18:15:52 +000049 if (strcmp(name, mountEntry->mnt_dir) == 0
50 || strcmp(name, mountEntry->mnt_fsname) == 0
51 ) { /* String match. */
Eric Andersenaad1a882001-03-16 22:47:14 +000052 break;
Denis Vlasenkoc6ce8732006-11-29 18:15:52 +000053 }
Denys Vlasenko6ae64262009-07-18 16:22:26 +020054
55 if (!(subdir_too || block_dev))
56 continue;
57
58 /* Is device's dev_t == name's dev_t? */
59 if (stat(mountEntry->mnt_fsname, &s) == 0 && s.st_rdev == devno_of_name)
Eric Andersenaad1a882001-03-16 22:47:14 +000060 break;
Denys Vlasenko09e63bb2009-07-05 04:50:36 +020061 /* Match the directory's mount point. */
Denys Vlasenko6ae64262009-07-18 16:22:26 +020062 if (stat(mountEntry->mnt_dir, &s) == 0 && s.st_dev == devno_of_name)
Eric Andersenaad1a882001-03-16 22:47:14 +000063 break;
64 }
Denys Vlasenko6ae64262009-07-18 16:22:26 +020065 endmntent(mtab_fp);
66
Eric Andersenaad1a882001-03-16 22:47:14 +000067 return mountEntry;
68}