Decode fcntl's F_{GET,SET}LEASE, F_NOTIFY, and F_DUPFD_CLOEXEC.
By Mike Frysinger (vapier AT gentoo.org)
* desc.c: Add F_SETLEASE, F_GETLEASE, F_NOTIFY,
F_DUPFD_CLOEXEC to fcntlcmds[]. Create notifyflags[] array.
(sys_fcntl): Handle new flags.
Optimize printing of open modes.
* defs.h: Declare sprint_open_modes(),
remove unused parameter in tprint_open_modes().
* desc.c (sprint_open_modes): Move fuction definition from here...
* file.c (sprint_open_modes): To here.
(tprint_open_modes): Use sprint_open_modes(), it already
generates needed string.
* ipc.c: Remove unused parameter from calls
to tprint_open_modes().
diff --git a/ChangeLog b/ChangeLog
index eb8026a..ce68580 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2009-03-10 Denys Vlasenko <dvlasenk@redhat.com>
+
+ Decode fcntl's F_{GET,SET}LEASE, F_NOTIFY, and F_DUPFD_CLOEXEC.
+ By Mike Frysinger (vapier AT gentoo.org)
+ * desc.c: Add F_SETLEASE, F_GETLEASE, F_NOTIFY,
+ F_DUPFD_CLOEXEC to fcntlcmds[]. Create notifyflags[] array.
+ (sys_fcntl): Handle new flags.
+
+ Optimize printing of open modes.
+ * defs.h: Declare sprint_open_modes(),
+ remove unused parameter in tprint_open_modes().
+ * desc.c (sprint_open_modes): Move fuction definition from here...
+ * file.c (sprint_open_modes): To here.
+ (tprint_open_modes): Use sprint_open_modes(), it already
+ generates needed string.
+ * ipc.c: Remove unused parameter from calls
+ to tprint_open_modes().
+
2009-02-27 Denys Vlasenko <dvlasenk@redhat.com>
AVR32 support by Hans-Christian Egtvedt
diff --git a/defs.h b/defs.h
index 9eb8162..2f5683b 100644
--- a/defs.h
+++ b/defs.h
@@ -534,7 +534,8 @@
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));
+extern void tprint_open_modes P((mode_t));
+extern const char *sprint_open_modes P((mode_t));
extern int is_restart_error P((struct tcb *));
extern int change_syscall P((struct tcb *, int));
diff --git a/desc.c b/desc.c
index cd6259a..3aae990 100644
--- a/desc.c
+++ b/desc.c
@@ -148,6 +148,18 @@
#ifdef F_UNSHARE
{ F_UNSHARE, "F_UNSHARE" },
#endif
+#ifdef F_SETLEASE
+ { F_SETLEASE, "F_SETLEASE" },
+#endif
+#ifdef F_GETLEASE
+ { F_GETLEASE, "F_GETLEASE" },
+#endif
+#ifdef F_NOTIFY
+ { F_NOTIFY, "F_NOTIFY" },
+#endif
+#ifdef F_DUPFD_CLOEXEC
+ { F_DUPFD_CLOEXEC,"F_DUPFD_CLOEXEC"},
+#endif
{ 0, NULL },
};
@@ -183,6 +195,33 @@
{ 0, NULL },
};
+#ifdef F_NOTIFY
+static const struct xlat notifyflags[] = {
+#ifdef DN_ACCESS
+ { DN_ACCESS, "DN_ACCESS" },
+#endif
+#ifdef DN_MODIFY
+ { DN_MODIFY, "DN_MODIFY" },
+#endif
+#ifdef DN_CREATE
+ { DN_CREATE, "DN_CREATE" },
+#endif
+#ifdef DN_DELETE
+ { DN_DELETE, "DN_DELETE" },
+#endif
+#ifdef DN_RENAME
+ { DN_RENAME, "DN_RENAME" },
+#endif
+#ifdef DN_ATTRIB
+ { DN_ATTRIB, "DN_ATTRIB" },
+#endif
+#ifdef DN_MULTISHOT
+ { DN_MULTISHOT, "DN_MULTISHOT" },
+#endif
+ { 0, NULL },
+};
+#endif
+
static const struct xlat whence[] = {
{ SEEK_SET, "SEEK_SET" },
{ SEEK_CUR, "SEEK_CUR" },
@@ -261,40 +300,6 @@
}
#endif
-/*
- * low bits of the open(2) flags define access mode,
- * other bits are real flags.
- */
-static const char *
-sprint_open_modes(mode_t 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)
{
@@ -307,11 +312,14 @@
printflags(fdflags, tcp->u_arg[2], "FD_???");
break;
case F_SETOWN: case F_DUPFD:
+#ifdef F_DUPFD_CLOEXEC
+ case F_DUPFD_CLOEXEC:
+#endif
tprintf(", %ld", tcp->u_arg[2]);
break;
case F_SETFL:
tprintf(", ");
- tprint_open_modes(tcp, tcp->u_arg[2]);
+ tprint_open_modes(tcp->u_arg[2]);
break;
case F_SETLK: case F_SETLKW:
#ifdef F_FREESP
@@ -326,30 +334,50 @@
#endif
/* Linux glibc defines SETLK64 as SETLK,
even though the kernel has different values - as does Solaris. */
-#if defined(F_SETLK64) && F_SETLK64+0!=F_SETLK
+#if defined(F_SETLK64) && F_SETLK64 + 0 != F_SETLK
case F_SETLK64:
#endif
-#if defined(F_SETLKW64) && F_SETLKW64+0!=F_SETLKW
+#if defined(F_SETLKW64) && F_SETLKW64 + 0 != F_SETLKW
case F_SETLKW64:
#endif
tprintf(", ");
printflock64(tcp, tcp->u_arg[2], 0);
break;
#endif
+#ifdef F_NOTIFY
+ case F_NOTIFY:
+ tprintf(", ");
+ printflags(notifyflags, tcp->u_arg[2], "DN_???");
+ break;
+#endif
+#ifdef F_SETLEASE
+ case F_SETLEASE:
+ tprintf(", ");
+ printxval(lockfcmds, tcp->u_arg[2], "F_???");
+ break;
+#endif
}
}
else {
switch (tcp->u_arg[1]) {
case F_DUPFD:
+#ifdef F_DUPFD_CLOEXEC
+ case F_DUPFD_CLOEXEC:
+#endif
case F_SETFD: case F_SETFL:
case F_SETLK: case F_SETLKW:
case F_SETOWN: case F_GETOWN:
+#ifdef F_NOTIFY
+ case F_NOTIFY:
+#endif
+#ifdef F_SETLEASE
+ case F_SETLEASE:
+#endif
break;
case F_GETFD:
if (syserror(tcp) || tcp->u_rval == 0)
return 0;
- tcp->auxstr =
- sprintflags("flags ", fdflags, tcp->u_rval);
+ tcp->auxstr = sprintflags("flags ", fdflags, tcp->u_rval);
return RVAL_HEX|RVAL_STR;
case F_GETFL:
if (syserror(tcp))
@@ -368,6 +396,13 @@
printflock64(tcp, tcp->u_arg[2], 1);
break;
#endif
+#ifdef F_GETLEASE
+ case F_GETLEASE:
+ if (syserror(tcp))
+ return 0;
+ tcp->auxstr = xlookup(lockfcmds, tcp->u_rval);
+ return RVAL_HEX|RVAL_STR;
+#endif
default:
tprintf(", %#lx", tcp->u_arg[2]);
break;
diff --git a/file.c b/file.c
index 3496bb2..f283a35 100644
--- a/file.c
+++ b/file.c
@@ -239,7 +239,7 @@
#ifdef O_RSYNC
{ O_RSYNC, "O_RSYNC" },
#endif
-#ifdef O_NDELAY
+#if defined(O_NDELAY) && (O_NDELAY != O_NONBLOCK)
{ O_NDELAY, "O_NDELAY" },
#endif
#ifdef O_PRIV
@@ -339,23 +339,61 @@
#endif
/*
+ * Pity stpcpy() is not standardized...
+ */
+static char *
+str_append(char *dst, const char *src)
+{
+ while ((*dst = *src++) != '\0')
+ dst++;
+ return dst;
+}
+
+/*
* 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 *
+sprint_open_modes(mode_t flags)
{
- const char *str = xlookup(open_access_modes, flags & 3);
+ static char outstr[1024];
+ char *p;
+ char sep = 0;
+ const char *str;
+ const struct xlat *x;
- if (str)
- {
- tprintf("%s", str);
+ p = str_append(outstr, "flags ");
+ str = xlookup(open_access_modes, flags & 3);
+ if (str) {
+ p = str_append(p, str);
flags &= ~3;
if (!flags)
- return;
- tprintf("|");
+ return outstr;
+ sep = '|';
}
- printflags(open_mode_flags, flags, "O_???");
+
+ for (x = open_mode_flags; x->str; x++) {
+ if ((flags & x->val) == x->val) {
+ if (sep)
+ *p++ = sep;
+ p = str_append(p, x->str);
+ flags &= ~x->val;
+ if (!flags)
+ return outstr;
+ sep = '|';
+ }
+ }
+ /* flags is still nonzero */
+ if (sep)
+ *p++ = sep;
+ sprintf(p, "%#x", flags);
+ return outstr;
+}
+
+void
+tprint_open_modes(mode_t flags)
+{
+ tprintf(sprint_open_modes(flags) + sizeof("flags"));
}
static int
@@ -365,7 +403,7 @@
printpath(tcp, tcp->u_arg[offset]);
tprintf(", ");
/* flags */
- tprint_open_modes(tcp, tcp->u_arg[offset + 1]);
+ tprint_open_modes(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 548d2e1..ab29412 100644
--- a/ipc.c
+++ b/ipc.c
@@ -420,7 +420,7 @@
printpath(tcp, tcp->u_arg[0]);
tprintf(", ");
/* flags */
- tprint_open_modes(tcp, tcp->u_arg[1]);
+ tprint_open_modes(tcp->u_arg[1]);
if (tcp->u_arg[1] & O_CREAT) {
# ifndef HAVE_MQUEUE_H
tprintf(", %lx", tcp->u_arg[2]);
@@ -489,7 +489,7 @@
return;
}
tprintf("{mq_flags=");
- tprint_open_modes(tcp, attr.mq_flags);
+ tprint_open_modes(attr.mq_flags);
tprintf(", mq_maxmsg=%ld, mq_msgsize=%ld, mq_curmsg=%ld}",
attr.mq_maxmsg, attr.mq_msgsize, attr.mq_curmsgs);
# endif