]> granicus.if.org Git - strace/blobdiff - file.c
2005-05-31 Dmitry V. Levin <ldv@altlinux.org>
[strace] / file.c
diff --git a/file.c b/file.c
index 199ecd54fe6f9e5f7cea2223df21d2eb8252f36c..52c36312f30cd270728a198e356f2a3ddb63a55c 100644 (file)
--- a/file.c
+++ b/file.c
@@ -1,7 +1,9 @@
 /*
+#ifdef LINUX
  * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
  * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
  * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
+ * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
 #include "defs.h"
 
 #include <dirent.h>
-#ifdef linux
+#ifdef LINUX
 #define dirent kernel_dirent
+#define dirent64 kernel_dirent64
 #include <linux/types.h>
 #include <linux/dirent.h>
 #undef dirent
+#undef dirent64
 #else
 #define kernel_dirent dirent
 #endif
 
-#ifdef linux
-#  include <asm/stat.h>
+#ifdef LINUX
+#  ifdef LINUXSPARC
+struct stat {
+       unsigned short  st_dev;
+       unsigned int    st_ino;
+       unsigned short  st_mode;
+       short           st_nlink;
+       unsigned short  st_uid;
+       unsigned short  st_gid;
+       unsigned short  st_rdev;
+       unsigned int    st_size;
+       int             st_atime;
+       unsigned int    __unused1;
+       int             st_mtime;
+       unsigned int    __unused2;
+       int             st_ctime;
+       unsigned int    __unused3;
+       int             st_blksize;
+       int             st_blocks;
+       unsigned int    __unused4[2];
+};
+#if defined(SPARC64)
+struct stat_sparc64 {
+       unsigned int    st_dev;
+       unsigned long   st_ino;
+       unsigned int    st_mode;
+       unsigned int    st_nlink;
+       unsigned int    st_uid;
+       unsigned int    st_gid;
+       unsigned int    st_rdev;
+       long            st_size;
+       long            st_atime;
+       long            st_mtime;
+       long            st_ctime;
+       long            st_blksize;
+       long            st_blocks;
+       unsigned long   __unused4[2];
+};
+#endif /* SPARC64 */
+#    define stat kernel_stat
+#    include <asm/stat.h>
+#    undef stat
+#  else
+#    undef dev_t
+#    undef ino_t
+#    undef mode_t
+#    undef nlink_t
+#    undef uid_t
+#    undef gid_t
+#    undef off_t
+#    undef loff_t
+
+#    define dev_t __kernel_dev_t
+#    define ino_t __kernel_ino_t
+#    define mode_t __kernel_mode_t
+#    define nlink_t __kernel_nlink_t
+#    define uid_t __kernel_uid_t
+#    define gid_t __kernel_gid_t
+#    define off_t __kernel_off_t
+#    define loff_t __kernel_loff_t
+
+#    include <asm/stat.h>
+
+#    undef dev_t
+#    undef ino_t
+#    undef mode_t
+#    undef nlink_t
+#    undef uid_t
+#    undef gid_t
+#    undef off_t
+#    undef loff_t
+
+#    define dev_t dev_t
+#    define ino_t ino_t
+#    define mode_t mode_t
+#    define nlink_t nlink_t
+#    define uid_t uid_t
+#    define gid_t gid_t
+#    define off_t off_t
+#    define loff_t loff_t
+#  endif
+#  ifdef HPPA  /* asm-parisc/stat.h defines stat64 */
+#    undef stat64
+#  endif
 #  define stat libc_stat
+#  define stat64 libc_stat64
 #  include <sys/stat.h>
 #  undef stat
+#  undef stat64
+   /* These might be macros. */
+#  undef st_atime
+#  undef st_mtime
+#  undef st_ctime
+#  ifdef HPPA
+#    define stat64 hpux_stat64
+#  endif
 #else
 #  include <sys/stat.h>
 #endif
 #  include <sys/cred.h>
 #endif /* SVR4 */
 
+#ifdef HAVE_SYS_VFS_H
 #include <sys/vfs.h>
+#endif
+
+#ifdef HAVE_LINUX_XATTR_H
+#include <linux/xattr.h>
+#elif defined linux
+#define XATTR_CREATE 1
+#define XATTR_REPLACE 2
+#endif
+
+#ifdef FREEBSD
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#endif
+
+#if HAVE_LONG_LONG_OFF_T
+/*
+ * Ugly hacks for systems that have typedef long long off_t
+ */
+
+#define stat64 stat
+#define HAVE_STAT64 1  /* Ugly hack */
+
+#define        sys_stat64      sys_stat
+#define sys_fstat64    sys_fstat
+#define sys_lstat64    sys_lstat
+#define sys_lseek64    sys_lseek
+#define sys_truncate64 sys_truncate
+#define sys_ftruncate64        sys_ftruncate
+#endif
 
 #ifdef MAJOR_IN_SYSMACROS
 #include <sys/sysmacros.h>
  * Unix says r/w/rw are 0/1/2, so we make them true flags 1/2/3 by
  * adding 1.  Just remember to add 1 to any arg decoded with openmodes.
  */
