[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH 09/10] Prefer glibc over direct syscalls
From: |
Aurelien Jarno |
Subject: |
Re: [Qemu-devel] [PATCH 09/10] Prefer glibc over direct syscalls |
Date: |
Wed, 15 Apr 2009 18:14:38 +0200 |
User-agent: |
Mutt/1.5.18 (2008-05-17) |
On Sun, Apr 05, 2009 at 11:59:25PM +0300, address@hidden wrote:
> From: Riku Voipio <address@hidden>
>
> The openat/*at syscalls are incredibly common with modern coreutils,
> calling them directly via syscalls breaks for example fakeroot. Use
> glibc stubs whenever directly available and provide old syscall
> calling for people still using older libc.
>
> Patch originally from Mika Westerberg, Adapted to
> apply to current trunk and cleaned up by Riku Voipio.
>
> Signed-off-by: Riku Voipio <address@hidden>
> ---
> configure | 53 +++++++++
> linux-user/syscall.c | 314
> ++++++++++++++++++++++++++++++++++++++++----------
> 2 files changed, 306 insertions(+), 61 deletions(-)
Thanks, applied.
> diff --git a/configure b/configure
> index fa77937..8955c83 100755
> --- a/configure
> +++ b/configure
> @@ -1115,6 +1115,53 @@ EOF
> fi
> fi
>
> +#
> +# Check for xxxat() functions when we are building linux-user
> +# emulator. This is done because older glibc versions don't
> +# have syscall stubs for these implemented.
> +#
> +atfile=no
> +if [ "$linux_user" = "yes" ] ; then
> + cat > $TMPC << EOF
> +#define _ATFILE_SOURCE
> +#include <sys/types.h>
> +#include <fcntl.h>
> +#include <unistd.h>
> +
> +int
> +main(void)
> +{
> + /* try to unlink nonexisting file */
> + return (unlinkat(AT_FDCWD, "nonexistent_file", 0));
> +}
> +EOF
> + if $cc $ARCH_CFLAGS -o $TMPE $TMPC 2> /dev/null ; then
> + atfile=yes
> + fi
> +fi
> +
> +# Check for initofy functions when we are building linux-user
> +# emulator. This is done because older glibc versions don't
> +# have syscall stubs for these implemented. In that case we
> +# don't provide them even if kernel supports them.
> +#
> +inotify=no
> +if [ "$linux_user" = "yes" ] ; then
> + cat > $TMPC << EOF
> +#include <sys/inotify.h>
> +
> +int
> +main(void)
> +{
> + /* try to start inotify */
> + return inotify_init(void);
> +}
> +EOF
> + if $cc $ARCH_CFLAGS -o $TMPE $TMPC 2> /dev/null ; then
> + inotify=yes
> + fi
> +fi
> +
> # Check if tools are available to build documentation.
> if [ -x "`which texi2html 2>/dev/null`" ] && \
> [ -x "`which pod2man 2>/dev/null`" ]; then
> @@ -1494,6 +1541,12 @@ if test "$curses" = "yes" ; then
> echo "CONFIG_CURSES=yes" >> $config_mak
> echo "CURSES_LIBS=-lcurses" >> $config_mak
> fi
> +if test "$atfile" = "yes" ; then
> + echo "#define CONFIG_ATFILE 1" >> $config_h
> +fi
> +if test "$inotify" = "yes" ; then
> + echo "#define CONFIG_INOTIFY 1" >> $config_h
> +fi
> if test "$brlapi" = "yes" ; then
> echo "CONFIG_BRLAPI=yes" >> $config_mak
> echo "#define CONFIG_BRLAPI 1" >> $config_h
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index 110cba0..52e9ff5 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -53,6 +53,7 @@
> #include <sys/statfs.h>
> #include <utime.h>
> #include <sys/sysinfo.h>
> +#include <sys/utsname.h>
> //#include <sys/user.h>
> #include <netinet/ip.h>
> #include <netinet/tcp.h>
> @@ -200,7 +201,229 @@ static int gettid(void) {
> return -ENOSYS;
> }
> #endif
> -_syscall1(int,sys_uname,struct new_utsname *,buf)
> +#if TARGET_ABI_BITS == 32
> +_syscall3(int, sys_getdents, uint, fd, struct linux_dirent *, dirp, uint,
> count);
> +#endif
> +#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
> +_syscall3(int, sys_getdents64, uint, fd, struct linux_dirent64 *, dirp,
> uint, count);
> +#endif
> +_syscall2(int, sys_getpriority, int, which, int, who);
> +#if !defined (__x86_64__)
> +_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo,
> + loff_t *, res, uint, wh);
> +#endif
> +_syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo)
> +_syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
> +#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
> +_syscall3(int,sys_tgkill,int,tgid,int,pid,int,sig)
> +#endif
> +#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
> +_syscall2(int,sys_tkill,int,tid,int,sig)
> +#endif
> +#ifdef __NR_exit_group
> +_syscall1(int,exit_group,int,error_code)
> +#endif
> +#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
> +_syscall1(int,set_tid_address,int *,tidptr)
> +#endif
> +#if defined(USE_NPTL)
> +#if defined(TARGET_NR_futex) && defined(__NR_futex)
> +_syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
> + const struct timespec *,timeout,int *,uaddr2,int,val3)
> +#endif
> +#endif
> +
> +static bitmask_transtbl fcntl_flags_tbl[] = {
> + { TARGET_O_ACCMODE, TARGET_O_WRONLY, O_ACCMODE, O_WRONLY, },
> + { TARGET_O_ACCMODE, TARGET_O_RDWR, O_ACCMODE, O_RDWR, },
> + { TARGET_O_CREAT, TARGET_O_CREAT, O_CREAT, O_CREAT, },
> + { TARGET_O_EXCL, TARGET_O_EXCL, O_EXCL, O_EXCL, },
> + { TARGET_O_NOCTTY, TARGET_O_NOCTTY, O_NOCTTY, O_NOCTTY, },
> + { TARGET_O_TRUNC, TARGET_O_TRUNC, O_TRUNC, O_TRUNC, },
> + { TARGET_O_APPEND, TARGET_O_APPEND, O_APPEND, O_APPEND, },
> + { TARGET_O_NONBLOCK, TARGET_O_NONBLOCK, O_NONBLOCK, O_NONBLOCK, },
> + { TARGET_O_SYNC, TARGET_O_SYNC, O_SYNC, O_SYNC, },
> + { TARGET_FASYNC, TARGET_FASYNC, FASYNC, FASYNC, },
> + { TARGET_O_DIRECTORY, TARGET_O_DIRECTORY, O_DIRECTORY, O_DIRECTORY, },
> + { TARGET_O_NOFOLLOW, TARGET_O_NOFOLLOW, O_NOFOLLOW, O_NOFOLLOW, },
> + { TARGET_O_LARGEFILE, TARGET_O_LARGEFILE, O_LARGEFILE, O_LARGEFILE, },
> +#if defined(O_DIRECT)
> + { TARGET_O_DIRECT, TARGET_O_DIRECT, O_DIRECT, O_DIRECT, },
> +#endif
> + { 0, 0, 0, 0 }
> +};
> +
> +#define COPY_UTSNAME_FIELD(dest, src) \
> + do { \
> + /* __NEW_UTS_LEN doesn't include terminating null */ \
> + (void) strncpy((dest), (src), __NEW_UTS_LEN); \
> + (dest)[__NEW_UTS_LEN] = '\0'; \
> + } while (0)
> +
> +static int sys_uname(struct new_utsname *buf)
> +{
> + struct utsname uts_buf;
> +
> + if (uname(&uts_buf) < 0)
> + return (-1);
> +
> + /*
> + * Just in case these have some differences, we
> + * translate utsname to new_utsname (which is the
> + * struct linux kernel uses).
> + */
> +
> + bzero(buf, sizeof (*buf));
> + COPY_UTSNAME_FIELD(buf->sysname, uts_buf.sysname);
> + COPY_UTSNAME_FIELD(buf->nodename, uts_buf.nodename);
> + COPY_UTSNAME_FIELD(buf->release, uts_buf.release);
> + COPY_UTSNAME_FIELD(buf->version, uts_buf.version);
> + COPY_UTSNAME_FIELD(buf->machine, uts_buf.machine);
> +#ifdef _GNU_SOURCE
> + COPY_UTSNAME_FIELD(buf->domainname, uts_buf.domainname);
> +#endif
> + return (0);
> +
> +#undef COPY_UTSNAME_FIELD
> +}
> +
> +static int sys_getcwd1(char *buf, size_t size)
> +{
> + if (getcwd(buf, size) == NULL) {
> + /* getcwd() sets errno */
> + return (-1);
> + }
> + return (0);
> +}
> +
> +#ifdef CONFIG_ATFILE
> +/*
> + * Host system seems to have atfile syscall stubs available. We
> + * now enable them one by one as specified by target syscall_nr.h.
> + */
> +
> +#ifdef TARGET_NR_faccessat
> +static int sys_faccessat(int dirfd, const char *pathname, int mode, int
> flags)
> +{
> + return (faccessat(dirfd, pathname, mode, flags));
> +}
> +#endif
> +#ifdef TARGET_NR_fchmodat
> +static int sys_fchmodat(int dirfd, const char *pathname, mode_t mode, int
> flags)
> +{
> + return (fchmodat(dirfd, pathname, mode, flags));
> +}
> +#endif
> +#ifdef TARGET_NR_fchownat
> +static int sys_fchownat(int dirfd, const char *pathname, uid_t owner,
> + gid_t group, int flags)
> +{
> + return (fchownat(dirfd, pathname, owner, group, flags));
> +}
> +#endif
> +#ifdef __NR_fstatat64
> +static int sys_fstatat64(int dirfd, const char *pathname, struct stat *buf,
> + int flags)
> +{
> + return (fstatat(dirfd, pathname, buf, flags));
> +}
> +#endif
> +#ifdef __NR_newfstatat
> +static int sys_newfstatat(int dirfd, const char *pathname, struct stat *buf,
> + int flags)
> +{
> + return (fstatat(dirfd, pathname, buf, flags));
> +}
> +#endif
> +#ifdef TARGET_NR_futimesat
> +static int sys_futimesat(int dirfd, const char *pathname,
> + const struct timeval times[2])
> +{
> + return (futimesat(dirfd, pathname, times));
> +}
> +#endif
> +#ifdef TARGET_NR_linkat
> +static int sys_linkat(int olddirfd, const char *oldpath,
> + int newdirfd, const char *newpath, int flags)
> +{
> + return (linkat(olddirfd, oldpath, newdirfd, newpath, flags));
> +}
> +#endif
> +#ifdef TARGET_NR_mkdirat
> +static int sys_mkdirat(int dirfd, const char *pathname, mode_t mode)
> +{
> + return (mkdirat(dirfd, pathname, mode));
> +}
> +#endif
> +#ifdef TARGET_NR_mknodat
> +static int sys_mknodat(int dirfd, const char *pathname, mode_t mode,
> + dev_t dev)
> +{
> + return (mknodat(dirfd, pathname, mode, dev));
> +}
> +#endif
> +#ifdef TARGET_NR_openat
> +static int sys_openat(int dirfd, const char *pathname, int flags, ...)
> +{
> + /*
> + * open(2) has extra parameter 'mode' when called with
> + * flag O_CREAT.
> + */
> + if ((flags & O_CREAT) != 0) {
> + va_list ap;
> + mode_t mode;
> +
> + /*
> + * Get the 'mode' parameter and translate it to
> + * host bits.
> + */
> + va_start(ap, flags);
> + mode = va_arg(ap, mode_t);
> + mode = target_to_host_bitmask(mode, fcntl_flags_tbl);
> + va_end(ap);
> +
> + return (openat(dirfd, pathname, flags, mode));
> + }
> + return (openat(dirfd, pathname, flags));
> +}
> +#endif
> +#ifdef TARGET_NR_readlinkat
> +static int sys_readlinkat(int dirfd, const char *pathname, char *buf, size_t
> bufsiz)
> +{
> + return (readlinkat(dirfd, pathname, buf, bufsiz));
> +}
> +#endif
> +#ifdef TARGET_NR_renameat
> +static int sys_renameat(int olddirfd, const char *oldpath,
> + int newdirfd, const char *newpath)
> +{
> + return (renameat(olddirfd, oldpath, newdirfd, newpath));
> +}
> +#endif
> +#ifdef TARGET_NR_symlinkat
> +static int sys_symlinkat(const char *oldpath, int newdirfd, const char
> *newpath)
> +{
> + return (symlinkat(oldpath, newdirfd, newpath));
> +}
> +#endif
> +#ifdef TARGET_NR_unlinkat
> +static int sys_unlinkat(int dirfd, const char *pathname, int flags)
> +{
> + return (unlinkat(dirfd, pathname, flags));
> +}
> +#endif
> +#ifdef TARGET_NR_utimensat
> +static int sys_utimensat(int dirfd, const char *pathname,
> + const struct timespec times[2], int flags)
> +{
> + return (utimensat(dirfd, pathname, times, flags));
> +}
> +#endif
> +#else /* !CONFIG_ATFILE */
> +
> +/*
> + * Try direct syscalls instead
> + */
> #if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
> _syscall4(int,sys_faccessat,int,dirfd,const char
> *,pathname,int,mode,int,flags)
> #endif
> @@ -221,21 +444,14 @@ _syscall4(int,sys_fstatat64,int,dirfd,const char
> *,pathname,
> _syscall3(int,sys_futimesat,int,dirfd,const char *,pathname,
> const struct timeval *,times)
> #endif
> -_syscall2(int,sys_getcwd1,char *,buf,size_t,size)
> -#if TARGET_ABI_BITS == 32
> -_syscall3(int, sys_getdents, uint, fd, struct linux_dirent *, dirp, uint,
> count);
> -#endif
> -#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
> -_syscall3(int, sys_getdents64, uint, fd, struct linux_dirent64 *, dirp,
> uint, count);
> -#endif
> -_syscall2(int, sys_getpriority, int, which, int, who);
> -#if !defined (__x86_64__)
> -_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo,
> - loff_t *, res, uint, wh);
> +#if (defined(TARGET_NR_newfstatat) || defined(TARGET_NR_fstatat64) ) && \
> + defined(__NR_newfstatat)
> +_syscall4(int,sys_newfstatat,int,dirfd,const char *,pathname,
> + struct stat *,buf,int,flags)
> #endif
> #if defined(TARGET_NR_linkat) && defined(__NR_linkat)
> _syscall5(int,sys_linkat,int,olddirfd,const char *,oldpath,
> - int,newdirfd,const char *,newpath,int,flags)
> + int,newdirfd,const char *,newpath,int,flags)
> #endif
> #if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
> _syscall3(int,sys_mkdirat,int,dirfd,const char *,pathname,mode_t,mode)
> @@ -244,11 +460,6 @@ _syscall3(int,sys_mkdirat,int,dirfd,const char
> *,pathname,mode_t,mode)
> _syscall4(int,sys_mknodat,int,dirfd,const char *,pathname,
> mode_t,mode,dev_t,dev)
> #endif
> -#if (defined(TARGET_NR_newfstatat) || defined(TARGET_NR_fstatat64) ) && \
> - defined(__NR_newfstatat)
> -_syscall4(int,sys_newfstatat,int,dirfd,const char *,pathname,
> - struct stat *,buf,int,flags)
> -#endif
> #if defined(TARGET_NR_openat) && defined(__NR_openat)
> _syscall4(int,sys_openat,int,dirfd,const char
> *,pathname,int,flags,mode_t,mode)
> #endif
> @@ -260,24 +471,10 @@ _syscall4(int,sys_readlinkat,int,dirfd,const char
> *,pathname,
> _syscall4(int,sys_renameat,int,olddirfd,const char *,oldpath,
> int,newdirfd,const char *,newpath)
> #endif
> -_syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo)
> #if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
> _syscall3(int,sys_symlinkat,const char *,oldpath,
> int,newdirfd,const char *,newpath)
> #endif
> -_syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
> -#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
> -_syscall3(int,sys_tgkill,int,tgid,int,pid,int,sig)
> -#endif
> -#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
> -_syscall2(int,sys_tkill,int,tid,int,sig)
> -#endif
> -#ifdef __NR_exit_group
> -_syscall1(int,exit_group,int,error_code)
> -#endif
> -#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
> -_syscall1(int,set_tid_address,int *,tidptr)
> -#endif
> #if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
> _syscall3(int,sys_unlinkat,int,dirfd,const char *,pathname,int,flags)
> #endif
> @@ -285,21 +482,36 @@ _syscall3(int,sys_unlinkat,int,dirfd,const char
> *,pathname,int,flags)
> _syscall4(int,sys_utimensat,int,dirfd,const char *,pathname,
> const struct timespec *,tsp,int,flags)
> #endif
> +
> +#endif /* CONFIG_ATFILE */
> +
> +#ifdef CONFIG_INOTIFY
> +
> #if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)
> -_syscall0(int,sys_inotify_init)
> +static int sys_inotify_init(void)
> +{
> + return (inotify_init());
> +}
> #endif
> #if defined(TARGET_NR_inotify_add_watch) && defined(__NR_inotify_add_watch)
> -_syscall3(int,sys_inotify_add_watch,int,fd,const char
> *,pathname,uint32_t,mask)
> +static int sys_inotify_add_watch(int fd,const char *pathname, int32_t mask)
> +{
> + return (inotify_add_watch(fd, pathname, mask));
> +}
> #endif
> #if defined(TARGET_NR_inotify_rm_watch) && defined(__NR_inotify_rm_watch)
> -_syscall2(int,sys_inotify_rm_watch,int,fd,uint32_t,wd)
> -#endif
> -#if defined(USE_NPTL)
> -#if defined(TARGET_NR_futex) && defined(__NR_futex)
> -_syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
> - const struct timespec *,timeout,int *,uaddr2,int,val3)
> -#endif
> +static int sys_inotify_rm_watch(int fd, int32_t wd)
> +{
> + return (inotify_rm_watch(fd,pathname, wd));
> +}
> #endif
> +#else
> +/* Userspace can usually survive runtime without inotify */
> +#undef TARGET_NR_inotify_init
> +#undef TARGET_NR_inotify_add_watch
> +#undef TARGET_NR_inotify_rm_watch
> +#endif /* CONFIG_INOTIFY */
> +
>
> extern int personality(int);
> extern int flock(int, int);
> @@ -2837,26 +3049,6 @@ static bitmask_transtbl mmap_flags_tbl[] = {
> { 0, 0, 0, 0 }
> };
>
> -static bitmask_transtbl fcntl_flags_tbl[] = {
> - { TARGET_O_ACCMODE, TARGET_O_WRONLY, O_ACCMODE, O_WRONLY, },
> - { TARGET_O_ACCMODE, TARGET_O_RDWR, O_ACCMODE, O_RDWR, },
> - { TARGET_O_CREAT, TARGET_O_CREAT, O_CREAT, O_CREAT, },
> - { TARGET_O_EXCL, TARGET_O_EXCL, O_EXCL, O_EXCL, },
> - { TARGET_O_NOCTTY, TARGET_O_NOCTTY, O_NOCTTY, O_NOCTTY, },
> - { TARGET_O_TRUNC, TARGET_O_TRUNC, O_TRUNC, O_TRUNC, },
> - { TARGET_O_APPEND, TARGET_O_APPEND, O_APPEND, O_APPEND, },
> - { TARGET_O_NONBLOCK, TARGET_O_NONBLOCK, O_NONBLOCK, O_NONBLOCK, },
> - { TARGET_O_SYNC, TARGET_O_SYNC, O_SYNC, O_SYNC, },
> - { TARGET_FASYNC, TARGET_FASYNC, FASYNC, FASYNC, },
> - { TARGET_O_DIRECTORY, TARGET_O_DIRECTORY, O_DIRECTORY, O_DIRECTORY, },
> - { TARGET_O_NOFOLLOW, TARGET_O_NOFOLLOW, O_NOFOLLOW, O_NOFOLLOW, },
> - { TARGET_O_LARGEFILE, TARGET_O_LARGEFILE, O_LARGEFILE, O_LARGEFILE, },
> -#if defined(O_DIRECT)
> - { TARGET_O_DIRECT, TARGET_O_DIRECT, O_DIRECT, O_DIRECT, },
> -#endif
> - { 0, 0, 0, 0 }
> -};
> -
> #if defined(TARGET_I386)
>
> /* NOTE: there is really one LDT for all the threads */
> --
> 1.6.2.1
>
>
>
>
--
Aurelien Jarno GPG: 1024D/F1BCDB73
address@hidden http://www.aurel32.net
- [Qemu-devel] [PATCH 00/10] misc userland patches [v2], riku . voipio, 2009/04/05
- [Qemu-devel] [PATCH 01/10] Fix fstatat64()/newfstatat() syscall implementation, riku . voipio, 2009/04/05
- [Qemu-devel] [PATCH 02/10] Rewrite mmap_find_vma() to work fine on 64-bit hosts with 32-bit targets, riku . voipio, 2009/04/05
- [Qemu-devel] [PATCH 06/10] Add support for passing contents of argv0, riku . voipio, 2009/04/05
- [Qemu-devel] [PATCH 05/10] Added posix message queue syscalls except mq_notify, riku . voipio, 2009/04/05
- [Qemu-devel] [PATCH 09/10] Prefer glibc over direct syscalls, riku . voipio, 2009/04/05
- Re: [Qemu-devel] [PATCH 09/10] Prefer glibc over direct syscalls,
Aurelien Jarno <=
- [Qemu-devel] [PATCH 10/10] linux-user: Proper exit code for uncaught signals, riku . voipio, 2009/04/05
- [Qemu-devel] [PATCH 08/10] linux-user: removed unnecessary MAX_SOCK_ADDR checks for socket syscalls, riku . voipio, 2009/04/05
- [Qemu-devel] [PATCH 07/10] linux-user: unix sockets - fix running dbus, riku . voipio, 2009/04/05
- [Qemu-devel] [PATCH 04/10] fix IPCOP_sem* and implement sem*, riku . voipio, 2009/04/05