Date: Fri, 17 Jun 2011 22:29:32 +0000 From: gk@FreeBSD.org To: svn-soc-all@FreeBSD.org Subject: socsvn commit: r223369 - in soc2011/gk/ino64-head/sys: compat/freebsd32 kern sys Message-ID: <20110617222932.68DD6106566B@hub.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: gk Date: Fri Jun 17 22:29:32 2011 New Revision: 223369 URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=223369 Log: Change dirent struct to use ino_t and add dir offset field; Add new syscalls Modified: soc2011/gk/ino64-head/sys/compat/freebsd32/freebsd32_misc.c soc2011/gk/ino64-head/sys/compat/freebsd32/syscalls.master soc2011/gk/ino64-head/sys/kern/syscalls.master soc2011/gk/ino64-head/sys/kern/vfs_syscalls.c soc2011/gk/ino64-head/sys/sys/dirent.h soc2011/gk/ino64-head/sys/sys/syscallsubr.h Modified: soc2011/gk/ino64-head/sys/compat/freebsd32/freebsd32_misc.c ============================================================================== --- soc2011/gk/ino64-head/sys/compat/freebsd32/freebsd32_misc.c Fri Jun 17 22:29:18 2011 (r223368) +++ soc2011/gk/ino64-head/sys/compat/freebsd32/freebsd32_misc.c Fri Jun 17 22:29:32 2011 (r223369) @@ -1478,6 +1478,42 @@ } #endif +#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \ + defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7) || \ + defined(COMPAT_FREEBSD8) +int +freebsd8_freebsd32_getdirentries(struct thread *td, + struct freebsd8_freebsd32_getdirentries_args *uap) +{ + long base; + int32_t base32; + int error; + + error = freebsd8_kern_getdirentries(td, uap->fd, uap->buf, uap->count, + &base, NULL); + if (error) + return (error); + if (uap->basep != NULL) { + base32 = base; + error = copyout(&base32, uap->basep, sizeof(int32_t)); + } + return (error); +} + +int +freebsd8_freebsd32_getdents(struct thread *td, + struct freebsd8_freebsd32_getdents_args *uap) +{ + struct freebsd8_freebsd32_getdirentries_args ap; + + ap.fd = uap->fd; + ap.buf = uap->buf; + ap.count = uap->count; + ap.basep = NULL; + return (freebsd8_freebsd32_getdirentries(td, &ap)); +} +#endif /* COMPAT_FREEBSD8 */ + int freebsd32_getdirentries(struct thread *td, struct freebsd32_getdirentries_args *uap) Modified: soc2011/gk/ino64-head/sys/compat/freebsd32/syscalls.master ============================================================================== --- soc2011/gk/ino64-head/sys/compat/freebsd32/syscalls.master Fri Jun 17 22:29:18 2011 (r223368) +++ soc2011/gk/ino64-head/sys/compat/freebsd32/syscalls.master Fri Jun 17 22:29:32 2011 (r223369) @@ -359,7 +359,7 @@ 195 AUE_SETRLIMIT NOPROTO { int setrlimit(u_int which, \ struct rlimit *rlp); } setrlimit \ __setrlimit_args int -196 AUE_GETDIRENTRIES STD { int freebsd32_getdirentries(int fd, \ +196 AUE_GETDIRENTRIES COMPAT8 { int freebsd32_getdirentries(int fd, \ char *buf, u_int count, int32_t *basep); } 197 AUE_MMAP COMPAT6 { caddr_t freebsd32_mmap(caddr_t addr, \ size_t len, int prot, int flags, int fd, \ @@ -485,7 +485,7 @@ 269 AUE_NULL UNIMPL nosys 270 AUE_NULL UNIMPL nosys 271 AUE_NULL UNIMPL nosys -272 AUE_O_GETDENTS NOPROTO { int getdents(int fd, char *buf, \ +272 AUE_O_GETDENTS COMPAT8 { int freebsd32_getdents(int fd, char *buf, \ size_t count); } 273 AUE_NULL UNIMPL nosys 274 AUE_LCHMOD NOPROTO { int lchmod(char *path, mode_t mode); } @@ -1002,3 +1002,7 @@ struct stat32 *sb); } 536 AUE_FSTATAT STD { int freebsd32_fstatat(int fd, char *path, \ struct stat32 *buf, int flag); } +537 AUE_O_GETDENTS NOPROTO { int getdents(int fd, char *buf, \ + size_t count); } +538 AUE_GETDIRENTRIES STD { int freebsd32_getdirentries(int fd, \ + char *buf, u_int count, int32_t *basep); } Modified: soc2011/gk/ino64-head/sys/kern/syscalls.master ============================================================================== --- soc2011/gk/ino64-head/sys/kern/syscalls.master Fri Jun 17 22:29:18 2011 (r223368) +++ soc2011/gk/ino64-head/sys/kern/syscalls.master Fri Jun 17 22:29:32 2011 (r223369) @@ -379,7 +379,7 @@ 195 AUE_SETRLIMIT STD { int setrlimit(u_int which, \ struct rlimit *rlp); } setrlimit \ __setrlimit_args int -196 AUE_GETDIRENTRIES STD { int getdirentries(int fd, char *buf, \ +196 AUE_GETDIRENTRIES COMPAT8 { int getdirentries(int fd, char *buf, \ u_int count, long *basep); } 197 AUE_MMAP STD { caddr_t freebsd6_mmap(caddr_t addr, \ size_t len, int prot, int flags, int fd, \ @@ -496,7 +496,7 @@ 269 AUE_NULL UNIMPL nosys 270 AUE_NULL UNIMPL nosys 271 AUE_NULL UNIMPL nosys -272 AUE_O_GETDENTS STD { int getdents(int fd, char *buf, \ +272 AUE_O_GETDENTS COMPAT8 { int getdents(int fd, char *buf, \ size_t count); } 273 AUE_NULL UNIMPL nosys 274 AUE_LCHMOD STD { int lchmod(char *path, mode_t mode); } @@ -958,5 +958,9 @@ struct stat *sb); } 536 AUE_FSTATAT STD { int fstatat(int fd, char *path, \ struct stat *buf, int flag); } +537 AUE_O_GETDENTS STD { int getdents(int fd, char *buf, \ + size_t count); } +538 AUE_GETDIRENTRIES STD { int getdirentries(int fd, char *buf, \ + u_int count, long *basep); } ; Please copy any additions and changes to the following compatability tables: ; sys/compat/freebsd32/syscalls.master Modified: soc2011/gk/ino64-head/sys/kern/vfs_syscalls.c ============================================================================== --- soc2011/gk/ino64-head/sys/kern/vfs_syscalls.c Fri Jun 17 22:29:18 2011 (r223368) +++ soc2011/gk/ino64-head/sys/kern/vfs_syscalls.c Fri Jun 17 22:29:32 2011 (r223369) @@ -4006,7 +4006,85 @@ return (error); } +#if defined(COMPAT_43) || defined(COMPAT_FREEBSD4) || \ + defined(COMPAT_FREEBSD5) || defined(COMPAT_FREEBSD6) || \ + defined(COMPAT_FREEBSD7) || defined(COMPAT_FREEBSD8) +int +freebsd8_kern_getdirentries(struct thread *td, int fd, char *ubuf, u_int count, + long *basep, void (*func)(struct freebsd8_dirent *)) +{ + struct freebsd8_dirent dstdp; + struct dirent *dp, *edp; + char *dirbuf; + ssize_t resid, ucount; + int error; + + /* XXX arbitrary sanity limit on `count'. */ + count = min(count, 64 * 1024); + + dirbuf = malloc(count, M_TEMP, M_WAITOK); + + error = kern_getdirentries(td, fd, dirbuf, count, basep, &resid, + UIO_SYSSPACE); + if (error != 0) + goto done; + + ucount = 0; + for (dp = (struct dirent *)dirbuf, + edp = (struct dirent *)&dirbuf[count - resid]; + ucount < count && dp < edp; ) { + if (dp->d_reclen == 0) + break; + if (dp->d_namlen > sizeof(dstdp.d_name) - 1) + continue; + dstdp.d_type = dp->d_type; + dstdp.d_namlen = dp->d_namlen; + dstdp.d_fileno = dp->d_fileno; /* truncate */ + dstdp.d_reclen = sizeof(dstdp) - sizeof(dstdp.d_name) + + ((dp->d_namlen + 1 + 3) &~ 3); + bcopy(dp->d_name, dstdp.d_name, dstdp.d_namlen); + bzero(dstdp.d_name + dstdp.d_namlen, + dstdp.d_reclen - offsetof(struct freebsd8_dirent, d_name) - + dstdp.d_namlen); + MPASS(dstdp.d_reclen <= dp->d_reclen); + MPASS(ucount + dstdp.d_reclen <= count); + if (func != NULL) + func(&dstdp); + error = copyout(&dstdp, ubuf + ucount, dstdp.d_reclen); + if (error != 0) + break; + dp = (struct dirent *)((char *)dp + dp->d_reclen); + ucount += dstdp.d_reclen; + } + +done: + free(dirbuf, M_TEMP); + if (error == 0) + td->td_retval[0] = ucount; + return (error); +} +#endif /* COMPAT */ + #ifdef COMPAT_43 +static void +ogetdirentries_cvt(struct freebsd8_dirent *dp) +{ +#if (BYTE_ORDER == LITTLE_ENDIAN) + /* + * The expected low byte of dp->d_namlen is our dp->d_type. + * The high MBZ byte of dp->d_namlen is our dp->d_namlen. + */ + dp->d_type = dp->d_namlen; + dp->d_namlen = 0; +#else + /* + * The dp->d_type is the high byte of the expected dp->d_namlen, + * so must be zero'ed. + */ + dp->d_type = 0; +#endif +} + /* * Read a block of directory entries in a filesystem independent format. */ @@ -4034,131 +4112,69 @@ kern_ogetdirentries(struct thread *td, struct ogetdirentries_args *uap, long *ploff) { - struct vnode *vp; - struct file *fp; - struct uio auio, kuio; - struct iovec aiov, kiov; - struct dirent *dp, *edp; - caddr_t dirbuf; - int error, eofflag, readcnt, vfslocked; - long loff; + long base; + int error; /* XXX arbitrary sanity limit on `count'. */ if (uap->count > 64 * 1024) return (EINVAL); - if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0) - return (error); - if ((fp->f_flag & FREAD) == 0) { - fdrop(fp, td); - return (EBADF); - } - vp = fp->f_vnode; -unionread: - vfslocked = VFS_LOCK_GIANT(vp->v_mount); - if (vp->v_type != VDIR) { - VFS_UNLOCK_GIANT(vfslocked); - fdrop(fp, td); - return (EINVAL); - } - aiov.iov_base = uap->buf; - aiov.iov_len = uap->count; - auio.uio_iov = &aiov; - auio.uio_iovcnt = 1; - auio.uio_rw = UIO_READ; - auio.uio_segflg = UIO_USERSPACE; - auio.uio_td = td; - auio.uio_resid = uap->count; - vn_lock(vp, LK_SHARED | LK_RETRY); - loff = auio.uio_offset = fp->f_offset; -#ifdef MAC - error = mac_vnode_check_readdir(td->td_ucred, vp); - if (error) { - VOP_UNLOCK(vp, 0); - VFS_UNLOCK_GIANT(vfslocked); - fdrop(fp, td); - return (error); - } -#endif -# if (BYTE_ORDER != LITTLE_ENDIAN) - if (vp->v_mount->mnt_maxsymlinklen <= 0) { - error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, - NULL, NULL); - fp->f_offset = auio.uio_offset; - } else -# endif - { - kuio = auio; - kuio.uio_iov = &kiov; - kuio.uio_segflg = UIO_SYSSPACE; - kiov.iov_len = uap->count; - dirbuf = malloc(uap->count, M_TEMP, M_WAITOK); - kiov.iov_base = dirbuf; - error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag, - NULL, NULL); - fp->f_offset = kuio.uio_offset; - if (error == 0) { - readcnt = uap->count - kuio.uio_resid; - edp = (struct dirent *)&dirbuf[readcnt]; - for (dp = (struct dirent *)dirbuf; dp < edp; ) { -# if (BYTE_ORDER == LITTLE_ENDIAN) - /* - * The expected low byte of - * dp->d_namlen is our dp->d_type. - * The high MBZ byte of dp->d_namlen - * is our dp->d_namlen. - */ - dp->d_type = dp->d_namlen; - dp->d_namlen = 0; -# else - /* - * The dp->d_type is the high byte - * of the expected dp->d_namlen, - * so must be zero'ed. - */ - dp->d_type = 0; -# endif - if (dp->d_reclen > 0) { - dp = (struct dirent *) - ((char *)dp + dp->d_reclen); - } else { - error = EIO; - break; - } - } - if (dp >= edp) - error = uiomove(dirbuf, readcnt, &auio); - } - free(dirbuf, M_TEMP); - } - if (error) { - VOP_UNLOCK(vp, 0); - VFS_UNLOCK_GIANT(vfslocked); - fdrop(fp, td); - return (error); - } - if (uap->count == auio.uio_resid && - (vp->v_vflag & VV_ROOT) && - (vp->v_mount->mnt_flag & MNT_UNION)) { - struct vnode *tvp = vp; - vp = vp->v_mount->mnt_vnodecovered; - VREF(vp); - fp->f_vnode = vp; - fp->f_data = vp; - fp->f_offset = 0; - vput(tvp); - VFS_UNLOCK_GIANT(vfslocked); - goto unionread; - } - VOP_UNLOCK(vp, 0); - VFS_UNLOCK_GIANT(vfslocked); - fdrop(fp, td); - td->td_retval[0] = uap->count - auio.uio_resid; - if (error == 0) - *ploff = loff; + + error = freebsd8_kern_getdirentries(td, uap->fd, uap->buf, uap->count, + &base, ogetdirentries_cvt); + + if (error == 0 && uap->basep != NULL) + error = copyout(&base, uap->basep, sizeof(long)); + return (error); } #endif /* COMPAT_43 */ +#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \ + defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7) || \ + defined(COMPAT_FREEBSD8) +#ifndef _SYS_SYSPROTO_H_ +struct freebsd8_getdirentries_args { + int fd; + char *buf; + u_int count; + long *basep; +}; +#endif +int +freebsd8_getdirentries(struct thread *td, + struct freebsd8_getdirentries_args *uap) +{ + long base; + int error; + + error = freebsd8_kern_getdirentries(td, uap->fd, uap->buf, uap->count, + &base, NULL); + + if (error == 0 && uap->basep != NULL) + error = copyout(&base, uap->basep, sizeof(long)); + return (error); +} + +#ifndef _SYS_SYSPROTO_H_ +struct freebsd8_getdents_args { + int fd; + char *buf; + size_t count; +}; +#endif +int +freebsd8_getdents(struct thread *td, struct freebsd8_getdents_args *uap) +{ + struct freebsd8_getdirentries_args ap; + + ap.fd = uap->fd; + ap.buf = uap->buf; + ap.count = uap->count; + ap.basep = NULL; + return (freebsd8_getdirentries(td, &ap)); +} +#endif /* COMPAT_FREEBSD8 */ + /* * Read a block of directory entries in a filesystem independent format. */ Modified: soc2011/gk/ino64-head/sys/sys/dirent.h ============================================================================== --- soc2011/gk/ino64-head/sys/sys/dirent.h Fri Jun 17 22:29:18 2011 (r223368) +++ soc2011/gk/ino64-head/sys/sys/dirent.h Fri Jun 17 22:29:32 2011 (r223369) @@ -36,6 +36,16 @@ #include <sys/cdefs.h> #include <sys/_types.h> +#ifndef _INO_T_DECLARED +typedef __ino_t ino_t; +#define _INO_T_DECLARED +#endif + +#ifndef _OFF_T_DECLARED +typedef __off_t off_t; +#define _OFF_T_DECLARED +#endif + /* * The dirent structure defines the format of directory entries returned by * the getdirentries(2) system call. @@ -48,10 +58,13 @@ */ struct dirent { - __uint32_t d_fileno; /* file number of entry */ + ino_t d_fileno; /* file number of entry */ + off_t d_off__unused; /* directory offset of entry */ __uint16_t d_reclen; /* length of this record */ + __uint16_t d_namlen; /* length of string in d_name */ __uint8_t d_type; /* file type, see below */ - __uint8_t d_namlen; /* length of string in d_name */ + __uint8_t d_unused1; + __uint16_t d_unused2; #if __BSD_VISIBLE #define MAXNAMLEN 255 char d_name[MAXNAMLEN + 1]; /* name must be no longer than this */ @@ -61,6 +74,14 @@ }; #if __BSD_VISIBLE +struct freebsd8_dirent { + __uint32_t d_fileno; /* file number of entry */ + __uint16_t d_reclen; /* length of this record */ + __uint8_t d_type; /* file type, see below */ + __uint8_t d_namlen; /* length of string in d_name */ + char d_name[255 + 1]; /* name must be no longer than this */ +}; + /* * File types */ Modified: soc2011/gk/ino64-head/sys/sys/syscallsubr.h ============================================================================== --- soc2011/gk/ino64-head/sys/sys/syscallsubr.h Fri Jun 17 22:29:18 2011 (r223368) +++ soc2011/gk/ino64-head/sys/sys/syscallsubr.h Fri Jun 17 22:29:32 2011 (r223369) @@ -238,4 +238,9 @@ #define KSA_OSIGSET 0x0001 /* uses osigact_t */ #define KSA_FREEBSD4 0x0002 /* uses ucontext4 */ +struct freebsd8_dirent; + +int freebsd8_kern_getdirentries(struct thread *td, int fd, char *ubuf, u_int + count, long *basep, void (*func)(struct freebsd8_dirent *)); + #endif /* !_SYS_SYSCALLSUBR_H_ */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20110617222932.68DD6106566B>