]> granicus.if.org Git - strace/blobdiff - file.c
Fix signed/unsigned problems
[strace] / file.c
diff --git a/file.c b/file.c
index f43d216a4cfd5d489cc0343a56bd5e87e1ec038d..bfb12ca30a3cfdb528690e8909f6d70e408ba275 100644 (file)
--- a/file.c
+++ b/file.c
@@ -1,4 +1,5 @@
 /*
+#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>
@@ -35,6 +36,7 @@
 #include <dirent.h>
 #ifdef linux
 #define dirent kernel_dirent
+#define dirent64 kernel_dirent64
 #include <linux/types.h>
 #include <linux/dirent.h>
 #undef dirent
@@ -105,11 +107,17 @@ struct stat {
 #    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
+#  ifdef HPPA
+#    define stat64 hpux_stat64
+#  endif
 #else
 #  include <sys/stat.h>
 #endif
@@ -120,7 +128,31 @@ struct stat {
 #  include <sys/cred.h>
 #endif /* SVR4 */
 
+#ifdef HAVE_SYS_VFS_H
 #include <sys/vfs.h>
+#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>
@@ -172,13 +204,16 @@ 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"   },
+       { O_LARGEFILE,  "O_LARGEFILE"   },
 #endif
 #ifdef O_DIRECTORY
-   { O_DIRECTORY,  "O_DIRECTORY"   },
+       { O_DIRECTORY,  "O_DIRECTORY"   },
+#endif
+#ifdef O_NOFOLLOW
+       { O_NOFOLLOW,   "O_NOFOLLOW"    },
 #endif
 
 #ifdef FNDELAY
@@ -219,6 +254,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            },
 };
@@ -332,20 +373,27 @@ static struct xlat whence[] = {
        { 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
 int
@@ -356,11 +404,11 @@ struct tcb *tcp;
        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;
@@ -374,6 +422,26 @@ struct tcb *tcp;
 }
 #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;
@@ -384,7 +452,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;
@@ -394,6 +478,21 @@ 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 */
 
@@ -480,7 +579,7 @@ struct solstat {
 static void
 printstatsol(tcp, addr)
 struct tcb *tcp;
-int addr;
+long addr;
 {
        struct solstat statbuf;
 
@@ -489,7 +588,7 @@ int addr;
                return;
        }
        if (syserror(tcp) || !verbose(tcp)) {
-               tprintf("%#x", addr);
+               tprintf("%#lx", addr);
                return;
        }
        if (umove(tcp, addr, &statbuf) < 0) {
@@ -531,6 +630,60 @@ int addr;
 }
 #endif /* LINUXSPARC */
 
+static 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(", ");
+               if (tcp->u_arg[1])
+                       printflags(fileflags, tcp->u_arg[1]);
+               else
+                       tprintf("0");
+       }
+       return 0;
+}
+
+int
+sys_fchflags(tcp)
+struct tcb *tcp;
+{
+       if (entering(tcp)) {
+               tprintf("%ld, ", tcp->u_arg[0]);
+               if (tcp->u_arg[1])
+                       printflags(fileflags, tcp->u_arg[1]);
+               else
+                       tprintf("0");
+       }
+       return 0;
+}
+#endif
+
+#ifndef HAVE_LONG_LONG_OFF_T
 static void
 realprintstat(tcp, statbuf)
 struct tcb *tcp;
@@ -574,7 +727,28 @@ 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_ST_FLAGS
+               tprintf(", st_flags=");
+               if (statbuf->st_flags) {
+                       printflags(fileflags, statbuf->st_flags);
+               } else
+                       tprintf("0");
+#endif
+#if HAVE_ST_ACLCNT
+               tprintf(", st_aclcnt=%d", statbuf->st_aclcnt);
+#endif
+#if HAVE_ST_LEVEL
+               tprintf(", st_level=%ld", statbuf->st_level);
+#endif
+#if HAVE_ST_FSTYPE
+               tprintf(", st_fstype=%.*s",
+                       (int) sizeof statbuf->st_fstype, statbuf->st_fstype);
+#endif
+#if HAVE_ST_GEN
+               tprintf(", st_gen=%u", statbuf->st_gen);
+#endif
+               tprintf("}");
     }
     else
            tprintf("...}");
