Mpersify parsers of readdir and getdents syscalls
authorDmitry V. Levin <ldv@altlinux.org>
Thu, 19 Nov 2015 18:13:53 +0000 (18:13 +0000)
committerDmitry V. Levin <ldv@altlinux.org>
Thu, 19 Nov 2015 22:49:58 +0000 (22:49 +0000)
* defs.h (dirent_types): New xlat prototype.
* dirent.c: Stop including "xlat/direnttypes.h".
(kernel_dirent): New typedef.  Mpersify it.
(print_old_dirent): Use it instead of old_dirent_t.
(SYS_FUNC(getdents)): Use it instead of struct kernel_dirent.
Rename direnttypes to dirent_types.
(SYS_FUNC(getdents64)): Move ...
* dirent64.c: ... here.  Rename direnttypes to dirent_types.
Include "xlat/dirent_types.h".
* Makefile.am (strace_SOURCES): Add dirent64.c.
* xlat/direnttypes.in: Rename to xlat/dirent_types.in.

Makefile.am
defs.h
dirent.c
dirent64.c [new file with mode: 0644]
xlat/dirent_types.in [moved from xlat/direnttypes.in with 100% similarity]

index c6af7d9921ff3a89de4a6cb383c591636034634e..a79d50c25372054cb4171cd3f980923bb69116d4 100644 (file)
@@ -49,6 +49,7 @@ strace_SOURCES =      \
        count.c         \
        desc.c          \
        dirent.c        \
+       dirent64.c      \
        empty.h         \
        epoll.c         \
        evdev.c         \
diff --git a/defs.h b/defs.h
index 1fe5975a804a1473342a080f1d2619c035b5c87c..5e40f4db0f0fad7d06f365ad41404fb601a0f64a 100644 (file)
--- a/defs.h
+++ b/defs.h
@@ -413,6 +413,7 @@ extern const struct xlat addrfams[];
 extern const struct xlat adjtimex_modes[];
 extern const struct xlat adjtimex_status[];
 extern const struct xlat at_flags[];
+extern const struct xlat dirent_types[];
 extern const struct xlat open_access_modes[];
 extern const struct xlat open_mode_flags[];
 extern const struct xlat resource_flags[];
index dec436b5f43892729f9da050d322691bbcbb8f82..cd50968d78cca779b09cbaae96962ab8f6623898 100644 (file)
--- a/dirent.c
+++ b/dirent.c
@@ -1,29 +1,55 @@
+/*
+ * 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>
+ * Copyright (c) 2005-2015 Dmitry V. Levin <ldv@altlinux.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
 #include "defs.h"
-#include <dirent.h>
 
-#define D_NAME_LEN_MAX 256
+#include DEF_MPERS_TYPE(kernel_dirent)
+
+#include <dirent.h>
 
-struct kernel_dirent {
+typedef struct {
        unsigned long   d_ino;
        unsigned long   d_off;
        unsigned short  d_reclen;
        char            d_name[1];
-};
+} kernel_dirent;
+
+#include MPERS_DEFS
+
+#define D_NAME_LEN_MAX 256
 
 static void
 print_old_dirent(struct tcb *tcp, long addr)
 {
-#ifdef SH64
-       typedef struct kernel_dirent old_dirent_t;
-#else
-       typedef struct {
-               uint32_t        d_ino;
-               uint32_t        d_off;
-               unsigned short  d_reclen;
-               char            d_name[1];
-       } old_dirent_t;
-#endif
-       old_dirent_t d;
+       kernel_dirent d;
 
        if (umove_or_printaddr(tcp, addr, &d))
                return;
@@ -32,7 +58,7 @@ print_old_dirent(struct tcb *tcp, long addr)
                (unsigned long) d.d_ino, (unsigned long) d.d_off, d.d_reclen);
        if (d.d_reclen > D_NAME_LEN_MAX)
                d.d_reclen = D_NAME_LEN_MAX;
-       printpathn(tcp, addr + offsetof(old_dirent_t, d_name), d.d_reclen);
+       printpathn(tcp, addr + offsetof(kernel_dirent, d_name), d.d_reclen);
        tprints("}");
 }
 
@@ -53,8 +79,6 @@ SYS_FUNC(readdir)
        return 0;
 }
 
-#include "xlat/direnttypes.h"
-
 SYS_FUNC(getdents)
 {
        unsigned int i, len, dents = 0;
@@ -74,7 +98,7 @@ SYS_FUNC(getdents)
        /* Beware of insanely large or too small values in tcp->u_rval */
        if (tcp->u_rval > 1024*1024)
                len = 1024*1024;