-struct xlat openmodes[] = {
+const struct xlat openmodes[] = {
        { O_RDWR+1,     "O_RDWR"        },
        { O_RDONLY+1,   "O_RDONLY"      },
        { O_WRONLY+1,   "O_WRONLY"      },
@@ -108,13 +234,29 @@ struct xlat openmodes[] = {
        { O_PRIV,       "O_PRIV"        },
 #endif
 #ifdef O_DIRECT
-   { O_DIRECT, "O_DIRECT"  },
+       { O_DIRECT,     "O_DIRECT"      },
 #endif
 #ifdef O_LARGEFILE
-   { O_LARGEFILE,  "O_LARGEFILE"   },
+# if O_LARGEFILE == 0          /* biarch platforms in 64-bit mode */
+#  undef O_LARGEFILE
+#  ifdef SPARC64
+#   define O_LARGEFILE 0x40000
+#  elif defined X86_64 || defined S390X
+#   define O_LARGEFILE 0100000
+#  endif
+# endif
+# ifdef O_LARGEFILE
+       { O_LARGEFILE,  "O_LARGEFILE"   },
+# endif
 #endif
 #ifdef O_DIRECTORY
-   { O_DIRECTORY,  "O_DIRECTORY"   },
+       { O_DIRECTORY,  "O_DIRECTORY"   },
+#endif
+#ifdef O_NOFOLLOW
+       { O_NOFOLLOW,   "O_NOFOLLOW"    },
+#endif
+#ifdef O_NOATIME
+       { O_NOATIME,    "O_NOATIME"     },
 #endif
 
 #ifdef FNDELAY
@@ -155,6 +297,12 @@ struct xlat openmodes[] = {
 #endif
 #ifdef FNOCTTY
        { FNOCTTY,      "FNOCTTY"       },
+#endif
+#ifdef O_SHLOCK
+       { O_SHLOCK,     "O_SHLOCK"      },
+#endif
+#ifdef O_EXLOCK
+       { O_EXLOCK,     "O_EXLOCK"      },
 #endif
        { 0,            NULL            },
 };
@@ -167,7 +315,7 @@ struct tcb *tcp;
                printpath(tcp, tcp->u_arg[0]);
                tprintf(", ");
                /* flags */
-               printflags(openmodes, tcp->u_arg[1] + 1);
+               printflags(openmodes, tcp->u_arg[1] + 1, "O_???");
                if (tcp->u_arg[1] & O_CREAT) {
                        /* mode */
                        tprintf(", %#lo", tcp->u_arg[2]);
@@ -177,7 +325,7 @@ struct tcb *tcp;
 }
 
 #ifdef LINUXSPARC
-struct xlat openmodessol[] = {
+const struct xlat openmodessol[] = {
        { 0,            "O_RDWR"        },
        { 1,            "O_RDONLY"      },
        { 2,            "O_WRONLY"      },
@@ -203,7 +351,7 @@ struct tcb *tcp;
                printpath(tcp, tcp->u_arg[0]);
                tprintf(", ");
                /* flags */
-               printflags(openmodessol, tcp->u_arg[1] + 1);
+               printflags(openmodessol, tcp->u_arg[1] + 1, "O_???");
                if (tcp->u_arg[1] & 0x100) {
                        /* mode */
                        tprintf(", %#lo", tcp->u_arg[2]);
@@ -225,7 +373,7 @@ struct tcb *tcp;
        return 0;
 }
 
-static struct xlat access_flags[] = {
+static const struct xlat access_flags[] = {
        { F_OK,         "F_OK",         },
        { R_OK,         "R_OK"          },
        { W_OK,         "W_OK"          },
@@ -246,7 +394,7 @@ struct tcb *tcp;
        if (entering(tcp)) {
                printpath(tcp, tcp->u_arg[0]);
                tprintf(", ");
-               printflags(access_flags, tcp->u_arg[1]);
+               printflags(access_flags, tcp->u_arg[1], "?_OK");
        }
        return 0;
 }
@@ -261,42 +409,54 @@ struct tcb *tcp;
        return RVAL_OCTAL;
 }
 
-static struct xlat whence[] = {
+static const struct xlat whence[] = {
        { SEEK_SET,     "SEEK_SET"      },
        { SEEK_CUR,     "SEEK_CUR"      },
        { SEEK_END,     "SEEK_END"      },
        { 0,            NULL            },
 };
 
+#ifndef HAVE_LONG_LONG_OFF_T
 int
 sys_lseek(tcp)
 struct tcb *tcp;
 {
+       off_t offset;
+       int _whence;
+
        if (entering(tcp)) {
                tprintf("%ld, ", tcp->u_arg[0]);
-               if (tcp->u_arg[2] == SEEK_SET)
-                       tprintf("%lu, ", tcp->u_arg[1]);
+               offset = tcp->u_arg[1];
+               _whence = tcp->u_arg[2];
+               if (_whence == SEEK_SET)
+                       tprintf("%lu, ", offset);
                else
-                       tprintf("%ld, ", tcp->u_arg[1]);
-               printxval(whence, tcp->u_arg[2], "SEEK_???");
+                       tprintf("%ld, ", offset);
+               printxval(whence, _whence, "SEEK_???");
        }
        return RVAL_UDECIMAL;
 }
+#endif
 
-#ifdef linux
+#ifdef LINUX
 int
 sys_llseek (tcp)
 struct tcb *tcp;
 {
     if (entering(tcp)) {
+       /*
+        * This one call takes explicitly two 32-bit arguments hi, lo,
+        * rather than one 64-bit argument for which LONG_LONG works
+        * appropriate for the native byte order.
+        */
        if (tcp->u_arg[4] == SEEK_SET)
            tprintf("%ld, %llu, ", tcp->u_arg[0],
                    (((long long int) tcp->u_arg[1]) << 32
-                    | (unsigned long long) tcp->u_arg[2]));
+                    | (unsigned long long) (unsigned) tcp->u_arg[2]));
        else
            tprintf("%ld, %lld, ", tcp->u_arg[0],
                    (((long long int) tcp->u_arg[1]) << 32
-                    | (unsigned long long) tcp->u_arg[2]));
+                    | (unsigned long long) (unsigned) tcp->u_arg[2]));
     }
     else {
        long long int off;
@@ -308,8 +468,44 @@ struct tcb *tcp;
     }
     return 0;
 }
+
+int
+sys_readahead (tcp)
+struct tcb *tcp;
+{
+    if (entering(tcp)) {
+       tprintf("%ld, %lld, %ld", tcp->u_arg[0],
+# if defined IA64 || defined X86_64 || defined ALPHA
+               (long long int) tcp->u_arg[1], tcp->u_arg[2]
+# else
+               LONG_LONG(tcp->u_arg[1], tcp->u_arg[2]), tcp->u_arg[3]
+# endif
+               );
+    }
+    return 0;
+}
+#endif
+
+#if _LFS64_LARGEFILE || HAVE_LONG_LONG_OFF_T
+int
+sys_lseek64 (tcp)
+struct tcb *tcp;
+{
+       if (entering(tcp)) {
+               long long offset;
+               ALIGN64 (tcp, 1);       /* FreeBSD aligns off_t args */
+               offset = LONG_LONG(tcp->u_arg [1], tcp->u_arg[2]);
+               if (tcp->u_arg[3] == SEEK_SET)
+                       tprintf("%ld, %llu, ", tcp->u_arg[0], offset);
+               else
+                       tprintf("%ld, %lld, ", tcp->u_arg[0], offset);
+               printxval(whence, tcp->u_arg[3], "SEEK_???");
+       }
+       return RVAL_LUDECIMAL;
+}
 #endif
 
+#ifndef HAVE_LONG_LONG_OFF_T
 int
 sys_truncate(tcp)
 struct tcb *tcp;
@@ -320,7 +516,23 @@ struct tcb *tcp;
        }
        return 0;
 }
+#endif
+
+#if _LFS64_LARGEFILE || HAVE_LONG_LONG_OFF_T
+int
+sys_truncate64(tcp)
+struct tcb *tcp;
+{
+       if (entering(tcp)) {
+               ALIGN64 (tcp, 1);
+               printpath(tcp, tcp->u_arg[0]);
+               tprintf(", %llu", LONG_LONG(tcp->u_arg[1],tcp->u_arg[2]));
+       }
+       return 0;
+}
+#endif
 
+#ifndef HAVE_LONG_LONG_OFF_T
 int
 sys_ftruncate(tcp)
 struct tcb *tcp;
@@ -330,10 +542,25 @@ struct tcb *tcp;
        }
        return 0;
 }
+#endif
+
+#if _LFS64_LARGEFILE || HAVE_LONG_LONG_OFF_T
+int
+sys_ftruncate64(tcp)
+struct tcb *tcp;
+{
+       if (entering(tcp)) {
+               ALIGN64 (tcp, 1);
+               tprintf("%ld, %llu", tcp->u_arg[0],
+                       LONG_LONG(tcp->u_arg[1] ,tcp->u_arg[2]));
+       }
+       return 0;
+}
+#endif
 
 /* several stats */
 