@@ -584,7 +758,7 @@ struct stat *statbuf;
 static void
 printstat(tcp, addr)
 struct tcb *tcp;
-int addr;
+long addr;
 {
        struct stat statbuf;
 
@@ -600,7 +774,7 @@ int addr;
                return;
        }
        if (syserror(tcp) || !verbose(tcp)) {
-               tprintf("%#x", addr);
+               tprintf("%#lx", addr);
                return;
        }
        if (umove(tcp, addr, &statbuf) < 0) {
@@ -610,12 +784,13 @@ int addr;
 
        realprintstat(tcp, &statbuf);
 }
+#endif /* !HAVE_LONG_LONG_OFF_T */
 
-#ifdef STAT64
+#ifdef HAVE_STAT64
 static void
 printstat64(tcp, addr)
 struct tcb *tcp;
-int addr;
+long addr;
 {
        struct stat64 statbuf;
 
@@ -631,7 +806,7 @@ int addr;
                return;
        }
        if (syserror(tcp) || !verbose(tcp)) {
-               tprintf("%#x", addr);
+               tprintf("%#lx", addr);
                return;
        }
        if (umove(tcp, addr, &statbuf) < 0) {
@@ -640,10 +815,18 @@ int addr;
        }
 
        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,
@@ -678,14 +861,35 @@ int addr;
        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_ST_FLAGS
+               tprintf(", st_flags=");
+               if (statbuf.st_flags) {
+                       printflags(fileflags, statbuf.st_flags);
+               } else
+                       tprintf("0");
+#endif
+#if HAVE_ST_ACLCNT
+               tprintf(", st_aclcnt=%d", statbuf.st_aclcnt);
+#endif
+#if HAVE_ST_LEVEL
+               tprintf(", st_level=%ld", statbuf.st_level);
+#endif
+#if HAVE_ST_FSTYPE
+               tprintf(", st_fstype=%.*s",
+                       (int) sizeof statbuf.st_fstype, statbuf.st_fstype);
+#endif
+#if HAVE_ST_GEN
+               tprintf(", st_gen=%u", statbuf.st_gen);
+#endif
+               tprintf("}");
        }
        else
                tprintf("...}");
 }
-#endif /* STAT64 */
+#endif /* HAVE_STAT64 */
 
-#ifdef linux
+#if defined(linux) && !defined(IA64) && !defined(HPPA)
 static void
 convertoldstat(oldbuf, newbuf)
 const struct __old_kernel_stat *oldbuf;
@@ -710,7 +914,7 @@ struct stat *newbuf;
 static void
 printoldstat(tcp, addr)
 struct tcb *tcp;
-int addr;
+long addr;
 {
        struct __old_kernel_stat statbuf;
        struct stat newstatbuf;
@@ -727,7 +931,7 @@ int addr;
                return;
        }
        if (syserror(tcp) || !verbose(tcp)) {
-               tprintf("%#x", addr);
+               tprintf("%#lx", addr);
                return;
        }
        if (umove(tcp, addr, &statbuf) < 0) {
@@ -738,9 +942,9 @@ int addr;
        convertoldstat(&statbuf, &newstatbuf);
        realprintstat(tcp, &newstatbuf);
 }
-#endif
-
+#endif /* linux && !IA64 */
 
+#ifndef HAVE_LONG_LONG_OFF_T
 int
 sys_stat(tcp)
 struct tcb *tcp;
@@ -753,8 +957,8 @@ struct tcb *tcp;
        }
        return 0;
 }
+#endif
 
-#ifdef linux
 int
 sys_stat64(tcp)
 struct tcb *tcp;
@@ -772,6 +976,8 @@ struct tcb *tcp;
 #endif
 }
 
