blob: 9676b5f52c6cf8b8da4937f713a7de007c3df9bc [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 *
Denys Vlasenko0ef64bd2010-08-16 20:14:46 +02007 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
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;
Javier Viguerace4f39a2012-01-18 01:49:11 +010033 /* Why S_ISCHR? - UBI volumes use char devices, not block */
34 if (S_ISBLK(s.st_mode) || S_ISCHR(s.st_mode)) {
Denys Vlasenko6ae64262009-07-18 16:22:26 +020035 devno_of_name = s.st_rdev;
36 block_dev = 1;
37 }
Eric Andersenaad1a882001-03-16 22:47:14 +000038
Denys Vlasenko6ae64262009-07-18 16:22:26 +020039 mtab_fp = setmntent(bb_path_mtab_file, "r");
40 if (!mtab_fp)
41 return NULL;
Eric Andersenaad1a882001-03-16 22:47:14 +000042
Denys Vlasenko6ae64262009-07-18 16:22:26 +020043 while ((mountEntry = getmntent(mtab_fp)) != NULL) {
Denys Vlasenko09e63bb2009-07-05 04:50:36 +020044 /* rootfs mount in Linux 2.6 exists always,
45 * and it makes sense to always ignore it.
46 * Otherwise people can't reference their "real" root! */
Lauri Kasanen55ae0e92011-01-31 06:27:35 +010047 if (ENABLE_FEATURE_SKIP_ROOTFS && strcmp(mountEntry->mnt_fsname, "rootfs") == 0)
Denys Vlasenko09e63bb2009-07-05 04:50:36 +020048 continue;
49
Denis Vlasenkoc6ce8732006-11-29 18:15:52 +000050 if (strcmp(name, mountEntry->mnt_dir) == 0
51 || strcmp(name, mountEntry->mnt_fsname) == 0
52 ) { /* String match. */
Eric Andersenaad1a882001-03-16 22:47:14 +000053 break;
Denis Vlasenkoc6ce8732006-11-29 18:15:52 +000054 }
Denys Vlasenko6ae64262009-07-18 16:22:26 +020055
56 if (!(subdir_too || block_dev))
57 continue;
58
59 /* Is device's dev_t == name's dev_t? */
60 if (stat(mountEntry->mnt_fsname, &s) == 0 && s.st_rdev == devno_of_name)
Eric Andersenaad1a882001-03-16 22:47:14 +000061 break;
Denys Vlasenko09e63bb2009-07-05 04:50:36 +020062 /* Match the directory's mount point. */
Denys Vlasenko6ae64262009-07-18 16:22:26 +020063 if (stat(mountEntry->mnt_dir, &s) == 0 && s.st_dev == devno_of_name)
Eric Andersenaad1a882001-03-16 22:47:14 +000064 break;
65 }
Denys Vlasenko6ae64262009-07-18 16:22:26 +020066 endmntent(mtab_fp);
67
Eric Andersenaad1a882001-03-16 22:47:14 +000068 return mountEntry;
69}