Here is the new diff. I tried to replicate the work done in
other *BSD and added a syscall.

The new syscall is named getdents(), it's almost an exact copy of
getdirentries() without the last (problematic) parameter.

I extended dd_seek and dd_rewind fields in DIR struct to off_t and 
switched readdir() to getdents() and lseek(). 

libexec/ld.so portion is not complete, because I am scared of
touching machdep code of anything besides x86.

diff -ur /mnt/include/dirent.h src/include/dirent.h
--- /mnt/include/dirent.h       Tue Jun  5 22:11:48 2007
+++ src/include/dirent.h        Sun Oct 17 17:44:59 2010
@@ -46,7 +46,7 @@
 
 /*
  * The kernel defines the format of directory entries returned by 
- * the getdirentries(2) system call.
+ * the getdirentries(2) and getdents(2) system calls.
  */
 #include <sys/dirent.h>
 
@@ -67,8 +67,8 @@
        long    dd_size;        /* amount of data returned by getdirentries */
        char    *dd_buf;        /* data buffer */
        int     dd_len;         /* size of data buffer */
-       long    dd_seek;        /* magic cookie returned by getdirentries */
-       long    dd_rewind;      /* magic cookie for rewinding */
+       off_t   dd_seek;        /* magic cookie returned by getdirentries */
+       off_t   dd_rewind;      /* magic cookie for rewinding */
        int     dd_flags;       /* flags for readdir */
        struct _telldir *dd_td; /* telldir position recording */
        void    *dd_lock;       /* mutex to protect struct */
@@ -106,6 +106,7 @@
 int alphasort(const void *, const void *);
 int getdirentries(int, char *, int, long *)
                __attribute__ ((__bounded__(__string__,2,3)));
+int getdents(int, char *, int);
 #endif /* __BSD_VISIBLE */
 #if __XPG_VISIBLE
 long telldir(DIR *);
diff -ur /mnt/lib/libc/gen/readdir.c src/lib/libc/gen/readdir.c
--- /mnt/lib/libc/gen/readdir.c Wed Nov 18 10:43:22 2009
+++ src/lib/libc/gen/readdir.c  Sun Oct 17 17:50:51 2010
@@ -29,6 +29,7 @@
  */
 
 #include <dirent.h>
+#include <unistd.h>
 #include "thread_private.h"
 
 /*
@@ -44,8 +45,9 @@
                if (dirp->dd_loc >= dirp->dd_size)
                        dirp->dd_loc = 0;
                if (dirp->dd_loc == 0) {
-                       dirp->dd_size = getdirentries(dirp->dd_fd,
-                           dirp->dd_buf, dirp->dd_len, &dirp->dd_seek);
+                       dirp->dd_seek = lseek(dirp->dd_fd, 0, SEEK_CUR);
+                       dirp->dd_size = getdents(dirp->dd_fd,
+                           dirp->dd_buf, dirp->dd_len);
                        if (dirp->dd_size == 0)
                                return (0);
                        if (dirp->dd_size < 0)
diff -ur /mnt/lib/libc/gen/telldir.h src/lib/libc/gen/telldir.h
--- /mnt/lib/libc/gen/telldir.h Sat Oct 13 02:41:42 2007
+++ src/lib/libc/gen/telldir.h  Sun Oct 17 17:53:21 2010
@@ -38,12 +38,12 @@
 
 /*
  * One of these structures is malloced to describe the current directory
- * position each time telldir is called. It records the current magic
- * cookie returned by getdirentries and the offset within the buffer
+ * position each time telldir is called. It records the current position
+ * returned by lseek(2) and the offset within the buffer
  * associated with that return value.
  */
 struct ddloc {
-       long    loc_seek;       /* magic cookie returned by getdirentries */
+       off_t   loc_seek;       /* position returned by lseek(2) */
        long    loc_loc;        /* offset of entry in buffer */
 };
 
diff -ur /mnt/lib/libc/sys/Makefile.inc src/lib/libc/sys/Makefile.inc
--- /mnt/lib/libc/sys/Makefile.inc      Sat Jul  3 08:44:51 2010
+++ src/lib/libc/sys/Makefile.inc       Mon Oct 18 00:51:51 2010
@@ -42,7 +42,7 @@
        close.o closefrom.o connect.o dup.o dup2.o execve.o fchdir.o \
        fchflags.o fchmod.o fchown.o fcntl.o fhopen.o fhstat.o fhstatfs.o \
        flock.o fpathconf.o fstat.o \
