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 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 */ 20struct mntent* FAST_FUNC find_mount_point(const char *name, int subdir_too) 21{ 22 struct stat s; 23 FILE *mtab_fp; 24 struct mntent *mountEntry; 25 dev_t devno_of_name; 26 bool block_dev; 27 28 if (stat(name, &s) != 0) 29 return NULL; 30 31 devno_of_name = s.st_dev; 32 block_dev = 0; 33 /* Why S_ISCHR? - UBI volumes use char devices, not block */ 34 if (S_ISBLK(s.st_mode) || S_ISCHR(s.st_mode)) { 35 devno_of_name = s.st_rdev; 36 block_dev = 1; 37 } 38 39 mtab_fp = setmntent(bb_path_mtab_file, "r"); 40 if (!mtab_fp) 41 return NULL; 42 43 while ((mountEntry = getmntent(mtab_fp)) != NULL) { 44 /* 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! */ 47 if (ENABLE_FEATURE_SKIP_ROOTFS && strcmp(mountEntry->mnt_fsname, "rootfs") == 0) 48 continue; 49 50 if (strcmp(name, mountEntry->mnt_dir) == 0 51 || strcmp(name, mountEntry->mnt_fsname) == 0 52 ) { /* String match. */ 53 break; 54 } 55 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) 61 break; 62 /* Match the directory's mount point. */ 63 if (stat(mountEntry->mnt_dir, &s) == 0 && s.st_dev == devno_of_name) 64 break; 65 } 66 endmntent(mtab_fp); 67 68 return mountEntry; 69} 70