Port-alpha archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
COMPAT_OSF1 getdirentries(2) fix
I'd like to commit, unless someone objects, the following patch.
It fix the compat_osf1 getdirentries syscall which seems to have been
broken for quite some time now ... mostly because native and osf1
struct dirent differs (members number and types).
--
Nicolas Joly
Biological Software and Databanks.
Institut Pasteur, Paris.
Index: sys/compat/osf1/osf1_dirent.h
===================================================================
RCS file: sys/compat/osf1/osf1_dirent.h
diff -N sys/compat/osf1/osf1_dirent.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ sys/compat/osf1/osf1_dirent.h 1 Dec 2008 16:25:10 -0000
@@ -0,0 +1,47 @@
+/* $NetBSD$ */
+
+/*-
+ * Copyright (c) 1994 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _OSF1_DIRENT_H_
+#define _OSF1_DIRENT_H_
+
+#define OSF1_MAXNAMLEN 255
+
+struct osf1_dirent {
+ osf1_ino_t d_ino;
+ u_short d_reclen;
+ u_short d_namlen;
+ char d_name[OSF1_MAXNAMLEN + 1];
+};
+
+#define OSF1_NAMEOFF(dp) ((char *)&(dp)->d_name - (char *)dp)
+#define OSF1_RECLEN(de,namlen) ALIGN((OSF1_NAMEOFF(de) + (namlen) + 1))
+
+#endif /* !_OSF1_DIRENT_H_ */
Index: sys/compat/osf1/osf1_file.c
===================================================================
RCS file: /cvsroot/src/sys/compat/osf1/osf1_file.c,v
retrieving revision 1.30
diff -u -p -r1.30 osf1_file.c
--- sys/compat/osf1/osf1_file.c 21 Mar 2008 21:54:59 -0000 1.30
+++ sys/compat/osf1/osf1_file.c 1 Dec 2008 16:25:10 -0000
@@ -86,11 +86,13 @@ __KERNEL_RCSID(0, "$NetBSD: osf1_file.c,
#include <sys/resourcevar.h>
#include <sys/wait.h>
#include <sys/vfs_syscalls.h>
+#include <sys/dirent.h>
#include <compat/osf1/osf1.h>
#include <compat/osf1/osf1_syscallargs.h>
#include <compat/common/compat_util.h>
#include <compat/osf1/osf1_cvt.h>
+#include <compat/osf1/osf1_dirent.h>
int
osf1_sys_access(struct lwp *l, const struct osf1_sys_access_args *uap,
register_t *retval)
@@ -121,6 +123,129 @@ osf1_sys_execve(struct lwp *l, const str
return sys_execve(l, &ap, retval);
}
+int
+osf1_sys_getdirentries(struct lwp *l, const struct osf1_sys_getdirentries_args
*uap, register_t *retval)
+{
+ /* {
+ syscallarg(int) fd;
+ syscallarg(char *) buf;
+ syscallarg(u_int) nbytes;
+ syscallarg(long *) basep;
+ } */
+ struct dirent *bdp;
+ struct vnode *vp;
+ char *inp, *buf; /* BSD-format */
+ int len, reclen; /* BSD-format */
+ char *outp; /* OSF1-format */
+ int resid, osf1_reclen; /* OSF1-format */
+ struct file *fp;
+ struct uio auio;
+ struct iovec aiov;
+ struct osf1_dirent idb;
+ off_t off; /* true file offset */
+ int buflen, error, eofflag;
+ off_t *cookiebuf = NULL, *cookie;
+ int ncookies, fd;
+
+ fd = SCARG(uap, fd);
+ if ((error = fd_getvnode(fd, &fp)) != 0)
+ return (error);
+ if ((fp->f_flag & FREAD) == 0) {
+ error = EBADF;
+ goto out1;
+ }
+
+ vp = (struct vnode *)fp->f_data;
+ if (vp->v_type != VDIR) {
+ error = EINVAL;
+ goto out1;
+ }
+
+ buflen = min(MAXBSIZE, SCARG(uap, nbytes));
+ buf = malloc(buflen, M_TEMP, M_WAITOK);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+ 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_resid = buflen;
+ auio.uio_offset = off;
+ UIO_SETUP_SYSSPACE(&auio);
+ /*
+ * 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, &cookiebuf,
+ &ncookies);
+ if (error)
+ goto out;
+
+ inp = buf;
+ outp = (char *)SCARG(uap, buf);
+ 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("osf1_sys_getdirentries: bad reclen");
+ if (cookie)
+ off = *cookie++; /* each entry points to the next */
+ else
+ off += reclen;
+ if ((off >> 32) != 0) {
+ compat_offseterr(vp, "osf1_sys_getdirentries");
+ error = EINVAL;
+ goto out;
+ }
+ osf1_reclen = OSF1_RECLEN(&idb, bdp->d_namlen);
+ if (reclen > len || resid < osf1_reclen) {
+ /* entry too big for buffer, so just stop */
+ outp++;
+ break;
+ }
+ /*
+ * Massage in place to make a OSF1-shaped dirent (otherwise
+ * we have to worry about touching user memory outside of
+ * the copyout() call).
+ */
+ idb.d_ino = (osf1_ino_t)bdp->d_fileno;
+ idb.d_reclen = (u_short)osf1_reclen;
+ idb.d_namlen = (u_short)bdp->d_namlen;
+ strlcpy(idb.d_name, bdp->d_name, sizeof(idb.d_name));
+ if ((error = copyout((void *)&idb, outp, osf1_reclen)))
+ goto out;
+ /* advance past this real entry */
+ inp += reclen;
+ /* advance output past OSF1-shaped entry */
+ outp += osf1_reclen;
+ resid -= osf1_reclen;
+ }
+
+ /* if we squished out the whole block, try again */
+ if (outp == (char *)SCARG(uap, buf))
+ goto again;
+ fp->f_offset = off; /* update the vnode offset */
+
+eof:
+ *retval = SCARG(uap, nbytes) - resid;
+out:
+ VOP_UNLOCK(vp, 0);
+ if (cookiebuf)
+ free(cookiebuf, M_TEMP);
+ free(buf, M_TEMP);
+out1:
+ fd_putfile(fd);
+ if (SCARG(uap, basep) != NULL)
+ error = copyout(&eofflag, SCARG(uap, basep), sizeof(long));
+ return error;
+}
+
/*
* Get file status; this version does not follow links.
*/
Index: sys/compat/osf1/syscalls.master
===================================================================
RCS file: /cvsroot/src/sys/compat/osf1/syscalls.master,v
retrieving revision 1.46
diff -u -p -r1.46 syscalls.master
--- sys/compat/osf1/syscalls.master 24 Nov 2008 00:25:30 -0000 1.46
+++ sys/compat/osf1/syscalls.master 1 Dec 2008 16:25:11 -0000
@@ -266,8 +266,8 @@
struct osf1_sigaction *osa); }
157 UNIMPL sigwaitprim
158 UNIMPL nfssvc
-159 NOARGS { int compat_43_sys_getdirentries(int fd, char *buf, \
- u_int count, long *basep); }
+159 STD { int osf1_sys_getdirentries(int fd, char *buf, \
+ int nbytes, long *basep); }
160 STD { int osf1_sys_statfs(const char *path, \
struct osf1_statfs *buf, int len); }
161 STD { int osf1_sys_fstatfs(int fd, \
Home |
Main Index |
Thread Index |
Old Index