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 source tree. 8 */ 9#include "libbb.h" 10#include <mntent.h> 11 12/* 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 */ 19struct mntent* FAST_FUNC find_mount_point(const char *name, int subdir_too) 20{ 21 struct stat s; 22 FILE *mtab_fp; 23 struct mntent *mountEntry; 24 dev_t devno_of_name; 25 bool block_dev; 26 27 if (stat(name, &s) != 0) 28 return NULL; 29 30 devno_of_name = s.st_dev; 31 block_dev = 0; 32 /* Why S_ISCHR? - UBI volumes use char devices, not block */ 33 if (S_ISBLK(s.st_mode) || S_ISCHR(s.st_mode)) { 34 devno_of_name = s.st_rdev; 35 block_dev = 1; 36 } 37 38 mtab_fp = setmntent(bb_path_mtab_file, "r"); 39 if (!mtab_fp) 40 return NULL; 41 42 while ((mountEntry = getmntent(mtab_fp)) != NULL) { 43 /* 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 (ENABLE_FEATURE_SKIP_ROOTFS && strcmp(mountEntry->mnt_fsname, "rootfs") == 0) 47 continue; 48 49 if (strcmp(name, mountEntry->mnt_dir) == 0 50 || strcmp(name, mountEntry->mnt_fsname) == 0 51 ) { /* String match. */ 52 break; 53 } 54 55 if (!(subdir_too || block_dev)) 56 continue; 57 58 /* Is device's dev_t == name's dev_t? */ 59 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 ) { 67 break; 68 } 69 /* Match the directory's mount point. */ 70 if (stat(mountEntry->mnt_dir, &s) == 0 71 && s.st_dev == devno_of_name 72 ) { 73 break; 74 } 75 } 76 endmntent(mtab_fp); 77 78 return mountEntry; 79} 80