-static struct xlat modetypes[] = {
+static const struct xlat modetypes[] = {
        { S_IFREG,      "S_IFREG"       },
        { S_IFSOCK,     "S_IFSOCK"      },
        { S_IFIFO,      "S_IFIFO"       },
@@ -344,12 +571,12 @@ static struct xlat modetypes[] = {
        { 0,            NULL            },
 };
 
-static char *
+static const char *
 sprintmode(mode)
 int mode;
 {
        static char buf[64];
-       char *s;
+       const char *s;
 
        if ((mode & S_IFMT) == 0)
                s = "";
@@ -381,7 +608,7 @@ time_t t;
        }
        tmp = localtime(&t);
        sprintf(buf, "%02d/%02d/%02d-%02d:%02d:%02d",
-               tmp->tm_year, tmp->tm_mon + 1, tmp->tm_mday,
+               tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday,
                tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
        return buf;
 }
@@ -416,7 +643,7 @@ struct solstat {
 static void
 printstatsol(tcp, addr)
 struct tcb *tcp;
-int addr;
+long addr;
 {
        struct solstat statbuf;
 
@@ -425,7 +652,7 @@ int addr;
                return;
        }
        if (syserror(tcp) || !verbose(tcp)) {
-               tprintf("%#x", addr);
+               tprintf("%#lx", addr);
                return;
        }
        if (umove(tcp, addr, &statbuf) < 0) {
@@ -465,8 +692,115 @@ int addr;
        else
                tprintf("...}");
 }
+
+#if defined (SPARC64)
+static void
+printstat_sparc64(tcp, addr)
+struct tcb *tcp;
+long addr;
+{
+       struct stat_sparc64 statbuf;
+
+       if (!addr) {
+               tprintf("NULL");
+               return;
+       }
+       if (syserror(tcp) || !verbose(tcp)) {
+               tprintf("%#lx", addr);
+               return;
+       }
+       if (umove(tcp, addr, &statbuf) < 0) {
+               tprintf("{...}");
+               return;
+       }
+
+       if (!abbrev(tcp)) {
+               tprintf("{st_dev=makedev(%lu, %lu), st_ino=%lu, st_mode=%s, ",
+                       (unsigned long) major(statbuf.st_dev),
+                       (unsigned long) minor(statbuf.st_dev),
+                       (unsigned long) statbuf.st_ino,
+                       sprintmode(statbuf.st_mode));
+               tprintf("st_nlink=%lu, st_uid=%lu, st_gid=%lu, ",
+                       (unsigned long) statbuf.st_nlink,
+                       (unsigned long) statbuf.st_uid,
+                       (unsigned long) statbuf.st_gid);
+               tprintf("st_blksize=%lu, ",
+                       (unsigned long) statbuf.st_blksize);
+               tprintf("st_blocks=%lu, ",
+                       (unsigned long) statbuf.st_blocks);
+       }
+       else
+               tprintf("{st_mode=%s, ", sprintmode(statbuf.st_mode));
+       switch (statbuf.st_mode & S_IFMT) {
+       case S_IFCHR: case S_IFBLK:
+               tprintf("st_rdev=makedev(%lu, %lu), ",
+                       (unsigned long) major(statbuf.st_rdev),
+                       (unsigned long) minor(statbuf.st_rdev));
+               break;
+       default:
+               tprintf("st_size=%lu, ", statbuf.st_size);
+               break;
+       }
+       if (!abbrev(tcp)) {
+               tprintf("st_atime=%s, ", sprinttime(statbuf.st_atime));
+               tprintf("st_mtime=%s, ", sprinttime(statbuf.st_mtime));
+               tprintf("st_ctime=%s", sprinttime(statbuf.st_ctime));
+               tprintf("}");
+       }
+       else
+               tprintf("...}");
+}
+#endif /* SPARC64 */
 #endif /* LINUXSPARC */
 
+const struct xlat fileflags[] = {
+#ifdef FREEBSD
+       { UF_NODUMP,    "UF_NODUMP"     },
+       { UF_IMMUTABLE, "UF_IMMUTABLE"  },
+       { UF_APPEND,    "UF_APPEND"     },
+       { UF_OPAQUE,    "UF_OPAQUE"     },
+       { UF_NOUNLINK,  "UF_NOUNLINK"   },
+       { SF_ARCHIVED,  "SF_ARCHIVED"   },
+       { SF_IMMUTABLE, "SF_IMMUTABLE"  },
+       { SF_APPEND,    "SF_APPEND"     },
+       { SF_NOUNLINK,  "SF_NOUNLINK"   },
+#elif UNIXWARE >= 2
+#ifdef         _S_ISMLD
+       { _S_ISMLD,     "_S_ISMLD"      },
+#endif
+#ifdef         _S_ISMOUNTED
+       { _S_ISMOUNTED, "_S_ISMOUNTED"  },
+#endif
+#endif
+       { 0,            NULL            },
+};
+
+#ifdef FREEBSD
+int
+sys_chflags(tcp)
+struct tcb *tcp;
+{
+       if (entering(tcp)) {
+               printpath(tcp, tcp->u_arg[0]);
+               tprintf(", ");
+               printflags(fileflags, tcp->u_arg[1], "UF_???");
+       }
+       return 0;
+}
+
+int
+sys_fchflags(tcp)
+struct tcb *tcp;
+{
+       if (entering(tcp)) {
+               tprintf("%ld, ", tcp->u_arg[0]);
+               printflags(fileflags, tcp->u_arg[1], "UF_???");
+       }
+       return 0;
+}
+#endif
+
+#ifndef HAVE_LONG_LONG_OFF_T
 static void
 realprintstat(tcp, statbuf)
 struct tcb *tcp;
@@ -482,26 +816,26 @@ struct stat *statbuf;
                    (unsigned long) statbuf->st_nlink,
                    (unsigned long) statbuf->st_uid,
                    (unsigned long) statbuf->st_gid);
-#ifdef HAVE_ST_BLKSIZE
+#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
            tprintf("st_blksize=%lu, ", (unsigned long) statbuf->st_blksize);
-#endif /* HAVE_ST_BLKSIZE */
-#ifdef HAVE_ST_BLOCKS
+#endif /* HAVE_STRUCT_STAT_ST_BLKSIZE */
+#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
            tprintf("st_blocks=%lu, ", (unsigned long) statbuf->st_blocks);
-#endif /* HAVE_ST_BLOCKS */
+#endif /* HAVE_STRUCT_STAT_ST_BLOCKS */
     }
     else
            tprintf("{st_mode=%s, ", sprintmode(statbuf->st_mode));
     switch (statbuf->st_mode & S_IFMT) {
     case S_IFCHR: case S_IFBLK:
-#ifdef HAVE_ST_RDEV
+#ifdef HAVE_STRUCT_STAT_ST_RDEV
            tprintf("st_rdev=makedev(%lu, %lu), ",
                    (unsigned long) major(statbuf->st_rdev),
                    (unsigned long) minor(statbuf->st_rdev));
-#else /* !HAVE_ST_RDEV */
+#else /* !HAVE_STRUCT_STAT_ST_RDEV */
            tprintf("st_size=makedev(%lu, %lu), ",
                    (unsigned long) major(statbuf->st_size),
                    (unsigned long) minor(statbuf->st_size));
-#endif /* !HAVE_ST_RDEV */
+#endif /* !HAVE_STRUCT_STAT_ST_RDEV */
            break;
     default:
            tprintf("st_size=%lu, ", statbuf->st_size);
@@ -510,7 +844,25 @@ struct stat *statbuf;
     if (!abbrev(tcp)) {
            tprintf("st_atime=%s, ", sprinttime(statbuf->st_atime));
            tprintf("st_mtime=%s, ", sprinttime(statbuf->st_mtime));
-           tprintf("st_ctime=%s}", sprinttime(statbuf->st_ctime));
+           tprintf("st_ctime=%s", sprinttime(statbuf->st_ctime));
+#if HAVE_STRUCT_STAT_ST_FLAGS
+               tprintf(", st_flags=");
+               printflags(fileflags, statbuf->st_flags, "UF_???");
+#endif
+#if HAVE_STRUCT_STAT_ST_ACLCNT
+               tprintf(", st_aclcnt=%d", statbuf->st_aclcnt);
+#endif
+#if HAVE_STRUCT_STAT_ST_LEVEL
+               tprintf(", st_level=%ld", statbuf->st_level);
+#endif
+#if HAVE_STRUCT_STAT_ST_FSTYPE
+               tprintf(", st_fstype=%.*s",
+                       (int) sizeof statbuf->st_fstype, statbuf->st_fstype);
+#endif
+#if HAVE_STRUCT_STAT_ST_GEN
+               tprintf(", st_gen=%u", statbuf->st_gen);
+#endif
+               tprintf("}");
     }
     else
            tprintf("...}");
@@ -520,7 +872,7 @@ struct stat *statbuf;
 static void
 printstat(tcp, addr)
 struct tcb *tcp;
-int addr;
+long addr;
 {
        struct stat statbuf;
 
@@ -529,6 +881,12 @@ int addr;
                printstatsol(tcp, addr);
                return;
        }
+#ifdef SPARC64
+       else if (current_personality == 2) {
+               printstat_sparc64(tcp, addr);
+               return;
+       }
+#endif
 #endif /* LINUXSPARC */
 
        if (!addr) {
@@ -536,7 +894,7 @@ int addr;
                return;
        }
        if (syserror(tcp) || !verbose(tcp)) {
-               tprintf("%#x", addr);
+               tprintf("%#lx", addr);
                return;
        }
        if (umove(tcp, addr, &statbuf) < 0) {
@@ -546,8 +904,115 @@ int addr;
 
        realprintstat(tcp, &statbuf);
 }
+#endif /* !HAVE_LONG_LONG_OFF_T */
+
+#ifdef HAVE_STAT64
+static void
+printstat64(tcp, addr)
+struct tcb *tcp;
+long addr;
+{
+       struct stat64 statbuf;
+
+#ifdef LINUXSPARC
+       if (current_personality == 1) {
+               printstatsol(tcp, addr);
+               return;
+       }
+#ifdef SPARC64
+       else if (current_personality == 2) {
+               printstat_sparc64(tcp, addr);
+               return;
+       }
+#endif
+#endif /* LINUXSPARC */
+
+       if (!addr) {
+               tprintf("NULL");
+               return;
+       }
+       if (syserror(tcp) || !verbose(tcp)) {
+               tprintf("%#lx", addr);
+               return;
+       }
+       if (umove(tcp, addr, &statbuf) < 0) {
+               tprintf("{...}");
+               return;
+       }
+
+       if (!abbrev(tcp)) {
+#ifdef HAVE_LONG_LONG
+               tprintf("{st_dev=makedev(%lu, %lu), st_ino=%llu, st_mode=%s, ",
+#else
+               tprintf("{st_dev=makedev(%lu, %lu), st_ino=%lu, st_mode=%s, ",
+#endif
+                       (unsigned long) major(statbuf.st_dev),
+                       (unsigned long) minor(statbuf.st_dev),
+#ifdef HAVE_LONG_LONG
+                       (unsigned long long) statbuf.st_ino,
+#else
+                       (unsigned long) statbuf.st_ino,
+#endif
+                       sprintmode(statbuf.st_mode));
+               tprintf("st_nlink=%lu, st_uid=%lu, st_gid=%lu, ",
+                       (unsigned long) statbuf.st_nlink,
+                       (unsigned long) statbuf.st_uid,
+                       (unsigned long) statbuf.st_gid);
+#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
+               tprintf("st_blksize=%lu, ",
+                       (unsigned long) statbuf.st_blksize);
+#endif /* HAVE_STRUCT_STAT_ST_BLKSIZE */
+#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
+               tprintf("st_blocks=%lu, ", (unsigned long) statbuf.st_blocks);
+#endif /* HAVE_STRUCT_STAT_ST_BLOCKS */
+       }
+       else
+               tprintf("{st_mode=%s, ", sprintmode(statbuf.st_mode));
+       switch (statbuf.st_mode & S_IFMT) {
+       case S_IFCHR: case S_IFBLK:
+#ifdef HAVE_STRUCT_STAT_ST_RDEV
+               tprintf("st_rdev=makedev(%lu, %lu), ",
+                       (unsigned long) major(statbuf.st_rdev),
+                       (unsigned long) minor(statbuf.st_rdev));
+#else /* !HAVE_STRUCT_STAT_ST_RDEV */
+               tprintf("st_size=makedev(%lu, %lu), ",
+                       (unsigned long) major(statbuf.st_size),
+                       (unsigned long) minor(statbuf.st_size));
+#endif /* !HAVE_STRUCT_STAT_ST_RDEV */
+               break;
+       default:
+               tprintf("st_size=%llu, ", statbuf.st_size);
+               break;
+       }
+       if (!abbrev(tcp)) {
+               tprintf("st_atime=%s, ", sprinttime(statbuf.st_atime));
+               tprintf("st_mtime=%s, ", sprinttime(statbuf.st_mtime));
+               tprintf("st_ctime=%s", sprinttime(statbuf.st_ctime));
+#if HAVE_STRUCT_STAT_ST_FLAGS
+               tprintf(", st_flags=");
+               printflags(fileflags, statbuf.st_flags, "UF_???");
+#endif
+#if HAVE_STRUCT_STAT_ST_ACLCNT
+               tprintf(", st_aclcnt=%d", statbuf.st_aclcnt);
+#endif
+#if HAVE_STRUCT_STAT_ST_LEVEL
+               tprintf(", st_level=%ld", statbuf.st_level);
+#endif
+#if HAVE_STRUCT_STAT_ST_FSTYPE
+               tprintf(", st_fstype=%.*s",
+                       (int) sizeof statbuf.st_fstype, statbuf.st_fstype);
+#endif
+#if HAVE_STRUCT_STAT_ST_GEN
+               tprintf(", st_gen=%u", statbuf.st_gen);
+#endif
+               tprintf("}");
+       }
+       else
+               tprintf("...}");
+}
+#endif /* HAVE_STAT64 */
 
-#ifdef linux
+#if defined(LINUX) && defined(HAVE_STRUCT___OLD_KERNEL_STAT)
 static void
 convertoldstat(oldbuf, newbuf)
 const struct __old_kernel_stat *oldbuf;
@@ -567,14 +1032,12 @@ struct stat *newbuf;
     newbuf->st_blksize=0;      /* not supported in old_stat */
     newbuf->st_blocks=0;               /* not supported in old_stat */
 }
-#endif
 
 
-#ifdef linux
 static void
 printoldstat(tcp, addr)
 struct tcb *tcp;
-int addr;
+long addr;
 {
        struct __old_kernel_stat statbuf;
        struct stat newstatbuf;
@@ -591,7 +1054,7 @@ int addr;
                return;
        }
        if (syserror(tcp) || !verbose(tcp)) {
-               tprintf("%#x", addr);
+               tprintf("%#lx", addr);
                return;
        }
        if (umove(tcp, addr, &statbuf) < 0) {
@@ -602,9 +1065,9 @@ int addr;
        convertoldstat(&statbuf, &newstatbuf);
        realprintstat(tcp, &newstatbuf);
 }
-#endif
-
+#endif /* LINUX && !IA64 && !HPPA && !X86_64 && !S390 && !S390X */
 
+#ifndef HAVE_LONG_LONG_OFF_T
 int
 sys_stat(tcp)
 struct tcb *tcp;
@@ -617,8 +1080,26 @@ struct tcb *tcp;
        }
        return 0;
 }
