Commit 3b3f24add09f8ab720860d4840f9755c102121b5

Authored by aurel32
1 parent be09ac41

linux-user: prefer glibc over direct syscalls

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 <riku.voipio@iki.fi>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@7118 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 2 changed files with 306 additions and 61 deletions
configure
... ... @@ -1156,6 +1156,53 @@ EOF
1156 1156 fi
1157 1157 fi
1158 1158  
  1159 +#
  1160 +# Check for xxxat() functions when we are building linux-user
  1161 +# emulator. This is done because older glibc versions don't
  1162 +# have syscall stubs for these implemented.
  1163 +#
  1164 +atfile=no
  1165 +if [ "$linux_user" = "yes" ] ; then
  1166 + cat > $TMPC << EOF
  1167 +#define _ATFILE_SOURCE
  1168 +#include <sys/types.h>
  1169 +#include <fcntl.h>
  1170 +#include <unistd.h>
  1171 +
  1172 +int
  1173 +main(void)
  1174 +{
  1175 + /* try to unlink nonexisting file */
  1176 + return (unlinkat(AT_FDCWD, "nonexistent_file", 0));
  1177 +}
  1178 +EOF
  1179 + if $cc $ARCH_CFLAGS -o $TMPE $TMPC 2> /dev/null ; then
  1180 + atfile=yes
  1181 + fi
  1182 +fi
  1183 +
  1184 +# Check for initofy functions when we are building linux-user
  1185 +# emulator. This is done because older glibc versions don't
  1186 +# have syscall stubs for these implemented. In that case we
  1187 +# don't provide them even if kernel supports them.
  1188 +#
  1189 +inotify=no
  1190 +if [ "$linux_user" = "yes" ] ; then
  1191 + cat > $TMPC << EOF
  1192 +#include <sys/inotify.h>
  1193 +
  1194 +int
  1195 +main(void)
  1196 +{
  1197 + /* try to start inotify */
  1198 + return inotify_init(void);
  1199 +}
  1200 +EOF
  1201 + if $cc $ARCH_CFLAGS -o $TMPE $TMPC 2> /dev/null ; then
  1202 + inotify=yes
  1203 + fi
  1204 +fi
  1205 +
1159 1206 # Check if tools are available to build documentation.
1160 1207 if [ -x "`which texi2html 2>/dev/null`" ] && \
1161 1208 [ -x "`which pod2man 2>/dev/null`" ]; then
... ... @@ -1544,6 +1591,12 @@ if test &quot;$curses&quot; = &quot;yes&quot; ; then
1544 1591 echo "CONFIG_CURSES=yes" >> $config_mak
1545 1592 echo "CURSES_LIBS=-lcurses" >> $config_mak
1546 1593 fi
  1594 +if test "$atfile" = "yes" ; then
  1595 + echo "#define CONFIG_ATFILE 1" >> $config_h
  1596 +fi
  1597 +if test "$inotify" = "yes" ; then
  1598 + echo "#define CONFIG_INOTIFY 1" >> $config_h
  1599 +fi
1547 1600 if test "$brlapi" = "yes" ; then
1548 1601 echo "CONFIG_BRLAPI=yes" >> $config_mak
1549 1602 echo "#define CONFIG_BRLAPI 1" >> $config_h
... ...
linux-user/syscall.c
... ... @@ -53,6 +53,7 @@
53 53 #include <sys/statfs.h>
54 54 #include <utime.h>
55 55 #include <sys/sysinfo.h>
  56 +#include <sys/utsname.h>
