blob: 0e1be38204541c79c3bf49f9ebb8f331b31bbba5 [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 */
Eric Andersenaad1a882001-03-16 22:47:14 +00009#include "libbb.h"
Eric Andersenaad1a882001-03-16 22:47:14 +000010#include <mntent.h>
Denis Vlasenkoc6ce8732006-11-29 18:15:52 +000011
Eric Andersenaad1a882001-03-16 22:47:14 +000012/*
13 * Given a block device, find the mount table entry if that block device
14 * is mounted.
15 *
16 * Given any other file (or directory), find the mount table entry for its
17 * filesystem.
18 */
Denys Vlasenko6ae64262009-07-18 16:22:26 +020019struct mntent* FAST_FUNC find_mount_point(const char *name, int subdir_too)
Eric Andersenaad1a882001-03-16 22:47:14 +000020{
21 struct stat s;
Denys Vlasenko6ae64262009-07-18 16:22:26 +020022 FILE *mtab_fp;
Eric Andersenaad1a882001-03-16 22:47:14 +000023 struct mntent *mountEntry;
Denys Vlasenko6ae64262009-07-18 16:22:26 +020024 dev_t devno_of_name;
25 bool block_dev;
Eric Andersenaad1a882001-03-16 22:47:14 +000026
27 if (stat(name, &s) != 0)
Denys Vlasenko09e63bb2009-07-05 04:50:36 +020028 return NULL;
Eric Andersenaad1a882001-03-16 22:47:14 +000029
Denys Vlasenko6ae64262009-07-18 16:22:26 +020030 devno_of_name = s.st_dev;
31 block_dev = 0;
Javier Viguerace4f39a2012-01-18 01:49:11 +010032 /* Why S_ISCHR? - UBI volumes use char devices, not block */
33 if (S_ISBLK(s.st_mode) || S_ISCHR(s.st_mode)) {
Denys Vlasenko6ae64262009-07-18 16:22:26 +020034 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! */
Lauri Kasanen55ae0e92011-01-31 06:27:35 +010046 if (ENABLE_FEATURE_SKIP_ROOTFS && strcmp(mountEntry->mnt_fsname, "rootfs") == 0)
Denys Vlasenko09e63bb2009-07-05 04:50:36 +020047 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? */
Denys Vlasenkof3a064f2019-04-29 17:59:08 +020059 if (mountEntry->mnt_fsname[0] == '/'
60 /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
61 * avoid stat'ing "sysfs", "proc", "none" and such,
62 * useless at best, can stat unrelated files at worst.
63 */
64 && stat(mountEntry->mnt_fsname, &s) == 0
65 && s.st_rdev == devno_of_name
66 ) {
Eric Andersenaad1a882001-03-16 22:47:14 +000067 break;
Denys Vlasenkof3a064f2019-04-29 17:59:08 +020068 }
Denys Vlasenko09e63bb2009-07-05 04:50:36 +020069 /* Match the directory's mount point. */
Denys Vlasenkof3a064f2019-04-29 17:59:08 +020070 if (stat(mountEntry->mnt_dir, &s) == 0
71 && s.st_dev == devno_of_name
72 ) {
Eric Andersenaad1a882001-03-16 22:47:14 +000073 break;
Denys Vlasenkof3a064f2019-04-29 17:59:08 +020074 }
Eric Andersenaad1a882001-03-16 22:47:14 +000075 }
Denys Vlasenko6ae64262009-07-18 16:22:26 +020076 endmntent(mtab_fp);
77
Eric Andersenaad1a882001-03-16 22:47:14 +000078 return mountEntry;
79}