+#ifdef linux
+# if !defined(IA64) && !defined(HPPA)
 int
 sys_oldstat(tcp)
 struct tcb *tcp;
@@ -784,8 +990,10 @@ struct tcb *tcp;
        }
        return 0;
 }
-#endif
+# endif /* !IA64 && !HPPA*/
+#endif /* linux */
 
+#ifndef HAVE_LONG_LONG_OFF_T
 int
 sys_fstat(tcp)
 struct tcb *tcp;
@@ -797,8 +1005,8 @@ struct tcb *tcp;
        }
        return 0;
 }
+#endif
 
-#ifdef linux
 int
 sys_fstat64(tcp)
 struct tcb *tcp;
@@ -815,6 +1023,8 @@ struct tcb *tcp;
 #endif
 }
 
+#ifdef linux
+# if !defined(IA64) && !defined(HPPA)
 int
 sys_oldfstat(tcp)
 struct tcb *tcp;
@@ -826,8 +1036,10 @@ struct tcb *tcp;
        }
        return 0;
 }
+# endif /* !IA64 && !HPPA*/
 #endif
 
+#ifndef HAVE_LONG_LONG_OFF_T
 int
 sys_lstat(tcp)
 struct tcb *tcp;
@@ -840,8 +1052,8 @@ struct tcb *tcp;
        }
        return 0;
 }
+#endif
 
-#ifdef linux
 int
 sys_lstat64(tcp)
 struct tcb *tcp;
@@ -859,6 +1071,8 @@ struct tcb *tcp;
 #endif
 }
 
+#ifdef linux
+# if !defined(IA64) && !defined(HPPA)
 int
 sys_oldlstat(tcp)
 struct tcb *tcp;
@@ -871,6 +1085,7 @@ struct tcb *tcp;
        }
        return 0;
 }
+# endif /* !IA64 && !HPPA */
 #endif
 
 
@@ -885,6 +1100,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;
@@ -897,6 +1117,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;
@@ -911,6 +1136,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;
@@ -1058,17 +1288,33 @@ struct tcb *tcp;
 #ifdef linux
 
 static 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"     },
        { 0,            NULL                    },
 };
@@ -1224,6 +1470,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)
@@ -1535,6 +1794,21 @@ struct tcb *tcp;
 
 #endif /* linux */
 
+#ifdef FREEBSD
+struct xlat direnttypes[] = {
+       { 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)
 struct tcb *tcp;
@@ -1589,6 +1863,19 @@ struct tcb *tcp;
                                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++;
        }
@@ -1601,8 +1888,131 @@ struct tcb *tcp;
        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("out of memory\n");
+               return 0;
+       }
+       if (umoven(tcp, tcp->u_arg[1], len, buf) < 0) {
+               tprintf("{...}, %lu", tcp->u_arg[2]);
+               free(buf);
+               return 0;
+       }
+       if (!abbrev(tcp))
+               tprintf("{");
+       for (i = 0; i < len;) {
+               struct dirent64 *d = (struct dirent64 *) &buf[i];
 #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 */
+#ifdef SVR4
+               if (!abbrev(tcp)) {
+                       tprintf("%s{d_ino=%llu, d_off=%llu, ",
+                               i ? " " : "", d->d_ino, 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 */
+               i += d->d_reclen;
+               dents++;
+       }
+       if (!abbrev(tcp))
+               tprintf("}");
+       else
+               tprintf("/* %u entries */", dents);
+       tprintf(", %lu", tcp->u_arg[2]);
+       free(buf);
+       return 0;
+}
+#endif
+#ifdef FREEBSD
+int
+sys_getdirentries(tcp)
+struct tcb * tcp;
+{
+       int i, len, dents = 0;
+       long basep;
+       char *buf;
 
+       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("out of memory\n");
+               return 0;
+       }
+       if (umoven(tcp, tcp->u_arg[1], len, buf) < 0) {
+               tprintf("{...}, %lu, %#lx", 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;
@@ -1618,6 +2028,22 @@ struct tcb *tcp;
 }
 #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
 
 int