+#endif
+
+int
+sys_stat64(tcp)
+struct tcb *tcp;
+{
+#ifdef HAVE_STAT64
+       if (entering(tcp)) {
+               printpath(tcp, tcp->u_arg[0]);
+               tprintf(", ");
+       } else {
+               printstat64(tcp, tcp->u_arg[1]);
+       }
+       return 0;
+#else
+       return printargs(tcp);
+#endif
+}
 
-#ifdef linux
+#if defined(LINUX) && defined(HAVE_STRUCT___OLD_KERNEL_STAT)
 int
 sys_oldstat(tcp)
 struct tcb *tcp;
@@ -631,8 +1112,9 @@ struct tcb *tcp;
        }
        return 0;
 }
-#endif
+#endif /* LINUX && HAVE_STRUCT___OLD_KERNEL_STAT */
 
+#ifndef HAVE_LONG_LONG_OFF_T
 int
 sys_fstat(tcp)
 struct tcb *tcp;
@@ -644,8 +1126,25 @@ struct tcb *tcp;
        }
        return 0;
 }
+#endif
+
+int
+sys_fstat64(tcp)
+struct tcb *tcp;
+{
+#ifdef HAVE_STAT64
+       if (entering(tcp))
+               tprintf("%ld, ", tcp->u_arg[0]);
+       else {
+               printstat64(tcp, tcp->u_arg[1]);
+       }
+       return 0;
+#else
+       return printargs(tcp);
+#endif
+}
 
-#ifdef linux
+#if defined(LINUX) && defined(HAVE_STRUCT___OLD_KERNEL_STAT)
 int
 sys_oldfstat(tcp)
 struct tcb *tcp;
@@ -657,8 +1156,9 @@ struct tcb *tcp;
        }
        return 0;
 }
-#endif
+#endif /* LINUX && HAVE_STRUCT___OLD_KERNEL_STAT */
 
+#ifndef HAVE_LONG_LONG_OFF_T
 int
 sys_lstat(tcp)
 struct tcb *tcp;
@@ -671,8 +1171,26 @@ struct tcb *tcp;
        }
        return 0;
 }
+#endif
+
+int
+sys_lstat64(tcp)
+struct tcb *tcp;
+{
+#ifdef HAVE_STAT64
+       if (entering(tcp)) {
+               printpath(tcp, tcp->u_arg[0]);
+               tprintf(", ");
+       } else {
+               printstat64(tcp, tcp->u_arg[1]);
+       }
+       return 0;
+#else
+       return printargs(tcp);
+#endif
+}
 
-#ifdef linux
+#if defined(LINUX) && defined(HAVE_STRUCT___OLD_KERNEL_STAT)
 int
 sys_oldlstat(tcp)
 struct tcb *tcp;
@@ -685,7 +1203,7 @@ struct tcb *tcp;
        }
        return 0;
 }
-#endif
+#endif /* LINUX && HAVE_STRUCT___OLD_KERNEL_STAT */
 
 
 #if defined(SVR4) || defined(LINUXSPARC)
