Mpersify parsers of readdir and getdents syscalls

* 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.
This commit is contained in:
Дмитрий Левин 2015-11-19 18:13:53 +00:00
parent a2df1c12de
commit a367db8e5b
5 changed files with 177 additions and 113 deletions

View File

@ -49,6 +49,7 @@ strace_SOURCES = \
count.c \
desc.c \
dirent.c \
dirent64.c \
empty.h \
epoll.c \
evdev.c \

1
defs.h
View File

@ -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[];

165
dirent.c
View File

@ -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 DEF_MPERS_TYPE(kernel_dirent)
#include <dirent.h>
#define D_NAME_LEN_MAX 256
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,12 +141,12 @@ 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) */");
if (d->d_reclen < sizeof(kernel_dirent)) {
tprints("/* d_reclen < sizeof(kernel_dirent) */");
break;
}
i += d->d_reclen;
@ -134,89 +159,3 @@ SYS_FUNC(getdents)
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) */");
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;
}

123
dirent64.c Normal file
View File

@ -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;
}