56 57 //#include <sys/user.h>
57 58 #include <netinet/ip.h>
58 59 #include <netinet/tcp.h>
... ... @@ -200,7 +201,229 @@ static int gettid(void) {
200 201 return -ENOSYS;
201 202 }
202 203 #endif
203   -_syscall1(int,sys_uname,struct new_utsname *,buf)
  204 +#if TARGET_ABI_BITS == 32
  205 +_syscall3(int, sys_getdents, uint, fd, struct linux_dirent *, dirp, uint, count);
  206 +#endif
  207 +#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
  208 +_syscall3(int, sys_getdents64, uint, fd, struct linux_dirent64 *, dirp, uint, count);
  209 +#endif
  210 +_syscall2(int, sys_getpriority, int, which, int, who);
  211 +#if !defined (__x86_64__)
  212 +_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo,
  213 + loff_t *, res, uint, wh);
  214 +#endif
  215 +_syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo)
  216 +_syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
  217 +#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
  218 +_syscall3(int,sys_tgkill,int,tgid,int,pid,int,sig)
  219 +#endif
  220 +#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
  221 +_syscall2(int,sys_tkill,int,tid,int,sig)
  222 +#endif
  223 +#ifdef __NR_exit_group
  224 +_syscall1(int,exit_group,int,error_code)
  225 +#endif
  226 +#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
  227 +_syscall1(int,set_tid_address,int *,tidptr)
  228 +#endif
  229 +#if defined(USE_NPTL)
  230 +#if defined(TARGET_NR_futex) && defined(__NR_futex)
  231 +_syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
  232 + const struct timespec *,timeout,int *,uaddr2,int,val3)
  233 +#endif
  234 +#endif
  235 +
  236 +static bitmask_transtbl fcntl_flags_tbl[] = {
  237 + { TARGET_O_ACCMODE, TARGET_O_WRONLY, O_ACCMODE, O_WRONLY, },
  238 + { TARGET_O_ACCMODE, TARGET_O_RDWR, O_ACCMODE, O_RDWR, },
  239 + { TARGET_O_CREAT, TARGET_O_CREAT, O_CREAT, O_CREAT, },
  240 + { TARGET_O_EXCL, TARGET_O_EXCL, O_EXCL, O_EXCL, },
  241 + { TARGET_O_NOCTTY, TARGET_O_NOCTTY, O_NOCTTY, O_NOCTTY, },
  242 + { TARGET_O_TRUNC, TARGET_O_TRUNC, O_TRUNC, O_TRUNC, },
  243 + { TARGET_O_APPEND, TARGET_O_APPEND, O_APPEND, O_APPEND, },
  244 + { TARGET_O_NONBLOCK, TARGET_O_NONBLOCK, O_NONBLOCK, O_NONBLOCK, },
  245 + { TARGET_O_SYNC, TARGET_O_SYNC, O_SYNC, O_SYNC, },
  246 + { TARGET_FASYNC, TARGET_FASYNC, FASYNC, FASYNC, },
  247 + { TARGET_O_DIRECTORY, TARGET_O_DIRECTORY, O_DIRECTORY, O_DIRECTORY, },
  248 + { TARGET_O_NOFOLLOW, TARGET_O_NOFOLLOW, O_NOFOLLOW, O_NOFOLLOW, },
  249 + { TARGET_O_LARGEFILE, TARGET_O_LARGEFILE, O_LARGEFILE, O_LARGEFILE, },
  250 +#if defined(O_DIRECT)
  251 + { TARGET_O_DIRECT, TARGET_O_DIRECT, O_DIRECT, O_DIRECT, },
  252 +#endif
  253 + { 0, 0, 0, 0 }
  254 +};
  255 +
  256 +#define COPY_UTSNAME_FIELD(dest, src) \
  257 + do { \
  258 + /* __NEW_UTS_LEN doesn't include terminating null */ \
  259 + (void) strncpy((dest), (src), __NEW_UTS_LEN); \
  260 + (dest)[__NEW_UTS_LEN] = '\0'; \
  261 + } while (0)
  262 +
  263 +static int sys_uname(struct new_utsname *buf)
  264 +{
  265 + struct utsname uts_buf;
  266 +
  267 + if (uname(&uts_buf) < 0)
  268 + return (-1);
  269 +
  270 + /*
  271 + * Just in case these have some differences, we
  272 + * translate utsname to new_utsname (which is the
  273 + * struct linux kernel uses).
  274 + */
  275 +
  276 + bzero(buf, sizeof (*buf));
  277 + COPY_UTSNAME_FIELD(buf->sysname, uts_buf.sysname);
  278 + COPY_UTSNAME_FIELD(buf->nodename, uts_buf.nodename);
  279 + COPY_UTSNAME_FIELD(buf->release, uts_buf.release);
  280 + COPY_UTSNAME_FIELD(buf->version, uts_buf.version);
  281 + COPY_UTSNAME_FIELD(buf->machine, uts_buf.machine);
  282 +#ifdef _GNU_SOURCE
  283 + COPY_UTSNAME_FIELD(buf->domainname, uts_buf.domainname);
  284 +#endif
  285 + return (0);
  286 +
  287 +#undef COPY_UTSNAME_FIELD
  288 +}
  289 +
  290 +static int sys_getcwd1(char *buf, size_t size)
  291 +{
  292 + if (getcwd(buf, size) == NULL) {
  293 + /* getcwd() sets errno */
  294 + return (-1);
  295 + }
  296 + return (0);
  297 +}
  298 +
  299 +#ifdef CONFIG_ATFILE
  300 +/*
  301 + * Host system seems to have atfile syscall stubs available. We
  302 + * now enable them one by one as specified by target syscall_nr.h.
  303 + */
  304 +
  305 +#ifdef TARGET_NR_faccessat
  306 +static int sys_faccessat(int dirfd, const char *pathname, int mode, int flags)
  307 +{
  308 + return (faccessat(dirfd, pathname, mode, flags));
  309 +}
  310 +#endif
  311 +#ifdef TARGET_NR_fchmodat
  312 +static int sys_fchmodat(int dirfd, const char *pathname, mode_t mode, int flags)
  313 +{
  314 + return (fchmodat(dirfd, pathname, mode, flags));
  315 +}
  316 +#endif
  317 +#ifdef TARGET_NR_fchownat
  318 +static int sys_fchownat(int dirfd, const char *pathname, uid_t owner,
  319 + gid_t group, int flags)
  320 +{
  321 + return (fchownat(dirfd, pathname, owner, group, flags));
  322 +}
  323 +#endif
  324 +#ifdef __NR_fstatat64
  325 +static int sys_fstatat64(int dirfd, const char *pathname, struct stat *buf,
  326 + int flags)
  327 +{
  328 + return (fstatat(dirfd, pathname, buf, flags));
  329 +}
  330 +#endif
  331 +#ifdef __NR_newfstatat
  332 +static int sys_newfstatat(int dirfd, const char *pathname, struct stat *buf,
  333 + int flags)
  334 +{
  335 + return (fstatat(dirfd, pathname, buf, flags));
  336 +}
  337 +#endif
  338 +#ifdef TARGET_NR_futimesat
  339 +static int sys_futimesat(int dirfd, const char *pathname,
  340 + const struct timeval times[2])
  341 +{
  342 + return (futimesat(dirfd, pathname, times));
  343 +}
  344 +#endif
  345 +#ifdef TARGET_NR_linkat
  346 +static int sys_linkat(int olddirfd, const char *oldpath,
  347 + int newdirfd, const char *newpath, int flags)
  348 +{
  349 + return (linkat(olddirfd, oldpath, newdirfd, newpath, flags));
  350 +}
  351 +#endif
  352 +#ifdef TARGET_NR_mkdirat
  353 +static int sys_mkdirat(int dirfd, const char *pathname, mode_t mode)
  354 +{
  355 + return (mkdirat(dirfd, pathname, mode));
  356 +}
  357 +#endif
  358 +#ifdef TARGET_NR_mknodat
  359 +static int sys_mknodat(int dirfd, const char *pathname, mode_t mode,
  360 + dev_t dev)
  361 +{
  362 + return (mknodat(dirfd, pathname, mode, dev));
  363 +}
  364 +#endif
  365 +#ifdef TARGET_NR_openat
  366 +static int sys_openat(int dirfd, const char *pathname, int flags, ...)
  367 +{
  368 + /*
  369 + * open(2) has extra parameter 'mode' when called with
  370 + * flag O_CREAT.
  371 + */
  372 + if ((flags & O_CREAT) != 0) {
  373 + va_list ap;
  374 + mode_t mode;
  375 +
  376 + /*
  377 + * Get the 'mode' parameter and translate it to
  378 + * host bits.
  379 + */
  380 + va_start(ap, flags);
  381 + mode = va_arg(ap, mode_t);
  382 + mode = target_to_host_bitmask(mode, fcntl_flags_tbl);
  383 + va_end(ap);
  384 +
  385 + return (openat(dirfd, pathname, flags, mode));
  386 + }
  387 + return (openat(dirfd, pathname, flags));
  388 +}
  389 +#endif
  390 +#ifdef TARGET_NR_readlinkat
  391 +static int sys_readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz)
  392 +{
  393 + return (readlinkat(dirfd, pathname, buf, bufsiz));
  394 +}
  395 +#endif
  396 +#ifdef TARGET_NR_renameat
  397 +static int sys_renameat(int olddirfd, const char *oldpath,
  398 + int newdirfd, const char *newpath)
  399 +{
  400 + return (renameat(olddirfd, oldpath, newdirfd, newpath));
  401 +}
  402 +#endif
  403 +#ifdef TARGET_NR_symlinkat
  404 +static int sys_symlinkat(const char *oldpath, int newdirfd, const char *newpath)
  405 +{
  406 + return (symlinkat(oldpath, newdirfd, newpath));
  407 +}
  408 +#endif
  409 +#ifdef TARGET_NR_unlinkat
  410 +static int sys_unlinkat(int dirfd, const char *pathname, int flags)
  411 +{
  412 + return (unlinkat(dirfd, pathname, flags));
  413 +}
  414 +#endif
  415 +#ifdef TARGET_NR_utimensat
  416 +static int sys_utimensat(int dirfd, const char *pathname,
  417 + const struct timespec times[2], int flags)
  418 +{
  419 + return (utimensat(dirfd, pathname, times, flags));
  420 +}
  421 +#endif
  422 +#else /* !CONFIG_ATFILE */
  423 +
  424 +/*
  425 + * Try direct syscalls instead
  426 + */