-       fstatfs.o fsync.o futimes.o getdirentries.o getegid.o geteuid.o \
+       fstatfs.o fsync.o futimes.o getdirentries.o getdents.o getegid.o 
geteuid.o \
        getfh.o getfsstat.o getgid.o getgroups.o getitimer.o \
        getpeername.o \
        getpgid.o \
@@ -249,6 +249,7 @@
 MLINKS+=clock_gettime.2 clock_getres.2
 MLINKS+=execve.2 exect.2
 MLINKS+=fhopen.2 fhstat.2 fhopen.2 fhstatfs.2
+MLINKS+=getdirentries.2 getdents.2
 MLINKS+=getgid.2 getegid.2
 MLINKS+=getitimer.2 setitimer.2
 MLINKS+=getitimer.2 timeradd.3
diff -ur /mnt/lib/libc/sys/getdirentries.2 src/lib/libc/sys/getdirentries.2
--- /mnt/lib/libc/sys/getdirentries.2   Sun Oct 17 00:50:11 2010
+++ src/lib/libc/sys/getdirentries.2    Mon Oct 18 00:47:17 2010
@@ -34,15 +34,20 @@
 .Dt GETDIRENTRIES 2
 .Os
 .Sh NAME
-.Nm getdirentries
+.Nm getdirentries ,
+.Nm getdents
 .Nd "get directory entries in a filesystem independent format"
 .Sh SYNOPSIS
 .Fd #include <dirent.h>
 .Ft int
 .Fn getdirentries "int fd" "char *buf" "int nbytes" "long *basep"
+.Ft int
+.Fn getdents "int fd" "char *buf" "int nbytes"
 .Sh DESCRIPTION
 .Fn getdirentries
-reads directory entries from the directory
+and
+.Fn getdents
+read directory entries from the directory
 referenced by the file descriptor
 .Fa fd
 into the buffer pointed to by
@@ -179,6 +184,8 @@
 .Ed
 .Sh ERRORS
 .Fn getdirentries
+and
+.Fn getdents
 will fail if:
 .Bl -tag -width Er
 .It Bq Er EBADF
@@ -212,3 +219,7 @@
 .Fn getdirentries
 function first appeared in
 .Bx 4.4 .
+The
+.Fn getdents
+function first appeared in
+.Ox 4.8 .
diff -ur /mnt/libexec/ld.so/amd64/ldasm.S src/libexec/ld.so/amd64/ldasm.S
--- /mnt/libexec/ld.so/amd64/ldasm.S    Sun Oct 17 00:50:16 2010
+++ src/libexec/ld.so/amd64/ldasm.S     Mon Oct 18 00:55:05 2010
@@ -86,7 +86,7 @@
 DL_SYSCALL(write)
 DL_SYSCALL(close)
 DL_SYSCALL(issetugid)
-DL_SYSCALL(getdirentries)
+DL_SYSCALL(getdents)
 DL_SYSCALL(mprotect)
 DL_SYSCALL(munmap)
 DL_SYSCALL(gettimeofday)
diff -ur /mnt/libexec/ld.so/amd64/syscall.h src/libexec/ld.so/amd64/syscall.h
--- /mnt/libexec/ld.so/amd64/syscall.h  Sun Oct 17 00:50:16 2010
+++ src/libexec/ld.so/amd64/syscall.h   Mon Oct 18 00:54:37 2010
@@ -50,7 +50,7 @@
 int    _dl_stat(const char *, struct stat *);
 int    _dl_fstat(int, struct stat *);
 int    _dl_fcntl(int, int, ...);
-int    _dl_getdirentries(int, char*, int, long *);
+int    _dl_getdents(int, char*, int);
 int    _dl_sigprocmask(int, const sigset_t *, sigset_t *);
 int    _dl_sysctl(int *, u_int, void *, size_t *, void *, size_t);
 int    _dl_gettimeofday(struct timeval *tp, struct timezone *tzp);
