From 3550dfd088b0929b7fb015e2ad8604048c2e86c9 Mon Sep 17 00:00:00 2001 From: "Federico G. Schwindt" Date: Sat, 24 Jun 2000 21:00:31 +0000 Subject: Implement getdents64, lstat64 and stat64, basically the same functions of the existing ones using 64bit vars. This makes netscape-solaris works on sparc. Particular note to those who want to try netscape: - netscape 4.73 was used for testing on a ss5 with -current. - apparently solaris uses pipes for communicating with the X server. I've checked the libraries I've installed from a solaris 2.6 box, and although there are references to X11-unix, it fails when it tries to open X11-pipe/X0, so in order to test it you need to specify -display :0 or it won't start. - i got some errors when starting, but besides that, it works fine. - it's not slow, but you better have all the requiered files in the correct paths, or it'll take some time to start. --- sys/compat/svr4/svr4_dirent.h | 9 ++- sys/compat/svr4/svr4_misc.c | 122 +++++++++++++++++++++++++++++++++++++++- sys/compat/svr4/svr4_stat.c | 72 +++++++++++++++++++++++- sys/compat/svr4/syscalls.master | 12 ++-- 4 files changed, 208 insertions(+), 7 deletions(-) (limited to 'sys/compat') diff --git a/sys/compat/svr4/svr4_dirent.h b/sys/compat/svr4/svr4_dirent.h index 60bf30c61b7..eae4e448512 100644 --- a/sys/compat/svr4/svr4_dirent.h +++ b/sys/compat/svr4/svr4_dirent.h @@ -1,4 +1,4 @@ -/* $OpenBSD: svr4_dirent.h,v 1.2 1996/08/02 20:35:35 niklas Exp $ */ +/* $OpenBSD: svr4_dirent.h,v 1.3 2000/06/24 21:00:29 fgsch Exp $ */ /* $NetBSD: svr4_dirent.h,v 1.4 1995/10/07 06:27:37 mycroft Exp $ */ /* @@ -40,6 +40,13 @@ struct svr4_dirent { char d_name[SVR4_MAXNAMLEN + 1]; }; +struct svr4_dirent64 { + svr4_ino64_t d_ino; + svr4_off64_t d_off; + u_short d_reclen; + char d_name[SVR4_MAXNAMLEN + 1]; +}; + #define SVR4_NAMEOFF(dp) ((char *)&(dp)->d_name - (char *)dp) #define SVR4_RECLEN(de,namlen) ALIGN((SVR4_NAMEOFF(de) + (namlen) + 1)) diff --git a/sys/compat/svr4/svr4_misc.c b/sys/compat/svr4/svr4_misc.c index 925aaec987e..855db9cc971 100644 --- a/sys/compat/svr4/svr4_misc.c +++ b/sys/compat/svr4/svr4_misc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: svr4_misc.c,v 1.25 1999/10/07 17:23:53 brad Exp $ */ +/* $OpenBSD: svr4_misc.c,v 1.26 2000/06/24 21:00:30 fgsch Exp $ */ /* $NetBSD: svr4_misc.c,v 1.42 1996/12/06 03:22:34 christos Exp $ */ /* @@ -337,6 +337,126 @@ out: return error; } +int +svr4_sys_getdents64(p, v, retval) + register struct proc *p; + void *v; + register_t *retval; +{ + struct svr4_sys_getdents64_args *uap = v; + register struct dirent *bdp; + struct vnode *vp; + caddr_t inp, buf; /* BSD-format */ + int len, reclen; /* BSD-format */ + caddr_t outp; /* SVR4-format */ + int resid, svr4_reclen; /* SVR4-format */ + struct file *fp; + struct uio auio; + struct iovec aiov; + struct svr4_dirent64 idb; + off_t off; /* true file offset */ + int buflen, error, eofflag; + u_long *cookiebuf = NULL, *cookie; + int ncookies = 0; + + if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) + return (error); + + if ((fp->f_flag & FREAD) == 0) + return (EBADF); + + vp = (struct vnode *)fp->f_data; + + if (vp->v_type != VDIR) /* XXX vnode readdir op should do this */ + return (EINVAL); + + buflen = min(MAXBSIZE, SCARG(uap, nbytes)); + buf = malloc(buflen, M_TEMP, M_WAITOK); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); + off = fp->f_offset; +again: + aiov.iov_base = buf; + aiov.iov_len = buflen; + auio.uio_iov = &aiov; + auio.uio_iovcnt = 1; + auio.uio_rw = UIO_READ; + auio.uio_segflg = UIO_SYSSPACE; + auio.uio_procp = p; + auio.uio_resid = buflen; + auio.uio_offset = off; + /* + * First we read into the malloc'ed buffer, then + * we massage it into user space, one record at a time. + */ + error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies, + &cookiebuf); + if (error) + goto out; + + if (!error && !cookiebuf && !eofflag) { + error = EPERM; + goto out; + } + + inp = buf; + outp = (char *) SCARG(uap, dp); + resid = SCARG(uap, nbytes); + if ((len = buflen - auio.uio_resid) == 0) + goto eof; + + for (cookie = cookiebuf; len > 0; len -= reclen) { + bdp = (struct dirent *)inp; + reclen = bdp->d_reclen; + if (reclen & 3) + panic("svr4_getdents64: bad reclen"); + if (bdp->d_fileno == 0) { + inp += reclen; /* it is a hole; squish it out */ + off = *cookie++; + continue; + } + svr4_reclen = SVR4_RECLEN(&idb, bdp->d_namlen); + if (reclen > len || resid < svr4_reclen) { + /* entry too big for buffer, so just stop */ + outp++; + break; + } + off = *cookie++; /* each entry points to the next */ + + /* + * Massage in place to make a SVR4-shaped dirent (otherwise + * we have to worry about touching user memory outside of + * the copyout() call). + */ + idb.d_ino = (svr4_ino64_t)bdp->d_fileno; + idb.d_off = (svr4_off64_t)off; + idb.d_reclen = (u_short)svr4_reclen; + strcpy(idb.d_name, bdp->d_name); + if ((error = copyout((caddr_t)&idb, outp, svr4_reclen))) + goto out; + + /* advance past this real entry */ + inp += reclen; + + /* advance output past SVR4-shaped entry */ + outp += svr4_reclen; + resid -= svr4_reclen; + } + + /* if we squished out the whole block, try again */ + if (outp == (char *) SCARG(uap, dp)) + goto again; + fp->f_offset = off; /* update the vnode offset */ + +eof: + *retval = SCARG(uap, nbytes) - resid; +out: + VOP_UNLOCK(vp, 0, p); + if (cookiebuf) + free(cookiebuf, M_TEMP); + free(buf, M_TEMP); + return error; +} + int svr4_sys_mmap(p, v, retval) register struct proc *p; diff --git a/sys/compat/svr4/svr4_stat.c b/sys/compat/svr4/svr4_stat.c index 3e064e83757..010fb73eef0 100644 --- a/sys/compat/svr4/svr4_stat.c +++ b/sys/compat/svr4/svr4_stat.c @@ -1,4 +1,4 @@ -/* $OpenBSD: svr4_stat.c,v 1.17 1999/10/07 16:14:28 brad Exp $ */ +/* $OpenBSD: svr4_stat.c,v 1.18 2000/06/24 21:00:30 fgsch Exp $ */ /* $NetBSD: svr4_stat.c,v 1.21 1996/04/22 01:16:07 christos Exp $ */ /* @@ -381,6 +381,76 @@ svr4_sys_fxstat(p, v, retval) } +int +svr4_sys_stat64(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct svr4_sys_stat64_args *uap = v; + struct stat st; + struct svr4_stat64 svr4_st; + struct sys_stat_args cup; + int error; + + caddr_t sg = stackgap_init(p->p_emul); + + SCARG(&cup, path) = SCARG(uap, path); + SCARG(&cup, ub) = stackgap_alloc(&sg, sizeof(struct stat)); + + if ((error = sys_stat(p, &cup, retval)) != 0) + return error; + + if ((error = copyin(SCARG(&cup, ub), &st, sizeof st)) != 0) + return error; + + bsd_to_svr4_stat64(&st, &svr4_st); + + if (S_ISSOCK(st.st_mode)) + (void) svr4_add_socket(p, SCARG(uap, path), &st); + + if ((error = copyout(&svr4_st, SCARG(uap, sb), sizeof svr4_st)) != 0) + return error; + + return 0; +} + + +int +svr4_sys_lstat64(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct svr4_sys_lstat64_args *uap = v; + struct stat st; + struct svr4_stat64 svr4_st; + struct sys_lstat_args cup; + int error; + + caddr_t sg = stackgap_init(p->p_emul); + + SCARG(&cup, path) = SCARG(uap, path); + SCARG(&cup, ub) = stackgap_alloc(&sg, sizeof(struct stat)); + + if ((error = sys_lstat(p, &cup, retval)) != 0) + return error; + + if ((error = copyin(SCARG(&cup, ub), &st, sizeof st)) != 0) + return error; + + bsd_to_svr4_stat64(&st, &svr4_st); + + if (S_ISSOCK(st.st_mode)) + (void) svr4_add_socket(p, SCARG(uap, path), &st); + + if ((error = copyout(&svr4_st, SCARG(uap, sb), sizeof svr4_st)) != 0) + return error; + + return 0; +} + + int svr4_sys_fstat64(p, v, retval) register struct proc *p; diff --git a/sys/compat/svr4/syscalls.master b/sys/compat/svr4/syscalls.master index b2c0b9b27b5..2a1f6ade88d 100644 --- a/sys/compat/svr4/syscalls.master +++ b/sys/compat/svr4/syscalls.master @@ -1,4 +1,4 @@ - $OpenBSD: syscalls.master,v 1.27 2000/06/15 05:28:30 brad Exp $ + $OpenBSD: syscalls.master,v 1.28 2000/06/24 21:00:30 fgsch Exp $ ; $NetBSD: syscalls.master,v 1.17 1996/02/10 17:12:51 christos Exp $ ; @(#)syscalls.master 8.1 (Berkeley) 7/19/93 @@ -322,10 +322,14 @@ 210 UNIMPL signotifywait 211 UNIMPL lwp_sigredirect 212 UNIMPL lwp_alarm -213 UNIMPL getdents64 +213 STD { int svr4_sys_getdents64(int fd, \ + struct svr4_dirent64 *dp, \ + int nbytes); } 214 UNIMPL mmap64 -215 UNIMPL stat64 -216 UNIMPL lstat64 +215 STD { int svr4_sys_stat64(const char *path, \ + struct svr4_stat64 *sb); } +216 STD { int svr4_sys_lstat64(const char *path, \ + struct svr4_stat64 *sb); } 217 STD { int svr4_sys_fstat64(int fd, \ struct svr4_stat64 *sb); } 218 UNIMPL statvfs64 -- cgit v1.2.3