diff options
-rw-r--r-- | sys/compat/linux/linux_dirent.h | 10 | ||||
-rw-r--r-- | sys/compat/linux/linux_dummy.c | 3 | ||||
-rw-r--r-- | sys/compat/linux/linux_misc.c | 75 | ||||
-rw-r--r-- | sys/compat/linux/linux_syscall.h | 6 | ||||
-rw-r--r-- | sys/compat/linux/linux_syscallargs.h | 10 | ||||
-rw-r--r-- | sys/compat/linux/linux_syscalls.c | 4 | ||||
-rw-r--r-- | sys/compat/linux/linux_sysent.c | 6 | ||||
-rw-r--r-- | sys/compat/linux/linux_types.h | 4 |
8 files changed, 84 insertions, 34 deletions
diff --git a/sys/compat/linux/linux_dirent.h b/sys/compat/linux/linux_dirent.h index 5eeec661746..04e1aeaa97d 100644 --- a/sys/compat/linux/linux_dirent.h +++ b/sys/compat/linux/linux_dirent.h @@ -1,4 +1,4 @@ -/* $OpenBSD: linux_dirent.h,v 1.2 1996/04/17 05:23:43 mickey Exp $ */ +/* $OpenBSD: linux_dirent.h,v 1.3 2002/10/28 03:39:30 fgsch Exp $ */ /* $NetBSD: linux_dirent.h,v 1.3 1995/10/07 06:26:59 mycroft Exp $ */ /* @@ -44,6 +44,14 @@ struct linux_dirent { char d_name[LINUX_MAXNAMLEN + 1]; }; +struct linux_dirent64 { + linux_ino64_t d_ino; + linux_off64_t d_off; + u_short d_reclen; + u_char d_type; + char d_name[LINUX_MAXNAMLEN + 1]; +}; + #define LINUX_NAMEOFF(dp) ((char *)&(dp)->d_name - (char *)dp) #define LINUX_RECLEN(de,namlen) ALIGN((LINUX_NAMEOFF(de) + (namlen) + 1)) diff --git a/sys/compat/linux/linux_dummy.c b/sys/compat/linux/linux_dummy.c index 7a0e732d4d6..ac06b9a0451 100644 --- a/sys/compat/linux/linux_dummy.c +++ b/sys/compat/linux/linux_dummy.c @@ -1,4 +1,4 @@ -/* $OpenBSD: linux_dummy.c,v 1.8 2002/06/02 22:49:59 deraadt Exp $ */ +/* $OpenBSD: linux_dummy.c,v 1.9 2002/10/28 03:39:30 fgsch Exp $ */ /*- * Copyright (c) 1994-1995 Søren Schmidt @@ -121,4 +121,3 @@ DUMMY(setfsgid); /* #216 */ DUMMY(pivot_root); /* #217 */ DUMMY(mincore); /* #218 */ DUMMY(madvise); /* #219 */ -DUMMY(getdents64); /* #220 */ diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c index d392fc85dda..58b4910cbd5 100644 --- a/sys/compat/linux/linux_misc.c +++ b/sys/compat/linux/linux_misc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: linux_misc.c,v 1.45 2002/08/23 15:39:31 art Exp $ */ +/* $OpenBSD: linux_misc.c,v 1.46 2002/10/28 03:39:30 fgsch Exp $ */ /* $NetBSD: linux_misc.c,v 1.27 1996/05/20 01:59:21 fvdl Exp $ */ /* @@ -84,6 +84,7 @@ static void bsd_to_linux_statfs(struct statfs *, struct linux_statfs *); int linux_select1(struct proc *, register_t *, int, fd_set *, fd_set *, fd_set *, struct timeval *); +static int getdents_common(struct proc *, void *, register_t *, int); /* * The information on a terminated (or stopped) process needs @@ -940,6 +941,7 @@ struct linux_readdir_callback_args { caddr_t outp; int resid; int oldcall; + int is64bit; }; int @@ -948,6 +950,7 @@ linux_readdir_callback(arg, bdp, cookie) struct dirent *bdp; off_t cookie; { + struct linux_dirent64 idb64; struct linux_dirent idb; struct linux_readdir_callback_args *cb = arg; int linux_reclen; @@ -956,30 +959,37 @@ linux_readdir_callback(arg, bdp, cookie) if (cb->oldcall == 2) return (ENOMEM); - linux_reclen = LINUX_RECLEN(&idb, bdp->d_namlen); + linux_reclen = (cb->is64bit) ? + LINUX_RECLEN(&idb64, bdp->d_namlen) : + LINUX_RECLEN(&idb, bdp->d_namlen); + if (cb->resid < linux_reclen) return (ENOMEM); - /* - * Massage in place to make a Linux-shaped dirent (otherwise - * we have to worry about touching user memory outside of - * the copyout() call). - */ - idb.d_ino = (linux_ino_t)bdp->d_fileno; - - /* - * The old readdir() call misuses the offset and reclen fields. - */ - if (cb->oldcall) { - idb.d_off = (linux_off_t)linux_reclen; - idb.d_reclen = (u_short)bdp->d_namlen; + if (cb->is64bit) { + idb64.d_ino = (linux_ino64_t)bdp->d_fileno; + idb64.d_off = (linux_off64_t)cookie; + idb64.d_reclen = (u_short)linux_reclen; + idb64.d_type = bdp->d_type; + strlcpy(idb64.d_name, bdp->d_name, sizeof(idb64.d_name)); + error = copyout((caddr_t)&idb64, cb->outp, linux_reclen); } else { - idb.d_off = (linux_off_t)cookie; - idb.d_reclen = (u_short)linux_reclen; + idb.d_ino = (linux_ino_t)bdp->d_fileno; + if (cb->oldcall) { + /* + * The old readdir() call misuses the offset + * and reclen fields. + */ + idb.d_off = (linux_off_t)linux_reclen; + idb.d_reclen = (u_short)bdp->d_namlen; + } else { + idb.d_off = (linux_off_t)cookie; + idb.d_reclen = (u_short)linux_reclen; + } + strlcpy(idb.d_name, bdp->d_name, sizeof(idb.d_name)); + error = copyout((caddr_t)&idb, cb->outp, linux_reclen); } - - strlcpy(idb.d_name, bdp->d_name, sizeof(idb.d_name)); - if ((error = copyout((caddr_t)&idb, cb->outp, linux_reclen))) + if (error) return (error); /* advance output past Linux-shaped entry */ @@ -993,11 +1003,30 @@ linux_readdir_callback(arg, bdp, cookie) } int +linux_sys_getdents64(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + return getdents_common(p, v, retval, 1); +} + +int linux_sys_getdents(p, v, retval) struct proc *p; void *v; register_t *retval; { + return getdents_common(p, v, retval, 0); +} + +static int +getdents_common(p, v, retval, is64bit) + struct proc *p; + void *v; + register_t *retval; + int is64bit; +{ struct linux_sys_getdents_args /* { syscallarg(int) fd; syscallarg(void *) dirent; @@ -1012,6 +1041,11 @@ linux_sys_getdents(p, v, retval) return (error); if (nbytes == 1) { /* emulating old, broken behaviour */ + /* readdir(2) case. Always struct dirent. */ + if (is64bit) { + FRELE(fp); + return (EINVAL); + } nbytes = sizeof(struct linux_dirent); args.oldcall = 1; } else { @@ -1020,6 +1054,7 @@ linux_sys_getdents(p, v, retval) args.resid = nbytes; args.outp = (caddr_t)SCARG(uap, dirent); + args.is64bit = is64bit; if ((error = readdir_with_callback(fp, &fp->f_offset, nbytes, linux_readdir_callback, &args)) != 0) diff --git a/sys/compat/linux/linux_syscall.h b/sys/compat/linux/linux_syscall.h index a175e4f3528..fa2805a5755 100644 --- a/sys/compat/linux/linux_syscall.h +++ b/sys/compat/linux/linux_syscall.h @@ -1,10 +1,10 @@ -/* $OpenBSD: linux_syscall.h,v 1.35 2002/06/05 19:43:44 jasoni Exp $ */ +/* $OpenBSD: linux_syscall.h,v 1.36 2002/10/28 03:39:30 fgsch Exp $ */ /* * System call numbers. * * DO NOT EDIT-- this file is automatically generated. - * created from OpenBSD: syscalls.master,v 1.34 2002/06/05 19:43:25 jasoni Exp + * created from OpenBSD: syscalls.master,v 1.35 2002/10/28 03:35:53 fgsch Exp */ /* syscall: "syscall" ret: "int" args: */ @@ -676,7 +676,7 @@ /* syscall: "madvise" ret: "int" args: */ #define LINUX_SYS_madvise 219 -/* syscall: "getdents64" ret: "int" args: */ +/* syscall: "getdents64" ret: "int" args: "int" "void *" "unsigned" */ #define LINUX_SYS_getdents64 220 /* syscall: "fcntl64" ret: "int" args: "u_int" "u_int" "void *" */ diff --git a/sys/compat/linux/linux_syscallargs.h b/sys/compat/linux/linux_syscallargs.h index f1c17c1b1a9..67fbd53602e 100644 --- a/sys/compat/linux/linux_syscallargs.h +++ b/sys/compat/linux/linux_syscallargs.h @@ -1,10 +1,10 @@ -/* $OpenBSD: linux_syscallargs.h,v 1.37 2002/06/05 19:43:44 jasoni Exp $ */ +/* $OpenBSD: linux_syscallargs.h,v 1.38 2002/10/28 03:39:30 fgsch Exp $ */ /* * System call argument lists. * * DO NOT EDIT-- this file is automatically generated. - * created from OpenBSD: syscalls.master,v 1.34 2002/06/05 19:43:25 jasoni Exp + * created from OpenBSD: syscalls.master,v 1.35 2002/10/28 03:35:53 fgsch Exp */ #ifdef syscallarg @@ -517,6 +517,12 @@ struct linux_sys_setfsuid_args { syscallarg(uid_t) uid; }; +struct linux_sys_getdents64_args { + syscallarg(int) fd; + syscallarg(void *) dirent; + syscallarg(unsigned) count; +}; + struct linux_sys_fcntl64_args { syscallarg(u_int) fd; syscallarg(u_int) cmd; diff --git a/sys/compat/linux/linux_syscalls.c b/sys/compat/linux/linux_syscalls.c index 1cd5c1af95c..4c3143de7c5 100644 --- a/sys/compat/linux/linux_syscalls.c +++ b/sys/compat/linux/linux_syscalls.c @@ -1,10 +1,10 @@ -/* $OpenBSD: linux_syscalls.c,v 1.35 2002/06/05 19:43:44 jasoni Exp $ */ +/* $OpenBSD: linux_syscalls.c,v 1.36 2002/10/28 03:39:30 fgsch Exp $ */ /* * System call names. * * DO NOT EDIT-- this file is automatically generated. - * created from OpenBSD: syscalls.master,v 1.34 2002/06/05 19:43:25 jasoni Exp + * created from OpenBSD: syscalls.master,v 1.35 2002/10/28 03:35:53 fgsch Exp */ char *linux_syscallnames[] = { diff --git a/sys/compat/linux/linux_sysent.c b/sys/compat/linux/linux_sysent.c index 93c5b9b3b31..ecc28670251 100644 --- a/sys/compat/linux/linux_sysent.c +++ b/sys/compat/linux/linux_sysent.c @@ -1,10 +1,10 @@ -/* $OpenBSD: linux_sysent.c,v 1.36 2002/06/05 19:43:44 jasoni Exp $ */ +/* $OpenBSD: linux_sysent.c,v 1.37 2002/10/28 03:39:30 fgsch Exp $ */ /* * System call switch table. * * DO NOT EDIT-- this file is automatically generated. - * created from OpenBSD: syscalls.master,v 1.34 2002/06/05 19:43:25 jasoni Exp + * created from OpenBSD: syscalls.master,v 1.35 2002/10/28 03:35:53 fgsch Exp */ #include <sys/param.h> @@ -480,7 +480,7 @@ struct sysent linux_sysent[] = { linux_sys_mincore }, /* 218 = mincore */ { 0, 0, linux_sys_madvise }, /* 219 = madvise */ - { 0, 0, + { 3, s(struct linux_sys_getdents64_args), linux_sys_getdents64 }, /* 220 = getdents64 */ { 3, s(struct linux_sys_fcntl64_args), linux_sys_fcntl64 }, /* 221 = fcntl64 */ diff --git a/sys/compat/linux/linux_types.h b/sys/compat/linux/linux_types.h index 368ddc04fa7..d43783e3880 100644 --- a/sys/compat/linux/linux_types.h +++ b/sys/compat/linux/linux_types.h @@ -1,4 +1,4 @@ -/* $OpenBSD: linux_types.h,v 1.5 2002/02/04 20:04:52 provos Exp $ */ +/* $OpenBSD: linux_types.h,v 1.6 2002/10/28 03:39:30 fgsch Exp $ */ /* $NetBSD: linux_types.h,v 1.5 1996/05/20 01:59:28 fvdl Exp $ */ /* @@ -42,11 +42,13 @@ typedef struct { typedef unsigned short linux_uid_t; typedef unsigned short linux_gid_t; typedef unsigned short linux_dev_t; +typedef unsigned long long linux_ino64_t; typedef unsigned long linux_ino_t; typedef unsigned short linux_mode_t; typedef unsigned short linux_nlink_t; typedef long linux_time_t; typedef long linux_clock_t; +typedef long long linux_off64_t; typedef long linux_off_t; typedef u_int64_t linux_loff_t; typedef int linux_pid_t; |