diff -ur /mnt/libexec/ld.so/dir.c src/libexec/ld.so/dir.c
--- /mnt/libexec/ld.so/dir.c    Sun Oct 17 00:50:16 2010
+++ src/libexec/ld.so/dir.c     Sun Oct 17 19:46:39 2010
@@ -116,8 +116,9 @@
                        dirp->dd_loc = 0;
                }
                if (dirp->dd_loc == 0) {
-                       dirp->dd_size = _dl_getdirentries(dirp->dd_fd,
-                           dirp->dd_buf, dirp->dd_len, &dirp->dd_seek);
+                       dirp->dd_seek = _dl_lseek(dirp->dd_fd, 0, SEEK_CUR);
+                       dirp->dd_size = _dl_getdents(dirp->dd_fd,
+                           dirp->dd_buf, dirp->dd_len);
                        if (dirp->dd_size <= 0)
                                return (NULL);
                }
diff -ur /mnt/libexec/ld.so/i386/ldasm.S src/libexec/ld.so/i386/ldasm.S
--- /mnt/libexec/ld.so/i386/ldasm.S     Sun Oct 17 00:50:16 2010
+++ src/libexec/ld.so/i386/ldasm.S      Sun Oct 17 19:47:21 2010
@@ -119,7 +119,7 @@
 DL_SYSCALL(fcntl)
 DL_SYSCALL(gettimeofday)
 DL_SYSCALL2(sysctl,__sysctl)
-DL_SYSCALL(getdirentries)
+DL_SYSCALL(getdents)
 
 .L_cerr:
        /* error: result = -errno; - handled here. */
diff -ur /mnt/libexec/ld.so/i386/syscall.h src/libexec/ld.so/i386/syscall.h
--- /mnt/libexec/ld.so/i386/syscall.h   Sun Oct 17 00:50:16 2010
+++ src/libexec/ld.so/i386/syscall.h    Sun Oct 17 19:47:13 2010
@@ -50,7 +50,7 @@
 int    _dl_stat(const char *, struct stat *);
 int    _dl_fstat(int, struct stat *);
 int    _dl_fcntl(int, int, ...);
-int    _dl_getdirentries(int, char*, int, long *);
+int    _dl_getdents(int, char*, int);
 int    _dl_sigprocmask(int, const sigset_t *, sigset_t *);
 int    _dl_sysctl(int *, u_int, void *, size_t *, void *, size_t);
 int    _dl_gettimeofday(struct timeval *tp, struct timezone *tzp);
diff -ur /mnt/sys/kern/init_sysent.c src/sys/kern/init_sysent.c
--- /mnt/sys/kern/init_sysent.c Mon Sep 20 11:20:35 2010
+++ src/sys/kern/init_sysent.c  Sun Oct 17 17:42:08 2010
@@ -1,4 +1,4 @@
-/*     $OpenBSD: init_sysent.c,v 1.115 2010/09/20 07:20:35 deraadt Exp $       
*/
+/*     $OpenBSD$       */
 
 /*
  * System call switch table.
@@ -821,5 +821,7 @@
            sys_setrtable },                    /* 310 = setrtable */
        { 0, 0, 0,
            sys_getrtable },                    /* 311 = getrtable */
+       { 3, s(struct sys_getdents_args), 0,
+           sys_getdents },                     /* 312 = getdents */
 };
 
diff -ur /mnt/sys/kern/syscalls.c src/sys/kern/syscalls.c
--- /mnt/sys/kern/syscalls.c    Mon Sep 20 11:20:35 2010
+++ src/sys/kern/syscalls.c     Sun Oct 17 17:42:08 2010
@@ -1,4 +1,4 @@
-/*     $OpenBSD: syscalls.c,v 1.116 2010/09/20 07:20:35 deraadt Exp $  */
+/*     $OpenBSD$       */
 
 /*
  * System call names.
@@ -421,4 +421,5 @@
        "fhstatfs",                     /* 309 = fhstatfs */
        "setrtable",                    /* 310 = setrtable */
        "getrtable",                    /* 311 = getrtable */
+       "getdents",                     /* 312 = getdents */
 };
