diff options
| author | Bruce Evans <bde@FreeBSD.org> | 2018-06-13 12:22:00 +0000 |
|---|---|---|
| committer | Bruce Evans <bde@FreeBSD.org> | 2018-06-13 12:22:00 +0000 |
| commit | ab35e1c71baa2084c05ec0caeb4fa66e2553040c (patch) | |
| tree | 32fc01d093fe1c018d7b8654676d3875c4ccd848 /sys/compat/linux | |
| parent | 8b47c1ae5426c8d2a9763c3ef36ec088caee31b1 (diff) | |
Notes
Diffstat (limited to 'sys/compat/linux')
| -rw-r--r-- | sys/compat/linux/linux_stats.c | 23 |
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; |