@@ -699,6 +1217,11 @@ struct tcb *tcp;
                printpath(tcp, tcp->u_arg[1]);
                tprintf(", ");
        } else {
+#ifdef _STAT64_VER
+               if (tcp->u_arg[0] == _STAT64_VER)
+                       printstat64 (tcp, tcp->u_arg[2]);
+               else
+#endif
                printstat(tcp, tcp->u_arg[2]);
        }
        return 0;
@@ -711,6 +1234,11 @@ struct tcb *tcp;
        if (entering(tcp))
                tprintf("%ld, %ld, ", tcp->u_arg[0], tcp->u_arg[1]);
        else {
+#ifdef _STAT64_VER
+               if (tcp->u_arg[0] == _STAT64_VER)
+                       printstat64 (tcp, tcp->u_arg[2]);
+               else
+#endif
                printstat(tcp, tcp->u_arg[2]);
        }
        return 0;
@@ -725,6 +1253,11 @@ struct tcb *tcp;
                printpath(tcp, tcp->u_arg[1]);
                tprintf(", ");
        } else {
+#ifdef _STAT64_VER
+               if (tcp->u_arg[0] == _STAT64_VER)
+                       printstat64 (tcp, tcp->u_arg[2]);
+               else
+#endif
                printstat(tcp, tcp->u_arg[2]);
        }
        return 0;
@@ -746,11 +1279,11 @@ struct tcb *tcp;
                        tprintf(", makedev(%lu, %lu)",
                                (unsigned long) ((tcp->u_arg[3] >> 18) & 0x3fff),
                                (unsigned long) (tcp->u_arg[3] & 0x3ffff));
-#else          
+#else
                        tprintf(", makedev(%lu, %lu)",
                                (unsigned long) major(tcp->u_arg[3]),
                                (unsigned long) minor(tcp->u_arg[3]));
-#endif                         
+#endif
                        break;
                default:
                        break;
@@ -759,44 +1292,169 @@ struct tcb *tcp;
        return 0;
 }
 
+#ifdef HAVE_SYS_ACL_H
+
+#include <sys/acl.h>
+
+const struct xlat aclcmds[] = {
+#ifdef SETACL
+       { SETACL,       "SETACL"        },
+#endif
+#ifdef GETACL
+       { GETACL,       "GETACL"        },
+#endif
+#ifdef GETACLCNT
+       { GETACLCNT,    "GETACLCNT"     },
+#endif
+#ifdef ACL_GET
+       { ACL_GET,      "ACL_GET"       },
+#endif
+#ifdef ACL_SET
+       { ACL_SET,      "ACL_SET"       },
+#endif
+#ifdef ACL_CNT
+       { ACL_CNT,      "ACL_CNT"       },
+#endif
+       { 0,            NULL            },
+};
+
+int
+sys_acl(tcp)
+struct tcb *tcp;
+{
+       if (entering(tcp)) {
+               printpath(tcp, tcp->u_arg[0]);
+               tprintf(", ");
+               printxval(aclcmds, tcp->u_arg[1], "???ACL???");
+               tprintf(", %ld", tcp->u_arg[2]);
+               /*
+                * FIXME - dump out the list of aclent_t's pointed to
+                * by "tcp->u_arg[3]" if it's not NULL.
+                */
+               if (tcp->u_arg[3])
+                       tprintf(", %#lx", tcp->u_arg[3]);
+               else
+                       tprintf(", NULL");
+       }
+       return 0;
+}
+
+
+int
+sys_facl(tcp)
+struct tcb *tcp;
+{
+       if (entering(tcp)) {
+               tprintf("%ld, ", tcp->u_arg[0]);
+               printxval(aclcmds, tcp->u_arg[1], "???ACL???");
+               tprintf(", %ld", tcp->u_arg[2]);
+               /*
+                * FIXME - dump out the list of aclent_t's pointed to
+                * by "tcp->u_arg[3]" if it's not NULL.
+                */
+               if (tcp->u_arg[3])
+                       tprintf(", %#lx", tcp->u_arg[3]);
+               else
+                       tprintf(", NULL");
+       }
+       return 0;
+}
+
+
+const struct xlat aclipc[] = {
+#ifdef IPC_SHM
+       { IPC_SHM,      "IPC_SHM"       },
+#endif
+#ifdef IPC_SEM
+       { IPC_SEM,      "IPC_SEM"       },
+#endif
+#ifdef IPC_MSG
+       { IPC_MSG,      "IPC_MSG"       },
+#endif
+       { 0,            NULL            },
+};
+
+
+int
+sys_aclipc(tcp)
+struct tcb *tcp;
+{
+       if (entering(tcp)) {
+               printxval(aclipc, tcp->u_arg[0], "???IPC???");
+               tprintf(", %#lx, ", tcp->u_arg[1]);
+               printxval(aclcmds, tcp->u_arg[2], "???ACL???");
+               tprintf(", %ld", tcp->u_arg[3]);
+               /*
+                * FIXME - dump out the list of aclent_t's pointed to
+                * by "tcp->u_arg[4]" if it's not NULL.
+                */
+               if (tcp->u_arg[4])
+                       tprintf(", %#lx", tcp->u_arg[4]);
+               else
+                       tprintf(", NULL");
+       }
+       return 0;
+}
+
+
+
+#endif /* HAVE_SYS_ACL_H */
+
 #endif /* SVR4 || LINUXSPARC */
 
-#ifdef linux
+#ifdef LINUX
 
-static struct xlat fsmagic[] = {
+static const struct xlat fsmagic[] = {
+       { 0x73757245,   "CODA_SUPER_MAGIC"      },
+       { 0x012ff7b7,   "COH_SUPER_MAGIC"       },
+       { 0x1373,       "DEVFS_SUPER_MAGIC"     },
+       { 0x1cd1,       "DEVPTS_SUPER_MAGIC"    },
+       { 0x414A53,     "EFS_SUPER_MAGIC"       },
        { 0xef51,       "EXT2_OLD_SUPER_MAGIC"  },
        { 0xef53,       "EXT2_SUPER_MAGIC"      },
        { 0x137d,       "EXT_SUPER_MAGIC"       },
+       { 0xf995e849,   "HPFS_SUPER_MAGIC"      },
        { 0x9660,       "ISOFS_SUPER_MAGIC"     },
        { 0x137f,       "MINIX_SUPER_MAGIC"     },
        { 0x138f,       "MINIX_SUPER_MAGIC2"    },
        { 0x2468,       "MINIX2_SUPER_MAGIC"    },
        { 0x2478,       "MINIX2_SUPER_MAGIC2"   },
        { 0x4d44,       "MSDOS_SUPER_MAGIC"     },
+       { 0x564c,       "NCP_SUPER_MAGIC"       },
        { 0x6969,       "NFS_SUPER_MAGIC"       },
        { 0x9fa0,       "PROC_SUPER_MAGIC"      },
+       { 0x002f,       "QNX4_SUPER_MAGIC"      },
+       { 0x52654973,   "REISERFS_SUPER_MAGIC"  },
+       { 0x02011994,   "SHMFS_SUPER_MAGIC"     },
+       { 0x517b,       "SMB_SUPER_MAGIC"       },
+       { 0x012ff7b6,   "SYSV2_SUPER_MAGIC"     },
+       { 0x012ff7b5,   "SYSV4_SUPER_MAGIC"     },
+       { 0x00011954,   "UFS_MAGIC"             },
+       { 0x54190100,   "UFS_CIGAM"             },
+       { 0x012ff7b4,   "XENIX_SUPER_MAGIC"     },
        { 0x012fd16d,   "XIAFS_SUPER_MAGIC"     },
+       { 0x62656572,   "SYSFS_MAGIC"           },
        { 0,            NULL                    },
 };
 
-#endif /* linux */
+#endif /* LINUX */
 
 #ifndef SVR4
 
-static char *
+static const char *
 sprintfstype(magic)
 int magic;
 {
        static char buf[32];
-#ifdef linux
-       char *s;
+#ifdef LINUX
+       const char *s;
 
        s = xlookup(fsmagic, magic);
        if (s) {
                sprintf(buf, "\"%s\"", s);
                return buf;
        }
-#endif /* linux */
+#endif /* LINUX */
        sprintf(buf, "%#x", magic);
        return buf;
 }
@@ -821,21 +1479,28 @@ long addr;
        tprintf("{f_type=%s, f_fbsize=%u, f_blocks=%u, f_bfree=%u, ",
                sprintfstype(statbuf.f_type),
                statbuf.f_bsize, statbuf.f_blocks, statbuf.f_bfree);
-       tprintf("f_bavail=%u, f_files=%u, f_ffree=%u, f_namelen=%u",
-               statbuf.f_bavail,statbuf.f_files, statbuf.f_ffree, statbuf.f_namelen);
+       tprintf("f_bavail=%u, f_files=%u, f_ffree=%u, f_fsid={%d, %d}, f_namelen=%u",
+               statbuf.f_bavail,statbuf.f_files, statbuf.f_ffree,
+               statbuf.f_fsid.__val[0], statbuf.f_fsid.__val[1],
+               statbuf.f_namelen);
 #else /* !ALPHA */
        tprintf("{f_type=%s, f_bsize=%lu, f_blocks=%lu, f_bfree=%lu, ",
                sprintfstype(statbuf.f_type),
                (unsigned long)statbuf.f_bsize,
                (unsigned long)statbuf.f_blocks,
                (unsigned long)statbuf.f_bfree);
-       tprintf("f_files=%lu, f_ffree=%lu",
+       tprintf("f_bavail=%lu, f_files=%lu, f_ffree=%lu, f_fsid={%d, %d}",
+               (unsigned long)statbuf.f_bavail,
                (unsigned long)statbuf.f_files,
-               (unsigned long)statbuf.f_ffree);
-#ifdef linux
+               (unsigned long)statbuf.f_ffree,
+               statbuf.f_fsid.__val[0], statbuf.f_fsid.__val[1]);
+#ifdef LINUX
        tprintf(", f_namelen=%lu", (unsigned long)statbuf.f_namelen);
-#endif /* linux */
+#endif /* LINUX */
 #endif /* !ALPHA */
+#ifdef _STATFS_F_FRSIZE
+       tprintf(", f_frsize=%lu", (unsigned long)statbuf.f_frsize);
+#endif
        tprintf("}");
 }
 