diff -ur /mnt/sys/kern/syscalls.master src/sys/kern/syscalls.master
--- /mnt/sys/kern/syscalls.master       Mon Sep 20 11:18:03 2010
+++ src/sys/kern/syscalls.master        Sun Oct 17 17:41:54 2010
@@ -607,3 +607,5 @@
                            struct statfs *buf); }
 310    STD             { int sys_setrtable(int rtableid); }
 311    STD             { int sys_getrtable(void); }
+312    STD             { int sys_getdents(int fd, char *buf, \
+                           int count); }
diff -ur /mnt/sys/kern/vfs_syscalls.c src/sys/kern/vfs_syscalls.c
--- /mnt/sys/kern/vfs_syscalls.c        Fri Jul  2 02:03:32 2010
+++ src/sys/kern/vfs_syscalls.c Mon Oct 18 00:17:40 2010
@@ -2287,6 +2287,7 @@
 
 /*
  * Read a block of directory entries in a file system independent format.
+ * Note: compatibility only.
  */
 int
 sys_getdirentries(struct proc *p, void *v, register_t *retval)
@@ -2338,6 +2339,61 @@
                goto bad;
        error = copyout(&loff, SCARG(uap, basep),
            sizeof(long));
+       *retval = SCARG(uap, count) - auio.uio_resid;
+bad:
+       FRELE(fp);
+       return (error);
+}
+
+/*
+ * Read a block of directory entries in a file system independent format.
+ */
+int
+sys_getdents(struct proc *p, void *v, register_t *retval)
+{
+       struct sys_getdirentries_args /* {
+               syscallarg(int) fd;
+               syscallarg(char *) buf;
+               syscallarg(int) count;
+       } */ *uap = v;
+       struct vnode *vp;
+       struct file *fp;
+       struct uio auio;
+       struct iovec aiov;
+       int error, eofflag;
+
+       if (SCARG(uap, count) < 0)
+               return EINVAL;
+       if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
+               return (error);
+       if ((fp->f_flag & FREAD) == 0) {
+               error = EBADF;
+               goto bad;
+       }
+       if (fp->f_offset < 0) {
+               error = EINVAL;
+               goto bad;
+       }
+       vp = (struct vnode *)fp->f_data;
+       if (vp->v_type != VDIR) {
+               error = EINVAL;
+               goto bad;
+       }
+       aiov.iov_base = SCARG(uap, buf);
+       aiov.iov_len = SCARG(uap, count);
+       auio.uio_iov = &aiov;
+       auio.uio_iovcnt = 1;
+       auio.uio_rw = UIO_READ;
+       auio.uio_segflg = UIO_USERSPACE;
+       auio.uio_procp = p;
+       auio.uio_resid = SCARG(uap, count);
+       vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
+       auio.uio_offset = fp->f_offset;
+       error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, 0, 0);
+       fp->f_offset = auio.uio_offset;
+       VOP_UNLOCK(vp, 0, p);
+       if (error)
+               goto bad;
        *retval = SCARG(uap, count) - auio.uio_resid;
 bad:
        FRELE(fp);
diff -ur /mnt/sys/sys/dirent.h src/sys/sys/dirent.h
--- /mnt/sys/sys/dirent.h       Thu Aug 17 16:40:11 2006
+++ src/sys/sys/dirent.h        Sun Oct 17 17:43:19 2010
@@ -39,7 +39,7 @@
 
 /*
  * The dirent structure defines the format of directory entries returned by
- * the getdirentries(2) system call.
+ * the getdirentries(2) and getdents(2) system calls.
  *
  * A directory entry has a struct dirent at the front of it, containing its
  * inode number, the length of the entry, and the length of the name
diff -ur /mnt/sys/sys/syscall.h src/sys/sys/syscall.h
--- /mnt/sys/sys/syscall.h      Mon Sep 20 11:20:35 2010
+++ src/sys/sys/syscall.h       Sun Oct 17 17:42:08 2010
@@ -1,4 +1,4 @@
-/*     $OpenBSD: syscall.h,v 1.115 2010/09/20 07:20:35 deraadt Exp $   */
+/*     $OpenBSD$       */
 
 /*
  * System call numbers.
@@ -687,4 +687,7 @@
 /* syscall: "getrtable" ret: "int" args: */
 #define        SYS_getrtable   311
 
