]> granicus.if.org Git - strace/blobdiff - file.c
replace wimpy get64 by powerful LONG_LONG :-)
[strace] / file.c
diff --git a/file.c b/file.c
index 149a5853c26c49119788c9187c774255189beac6..e618b0360cf8061beb5740d29127a0204df6a078 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
@@ -120,7 +122,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 +198,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 +248,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 +367,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
@@ -374,6 +416,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 +446,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 +472,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 */
 
@@ -445,7 +538,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;
 }
@@ -480,7 +573,7 @@ struct solstat {
 static void
 printstatsol(tcp, addr)
 struct tcb *tcp;
-int addr;
+long addr;
 {
        struct solstat statbuf;
 
@@ -489,7 +582,7 @@ int addr;
                return;
        }
        if (syserror(tcp) || !verbose(tcp)) {
-               tprintf("%#x", addr);
+               tprintf("%#lx", addr);
                return;
        }
        if (umove(tcp, addr, &statbuf) < 0) {
@@ -531,6 +624,51 @@ int addr;
 }
 #endif /* LINUXSPARC */
 
+#ifdef FREEBSD
+static struct xlat fileflags[] = {
+       { 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"   },
+       { 0,            NULL            },
+};
+
+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;
@@ -584,7 +722,7 @@ struct stat *statbuf;
 static void
 printstat(tcp, addr)
 struct tcb *tcp;
-int addr;
+long addr;
 {
        struct stat statbuf;
 
@@ -600,7 +738,7 @@ int addr;
                return;
        }
        if (syserror(tcp) || !verbose(tcp)) {
-               tprintf("%#x", addr);
+               tprintf("%#lx", addr);
                return;
        }
        if (umove(tcp, addr, &statbuf) < 0) {
@@ -610,12 +748,13 @@ int addr;
 
        realprintstat(tcp, &statbuf);
 }
+#endif /* !HAVE_LONG_LONG_OFF_T */
 
-#ifdef linux
+#ifdef HAVE_STAT64
 static void
 printstat64(tcp, addr)
 struct tcb *tcp;
-int addr;
+long addr;
 {
        struct stat64 statbuf;
 
@@ -631,7 +770,7 @@ int addr;
                return;
        }
        if (syserror(tcp) || !verbose(tcp)) {
-               tprintf("%#x", addr);
+               tprintf("%#lx", addr);
                return;
        }
        if (umove(tcp, addr, &statbuf) < 0) {
@@ -640,10 +779,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,12 +825,24 @@ int addr;
        if (!abbrev(tcp)) {
                tprintf("st_atime=%s, ", sprinttime(statbuf.st_atime));
                tprintf("st_mtime=%s, ", sprinttime(statbuf.st_mtime));
+#ifndef FREEBSD
                tprintf("st_ctime=%s}", sprinttime(statbuf.st_ctime));
+#else /* FREEBSD */
+               tprintf("st_ctime=%s, ", sprinttime(statbuf.st_ctime));
+               tprintf("st_flags=");
+               if (statbuf.st_flags) {
+                       printflags(fileflags, statbuf.st_flags);
+               } else
+                       tprintf("0");
+               tprintf(", st_gen=%u}", statbuf.st_gen);
+#endif /* FREEBSD */
        }
        else
                tprintf("...}");
 }
+#endif /* HAVE_STAT64 */
 
+#if defined(linux) && !defined(IA64)
 static void
 convertoldstat(oldbuf, newbuf)
 const struct __old_kernel_stat *oldbuf;
@@ -703,14 +862,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;
@@ -727,7 +884,7 @@ int addr;
                return;
        }
        if (syserror(tcp) || !verbose(tcp)) {
-               tprintf("%#x", addr);
+               tprintf("%#lx", addr);
                return;
        }
        if (umove(tcp, addr, &statbuf) < 0) {
@@ -738,9 +895,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 +910,8 @@ struct tcb *tcp;
        }
        return 0;
 }
+#endif
 
-#ifdef linux
 int
 sys_stat64(tcp)
 struct tcb *tcp;
@@ -772,6 +929,8 @@ struct tcb *tcp;
 #endif
 }
 
+#ifdef linux
+# if !defined(IA64)
 int
 sys_oldstat(tcp)
 struct tcb *tcp;
@@ -784,8 +943,10 @@ struct tcb *tcp;
        }
        return 0;
 }
-#endif
+# endif /* !IA64 */
+#endif /* linux */
 
+#ifndef HAVE_LONG_LONG_OFF_T
 int
 sys_fstat(tcp)
 struct tcb *tcp;
@@ -797,8 +958,8 @@ struct tcb *tcp;
        }
        return 0;
 }
+#endif
 
-#ifdef linux
 int
 sys_fstat64(tcp)
 struct tcb *tcp;
@@ -815,6 +976,8 @@ struct tcb *tcp;
 #endif
 }
 
+#ifdef linux
+# if !defined(IA64)
 int
 sys_oldfstat(tcp)
 struct tcb *tcp;
@@ -826,8 +989,10 @@ struct tcb *tcp;
        }
        return 0;
 }
+# endif /* !IA64 */
 #endif
 
+#ifndef HAVE_LONG_LONG_OFF_T
 int
 sys_lstat(tcp)
 struct tcb *tcp;
@@ -840,8 +1005,8 @@ struct tcb *tcp;
        }
        return 0;
 }
+#endif
 
-#ifdef linux
 int
 sys_lstat64(tcp)
 struct tcb *tcp;
@@ -859,6 +1024,8 @@ struct tcb *tcp;
 #endif
 }
 
+#ifdef linux
+# if !defined(IA64)
 int
 sys_oldlstat(tcp)
 struct tcb *tcp;
@@ -871,6 +1038,7 @@ struct tcb *tcp;
        }
        return 0;
 }
+# endif /* !IA64 */
 #endif
 
 
@@ -885,6 +1053,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 +1070,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 +1089,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 +1241,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 +1423,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 +1747,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 +1816,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 +1841,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 +1981,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