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 (stat(mountEntry->mnt_fsname, &s) == 0 && s.st_rdev == devno_of_name) 60 break; 61 /* Match the directory's mount point. */ 62 if (stat(mountEntry->mnt_dir, &s) == 0 && s.st_dev == devno_of_name) 63 break; 64 } 65 endmntent(mtab_fp); 66 67 return mountEntry; 68} 69