]> 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 5ab057ca69ebffa1bd6e4c5d0ff1758fa378e9a9..52c36312f30cd270728a198e356f2a3ddb63a55c 100644 (file)
--- a/file.c
+++ b/file.c
@@ -66,6 +66,24 @@ struct stat {
        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
@@ -187,7 +205,7 @@ struct stat {
  * 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"      },
@@ -219,7 +237,17 @@ struct xlat openmodes[] = {
        { O_DIRECT,     "O_DIRECT"      },
 #endif
 #ifdef 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"   },
@@ -227,6 +255,9 @@ struct xlat openmodes[] = {
 #ifdef O_NOFOLLOW
        { O_NOFOLLOW,   "O_NOFOLLOW"    },
 #endif
+#ifdef O_NOATIME
+       { O_NOATIME,    "O_NOATIME"     },
+#endif
 
 #ifdef FNDELAY
        { FNDELAY,      "FNDELAY"       },
@@ -284,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]);
@@ -294,7 +325,7 @@ struct tcb *tcp;
 }
 
 #ifdef LINUXSPARC
-struct xlat openmodessol[] = {
+const struct xlat openmodessol[] = {
        { 0,            "O_RDWR"        },
        { 1,            "O_RDONLY"      },
        { 2,            "O_WRONLY"      },
@@ -320,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]);
@@ -342,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"          },
@@ -363,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;
 }
@@ -378,7 +409,7 @@ 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"      },
@@ -413,6 +444,11 @@ 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
@@ -442,9 +478,7 @@ struct tcb *tcp;
 # if defined IA64 || defined X86_64 || defined ALPHA
                (long long int) tcp->u_arg[1], tcp->u_arg[2]
 # else
-               (((long long int) tcp->u_arg[1]) << 32
-                | ((unsigned long *) tcp->u_arg)[2]),
-               tcp->u_arg[3]
+               LONG_LONG(tcp->u_arg[1], tcp->u_arg[2]), tcp->u_arg[3]
 # endif
                );
     }
@@ -526,7 +560,7 @@ struct tcb *tcp;
 
 /* several stats */
 
-static struct xlat modetypes[] = {
+static const struct xlat modetypes[] = {
        { S_IFREG,      "S_IFREG"       },
        { S_IFSOCK,     "S_IFSOCK"      },
        { S_IFIFO,      "S_IFIFO"       },
@@ -537,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 = "";
@@ -658,9 +692,68 @@ long 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 */
 
-struct xlat fileflags[] = {
+const struct xlat fileflags[] = {
 #ifdef FREEBSD
        { UF_NODUMP,    "UF_NODUMP"     },
        { UF_IMMUTABLE, "UF_IMMUTABLE"  },
@@ -690,10 +783,7 @@ 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");
+               printflags(fileflags, tcp->u_arg[1], "UF_???");
        }
        return 0;
 }
@@ -704,10 +794,7 @@ 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");
+               printflags(fileflags, tcp->u_arg[1], "UF_???");
        }
        return 0;
 }
@@ -760,10 +847,7 @@ struct stat *statbuf;
            tprintf("st_ctime=%s", sprinttime(statbuf->st_ctime));
 #if HAVE_STRUCT_STAT_ST_FLAGS
                tprintf(", st_flags=");
-               if (statbuf->st_flags) {
-                       printflags(fileflags, statbuf->st_flags);
-               } else
-                       tprintf("0");
+               printflags(fileflags, statbuf->st_flags, "UF_???");
 #endif
 #if HAVE_STRUCT_STAT_ST_ACLCNT
                tprintf(", st_aclcnt=%d", statbuf->st_aclcnt);
@@ -797,6 +881,12 @@ long addr;
                printstatsol(tcp, addr);
                return;
        }
+#ifdef SPARC64
+       else if (current_personality == 2) {
+               printstat_sparc64(tcp, addr);
+               return;
+       }
+#endif
 #endif /* LINUXSPARC */
 
        if (!addr) {
@@ -829,6 +919,12 @@ long addr;
                printstatsol(tcp, addr);
                return;
        }
