summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry V. Levin <ldv@altlinux.org>2007-01-11 23:19:55 +0000
committerDmitry V. Levin <ldv@altlinux.org>2007-01-11 23:19:55 +0000
commit9b5b67eb43bf90e83834126dfde4472e5a721080 (patch)
tree16b9bc5f7448ff1f8bf5124e290fa515cd3aabd0
parent5eb1aa539cdfe5be4a462f983c16cafdd94023e6 (diff)
downloadstrace-9b5b67eb43bf90e83834126dfde4472e5a721080.tar.gz
strace-9b5b67eb43bf90e83834126dfde4472e5a721080.tar.bz2
strace-9b5b67eb43bf90e83834126dfde4472e5a721080.tar.xz
2007-01-11 Dmitry V. Levin <ldv@altlinux.org>
Fix open(2) flags parser. * defs.h (tprint_open_modes): New function. * desc.c (sprint_open_modes): New function. (sys_fcntl): Use tprint_open_modes() and sprint_open_modes(). * file.c (openmodes): Split xlat into open_access_modes and open_mode_flags. (tprint_open_modes): New function. (decode_open): Use it. * ipc.c (sys_mq_open, printmqattr): Likewise. Fixes RH#222385.
-rw-r--r--ChangeLog13
-rw-r--r--defs.h1
-rw-r--r--desc.c48
-rw-r--r--file.c48
-rw-r--r--ipc.c30
5 files changed, 105 insertions, 35 deletions
diff --git a/ChangeLog b/ChangeLog
index 82048ab..ecab1df 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2007-01-11 Dmitry V. Levin <ldv@altlinux.org>
+
+ Fix open(2) flags parser.
+ * defs.h (tprint_open_modes): New function.
+ * desc.c (sprint_open_modes): New function.
+ (sys_fcntl): Use tprint_open_modes() and sprint_open_modes().
+ * file.c (openmodes): Split xlat into open_access_modes and
+ open_mode_flags.
+ (tprint_open_modes): New function.
+ (decode_open): Use it.
+ * ipc.c (sys_mq_open, printmqattr): Likewise.
+ Fixes RH#222385.
+
2007-01-11 Roland McGrath <roland@redhat.com>
* configure.ac, NEWS: Version 4.5.15.
diff --git a/defs.h b/defs.h
index 8d89385..c25fde8 100644
--- a/defs.h
+++ b/defs.h
@@ -474,6 +474,7 @@ extern void printtrailer P((struct tcb *));
extern void tabto P((int));
extern void call_summary P((FILE *));
extern void tprint_iov P((struct tcb *, unsigned long, unsigned long));
+extern void tprint_open_modes P((struct tcb *, mode_t));
#ifdef LINUX
extern int internal_clone P((struct tcb *));
diff --git a/desc.c b/desc.c
index 29f8a95..caa7ccf 100644
--- a/desc.c
+++ b/desc.c
@@ -264,12 +264,48 @@ sprintflags(const struct xlat *xlat, int flags)
return outstr;
}
-int
-sys_fcntl(tcp)
-struct tcb *tcp;
+/*
+ * low bits of the open(2) flags define access mode,
+ * other bits are real flags.
+ */
+static const char *
+sprint_open_modes(mode_t flags)
{
- extern const struct xlat openmodes[];
+ extern const struct xlat open_access_modes[];
+ extern const struct xlat open_mode_flags[];
+ static char outstr[1024];
+ const char *str = xlookup(open_access_modes, flags & 3);
+ const char *sep = "";
+ const struct xlat *x;
+ strcpy(outstr, "flags ");
+ if (str)
+ {
+ strcat(outstr, str);
+ flags &= ~3;
+ if (!flags)
+ return outstr;
+ strcat(outstr, "|");
+ }
+
+ for (x = open_mode_flags; x->str; x++)
+ {
+ if ((flags & x->val) == x->val)
+ {
+ sprintf(outstr + strlen(outstr),
+ "%s%s", sep, x->str);
+ sep = "|";
+ flags &= ~x->val;
+ }
+ }
+ if (flags)
+ sprintf(outstr + strlen(outstr), "%s%#x", sep, flags);
+ return outstr;
+}
+
+int
+sys_fcntl(struct tcb *tcp)
+{
if (entering(tcp)) {
tprintf("%ld, ", tcp->u_arg[0]);
printxval(fcntlcmds, tcp->u_arg[1], "F_???");
@@ -283,7 +319,7 @@ struct tcb *tcp;
break;
case F_SETFL:
tprintf(", ");
- printflags(openmodes, tcp->u_arg[2] + 1, "O_???");
+ tprint_open_modes(tcp, tcp->u_arg[2]);
break;
case F_SETLK: case F_SETLKW:
#ifdef F_FREESP
@@ -323,7 +359,7 @@ struct tcb *tcp;
tcp->auxstr = sprintflags(fdflags, tcp->u_rval);
return RVAL_HEX|RVAL_STR;
case F_GETFL:
- tcp->auxstr = sprintflags(openmodes, tcp->u_rval + 1);
+ tcp->auxstr = sprint_open_modes(tcp->u_rval);
return RVAL_HEX|RVAL_STR;
case F_GETLK:
tprintf(", ");
diff --git a/file.c b/file.c
index d03e5f4..3d73389 100644
--- a/file.c
+++ b/file.c
@@ -209,21 +209,23 @@ struct stat_sparc64 {
#include <ustat.h>
#endif
-/*
- * This is a really dirty trick but it should always work. Traditional
- * 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.
- */
-const struct xlat openmodes[] = {
- { O_RDWR+1, "O_RDWR" },
- { O_RDONLY+1, "O_RDONLY" },
- { O_WRONLY+1, "O_WRONLY" },
- { O_NONBLOCK, "O_NONBLOCK" },
- { O_APPEND, "O_APPEND" },
+const struct xlat open_access_modes[] = {
+ { O_RDONLY, "O_RDONLY" },
+ { O_WRONLY, "O_WRONLY" },
+ { O_RDWR, "O_RDWR" },
+#ifdef O_ACCMODE
+ { O_ACCMODE, "O_ACCMODE" },
+#endif
+ { 0, NULL },
+};
+
+const struct xlat open_mode_flags[] = {
{ O_CREAT, "O_CREAT" },
- { O_TRUNC, "O_TRUNC" },
{ O_EXCL, "O_EXCL" },
{ O_NOCTTY, "O_NOCTTY" },
+ { O_TRUNC, "O_TRUNC" },
+ { O_APPEND, "O_APPEND" },
+ { O_NONBLOCK, "O_NONBLOCK" },
#ifdef O_SYNC
{ O_SYNC, "O_SYNC" },
#endif
@@ -332,6 +334,26 @@ print_dirfd(long fd)
}
#endif
+/*
+ * low bits of the open(2) flags define access mode,
+ * other bits are real flags.
+ */
+void
+tprint_open_modes(struct tcb *tcp, mode_t flags)
+{
+ const char *str = xlookup(open_access_modes, flags & 3);
+
+ if (str)
+ {
+ tprintf("%s", str);
+ flags &= ~3;
+ if (!flags)
+ return;
+ tprintf("|");
+ }
+ printflags(open_mode_flags, flags, "O_???");
+}
+
static int
decode_open(struct tcb *tcp, int offset)
{
@@ -339,7 +361,7 @@ decode_open(struct tcb *tcp, int offset)
printpath(tcp, tcp->u_arg[offset]);
tprintf(", ");
/* flags */
- printflags(openmodes, tcp->u_arg[offset + 1] + 1, "O_???");
+ tprint_open_modes(tcp, tcp->u_arg[offset + 1]);
if (tcp->u_arg[offset + 1] & O_CREAT) {
/* mode */
tprintf(", %#lo", tcp->u_arg[offset + 2]);
diff --git a/ipc.c b/ipc.c
index 365fae2..548d2e1 100644
--- a/ipc.c
+++ b/ipc.c
@@ -67,7 +67,6 @@
# define IPC_64 0x100
#endif
-extern const struct xlat openmodes[];
extern void printsigevent(struct tcb *tcp, long arg);
static const struct xlat msgctl_flags[] = {
@@ -414,14 +413,14 @@ struct tcb *tcp;
#endif /* defined(LINUX) || defined(SUNOS4) || defined(FREEBSD) */
#ifdef LINUX
-int sys_mq_open(tcp)
-struct tcb *tcp;
+int
+sys_mq_open(struct tcb *tcp)
{
if (entering(tcp)) {
printpath(tcp, tcp->u_arg[0]);
tprintf(", ");
/* flags */
- printflags(openmodes, tcp->u_arg[1] + 1, "O_???");
+ tprint_open_modes(tcp, tcp->u_arg[1]);
if (tcp->u_arg[1] & O_CREAT) {
# ifndef HAVE_MQUEUE_H
tprintf(", %lx", tcp->u_arg[2]);
@@ -440,8 +439,8 @@ struct tcb *tcp;
return 0;
}
-int sys_mq_timedsend(tcp)
-struct tcb *tcp;
+int
+sys_mq_timedsend(struct tcb *tcp)
{
if (entering(tcp)) {
tprintf("%ld, ", tcp->u_arg[0]);
@@ -452,8 +451,8 @@ struct tcb *tcp;
return 0;
}
-int sys_mq_timedreceive(tcp)
-struct tcb *tcp;
+int
+sys_mq_timedreceive(struct tcb *tcp)
{
if (entering(tcp))
tprintf("%ld, ", tcp->u_arg[0]);
@@ -465,8 +464,8 @@ struct tcb *tcp;
return 0;
}
-int sys_mq_notify(tcp)
-struct tcb *tcp;
+int
+sys_mq_notify(struct tcb *tcp)
{
if (entering(tcp)) {
tprintf("%ld, ", tcp->u_arg[0]);
@@ -475,9 +474,8 @@ struct tcb *tcp;
return 0;
}
-static void printmqattr(tcp, addr)
-struct tcb *tcp;
-long addr;
+static void
+printmqattr(struct tcb *tcp, long addr)
{
if (addr == 0)
tprintf("NULL");
@@ -491,15 +489,15 @@ long addr;
return;
}
tprintf("{mq_flags=");
- printflags(openmodes, attr.mq_flags + 1, "O_???");
+ tprint_open_modes(tcp, attr.mq_flags);
tprintf(", mq_maxmsg=%ld, mq_msgsize=%ld, mq_curmsg=%ld}",
attr.mq_maxmsg, attr.mq_msgsize, attr.mq_curmsgs);
# endif
}
}
-int sys_mq_getsetattr(tcp)
-struct tcb *tcp;
+int
+sys_mq_getsetattr(struct tcb *tcp)
{
if (entering(tcp)) {
tprintf("%ld, ", tcp->u_arg[0]);