aboutsummaryrefslogtreecommitdiff
path: root/sys/compat/linux
diff options
context:
space:
mode:
authorBruce Evans <bde@FreeBSD.org>2018-06-13 12:22:00 +0000
committerBruce Evans <bde@FreeBSD.org>2018-06-13 12:22:00 +0000
commitab35e1c71baa2084c05ec0caeb4fa66e2553040c (patch)
tree32fc01d093fe1c018d7b8654676d3875c4ccd848 /sys/compat/linux
parent8b47c1ae5426c8d2a9763c3ef36ec088caee31b1 (diff)
Notes
Diffstat (limited to 'sys/compat/linux')
-rw-r--r--sys/compat/linux/linux_stats.c23
1 files changed, 20 insertions, 3 deletions
diff --git a/sys/compat/linux/linux_stats.c b/sys/compat/linux/linux_stats.c
index 92b23c7dcc2d..0a8ee6e612b7 100644
--- a/sys/compat/linux/linux_stats.c
+++ b/sys/compat/linux/linux_stats.c
@@ -128,13 +128,30 @@ translate_fd_major_minor(struct thread *td, int fd, struct stat *buf)
fdrop(fp, td);
}
+/*
+ * l_dev_t has the same encoding as dev_t in the latter's low 16 bits, so
+ * don't bother going through major() and minor(). Keep doing blind
+ * truncation, as for other fields. The previous version didn't even do
+ * blind truncation after dev_t was expanded to 64 bits. It failed to
+ * mask out bits 8-15 in minor(). These bits can only be nonzero in th
+ * 64-bit version.
+ *
+ * This is only used for st_dev. st_dev is for the mounted-on device so
+ * it can't be a device that needs very special translation. The translation
+ * of blind truncation is done here. st_rdev is supposed to be specially
+ * translated in callers, with the blind truncation done there too and
+ * st_rdev in the native struct state abused to hold the linux st_rdev.
+ * Callers do the last step using an open-coded Linux makedev().
+ */
+#define dev_to_ldev(d) ((uint16_t)(d))
+
static int
newstat_copyout(struct stat *buf, void *ubuf)
{
struct l_newstat tbuf;
bzero(&tbuf, sizeof(tbuf));
- tbuf.st_dev = minor(buf->st_dev) | (major(buf->st_dev) << 8);
+ tbuf.st_dev = dev_to_ldev(buf->st_dev);
tbuf.st_ino = buf->st_ino;
tbuf.st_mode = buf->st_mode;
tbuf.st_nlink = buf->st_nlink;
@@ -222,7 +239,7 @@ stat_copyout(struct stat *buf, void *ubuf)
struct l_stat lbuf;
bzero(&lbuf, sizeof(lbuf));
- lbuf.st_dev = buf->st_dev;
+ lbuf.st_dev = dev_to_ldev(buf->st_dev);
lbuf.st_ino = buf->st_ino;
lbuf.st_mode = buf->st_mode;
lbuf.st_nlink = buf->st_nlink;
@@ -524,7 +541,7 @@ stat64_copyout(struct stat *buf, void *ubuf)
struct l_stat64 lbuf;
bzero(&lbuf, sizeof(lbuf));
- lbuf.st_dev = minor(buf->st_dev) | (major(buf->st_dev) << 8);
+ lbuf.st_dev = dev_to_ldev(buf->st_dev);
lbuf.st_ino = buf->st_ino;
lbuf.st_mode = buf->st_mode;
lbuf.st_nlink = buf->st_nlink;