diff options
author | Dmitry V. Levin <ldv@altlinux.org> | 2007-01-11 23:19:55 +0000 |
---|---|---|
committer | Dmitry V. Levin <ldv@altlinux.org> | 2007-01-11 23:19:55 +0000 |
commit | 9b5b67eb43bf90e83834126dfde4472e5a721080 (patch) | |
tree | 16b9bc5f7448ff1f8bf5124e290fa515cd3aabd0 | |
parent | 5eb1aa539cdfe5be4a462f983c16cafdd94023e6 (diff) | |
download | strace-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-- | ChangeLog | 13 | ||||
-rw-r--r-- | defs.h | 1 | ||||
-rw-r--r-- | desc.c | 48 | ||||
-rw-r--r-- | file.c | 48 | ||||
-rw-r--r-- | ipc.c | 30 |
5 files changed, 105 insertions, 35 deletions
@@ -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. @@ -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 *)); @@ -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(", "); @@ -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]); @@ -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]); |