-#define        SYS_MAXSYSCALL  312
+/* syscall: "getdents" ret: "int" args: "int" "char *" "int" */
+#define        SYS_getdents    312
+
+#define        SYS_MAXSYSCALL  313
diff -ur /mnt/sys/sys/syscallargs.h src/sys/sys/syscallargs.h
--- /mnt/sys/sys/syscallargs.h  Mon Sep 20 11:20:35 2010
+++ src/sys/sys/syscallargs.h   Sun Oct 17 17:42:08 2010
@@ -1,4 +1,4 @@
-/*     $OpenBSD: syscallargs.h,v 1.117 2010/09/20 07:20:35 deraadt Exp $       
*/
+/*     $OpenBSD$       */
 
 /*
  * System call argument lists.
@@ -1221,6 +1221,12 @@
        syscallarg(int) rtableid;
 };
 
+struct sys_getdents_args {
+       syscallarg(int) fd;
+       syscallarg(char *) buf;
+       syscallarg(int) count;
+};
+
 /*
  * System call prototypes.
  */
@@ -1533,3 +1539,4 @@
 int    sys_fhstatfs(struct proc *, void *, register_t *);
 int    sys_setrtable(struct proc *, void *, register_t *);
 int    sys_getrtable(struct proc *, void *, register_t *);
+int    sys_getdents(struct proc *, void *, register_t *);
diff -ur /mnt/usr.bin/cvs/file.c src/usr.bin/cvs/file.c
--- /mnt/usr.bin/cvs/file.c     Sun Oct 17 00:50:13 2010
+++ src/usr.bin/cvs/file.c      Sun Oct 17 20:25:08 2010
@@ -393,7 +393,6 @@
        int l, type;
        FILE *fp;
        int nbytes;
-       long base;
        size_t bufsize;
        struct stat st;
        struct dirent *dp;
@@ -472,7 +471,7 @@
        RB_INIT(&fl);
        RB_INIT(&dl);
 
-       while ((nbytes = getdirentries(cf->fd, buf, bufsize, &base)) > 0) {
+       while ((nbytes = getdents(cf->fd, buf, bufsize)) > 0) {
                ebuf = buf + nbytes;
                cp = buf;
 
diff -ur /mnt/usr.bin/cvs/update.c src/usr.bin/cvs/update.c
--- /mnt/usr.bin/cvs/update.c   Sun Oct 17 00:50:13 2010
+++ src/usr.bin/cvs/update.c    Sun Oct 17 20:25:00 2010
@@ -235,7 +235,6 @@
 void
 cvs_update_leavedir(struct cvs_file *cf)
 {
-       long base;
        int nbytes;
        int isempty;
        size_t bufsize;
@@ -272,7 +271,7 @@
        if (lseek(cf->fd, 0, SEEK_SET) == -1)
                fatal("cvs_update_leavedir: %s", strerror(errno));
 
-       while ((nbytes = getdirentries(cf->fd, buf, bufsize, &base)) > 0) {
+       while ((nbytes = getdents(cf->fd, buf, bufsize)) > 0) {
                ebuf = buf + nbytes;
                cp = buf;
 
diff -ur /mnt/usr.bin/diff/diffdir.c src/usr.bin/diff/diffdir.c
--- /mnt/usr.bin/diff/diffdir.c Sun Oct 17 00:50:14 2010
+++ src/usr.bin/diff/diffdir.c  Sun Oct 17 20:25:43 2010
@@ -167,7 +167,6 @@
 {
        char *buf, *ebuf, *cp;
        size_t bufsize, have, need;
-       long base;
        int fd, nbytes, entries;
        struct stat sb;
        struct dirent **dirlist, *dp;
@@ -201,7 +200,7 @@
                    ebuf = cp + (ebuf - buf);
                    buf = cp;
                }
-               nbytes = getdirentries(fd, ebuf, have, &base);
+               nbytes = getdents(fd, ebuf, have);
                if (nbytes == -1) {
                        warn("%s", path);
                        xfree(buf);



Comments?

-- 
Alexander Polakov | plhk.ru

Reply via email to