+#ifdef SPARC64
+       else if (current_personality == 2) {
+               printstat_sparc64(tcp, addr);
+               return;
+       }
+#endif
 #endif /* LINUXSPARC */
 
        if (!addr) {
@@ -894,10 +990,7 @@ long addr;
                tprintf("st_ctime=%s", sprinttime(statbuf.st_ctime));
 #if HAVE_STRUCT_STAT_ST_FLAGS
                tprintf(", st_flags=");
-               if (statbuf.st_flags) {
-                       printflags(fileflags, statbuf.st_flags);
-               } else
-                       tprintf("0");
+               printflags(fileflags, statbuf.st_flags, "UF_???");
 #endif
 #if HAVE_STRUCT_STAT_ST_ACLCNT
                tprintf(", st_aclcnt=%d", statbuf.st_aclcnt);
@@ -1203,7 +1296,7 @@ struct tcb *tcp;
 
 #include <sys/acl.h>
 
-struct xlat aclcmds[] = {
+const struct xlat aclcmds[] = {
 #ifdef SETACL
        { SETACL,       "SETACL"        },
 #endif
@@ -1268,7 +1361,7 @@ struct tcb *tcp;
 }
 
 
-struct xlat aclipc[] = {
+const struct xlat aclipc[] = {
 #ifdef IPC_SHM
        { IPC_SHM,      "IPC_SHM"       },
 #endif
@@ -1311,7 +1404,7 @@ struct tcb *tcp;
 
 #ifdef LINUX
 
-static struct xlat fsmagic[] = {
+static const struct xlat fsmagic[] = {
        { 0x73757245,   "CODA_SUPER_MAGIC"      },
        { 0x012ff7b7,   "COH_SUPER_MAGIC"       },
        { 0x1373,       "DEVFS_SUPER_MAGIC"     },
@@ -1340,6 +1433,7 @@ static struct xlat fsmagic[] = {
        { 0x54190100,   "UFS_CIGAM"             },
        { 0x012ff7b4,   "XENIX_SUPER_MAGIC"     },
        { 0x012fd16d,   "XIAFS_SUPER_MAGIC"     },
+       { 0x62656572,   "SYSFS_MAGIC"           },
        { 0,            NULL                    },
 };
 
@@ -1347,13 +1441,13 @@ static struct xlat fsmagic[] = {
 
 #ifndef SVR4
 
-static char *
+static const char *
 sprintfstype(magic)
 int magic;
 {
        static char buf[32];
 #ifdef LINUX
-       char *s;
+       const char *s;
 
        s = xlookup(fsmagic, magic);
        if (s) {
@@ -1903,8 +1997,9 @@ struct tcb *tcp;
 
 #endif /* LINUX */
 
-#ifdef FREEBSD
-struct xlat direnttypes[] = {
+#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"        },
@@ -1935,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;
        }
@@ -2018,11 +2114,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;
        }
@@ -2032,10 +2129,15 @@ struct tcb *tcp;
                struct dirent64 *d = (struct dirent64 *) &buf[i];
 #if defined(LINUX) || defined(SVR4)
                if (!abbrev(tcp)) {
-                       tprintf("%s{d_ino=%lu, d_off=%lu, ",
+                       tprintf("%s{d_ino=%llu, d_off=%llu, ",
                                i ? " " : "",
-                               (unsigned long)d->d_ino,
-                               (unsigned long)d->d_off);
+                               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);
                }
@@ -2081,11 +2183,12 @@ struct tcb * tcp;
        }
        len = tcp->u_rval;
        if ((buf = malloc(len)) == NULL) {
-               tprintf("out of memory\n");
+               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("{...}, %lu, %#lx", tcp->u_arg[2], tcp->u_arg[3]);
+               tprintf("%#lx, %lu, %#lx", tcp->u_arg[1], tcp->u_arg[2], tcp->u_arg[3]);
                free(buf);
                return 0;
        }
@@ -2231,7 +2334,7 @@ struct tcb *tcp;
 
 #endif /* HAVE_SYS_ASYNCH_H */
 
-struct xlat xattrflags[] = {
+const struct xlat xattrflags[] = {
 #ifdef XATTR_CREATE
        { XATTR_CREATE,  "XATTR_CREATE" },
        { XATTR_REPLACE, "XATTR_REPLACE" },
@@ -2239,6 +2342,46 @@ struct xlat xattrflags[] = {
        { 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;
@@ -2247,9 +2390,9 @@ struct tcb *tcp;
        printpath(tcp, tcp->u_arg[0]);
        tprintf(", ");
        printstr(tcp, tcp->u_arg[1], -1);
-       /* XXX Print value in format */
-       tprintf(", %p, %ld, ", (void *) tcp->u_arg[2], tcp->u_arg[3]);
-       printflags(xattrflags, tcp->u_arg[4]);
+       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;
 }
@@ -2261,9 +2404,9 @@ struct tcb *tcp;
     if (entering(tcp)) {
        tprintf("%ld, ", tcp->u_arg[0]);
        printstr(tcp, tcp->u_arg[1], -1);
-       /* XXX Print value in format */
-       tprintf(", %p, %ld, ", (void *) tcp->u_arg[2], tcp->u_arg[3]);
-       printflags(xattrflags, tcp->u_arg[4]);
+       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;
 }
@@ -2277,8 +2420,8 @@ struct tcb *tcp;
        tprintf(", ");
        printstr(tcp, tcp->u_arg[1], -1);
     } else {
-       /* XXX Print value in format */
-       tprintf(", %p, %ld", (void *) tcp->u_arg[2], tcp->u_arg[3]);
+       print_xattr_val(tcp, syserror(tcp), tcp->u_arg[2], tcp->u_arg[3],
+                       tcp->u_rval);
     }
     return 0;
 }
@@ -2291,8 +2434,8 @@ struct tcb *tcp;
        tprintf("%ld, ", tcp->u_arg[0]);
        printstr(tcp, tcp->u_arg[1], -1);
     } else {
-       /* XXX Print value in format */
-       tprintf(", %p, %ld", (void *) tcp->u_arg[2], tcp->u_arg[3]);
+       print_xattr_val(tcp, syserror(tcp), tcp->u_arg[2], tcp->u_arg[3],
+                       tcp->u_rval);
     }
     return 0;
 }
@@ -2345,3 +2488,55 @@ struct tcb *tcp;
     }
     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;
+}