204 427 #if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
205 428 _syscall4(int,sys_faccessat,int,dirfd,const char *,pathname,int,mode,int,flags)
206 429 #endif
... ... @@ -221,21 +444,14 @@ _syscall4(int,sys_fstatat64,int,dirfd,const char *,pathname,
221 444 _syscall3(int,sys_futimesat,int,dirfd,const char *,pathname,
222 445 const struct timeval *,times)
223 446 #endif
224   -_syscall2(int,sys_getcwd1,char *,buf,size_t,size)
225   -#if TARGET_ABI_BITS == 32
226   -_syscall3(int, sys_getdents, uint, fd, struct linux_dirent *, dirp, uint, count);
227   -#endif
228   -#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
229   -_syscall3(int, sys_getdents64, uint, fd, struct linux_dirent64 *, dirp, uint, count);
230   -#endif
231   -_syscall2(int, sys_getpriority, int, which, int, who);
232   -#if !defined (__x86_64__)
233   -_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo,
234   - loff_t *, res, uint, wh);
  447 +#if (defined(TARGET_NR_newfstatat) || defined(TARGET_NR_fstatat64) ) && \
  448 + defined(__NR_newfstatat)
  449 +_syscall4(int,sys_newfstatat,int,dirfd,const char *,pathname,
  450 + struct stat *,buf,int,flags)