@@ -864,7 +1529,83 @@ struct tcb *tcp;
        return 0;
 }
 
-#if defined(linux) && defined(__alpha)
+#ifdef LINUX
+static void
+printstatfs64(tcp, addr)
+struct tcb *tcp;
+long addr;
+{
+       struct statfs64 statbuf;
+
+       if (syserror(tcp) || !verbose(tcp)) {
+               tprintf("%#lx", addr);
+               return;
+       }
+       if (umove(tcp, addr, &statbuf) < 0) {
+               tprintf("{...}");
+               return;
+       }
+#ifdef ALPHA
+
+       tprintf("{f_type=%s, f_fbsize=%u, f_blocks=%u, f_bfree=%u, ",
+               sprintfstype(statbuf.f_type),
+               statbuf.f_bsize, statbuf.f_blocks, statbuf.f_bfree);
+       tprintf("f_bavail=%u, f_files=%u, f_ffree=%u, f_fsid={%d, %d}, f_namelen=%u",
+               statbuf.f_bavail,statbuf.f_files, statbuf.f_ffree,
+               statbuf.f_fsid.__val[0], statbuf.f_fsid.__val[1],
+               statbuf.f_namelen);
+#else /* !ALPHA */
+       tprintf("{f_type=%s, f_bsize=%lu, f_blocks=%lu, f_bfree=%lu, ",
+               sprintfstype(statbuf.f_type),
+               (unsigned long)statbuf.f_bsize,
+               (unsigned long)statbuf.f_blocks,
+               (unsigned long)statbuf.f_bfree);
+       tprintf("f_bavail=%lu, f_files=%lu, f_ffree=%lu, f_fsid={%d, %d}",
+               (unsigned long)statbuf.f_bavail,
+               (unsigned long)statbuf.f_files,
+               (unsigned long)statbuf.f_ffree,
+               statbuf.f_fsid.__val[0], statbuf.f_fsid.__val[1]);
+       tprintf(", f_namelen=%lu", (unsigned long)statbuf.f_namelen);
+#endif /* !ALPHA */
+#ifdef _STATFS_F_FRSIZE
+       tprintf(", f_frsize=%lu", (unsigned long)statbuf.f_frsize);
+#endif
+       tprintf("}");
+}
+
+int
+sys_statfs64(tcp)
+struct tcb *tcp;
+{
+       if (entering(tcp)) {
+               printpath(tcp, tcp->u_arg[0]);
+               tprintf(", %lu, ", tcp->u_arg[1]);
+       } else {
+               if (tcp->u_arg[1] == sizeof (struct statfs64))
+                       printstatfs64(tcp, tcp->u_arg[2]);
+               else
+                       tprintf("{???}");
+       }
+       return 0;
+}
+
+int
+sys_fstatfs64(tcp)
+struct tcb *tcp;
+{
+       if (entering(tcp)) {
+               tprintf("%lu, %lu, ", tcp->u_arg[0], tcp->u_arg[1]);
+       } else {
+               if (tcp->u_arg[1] == sizeof (struct statfs64))
+                       printstatfs64(tcp, tcp->u_arg[2]);
+               else
+                       tprintf("{???}");
+       }
+       return 0;
+}
+#endif
+
+#if defined(LINUX) && defined(__alpha)
 
 int
 osf_statfs(tcp)
@@ -892,7 +1633,7 @@ struct tcb *tcp;
        }
        return 0;
 }
-#endif /* linux && __alpha */
+#endif /* LINUX && __alpha */
 
 #endif /* !SVR4 */
 
@@ -930,6 +1671,19 @@ struct tcb *tcp;
 
 #endif /* SUNOS4 */
 
+int
+sys_pivotroot(tcp)
+struct tcb *tcp;
+{
+       if (entering(tcp)) {
+               printpath(tcp, tcp->u_arg[0]);
+               tprintf(", ");
+               printpath(tcp, tcp->u_arg[1]);
+       }
+       return 0;
+}
+
+
 /* directory */
 int
 sys_chdir(tcp)
@@ -1061,7 +1815,8 @@ struct tcb *tcp;
 {
        if (entering(tcp)) {
                printpath(tcp, tcp->u_arg[0]);
-               tprintf(", %lu, %lu", tcp->u_arg[1], tcp->u_arg[2]);
+               printuid(", ", tcp->u_arg[1]);
+               printuid(", ", tcp->u_arg[2]);
        }
        return 0;
 }
@@ -1071,8 +1826,9 @@ sys_fchown(tcp)
 struct tcb *tcp;
 {
        if (entering(tcp)) {
-               tprintf("%ld, %lu, %lu",
-                       tcp->u_arg[0], tcp->u_arg[1], tcp->u_arg[2]);
+               tprintf("%ld", tcp->u_arg[0]);
+               printuid(", ", tcp->u_arg[1]);
+               printuid(", ", tcp->u_arg[2]);
        }
        return 0;
 }
@@ -1098,6 +1854,20 @@ struct tcb *tcp;
        return 0;
 }
 
+#ifdef ALPHA
+int
+sys_osf_utimes(tcp)
+struct tcb *tcp;
+{
+    if (entering(tcp)) {
+       printpath(tcp, tcp->u_arg[0]);
+       tprintf(", ");
+       printtv32(tcp, tcp->u_arg[1]);
+    }
+    return 0;
+}
+#endif
+
 int
 sys_utimes(tcp)
 struct tcb *tcp;
@@ -1151,7 +1921,7 @@ struct tcb *tcp;
                                (unsigned long) ((tcp->u_arg[2] >> 18) & 0x3fff),
                                (unsigned long) (tcp->u_arg[2] & 0x3ffff));
                        else
-#endif 
+#endif
                        tprintf(", makedev(%lu, %lu)",
                                (unsigned long) major(tcp->u_arg[2]),
                                (unsigned long) minor(tcp->u_arg[2]));
@@ -1184,7 +1954,7 @@ struct tcb *tcp;
        return 0;
 }
 
