From owner-svn-src-all@FreeBSD.ORG Sat May 26 12:21:46 2012 Return-Path: Delivered-To: svn-src-all@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 05F041065670; Sat, 26 May 2012 12:21:46 +0000 (UTC) (envelope-from brde@optusnet.com.au) Received: from fallbackmx10.syd.optusnet.com.au (fallbackmx10.syd.optusnet.com.au [211.29.132.251]) by mx1.freebsd.org (Postfix) with ESMTP id 204FF8FC16; Sat, 26 May 2012 12:21:44 +0000 (UTC) Received: from mail01.syd.optusnet.com.au (mail01.syd.optusnet.com.au [211.29.132.182]) by fallbackmx10.syd.optusnet.com.au (8.13.1/8.13.1) with ESMTP id q4QCLbUw029522; Sat, 26 May 2012 22:21:37 +1000 Received: from c122-106-171-232.carlnfd1.nsw.optusnet.com.au (c122-106-171-232.carlnfd1.nsw.optusnet.com.au [122.106.171.232]) by mail01.syd.optusnet.com.au (8.13.1/8.13.1) with ESMTP id q4QCLQ6a013722 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Sat, 26 May 2012 22:21:28 +1000 Date: Sat, 26 May 2012 22:21:25 +1000 (EST) From: Bruce Evans X-X-Sender: bde@besplex.bde.org To: Ed Schouten In-Reply-To: <201205252150.q4PLomFk035064@svn.freebsd.org> Message-ID: <20120526173233.A885@besplex.bde.org> References: <201205252150.q4PLomFk035064@svn.freebsd.org> MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII; format=flowed Cc: svn-src-head@FreeBSD.org, svn-src-all@FreeBSD.org, src-committers@FreeBSD.org, kib@FreeBSD.org Subject: Re: svn commit: r236026 - in head/sys: amd64/linux32 compat/freebsd32 kern X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 26 May 2012 12:21:46 -0000 On Fri, 25 May 2012, Ed Schouten wrote: > Log: > Remove use of non-ISO-C integer types from system call tables. > > These files already use ISO-C-style integer types, so make them less > inconsistent by preferring the standard types. These should actually be Linux types l_foo_t. ISO-C-style integer types seem to have only been used for a couple of uintptr_t's, and these uses are more than just style bugs on amd64 since uintptr_t is for the host (64 bits on amd64) while the target uintptr_t is only 32 bits. There are also a few misuses of the abominable caddr_t instead of l_caddr_t, so syscalls that don't even take a caddr_t. Otherwise, Linux types are used a lot to avoid size mismatches. > Modified: head/sys/amd64/linux32/syscalls.master > ============================================================================== > --- head/sys/amd64/linux32/syscalls.master Fri May 25 21:12:24 2012 (r236025) > +++ head/sys/amd64/linux32/syscalls.master Fri May 25 21:50:48 2012 (r236026) > @@ -54,8 +54,8 @@ > l_int mode); } > 9 AUE_LINK STD { int linux_link(char *path, char *to); } > 10 AUE_UNLINK STD { int linux_unlink(char *path); } > -11 AUE_EXECVE STD { int linux_execve(char *path, u_int32_t *argp, \ > - u_int32_t *envp); } > +11 AUE_EXECVE STD { int linux_execve(char *path, uint32_t *argp, \ > + uint32_t *envp); } argp and envp aren't uintany_t * in either Linux or FreeBSD. They start as "char * const *". There is no Linux type for an indirect "char *", and one was hacked up here by pretending that "char *" is u_int32_t (it is actually just 32 bits). Using l_caddr_t seems to be the best hack available (since by abusing l_caddr_t, we know that it is actually char *). The `const' in the type for argp and envp is further from being handled correctly. Most or all syscall.master's just type-pun it away. Similarly for "const char *path". All the non-indirect "char *"s for pathnames and other things seem to be completely wrong on amd64 too. These pointers start as 32 bits, and it takes more than a bad type pun to turn then into kernel 64-bit pointers. The magic for this seems to be: - all args are converted to 64 bits (by zero-extension?) at a low level - the args struct for a pathname is [left padding]; char *; [right padding]; Since the char * is misdeclared, the explicit padding is null, but the layout of the args struct is correct because the wrong arg type in it supplies equivalent padding (extra 32 bits on the right). - the "char *" in the args struct is not actually a char *, and is unusable directly in the kernel. However, it is only used in copyin() and copyout(), where it becomes a user address and works correctly. (An older bug in this that the user address for copy*() is declared as "void *". "void *" means a kernel pointer. The type of a user address should be more like vm_offset_t, but even that needs logical translation for linux32). The same mechanism presumably avoids problems when raw caddr_t is used instead of l_caddr_t, and when uintptr_t is used instead of l_uintptr_t. > 12 AUE_CHDIR STD { int linux_chdir(char *path); } > 13 AUE_NULL STD { int linux_time(l_time_t *tm); } Example of a correct use of a linux type. Again, the first-level pointer is handled by the above magic, but for the second level we need an l_foo_t to describe its size correctly. > 14 AUE_MKNOD STD { int linux_mknod(char *path, l_int mode, \ Broken except in the K&R case, but amd64 is too new to pretend to support K&R. Bug for bug compatible with mknod() and some other syscalls in kern/syscalls.master. mknod() takes an arg of type mode_t, not one of type int. l_mode_t exists so that the above can be declared correctly, and is already used for linux_chmod() and linux_chmodat(). OTOH, int for the mode arg is correct for open(), since open() is variadic at a level before the syscall, so its mode_t arg gets promoted to int. Similarly, if mknod() is compiled by a K&R compiler, or by a STDC compiler with no prototype in scope, then its mode_t arg gets promoted to int (but for the STDC case, the behaviour is then undefined once mknod() is reached). Normally this doesn't cause any problems, but it is easy to declare things correctly. > Modified: head/sys/compat/freebsd32/syscalls.master > ============================================================================== > --- head/sys/compat/freebsd32/syscalls.master Fri May 25 21:12:24 2012 (r236025) > +++ head/sys/compat/freebsd32/syscalls.master Fri May 25 21:50:48 2012 (r236026) > @@ -104,9 +104,9 @@ > int flags); } > 28 AUE_SENDMSG STD { int freebsd32_sendmsg(int s, struct msghdr32 *msg, \ > int flags); } > -29 AUE_RECVFROM STD { int freebsd32_recvfrom(int s, u_int32_t buf, \ > - u_int32_t len, int flags, u_int32_t from, \ > - u_int32_t fromlenaddr); } > +29 AUE_RECVFROM STD { int freebsd32_recvfrom(int s, uint32_t buf, \ > + uint32_t len, int flags, uint32_t from, \ > + uint32_t fromlenaddr); } Oops, I didn't looke at this file when I said that "ISO-C-style integer types seem to have only been used for a couple of uintptr_t's". This file is independent of Linux, so it can't use l_foo. It hard-codes 32 instead, starting with the directory name. Still, all of the types in the above are fairly bogus and hard to understand: - "int" for `s' and `flags' depends on ints being 32 bits - "struct msghdr32 *msg" depends on magic to translate first-level target 32-bit pointers to host N-bit pointers - uint32_t for `buf' and `from' is for pointers too. Now the magic for first-level pointers is not depended on - uint32_t for lengths is for size_t's. This is reasonable but would be clearer if spelled as size32_t (corresponding to l_size_t). > 30 AUE_ACCEPT NOPROTO { int accept(int s, caddr_t name, \ > int *anamelen); } As above for "int s". The use of caddr_t is more nonsense than usual. accept()'s second arg is not a caddr_t, but is "struct sockaddr * restrict". We depend first on type punning this to caddr_t, then to caddr_t actually being "char *", then on "char *" being a pointer, then on the usual magic for first-level pointers. kern/syscalls.master has the same caddr_t for the MCPT_NOA case of accept(), but not for the MSTD case. Perhaps userland accept() once actually took a caddr_t arg, but hopefully Linux is too new to have ever done that, and even compat cruft in FreeeBSD is too new to need that. > 31 AUE_GETPEERNAME NOPROTO { int getpeername(int fdes, caddr_t asa, \ Similarly. For getpeername(), the compat cruft in kern/syscalls.master is more clearly typed as MCOMPAT. > @@ -152,7 +152,7 @@ > 58 AUE_READLINK NOPROTO { ssize_t readlink(char *path, char *buf, \ > size_t count); } All uses of basic C types and POSIX types are wronger than uses of fixed-width types. Here the size_t is not translated to uint32_t as above. This presumably works due to essentially the same magic as for first-level pointers, up to the copyout step: the 32-bit size_t gets extended to an N-bit one (where N is 32 or 64 on supported arches). Zero extension of it works right for size_t, and there is no further magic corresponding to the copy*() step. The magic is very convenient. It should probably be explicitly depended on for all first-level pointers. For size_t's it should be depended on in no cases or all cases. > 59 AUE_EXECVE STD { int freebsd32_execve(char *fname, \ > - u_int32_t *argv, u_int32_t *envv); } > + uint32_t *argv, uint32_t *envv); } Usual hack for second-level pointers. > 60 AUE_UMASK NOPROTO { int umask(int newmask); } umask \ > umask_args int Usual bug for mode_t. > 61 AUE_CHROOT NOPROTO { int chroot(char *path); } > @@ -325,10 +325,10 @@ > 172 AUE_NULL UNIMPL nosys > 173 AUE_PREAD COMPAT6 { ssize_t freebsd32_pread(int fd, void *buf, \ > size_t nbyte, int pad, \ > - u_int32_t offset1, u_int32_t offset2); } > + uint32_t offset1, uint32_t offset2); } More confusing than usual. The size_t is translated by magic. Then there is bogus historical padding to be compatible with old mistakes in this area. Then there are 2 64-bit offsets (off_t's in the API) which are split because the translation code only understands 32-bit args. > [... stuff in which the largest obvious bugs are untranslated size_t's] > 481 AUE_KILL NOPROTO { int thr_kill2(pid_t pid, long id, int sig); } Untranslated pid_t depends on pid_t being no larger than int. Untranslated long completely breaks this. > 482 AUE_SHMOPEN NOPROTO { int shm_open(const char *path, int flags, \ > @@ -892,25 +892,25 @@ > #ifdef PAD64_REQUIRED > 485 AUE_NULL STD { int freebsd32_cpuset_setid(cpuwhich_t which, \ > int pad, \ > - u_int32_t id1, u_int32_t id2, \ > + uint32_t id1, uint32_t id2, \ > cpusetid_t setid); } Untranslated cpusetid_t. It works since it is int. > #else > 485 AUE_NULL STD { int freebsd32_cpuset_setid(cpuwhich_t which, \ > - u_int32_t id1, u_int32_t id2, \ > + uint32_t id1, uint32_t id2, \ > cpusetid_t setid); } > #endif > 486 AUE_NULL STD { int freebsd32_cpuset_getid(cpulevel_t level, \ > cpuwhich_t which, \ > - u_int32_t id1, u_int32_t id2, \ > + uint32_t id1, uint32_t id2, \ > cpusetid_t *setid); } This and later have several more cpsetid_t's. Also cpuwhich_t's. id_t's are translated since they are 64 bits. This is painful. All types that are documented to be represented by id_t are only 32 bits, and id_t is wrong for representing 64-bit unsigned types since it is signed. The above has type puns to represent the signed 64-bit int in 2 uint32_t's. A pid of -1 would become pid_t -1, then id_t -1, then 0xffffffff, 0xffffffff. Signed off_t also requires type puns to represent in 2 uint32_t's. > ... > @@ -920,7 +920,7 @@ > 491 AUE_FCHOWNAT NOPROTO { int fchownat(int fd, char *path, uid_t uid, \ > gid_t gid, int flag); } Untranslated foo_t's. > @@ -959,9 +959,9 @@ > 512 AUE_SHMCTL NOSTD { int freebsd32_shmctl(int shmid, int cmd, \ > struct shmid_ds32 *buf); } > 513 AUE_LPATHCONF NOPROTO { int lpathconf(char *path, int name); } > -514 AUE_CAP_NEW NOPROTO { int cap_new(int fd, u_int64_t rights); } > +514 AUE_CAP_NEW NOPROTO { int cap_new(int fd, uint64_t rights); } Broken, assuming that all the other spittings into 2 uint32_t's are needed. > 515 AUE_CAP_GETRIGHTS NOPROTO { int cap_getrights(int fd, \ > - u_int64_t *rightsp); } > + uint64_t *rightsp); } Now the uint64_t is indirect, so it pronbably works. > Modified: head/sys/kern/syscalls.master > ============================================================================== > --- head/sys/kern/syscalls.master Fri May 25 21:12:24 2012 (r236025) > +++ head/sys/kern/syscalls.master Fri May 25 21:50:48 2012 (r236026) I didn't think of uint*N_t in this at first either. > @@ -916,9 +916,9 @@ > 512 AUE_SHMCTL NOSTD { int shmctl(int shmid, int cmd, \ > struct shmid_ds *buf); } > 513 AUE_LPATHCONF STD { int lpathconf(char *path, int name); } > -514 AUE_CAP_NEW STD { int cap_new(int fd, u_int64_t rights); } > +514 AUE_CAP_NEW STD { int cap_new(int fd, uint64_t rights); } > 515 AUE_CAP_GETRIGHTS STD { int cap_getrights(int fd, \ > - u_int64_t *rightsp); } > + uint64_t *rightsp); } > 516 AUE_CAP_ENTER STD { int cap_enter(void); } > 517 AUE_CAP_GETMODE STD { int cap_getmode(u_int *modep); } > 518 AUE_PDFORK STD { int pdfork(int *fdp, int flags); } In fact, this file has only 3 uint*N_t's. This shows that these 3 are all API design bugs no matter how they are spelled. All the very old syscalls use basic C types. All the not so old ones use a STDC or POSIX typedefed type, with the typedef specific to the context. The 3 exceptions new ones that hard-code a fixed width are the above 2 CAP ones and sctp_peeloff(), which uses "uint32_t name". These bugs are easiest to fix in the Linux syscall.master's since the bugs are mostly already avoided using l_foo_t. In amd64/linux32/ syscalls.master, I only noticed the following ones: % 1 AUE_EXIT NOPROTO { void sys_exit(int rval); } exit \ % sys_exit_args void "int" for the return and args is not quite right, and it bogotifies the use of l_int for some args. It works though (assuming 32-bit host ints). Assumptions that the return type is 32-bit int and that the host int is 32-bits are implicit in all over, so we should assume them here for simplicity. (Hmm, td_retval is actually 2 register_t's. 64 bits each on amd64. amd64/linux32 has remarkably little code to convert these 2 64-bit ints into 4 32-bit ints.) % 2 AUE_FORK STD { int linux_fork(void); } % 3 AUE_NULL NOPROTO { int read(int fd, char *buf, \ % u_int nbyte); } This u_int should strictly be l_size_t. l_size_t is used a lot elswhere in this file. In syscalls where the type is actually u_int, l_uint should be used. l_uint is used a lot elsewhere in this file. But not many syscsalls use u_int, so many of these l_uints are probably just different misspellings of l_size_t. So the density of logical type bugs is high even in this file. % 4 AUE_NULL NOPROTO { int write(int fd, char *buf, \ % u_int nbyte); } u_int seems to be more common in older syscalls. % 5 AUE_OPEN_RWTC STD { int linux_open(char *path, l_int flags, \ % l_int mode); } Finally, an example of perfectly correct use of l_int. It even correctly handles the subtlety that l_mode_t promotes to l_int since open() is variadic. (BTW, I don't like hard-coding this promotion and have wished for the __promoteof() operator for giving it for more than 20 years. The promotion of a typedefed type even harder to determine than the correct PRI* mistake to use for printing a typedefed type.) This declaration is still far from correct altogether, since it depends on the usual hacks: - int return type is actual l_int - char *path is actually "const char *path" at the target level - magic to convert target "char *" to and from host "char *" % 11 AUE_EXECVE STD { int linux_execve(char *path, uint32_t *argp, \ % uint32_t *envp); } See above. % 41 AUE_DUP NOPROTO { int dup(u_int fd); } Another untranslated type. dup() doesn't even take a u_int to begin with (it takes a normal int descriptor). Untranslated int args aren't actually very common. % 54 AUE_IOCTL STD { int linux_ioctl(l_uint fd, l_uint cmd, \ % uintptr_t arg); } Now l_foo is used for the descriptor, but u_int is wrong -- Linux uses a normal int for the descriptor for ioctl() too. l_uint for cmd is wrong too. The type starts as u_long (same as in FreeBSD), at least in the 1997 Linux userland that I used to check this. This type mismatch is harmless because ints and longs are both 32 bits on Linux-i386. uintptr_t for arg is wronger. For ioctl(), this arg is the first variadic one and might not be present. I think declaring it in the above gives (via the Linux ABI) the garbage contents of a register for it when it isn't present. Native FreeBSD ioctl() has evem more magic. It misdeclares the arg as caddr_t instead, and gives stack garbage for it when it isn't present, and depends on the stack being large enough to avoid a memory fault when copying the stack garbage (the FreeBSD ABO gives at least a return address there). The type of the arg, when it is present, is specified to be caddr_t (:-() in FreeBSD. Linux (1997 userland) is better and says it is "char *". It should have been "void *". syscall.master's should probably declare it as "void *". Here it starts as a 32-bit pointer and the usual magic will convert it to a 64-bit non-pointer represented as a host uintptr_t by the above or by a host "void *" with "void *" in the above. copy*() will eventually turn it into "void *uaddr" either way. Then it will still not really be a kernel pointer, but is used as one in the implementation of copy*() on amd64 (this depends on a flat address space). % 55 AUE_FCNTL STD { int linux_fcntl(l_uint fd, l_uint cmd, \ % uintptr_t arg); } Same errors for the types of fd and arg. Different error for the type of cmd. Unlike for ioctl(), it starts as neither long or unsigned, but just int (POSIX spec). % 56 AUE_NULL UNIMPL mpx % 57 AUE_SETPGRP NOPROTO { int setpgid(int pid, int pgid); } l_pid_t exists and should be used. % 60 AUE_UMASK NOPROTO { int umask(int newmask); } l_mode_t exists and should be used. % 63 AUE_DUP2 NOPROTO { int dup2(u_int from, u_int to); } Bogus fd types, as usual. % 65 AUE_GETPGRP NOPROTO { int getpgrp(void); } Should really be more careful with return types that are typedefed in the API (and are not just int statuses or fds). kern/syscalls.master is sloppy with this too. % 74 AUE_SYSCTL STD { int linux_sethostname(char *hostname, \ % u_int len); } get/sethostname() is horribly inconsistent. In FreeBSD, gethostname() is documented as taking a size_t and sethostname() is documented as taking an int. kern/syscalls.master uses u_int for both. Apparently there is enough magic with arg packing for this to work even on supported 64-bit big-endian systems. Linux userland was better even in 1997 -- it uses size_t for both. POSIX has specified gethostname() since at least 2001. It uses size_t of course. It says that these are 4.3BSD functions but it only specifies gethostname(), and it applies an OpenGroup resolution to change the type from socklen_t to size_t for gethostname(). This made it incompatible with BSD. Old BSD uses int for both, and FreeBSD apparently changed the documentation but not the code for gethostname() only, to be bug for compatible with POSIX. So the above should use l_size_t, and strictly, the code probably needs to be more careful than it is with unrepresentable sizes (native sethostname() wants a signed int and might not have the right checking for a 32-bit unsigned size_t). % 75 AUE_SETRLIMIT STD { int linux_setrlimit(l_uint resource, \ % struct l_rlimit *rlim); } % 76 AUE_GETRLIMIT STD { int linux_old_getrlimit(l_uint resource, \ % struct l_rlimit *rlim); } Resource numbers should be plain ints too. They are documented to be as such in old Linux userland man pages. But in old Linux (glibc) headers, they are obfuscated as __rlimit_resource_t, which an enum with gnu extensions, else plain int. % 78 AUE_NULL STD { int linux_gettimeofday( \ % struct l_timeval *tp, \ % struct timezone *tzp); } % 79 AUE_SETTIMEOFDAY STD { int linux_settimeofday( \ % struct l_timeval *tp, \ % struct timezone *tzp); } The timezone struct only has a couple of ints in it, so this abuse of the native timezone works, but is fragile. I forget if the timezone arg is deprecated to the point of ignoring it for native get/settimeofday(). If so, then this won't work for emulated get/settimeofday() % 85 AUE_READLINK STD { int linux_readlink(char *name, char *buf, \ % l_int count); } Native readlink was churned by POSIX from an int count to a size_t count. Linux readlink has takes a size_t count even in 1997 and probably still does. % 88 AUE_REBOOT STD { int linux_reboot(l_int magic1, \ % l_int magic2, l_uint cmd, void *arg); } In old Linux userland it is documented to take only 3 int args, with the 3rd one named `flag'. % ; 89: old_readdir % 89 AUE_GETDIRENTRIES STD { int linux_readdir(l_uint fd, \ % struct l_dirent *dent, l_uint count); } Matches old Linux userland man page right down to the u_int for fd. % 91 AUE_MUNMAP NOPROTO { int munmap(caddr_t addr, int len); } Takes a void * and a size_t in modern munmap() and Linux had that in 1997. FreeBSD-3 had this too. The above matches FreeBSD-1. % 92 AUE_TRUNCATE STD { int linux_truncate(char *path, \ % l_ulong length); } Should use l_off_t, not l_ulong (except possibly if their is an unsigned hack to support file sizes of 2G-4G). % 93 AUE_FTRUNCATE STD { int linux_ftruncate(int fd, long length); } Using long is very broken. l_off_t is correct here too. % 94 AUE_FCHMOD NOPROTO { int fchmod(int fd, int mode); } mode_t is used for all other *chmod*()'s in this file % 95 AUE_FCHOWN NOPROTO { int fchown(int fd, int uid, int gid); } l_uid16_t and l_gid16_t are used for all other old *chown*() in this file. (Newer ones are spelled *lchown*() and take l_uid_t and l_gid_t's.) % 96 AUE_GETPRIORITY STD { int linux_getpriority(int which, int who); } % 97 AUE_SETPRIORITY NOPROTO { int setpriority(int which, int who, \ % int prio); } `who' should have type pid_t, but is still int in FreeBSD native. In old Linux, it is int in the man page but is obfuscated as id_t in the glibc header. Even `which' is obfuscated as __priority_which_t in the glibc header. (I consider even using size_t for read() to be a regression. Typedefed types are hard to use correctly, as shown by this mail which points out that hundreds of incorrect uses, where the bugs are only harmless because the use of typedefed types makes no significant difference.) Got bored here, and looked at the rest less carefully. The newer syscalls seem to be handled more carefully, probably because plenty of Linux types existed when they were written. There just seemed to be too many l_[u]longs in them. % 168 AUE_POLL NOPROTO { int poll(struct pollfd *fds, \ % unsigned int nfds, int timeout); } Hrmph, this is the only one that misspells "unsigned" more verbosely as "unsigned int" instead of as the usual KNF abbreviation "u_int". Of course, poll() doesn't even take a u_int type. Modern poll takes an nfds_t type. Linux had that in 1997, and it was u_long, not u_int. Use of the native struct pollfd is dangerous. It works because it consists of an int followed by 2 shorts, and this matches the Linux type and neither has neither unnamed padding on at least amd64 and i386. % 180 AUE_PREAD STD { int linux_pread(l_uint fd, char *buf, \ % l_size_t nbyte, l_loff_t offset); } % [... several more bogus l_uints for fds] % 183 AUE_GETCWD STD { int linux_getcwd(char *buf, \ % l_ulong bufsize); } A different misspelling of l_size_t. % 191 AUE_GETRLIMIT STD { int linux_getrlimit(l_uint resource, \ % struct l_rlimit *rlim); } Bogus resource number times for new rlimit syscalls too. % 193 AUE_TRUNCATE STD { int linux_truncate64(char *path, \ % l_loff_t length); } % 194 AUE_FTRUNCATE STD { int linux_ftruncate64(l_uint fd, \ % l_loff_t length); } How can this work? I was going to say that the splitting up of the 64-bit args in compat/freebsd32/syscalls.master was unnecessary because it is apparently not needed here. Then I misread this as doing the splitting. But it doesn't. Similarly later in this file. % 218 AUE_MINCORE STD { int linux_mincore(l_ulong start, \ % l_size_t len, u_char *vec); } % 219 AUE_MADVISE NOPROTO { int madvise(void *addr, size_t len, \ % int behav); } SIlly to have l_size_t in one and raw size_t in the next. I just noticed that NOPROTO calls never use l_foo. They go direct to the native calls, and spelling things without an l_ may be necessary for hiding the type mismatches from this. But this is especially fragile, and maybe the l_'s here would be harmless since they have no effect, since type checking for the direct calls is destroyed better using (sy_call_t *) casts. % 220 AUE_GETDIRENTRIES STD { int linux_getdents64(l_uint fd, \ % void *dirent, l_uint count); } % 221 AUE_FCNTL STD { int linux_fcntl64(l_uint fd, l_uint cmd, \ % uintptr_t arg); } Type errors for 32-bit syscalls are often duplicated for the corresponding 64-bit ones. My old userland doesn't have these new syscalls to check, but I doubt that Linux changed the API for the non-64 bit parts, and u_int fds are bogus as usual. % 240 AUE_NULL STD { int linux_sys_futex(void *uaddr, int op, uint32_t val, \ % struct l_timespec *timeout, uint32_t *uaddr2, uint32_t val3); } % 241 AUE_NULL STD { int linux_sched_setaffinity(l_pid_t pid, l_uint len, \ % l_ulong *user_mask_ptr); } % 242 AUE_NULL STD { int linux_sched_getaffinity(l_pid_t pid, l_uint len, \ % l_ulong *user_mask_ptr); } % 243 AUE_NULL STD { int linux_set_thread_area(struct l_user_desc *desc); } Lots of style bugs which are not present in old code: - lines are not wrapped at 80 columns - wrapped lines are misindented. % 250 AUE_NULL STD { int linux_fadvise64(int fd, l_loff_t offset, \ % l_size_t len, int advice); } More style bugs. % 264 AUE_CLOCK_SETTIME STD { int linux_clock_settime(clockid_t which, struct l_timespec *tp); } % 265 AUE_NULL STD { int linux_clock_gettime(clockid_t which, struct l_timespec *tp); } % 266 AUE_NULL STD { int linux_clock_getres(clockid_t which, struct l_timespec *tp); } % 267 AUE_NULL STD { int linux_clock_nanosleep(clockid_t which, int flags, \ % struct l_timespec *rqtp, struct l_timespec *rmtp); } % 268 AUE_STATFS STD { int linux_statfs64(char *path, size_t bufsize, struct l_statfs64_buf *buf); } Another raw size_t. Another long line. % 269 AUE_FSTATFS STD { int linux_fstatfs64(void); } % 270 AUE_NULL STD { int linux_tgkill(int tgid, int pid, int sig); } Raw ints for pids. % 271 AUE_UTIMES STD { int linux_utimes(char *fname, \ % struct l_timeval *tptr); } % 272 AUE_NULL STD { int linux_fadvise64_64(int fd, \ % l_loff_t offset, l_loff_t len, \ % int advice); } Just about all syscalls added since #239 are misformatted :-(. % 295 AUE_OPEN_RWTC STD { int linux_openat(l_int dfd, const char *filename, \ % l_int flags, l_int mode); } % 296 AUE_MKDIRAT STD { int linux_mkdirat(l_int dfd, const char *pathname, \ % l_int mode); } % 297 AUE_MKNODAT STD { int linux_mknodat(l_int dfd, const char *filename, \ % l_int mode, l_uint dev); } % 298 AUE_FCHOWNAT STD { int linux_fchownat(l_int dfd, const char *filename, \ % l_uid16_t uid, l_gid16_t gid, l_int flag); } % 299 AUE_FUTIMESAT STD { int linux_futimesat(l_int dfd, char *filename, \ % struct l_timeval *utimes); } % 300 AUE_FSTATAT STD { int linux_fstatat64(l_int dfd, char *pathname, \ % struct l_stat64 *statbuf, l_int flag); } % 301 AUE_UNLINKAT STD { int linux_unlinkat(l_int dfd, const char *pathname, \ % l_int flag); } % 302 AUE_RENAMEAT STD { int linux_renameat(l_int olddfd, const char *oldname, \ % l_int newdfd, const char *newname); } % 303 AUE_LINKAT STD { int linux_linkat(l_int olddfd, const char *oldname, \ % l_int newdfd, const char *newname, l_int flag); } % 304 AUE_SYMLINKAT STD { int linux_symlinkat(const char *oldname, l_int newdfd, \ % const char *newname); } % 305 AUE_READLINKAT STD { int linux_readlinkat(l_int dfd, const char *path, \ % char *buf, l_int bufsiz); } % 306 AUE_FCHMODAT STD { int linux_fchmodat(l_int dfd, const char *filename, \ % l_mode_t mode); } % 307 AUE_FACCESSAT STD { int linux_faccessat(l_int dfd, const char *filename, l_int amode, int flag); } Mounds more misformatting. [... A small pile of misformatting] Bruce