235 451 #endif
236 452 #if defined(TARGET_NR_linkat) && defined(__NR_linkat)
237 453 _syscall5(int,sys_linkat,int,olddirfd,const char *,oldpath,
238   - int,newdirfd,const char *,newpath,int,flags)
  454 + int,newdirfd,const char *,newpath,int,flags)
239 455 #endif
240 456 #if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
241 457 _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)
244 460 _syscall4(int,sys_mknodat,int,dirfd,const char *,pathname,
245 461 mode_t,mode,dev_t,dev)
246 462 #endif
247   -#if (defined(TARGET_NR_newfstatat) || defined(TARGET_NR_fstatat64) ) && \
248   - defined(__NR_newfstatat)
249   -_syscall4(int,sys_newfstatat,int,dirfd,const char *,pathname,
250   - struct stat *,buf,int,flags)
251   -#endif
252 463 #if defined(TARGET_NR_openat) && defined(__NR_openat)
253 464 _syscall4(int,sys_openat,int,dirfd,const char *,pathname,int,flags,mode_t,mode)
254 465 #endif
... ... @@ -260,24 +471,10 @@ _syscall4(int,sys_readlinkat,int,dirfd,const char *,pathname,
260 471 _syscall4(int,sys_renameat,int,olddirfd,const char *,oldpath,
261 472 int,newdirfd,const char *,newpath)
262 473 #endif
263   -_syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo)
264 474 #if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
265 475 _syscall3(int,sys_symlinkat,const char *,oldpath,
266 476 int,newdirfd,const char *,newpath)
267 477 #endif
268   -_syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
269   -#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
270   -_syscall3(int,sys_tgkill,int,tgid,int,pid,int,sig)
271   -#endif
272   -#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
273   -_syscall2(int,sys_tkill,int,tid,int,sig)
274   -#endif
275   -#ifdef __NR_exit_group
276   -_syscall1(int,exit_group,int,error_code)
277   -#endif
278   -#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
279   -_syscall1(int,set_tid_address,int *,tidptr)
280   -#endif
281 478 #if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
282 479 _syscall3(int,sys_unlinkat,int,dirfd,const char *,pathname,int,flags)
283 480 #endif
... ... @@ -285,21 +482,36 @@ _syscall3(int,sys_unlinkat,int,dirfd,const char *,pathname,int,flags)
285 482 _syscall4(int,sys_utimensat,int,dirfd,const char *,pathname,
286 483 const struct timespec *,tsp,int,flags)
287 484 #endif
  485 +
  486 +#endif /* CONFIG_ATFILE */
  487 +
  488 +#ifdef CONFIG_INOTIFY
  489 +