-#ifdef linux
+#ifdef LINUX
 
 static void
 printdir(tcp, addr)
@@ -1225,7 +1995,23 @@ struct tcb *tcp;
        return 0;
 }
 
-#endif /* linux */
+#endif /* LINUX */
+
+#if defined FREEBSD || defined LINUX
+const struct xlat direnttypes[] = {
+       { DT_UNKNOWN,   "DT_UNKNOWN"    },
+       { DT_FIFO,      "DT_FIFO"       },
+       { DT_CHR,       "DT_CHR"        },
+       { DT_DIR,       "DT_DIR"        },
+       { DT_BLK,       "DT_BLK"        },
+       { DT_REG,       "DT_REG"        },
+       { DT_LNK,       "DT_LNK"        },
+       { DT_SOCK,      "DT_SOCK"       },
+       { DT_WHT,       "DT_WHT"        },
+       { 0,            NULL            },
+};
+
+#endif
 
 int
 sys_getdents(tcp)
@@ -1244,11 +2030,12 @@ struct tcb *tcp;
        }
        len = tcp->u_rval;
        if ((buf = malloc(len)) == NULL) {
-               tprintf("out of memory\n");
+               tprintf("%#lx, %lu", tcp->u_arg[1], tcp->u_arg[2]);
+               fprintf(stderr, "out of memory\n");
                return 0;
        }
        if (umoven(tcp, tcp->u_arg[1], len, buf) < 0) {
-               tprintf("{...}, %lu", tcp->u_arg[2]);
+               tprintf("%#lx, %lu", tcp->u_arg[1], tcp->u_arg[2]);
                free(buf);
                return 0;
        }
@@ -1256,22 +2043,105 @@ struct tcb *tcp;
                tprintf("{");
        for (i = 0; i < len;) {
                struct kernel_dirent *d = (struct kernel_dirent *) &buf[i];
-#ifdef linux
+#ifdef LINUX
                if (!abbrev(tcp)) {
                        tprintf("%s{d_ino=%lu, d_off=%lu, ",
                                i ? " " : "", d->d_ino, d->d_off);
                        tprintf("d_reclen=%u, d_name=\"%s\"}",
                                d->d_reclen, d->d_name);
                }
-#endif /* linux */
+#endif /* LINUX */
 #ifdef SVR4
                if (!abbrev(tcp)) {
                        tprintf("%s{d_ino=%lu, d_off=%lu, ",
-                               i ? " " : "", d->d_ino, d->d_off);
+                               i ? " " : "",
+                               (unsigned long) d->d_ino,
+                               (unsigned long) d->d_off);
                        tprintf("d_reclen=%u, d_name=\"%s\"}",
                                d->d_reclen, d->d_name);
                }
 #endif /* SVR4 */
+#ifdef SUNOS4
+               if (!abbrev(tcp)) {
+                       tprintf("%s{d_off=%lu, d_fileno=%lu, d_reclen=%u, ",
+                               i ? " " : "", d->d_off, d->d_fileno,
+                               d->d_reclen);
+                       tprintf("d_namlen=%u, d_name=\"%.*s\"}",
+                               d->d_namlen, d->d_namlen, d->d_name);
+               }
+#endif /* SUNOS4 */
+#ifdef FREEBSD
+               if (!abbrev(tcp)) {
+                       tprintf("%s{d_fileno=%u, d_reclen=%u, d_type=",
+                               i ? " " : "", d->d_fileno, d->d_reclen);
+                       printxval(direnttypes, d->d_type, "DT_???");
+                       tprintf(", d_namlen=%u, d_name=\"%.*s\"}",
+                               d->d_namlen, d->d_namlen, d->d_name);
+               }
+#endif /* FREEBSD */
+               if (!d->d_reclen) {
+                       tprintf("/* d_reclen == 0, problem here */");
+                       break;
+               }
+               i += d->d_reclen;
+               dents++;
+       }
+       if (!abbrev(tcp))
+               tprintf("}");
+       else
+               tprintf("/* %u entries */", dents);
+       tprintf(", %lu", tcp->u_arg[2]);
+       free(buf);
+       return 0;
+}
+
+
+#if _LFS64_LARGEFILE
+int
+sys_getdents64(tcp)
+struct tcb *tcp;
+{
+       int i, len, dents = 0;
+       char *buf;
+
+       if (entering(tcp)) {
+               tprintf("%lu, ", tcp->u_arg[0]);
+               return 0;
+       }
+       if (syserror(tcp) || !verbose(tcp)) {
+               tprintf("%#lx, %lu", tcp->u_arg[1], tcp->u_arg[2]);
+               return 0;
+       }
+       len = tcp->u_rval;
+       if ((buf = malloc(len)) == NULL) {
+               tprintf("%#lx, %lu", tcp->u_arg[1], tcp->u_arg[2]);
+               fprintf(stderr, "out of memory\n");
+               return 0;
+       }
+       if (umoven(tcp, tcp->u_arg[1], len, buf) < 0) {
+               tprintf("%#lx, %lu", tcp->u_arg[1], tcp->u_arg[2]);
+               free(buf);
+               return 0;
+       }
+       if (!abbrev(tcp))
+               tprintf("{");
+       for (i = 0; i < len;) {
+               struct dirent64 *d = (struct dirent64 *) &buf[i];
+#if defined(LINUX) || defined(SVR4)
+               if (!abbrev(tcp)) {
+                       tprintf("%s{d_ino=%llu, d_off=%llu, ",
+                               i ? " " : "",
+                               d->d_ino,
+                               d->d_off);
+#ifdef LINUX
+                       tprintf("d_type=");
+                       printxval(direnttypes, d->d_type, "DT_???");
+                       tprintf(", ");
+#endif
+                       tprintf("d_reclen=%u, d_name=\"%s\"}",
+                               d->d_reclen, d->d_name);
+               }
+#endif /* LINUX || SVR4 */
 #ifdef SUNOS4
                if (!abbrev(tcp)) {
                        tprintf("%s{d_off=%lu, d_fileno=%lu, d_reclen=%u, ",
@@ -1292,9 +2162,65 @@ struct tcb *tcp;
        free(buf);
        return 0;
 }
+#endif
+
+#ifdef FREEBSD
+int
+sys_getdirentries(tcp)
+struct tcb * tcp;
+{
+       int i, len, dents = 0;
+       long basep;
+       char *buf;
 
-#ifdef linux
+       if (entering(tcp)) {
+               tprintf("%lu, ", tcp->u_arg[0]);
+               return 0;
+       }
+       if (syserror(tcp) || !verbose(tcp)) {
+               tprintf("%#lx, %lu, %#lx", tcp->u_arg[1], tcp->u_arg[2], tcp->u_arg[3]);
+               return 0;
+       }
+       len = tcp->u_rval;
+       if ((buf = malloc(len)) == NULL) {
+               tprintf("%#lx, %lu, %#lx", tcp->u_arg[1], tcp->u_arg[2], tcp->u_arg[3]);
+               fprintf(stderr, "out of memory\n");
+               return 0;
+       }
+       if (umoven(tcp, tcp->u_arg[1], len, buf) < 0) {
+               tprintf("%#lx, %lu, %#lx", tcp->u_arg[1], tcp->u_arg[2], tcp->u_arg[3]);
+               free(buf);
+               return 0;
+       }
+       if (!abbrev(tcp))
+               tprintf("{");
+       for (i = 0; i < len;) {
+               struct kernel_dirent *d = (struct kernel_dirent *) &buf[i];
+               if (!abbrev(tcp)) {
+                       tprintf("%s{d_fileno=%u, d_reclen=%u, d_type=",
+                               i ? " " : "", d->d_fileno, d->d_reclen);
+                       printxval(direnttypes, d->d_type, "DT_???");
+                       tprintf(", d_namlen=%u, d_name=\"%.*s\"}",
+                               d->d_namlen, d->d_namlen, d->d_name);
+               }
+               i += d->d_reclen;
+               dents++;
+       }
+       if (!abbrev(tcp))
+               tprintf("}");
+       else
+               tprintf("/* %u entries */", dents);
+       free(buf);
+       tprintf(", %lu", tcp->u_arg[2]);
+       if (umove(tcp, tcp->u_arg[3], &basep) < 0)
+               tprintf(", %#lx", tcp->u_arg[3]);
+       else
+               tprintf(", [%lu]", basep);
+       return 0;
+}
+#endif
 
+#ifdef LINUX
 int
 sys_getcwd(tcp)
 struct tcb *tcp;
@@ -1308,7 +2234,23 @@ struct tcb *tcp;
     }
     return 0;
 }
-#endif /* linux */
+#endif /* LINUX */
+
+#ifdef FREEBSD
+int
+sys___getcwd(tcp)
+struct tcb *tcp;
+{
+    if (exiting(tcp)) {
+       if (syserror(tcp))
+           tprintf("%#lx", tcp->u_arg[0]);
+       else
+           printpathn(tcp, tcp->u_arg[0], tcp->u_arg[1]);
+       tprintf(", %lu", tcp->u_arg[1]);
+    }
+    return 0;
+}
+#endif
 
 #ifdef HAVE_SYS_ASYNCH_H
 
@@ -1391,3 +2333,210 @@ struct tcb *tcp;
 }
 
 #endif /* HAVE_SYS_ASYNCH_H */
