blob: 6ce1858dd64321049303b3849797d9684795c4d0 [file] [log] [blame]
/*
* Copyright 1996-2004 by Hans Reiser, licensing governed by
* reiserfsprogs/README
*/
/* Lookup the @file in the @mntfile. @file is mntent.mnt_fsname if @fsname
is set; mntent.mnt_dir otherwise. Return the mnt entry from the @mntfile.
Warning: if the root fs is mounted RO, the content of /etc/mtab may be
not correct. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "misc/types.h"
#include "util/device.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/vfs.h>
#include <mntent.h>
#include <assert.h>
#include <stdio.h>
static struct mntent *util_mntent_lookup(char *mntfile,
char *file,
int path)
{
struct mntent *mnt;
int name_match = 0;
struct stat st;
dev_t rdev = 0;
dev_t dev = 0;
ino_t ino = 0;
char *name;
FILE *fp;
assert(mntfile != NULL);
assert(file != NULL);
if (stat(file, &st) == 0) {
/* Devices is stated. */
if (S_ISBLK(st.st_mode)) {
rdev = st.st_rdev;
} else {
dev = st.st_dev;
ino = st.st_ino;
}
}
if ((fp = setmntent(mntfile, "r")) == NULL)
return INVAL_PTR;
while ((mnt = getmntent(fp)) != NULL) {
/* Check if names match. */
name = path ? mnt->mnt_dir : mnt->mnt_fsname;
if (strcmp(file, name) == 0)
name_match = 1;
if (stat(name, &st))
continue;
/* If names do not match, check if stats match. */
if (!name_match) {
if (rdev && S_ISBLK(st.st_mode)) {
if (rdev != st.st_rdev)
continue;
} else if (dev && !S_ISBLK(st.st_mode)) {
if (dev != st.st_dev ||
ino != st.st_ino)
continue;
} else {
continue;
}
}
/* If not path and not block device do not check anything more. */
if (!path && !rdev)
break;
if (path) {
/* Either names or stats match. Make sure the st_dev of
the path is same as @mnt_fsname device rdev. */
if (stat(mnt->mnt_fsname, &st) == 0 &&
dev == st.st_rdev)
break;
} else {
/* Either names or stats match. Make sure the st_dev of
the mount entry is same as the given device rdev. */
if (stat(mnt->mnt_dir, &st) == 0 &&
rdev == st.st_dev)
break;
}
}
endmntent (fp);
return mnt;
}
struct mntent *util_mntent(char *device) {
int proc = 0, path = 0, root = 0;
struct mntent *mnt;
struct statfs stfs;
assert(device != NULL);
/* Check if the root. */
if (util_root_mounted(device) == 1)
root = 1;
#ifdef __linux__
/* Check if /proc is procfs. */
if (statfs("/proc", &stfs) == 0 && stfs.f_type == 0x9fa0) {
proc = 1;
if (root) {
/* Lookup the "/" entry in /proc/mounts. Special
case as root entry can present as:
rootfs / rootfs rw 0 0
Look up the mount point in this case. */
mnt = util_mntent_lookup("/proc/mounts", "/", 1);
} else {
/* Lookup the @device /proc/mounts */
mnt = util_mntent_lookup("/proc/mounts", device, 0);
}
if (mnt == INVAL_PTR)
proc = 0;
else if (mnt)
return mnt;
}
#endif /* __linux__ */
#if defined(MOUNTED) || defined(_PATH_MOUNTED)
#ifndef MOUNTED
#define MOUNTED _PATH_MOUNTED
#endif
/* Check in MOUNTED (/etc/mtab) if RW. */
if (!util_file_ro(MOUNTED)) {
path = 1;
if (root) {
mnt = util_mntent_lookup(MOUNTED, "/", 1);
} else {
mnt = util_mntent_lookup(MOUNTED, device, 0);
}
if (mnt == INVAL_PTR)
path = 0;
else if (mnt)
return mnt;
}
#endif /* defined(MOUNTED) || defined(_PATH_MOUNTED) */
/* If has not been checked in neither /proc/mounts nor /etc/mtab (or
errors have occured), return INVAL_PTR, NULL otherwise. */
return (!proc && !path) ? INVAL_PTR : NULL;
}