aboutsummaryrefslogtreecommitdiff
path: root/sys/compat/linux/linux_util.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/compat/linux/linux_util.c')
-rw-r--r--sys/compat/linux/linux_util.c26
1 files changed, 26 insertions, 0 deletions
diff --git a/sys/compat/linux/linux_util.c b/sys/compat/linux/linux_util.c
index 2a21fdc10bd7..5995ac5e18af 100644
--- a/sys/compat/linux/linux_util.c
+++ b/sys/compat/linux/linux_util.c
@@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
#include <sys/malloc.h>
#include <sys/namei.h>
#include <sys/proc.h>
+#include <sys/stat.h>
#include <sys/syscallsubr.h>
#include <sys/vnode.h>
@@ -225,6 +226,31 @@ linux_vn_get_major_minor(const struct vnode *vp, int *major, int *minor)
return (error);
}
+void
+translate_vnhook_major_minor(struct vnode *vp, struct stat *sb)
+{
+ int major, minor;
+
+ if (vn_isdisk(vp)) {
+ sb->st_mode &= ~S_IFMT;
+ sb->st_mode |= S_IFBLK;
+ }
+
+ /*
+ * Return the same st_dev for every devfs instance. The reason
+ * for this is to work around an idiosyncrasy of glibc getttynam()
+ * implementation: it checks whether st_dev returned for fd 0
+ * is the same as st_dev returned for the target of /proc/self/fd/0
+ * symlink, and with linux chroots having their own devfs instance,
+ * the check will fail if you chroot into it.
+ */
+ if (rootdevmp != NULL && vp->v_mount->mnt_vfc == rootdevmp->mnt_vfc)
+ sb->st_dev = rootdevmp->mnt_stat.f_fsid.val[0];
+
+ if (linux_vn_get_major_minor(vp, &major, &minor) == 0)
+ sb->st_rdev = (major << 8 | minor);
+}
+
char *
linux_get_char_devices(void)
{