288 490 #if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)
289   -_syscall0(int,sys_inotify_init)
  491 +static int sys_inotify_init(void)
  492 +{
  493 + return (inotify_init());
  494 +}
290 495 #endif
291 496 #if defined(TARGET_NR_inotify_add_watch) && defined(__NR_inotify_add_watch)
292   -_syscall3(int,sys_inotify_add_watch,int,fd,const char *,pathname,uint32_t,mask)
  497 +static int sys_inotify_add_watch(int fd,const char *pathname, int32_t mask)
  498 +{
  499 + return (inotify_add_watch(fd, pathname, mask));
  500 +}
293 501 #endif
294 502 #if defined(TARGET_NR_inotify_rm_watch) && defined(__NR_inotify_rm_watch)
295   -_syscall2(int,sys_inotify_rm_watch,int,fd,uint32_t,wd)
296   -#endif
297   -#if defined(USE_NPTL)
298   -#if defined(TARGET_NR_futex) && defined(__NR_futex)
299   -_syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
300   - const struct timespec *,timeout,int *,uaddr2,int,val3)
301   -#endif
  503 +static int sys_inotify_rm_watch(int fd, int32_t wd)
  504 +{
  505 + return (inotify_rm_watch(fd,pathname, wd));
  506 +}
302 507 #endif
  508 +#else
  509 +/* Userspace can usually survive runtime without inotify */
  510 +#undef TARGET_NR_inotify_init
  511 +#undef TARGET_NR_inotify_add_watch
  512 +#undef TARGET_NR_inotify_rm_watch
  513 +#endif /* CONFIG_INOTIFY */
  514 +
303 515  
304 516 extern int personality(int);
305 517 extern int flock(int, int);
... ... @@ -2580,26 +2792,6 @@ static bitmask_transtbl mmap_flags_tbl[] = {
2580 2792 { 0, 0, 0, 0 }
2581 2793 };
2582 2794  
2583   -static bitmask_transtbl fcntl_flags_tbl[] = {
2584   - { TARGET_O_ACCMODE, TARGET_O_WRONLY, O_ACCMODE, O_WRONLY, },
2585   - { TARGET_O_ACCMODE, TARGET_O_RDWR, O_ACCMODE, O_RDWR, },
2586   - { TARGET_O_CREAT, TARGET_O_CREAT, O_CREAT, O_CREAT, },
2587   - { TARGET_O_EXCL, TARGET_O_EXCL, O_EXCL, O_EXCL, },
2588   - { TARGET_O_NOCTTY, TARGET_O_NOCTTY, O_NOCTTY, O_NOCTTY, },
2589   - { TARGET_O_TRUNC, TARGET_O_TRUNC, O_TRUNC, O_TRUNC, },
2590   - { TARGET_O_APPEND, TARGET_O_APPEND, O_APPEND, O_APPEND, },
2591   - { TARGET_O_NONBLOCK, TARGET_O_NONBLOCK, O_NONBLOCK, O_NONBLOCK, },
2592   - { TARGET_O_SYNC, TARGET_O_SYNC, O_SYNC, O_SYNC, },
2593   - { TARGET_FASYNC, TARGET_FASYNC, FASYNC, FASYNC, },
2594   - { TARGET_O_DIRECTORY, TARGET_O_DIRECTORY, O_DIRECTORY, O_DIRECTORY, },
2595   - { TARGET_O_NOFOLLOW, TARGET_O_NOFOLLOW, O_NOFOLLOW, O_NOFOLLOW, },
2596   - { TARGET_O_LARGEFILE, TARGET_O_LARGEFILE, O_LARGEFILE, O_LARGEFILE, },
2597   -#if defined(O_DIRECT)
2598   - { TARGET_O_DIRECT, TARGET_O_DIRECT, O_DIRECT, O_DIRECT, },
2599   -#endif
2600   - { 0, 0, 0, 0 }
2601   -};
2602   -
2603 2795 #if defined(TARGET_I386)
2604 2796  
2605 2797 /* NOTE: there is really one LDT for all the threads */
... ...