-       else if (tcp->u_rval < (int) sizeof(struct kernel_dirent))
+       else if (tcp->u_rval < (int) sizeof(kernel_dirent))
                len = 0;
        else
                len = tcp->u_rval;
@@ -93,19 +117,20 @@ SYS_FUNC(getdents)
 
        if (!abbrev(tcp))
                tprints("[");
-       for (i = 0; len && i <= len - sizeof(struct kernel_dirent); ) {
-               struct kernel_dirent *d = (struct kernel_dirent *) &buf[i];
+       for (i = 0; len && i <= len - sizeof(kernel_dirent); ) {
+               kernel_dirent *d = (kernel_dirent *) &buf[i];
 
                if (!abbrev(tcp)) {
-                       int oob = d->d_reclen < sizeof(struct kernel_dirent) ||
+                       int oob = d->d_reclen < sizeof(kernel_dirent) ||
                                  i + d->d_reclen - 1 >= len;
                        int d_name_len = oob ? len - i : d->d_reclen;
-                       d_name_len -= offsetof(struct kernel_dirent, d_name) + 1;
+                       d_name_len -= offsetof(kernel_dirent, d_name) + 1;
                        if (d_name_len > D_NAME_LEN_MAX)
                                d_name_len = D_NAME_LEN_MAX;
 
                        tprintf("%s{d_ino=%lu, d_off=%lu, d_reclen=%u, d_name=",
-                               i ? ", " : "", d->d_ino, d->d_off, d->d_reclen);
+                               i ? ", " : "", (unsigned long) d->d_ino,
+                               (unsigned long) d->d_off, d->d_reclen);
 
                        if (print_quoted_string(d->d_name, d_name_len,
                                                QUOTE_0_TERMINATED) > 0) {
@@ -116,101 +141,15 @@ SYS_FUNC(getdents)
                        if (oob)
                                tprints("?");
                        else
-                               printxval(direnttypes, buf[i + d->d_reclen - 1], "DT_???");
+                               printxval(dirent_types, buf[i + d->d_reclen - 1], "DT_???");
                        tprints("}");
                }
                dents++;
-               if (d->d_reclen < sizeof(struct kernel_dirent)) {
-                       tprints("/* d_reclen < sizeof(struct kernel_dirent) */");
-                       break;
-               }
-               i += d->d_reclen;
-       }
-       if (!abbrev(tcp))
-               tprints("]");
-       else
-               tprintf("/* %u entries */", dents);
-       tprintf(", %lu", tcp->u_arg[2]);
-       free(buf);
-       return 0;
-}
-
-SYS_FUNC(getdents64)
-{
-       /* the minimum size of a valid dirent64 structure */
-       const unsigned int d_name_offset = offsetof(struct dirent64, d_name);
-
-       unsigned int i, len, dents = 0;
-       char *buf;
-
-       if (entering(tcp)) {
-               printfd(tcp, tcp->u_arg[0]);
-               tprints(", ");
-               return 0;
-       }
-       if (syserror(tcp) || !verbose(tcp)) {
-               printaddr(tcp->u_arg[1]);
-               tprintf(", %lu", tcp->u_arg[2]);
-               return 0;
-       }
-
-       /* Beware of insanely large or too small tcp->u_rval */
-       if (tcp->u_rval > 1024*1024)
-               len = 1024*1024;
-       else if (tcp->u_rval < (int) d_name_offset)
-               len = 0;
-       else
-               len = tcp->u_rval;
-
-       if (len) {
-               buf = malloc(len);
-               if (!buf || umoven(tcp, tcp->u_arg[1], len, buf) < 0) {
-                       printaddr(tcp->u_arg[1]);
-                       tprintf(", %lu", tcp->u_arg[2]);
-                       free(buf);
-                       return 0;
-               }
-       } else {
-               buf = NULL;
-       }
-
-       if (!abbrev(tcp))
-               tprints("[");
-       for (i = 0; len && i <= len - d_name_offset; ) {
-               struct dirent64 *d = (struct dirent64 *) &buf[i];
-               if (!abbrev(tcp)) {
-                       int d_name_len;
-                       if (d->d_reclen >= d_name_offset
-                           && i + d->d_reclen <= len) {
-                               d_name_len = d->d_reclen - d_name_offset;
-                       } else {
-                               d_name_len = len - i - d_name_offset;
-                       }
-                       if (d_name_len > D_NAME_LEN_MAX)
-                               d_name_len = D_NAME_LEN_MAX;
-
-                       tprintf("%s{d_ino=%" PRIu64 ", d_off=%" PRId64
-                               ", d_reclen=%u, d_type=",
-                               i ? ", " : "",
-                               d->d_ino,
-                               d->d_off,
-                               d->d_reclen);
-                       printxval(direnttypes, d->d_type, "DT_???");
-
-                       tprints(", d_name=");
-                       if (print_quoted_string(d->d_name, d_name_len,
-                                               QUOTE_0_TERMINATED) > 0) {
-                               tprints("...");
-                       }
-
-                       tprints("}");
-               }
-               if (d->d_reclen < d_name_offset) {
-                       tprints("/* d_reclen < offsetof(struct dirent64, d_name) */");
+               if (d->d_reclen < sizeof(kernel_dirent)) {
+                       tprints("/* d_reclen < sizeof(kernel_dirent) */");
                        break;
                }
                i += d->d_reclen;
-               dents++;
        }
        if (!abbrev(tcp))
                tprints("]");
diff --git a/dirent64.c b/dirent64.c
new file mode 100644 (file)
index 0000000..3c90a25
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * 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>
+ * Copyright (c) 2005-2015 Dmitry V. Levin <ldv@altlinux.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "defs.h"
+#include <dirent.h>
+
+#include "xlat/dirent_types.h"
+
+#define D_NAME_LEN_MAX 256
+
+SYS_FUNC(getdents64)
+{
+       /* the minimum size of a valid dirent64 structure */
+       const unsigned int d_name_offset = offsetof(struct dirent64, d_name);
+
+       unsigned int i, len, dents = 0;
+       char *buf;
+
+       if (entering(tcp)) {
+               printfd(tcp, tcp->u_arg[0]);
+               tprints(", ");
+               return 0;
+       }
+       if (syserror(tcp) || !verbose(tcp)) {
+               printaddr(tcp->u_arg[1]);
+               tprintf(", %lu", tcp->u_arg[2]);
+               return 0;
+       }
+
+       /* Beware of insanely large or too small values in tcp->u_rval */
+       if (tcp->u_rval > 1024*1024)
+               len = 1024*1024;
+       else if (tcp->u_rval < (int) d_name_offset)
+               len = 0;
+       else
+               len = tcp->u_rval;
+
+       if (len) {
+               buf = malloc(len);
+               if (!buf || umoven(tcp, tcp->u_arg[1], len, buf) < 0) {
+                       printaddr(tcp->u_arg[1]);
+                       tprintf(", %lu", tcp->u_arg[2]);
+                       free(buf);
+                       return 0;
+               }
+       } else {
+               buf = NULL;
+       }
+
+       if (!abbrev(tcp))
+               tprints("[");
+       for (i = 0; len && i <= len - d_name_offset; ) {
+               struct dirent64 *d = (struct dirent64 *) &buf[i];
+               if (!abbrev(tcp)) {
+                       int d_name_len;
+                       if (d->d_reclen >= d_name_offset
+                           && i + d->d_reclen <= len) {
+                               d_name_len = d->d_reclen - d_name_offset;
+                       } else {
+                               d_name_len = len - i - d_name_offset;
+                       }
+                       if (d_name_len > D_NAME_LEN_MAX)
+                               d_name_len = D_NAME_LEN_MAX;
+
+                       tprintf("%s{d_ino=%" PRIu64 ", d_off=%" PRId64
+                               ", d_reclen=%u, d_type=",
+                               i ? ", " : "",
+                               d->d_ino,
+                               d->d_off,
+                               d->d_reclen);
+                       printxval(dirent_types, d->d_type, "DT_???");
+
+                       tprints(", d_name=");
+                       if (print_quoted_string(d->d_name, d_name_len,
+                                               QUOTE_0_TERMINATED) > 0) {
+                               tprints("...");
+                       }
+
+                       tprints("}");
+               }
+               if (d->d_reclen < d_name_offset) {
+                       tprints("/* d_reclen < offsetof(struct dirent64, d_name) */");
+                       break;
+               }
+               i += d->d_reclen;
+               dents++;
+       }
+       if (!abbrev(tcp))
+               tprints("]");
+       else
+               tprintf("/* %u entries */", dents);
+       tprintf(", %lu", tcp->u_arg[2]);
+       free(buf);
+       return 0;
+}
similarity index 100%
rename from xlat/direnttypes.in
rename to xlat/dirent_types.in