+
+const struct xlat xattrflags[] = {
+#ifdef XATTR_CREATE
+       { XATTR_CREATE,  "XATTR_CREATE" },
+       { XATTR_REPLACE, "XATTR_REPLACE" },
+#endif
+       { 0,             NULL }
+};
+
+static void
+print_xattr_val(tcp, failed, arg, insize, size)
+struct tcb *tcp;
+int failed;
+unsigned long arg;
+unsigned long insize, size;
+{
+    if (!failed) {
+       unsigned long capacity = 4 * size + 1;
+       unsigned char *buf = (capacity < size) ? NULL : malloc(capacity);
+       if (buf == NULL || /* probably a bogus size argument */
+           umoven(tcp, arg, size, (char *) &buf[3 * size]) < 0) {
+           failed = 1;
+       }
+       else {
+           unsigned char *out = buf;
+           unsigned char *in = &buf[3 * size];
+           size_t i;
+           for (i = 0; i < size; ++i)
+               if (isprint(in[i]))
+                   *out++ = in[i];
+               else {
+#define tohex(n) "0123456789abcdef"[n]
+                   *out++ = '\\';
+                   *out++ = 'x';
+                   *out++ = tohex(in[i] / 16);
+                   *out++ = tohex(in[i] % 16);
+               }
+           /* Don't print terminating NUL if there is one.  */
+           if (in[i - 1] == '\0')
+               out -= 4;
+           *out = '\0';
+           tprintf(", \"%s\", %ld", buf, insize);
+       }
+       free(buf);
+    }
+    if (failed)
+       tprintf(", 0x%lx, %ld", arg, insize);
+}
+
+int
+sys_setxattr(tcp)
+struct tcb *tcp;
+{
+    if (entering(tcp)) {
+       printpath(tcp, tcp->u_arg[0]);
+       tprintf(", ");
+       printstr(tcp, tcp->u_arg[1], -1);
+       print_xattr_val(tcp, 0, tcp->u_arg[2], tcp->u_arg[3], tcp->u_arg[3]);
+       tprintf(", ");
+       printflags(xattrflags, tcp->u_arg[4], "XATTR_???");
+    }
+    return 0;
+}
+
+int
+sys_fsetxattr(tcp)
+struct tcb *tcp;
+{
+    if (entering(tcp)) {
+       tprintf("%ld, ", tcp->u_arg[0]);
+       printstr(tcp, tcp->u_arg[1], -1);
+       print_xattr_val(tcp, 0, tcp->u_arg[2], tcp->u_arg[3], tcp->u_arg[3]);
+       tprintf(", ");
+       printflags(xattrflags, tcp->u_arg[4], "XATTR_???");
+    }
+    return 0;
+}
+
+int
+sys_getxattr(tcp)
+struct tcb *tcp;
+{
+    if (entering(tcp)) {
+       printpath(tcp, tcp->u_arg[0]);
+       tprintf(", ");
+       printstr(tcp, tcp->u_arg[1], -1);
+    } else {
+       print_xattr_val(tcp, syserror(tcp), tcp->u_arg[2], tcp->u_arg[3],
+                       tcp->u_rval);
+    }
+    return 0;
+}
+
+int
+sys_fgetxattr(tcp)
+struct tcb *tcp;
+{
+    if (entering(tcp)) {
+       tprintf("%ld, ", tcp->u_arg[0]);
+       printstr(tcp, tcp->u_arg[1], -1);
+    } else {
+       print_xattr_val(tcp, syserror(tcp), tcp->u_arg[2], tcp->u_arg[3],
+                       tcp->u_rval);
+    }
+    return 0;
+}
+
+int
+sys_listxattr(tcp)
+struct tcb *tcp;
+{
+    if (entering(tcp)) {
+       printpath(tcp, tcp->u_arg[0]);
+    } else {
+       /* XXX Print value in format */
+       tprintf(", %p, %lu", (void *) tcp->u_arg[1], tcp->u_arg[2]);
+    }
+    return 0;
+}
+
+int
+sys_flistxattr(tcp)
+struct tcb *tcp;
+{
+    if (entering(tcp)) {
+       tprintf("%ld", tcp->u_arg[0]);
+    } else {
+       /* XXX Print value in format */
+       tprintf(", %p, %lu", (void *) tcp->u_arg[1], tcp->u_arg[2]);
+    }
+    return 0;
+}
+
+int
+sys_removexattr(tcp)
+struct tcb *tcp;
+{
+    if (entering(tcp)) {
+       printpath(tcp, tcp->u_arg[0]);
+       tprintf(", ");
+       printstr(tcp, tcp->u_arg[1], -1);
+    }
+    return 0;
+}
+
+int
+sys_fremovexattr(tcp)
+struct tcb *tcp;
+{
+    if (entering(tcp)) {
+       tprintf("%ld, ", tcp->u_arg[0]);
+       printstr(tcp, tcp->u_arg[1], -1);
+    }
+    return 0;
+}
+
+
+static const struct xlat advise[] = {
+  { POSIX_FADV_NORMAL,         "POSIX_FADV_NORMAL"     },
+  { POSIX_FADV_RANDOM,         "POSIX_FADV_RANDOM"     },
+  { POSIX_FADV_SEQUENTIAL,     "POSIX_FADV_SEQUENTIAL" },
+  { POSIX_FADV_WILLNEED,       "POSIX_FADV_WILLNEED"   },
+  { POSIX_FADV_DONTNEED,       "POSIX_FADV_DONTNEED"   },
+  { POSIX_FADV_NOREUSE,                "POSIX_FADV_NOREUSE"    },
+  { 0,                         NULL                    }
+};
+
+
+#ifdef LINUX
+int
+sys_fadvise64(tcp)
+struct tcb *tcp;
+{
+    if (entering(tcp)) {
+       tprintf("%ld, %lld, %ld, ",
+               tcp->u_arg[0],
+# if defined IA64 || defined X86_64 || defined ALPHA
+               (long long int) tcp->u_arg[1], tcp->u_arg[2]);
+       printxval(advise, tcp->u_arg[3], "POSIX_FADV_???");
+#else
+               LONG_LONG(tcp->u_arg[1], tcp->u_arg[2]), tcp->u_arg[3]);
+       printxval(advise, tcp->u_arg[4], "POSIX_FADV_???");
+#endif
+    }
+    return 0;
+}
+#endif
+
+
+int
+sys_fadvise64_64(tcp)
+struct tcb *tcp;
+{
+    if (entering(tcp)) {
+       tprintf("%ld, %lld, %lld, ",
+               tcp->u_arg[0],
+# if defined IA64 || defined X86_64 || defined ALPHA
+               (long long int) tcp->u_arg[1], (long long int) tcp->u_arg[2]);
+       printxval(advise, tcp->u_arg[3], "POSIX_FADV_???");
+#else
+               LONG_LONG(tcp->u_arg[1], tcp->u_arg[2]),
+               LONG_LONG(tcp->u_arg[3], tcp->u_arg[4]));
+       printxval(advise, tcp->u_arg[5], "POSIX_FADV_???");
+#endif
+    }
+    return 0;
+}