Index: src/sys/compat/linux/linux_stats.c @@ -61,6 +61,31 @@ __FBSDID("$FreeBSD: src/sys/compat/linux #include static void +linux_disk_foo(struct cdev *dev, struct stat *tbuf) +{ + struct cdevsw *cdevsw; + + /* Lie about disk drives which are character devices + * in FreeBSD but block devices under Linux. + */ + if (S_ISCHR(tbuf->st_mode) && dev != NULL) { + cdevsw = dev_refthread(dev); + if (cdevsw != NULL) { + if (cdevsw->d_flags & D_DISK) { + tbuf->st_mode &= ~S_IFMT; + tbuf->st_mode |= S_IFBLK; + + /* XXX this may not be quite right */ + /* Map major number to 0 */ + tbuf->st_dev = minor(tbuf->st_dev) & 0xf; + tbuf->st_rdev = tbuf->st_rdev & 0xff; + } + dev_relthread(dev); + } + } +} + +static void translate_vnhook_major_minor(struct vnode *vp, struct stat *sb) { int major, minor; @@ -70,6 +95,7 @@ translate_vnhook_major_minor(struct vnod &major, &minor) == 0) { sb->st_rdev = (major << 8 | minor); } + linux_disk_foo(vp->v_rdev, sb); } static int @@ -98,65 +124,31 @@ linux_kern_lstat(struct thread *td, char pathseg, sbp)); } -/* - * XXX: This was removed from newstat_copyout(), and almost identical - * XXX: code was in stat64_copyout(). findcdev() needs to be replaced - * XXX: with something that does lookup and locking properly. - * XXX: When somebody fixes this: please try to avoid duplicating it. - */ -#if 0 -static void -disk_foo(struct somestat *tbuf) -{ - struct cdevsw *cdevsw; - struct cdev *dev; - - /* Lie about disk drives which are character devices - * in FreeBSD but block devices under Linux. - */ - if (S_ISCHR(tbuf.st_mode) && - (dev = findcdev(buf->st_rdev)) != NULL) { - cdevsw = dev_refthread(dev); - if (cdevsw != NULL) { - if (cdevsw->d_flags & D_DISK) { - tbuf.st_mode &= ~S_IFMT; - tbuf.st_mode |= S_IFBLK; - - /* XXX this may not be quite right */ - /* Map major number to 0 */ - tbuf.st_dev = minor(buf->st_dev) & 0xf; - tbuf.st_rdev = buf->st_rdev & 0xff; - } - dev_relthread(dev); - } - } - -} -#endif - static void translate_fd_major_minor(struct thread *td, int fd, struct stat *buf) { struct file *fp; struct vnode *vp; + struct cdev *dev = NULL; int major, minor; if ((!S_ISCHR(buf->st_mode) && !S_ISBLK(buf->st_mode)) || fget(td, fd, &fp) != 0) return; vp = fp->f_vnode; - if (vp != NULL && vp->v_rdev != NULL && - linux_driver_get_major_minor(vp->v_rdev->si_name, - &major, &minor) == 0) { - buf->st_rdev = (major << 8 | minor); + if (vp != NULL && vp->v_rdev != NULL) { + dev = vp->v_rdev; } else if (fp->f_type == DTYPE_PTS) { struct tty *tp = fp->f_data; - /* Convert the numbers for the slave device. */ - if (linux_driver_get_major_minor(tp->t_dev->si_name, + dev = tp->t_dev; + } + if (dev) { + if (linux_driver_get_major_minor(dev->si_name, &major, &minor) == 0) { buf->st_rdev = (major << 8 | minor); } + linux_disk_foo(dev, buf); } fdrop(fp, td); }