[PATCH v5] Print absolute paths in printpathn when -yy is used

Zubin Mithra zubin.mithra at gmail.com
Sat Aug 30 19:56:06 UTC 2014


Hi Dmitry,

> print_tracee_cwd() prints a quoted string, while getfdpath() returns
> a raw string.
> 

Thank you for the review! Please find below a diff for renameat+renameat2.

diff --git a/defs.h b/defs.h
index 625cac6..a5fd654 100644
--- a/defs.h
+++ b/defs.h
@@ -562,7 +562,8 @@ extern bool iflag;
 extern bool count_wallclock;
 extern unsigned int qflag;
 extern bool not_failing_only;
-extern unsigned int show_fd_path;
+extern bool show_fd_path;
+extern bool show_abs_path;
 extern bool hide_log_until_execve;
 /* are we filtering traces based on paths? */
 extern const char **paths_selected;
@@ -678,6 +679,7 @@ extern void printstr(struct tcb *, long, long);
 extern void printnum(struct tcb *, long, const char *);
 extern void printnum_int(struct tcb *, long, const char *);
 extern void printpath(struct tcb *, long);
+extern void printpathat(struct tcb *, int, long);
 extern void printpathn(struct tcb *, long, int);
 #define TIMESPEC_TEXT_BUFSIZE (sizeof(long)*3 * 2 + sizeof("{%u, %u}"))
 #define TIMEVAL_TEXT_BUFSIZE  TIMESPEC_TEXT_BUFSIZE
diff --git a/file.c b/file.c
index 986f446..37495ba 100644
--- a/file.c
+++ b/file.c
@@ -1771,10 +1771,10 @@ static void
 decode_renameat(struct tcb *tcp)
 {
 	print_dirfd(tcp, tcp->u_arg[0]);
-	printpath(tcp, tcp->u_arg[1]);
+	printpathat(tcp, tcp->u_arg[0], tcp->u_arg[1]);
 	tprints(", ");
 	print_dirfd(tcp, tcp->u_arg[2]);
-	printpath(tcp, tcp->u_arg[3]);
+	printpathat(tcp, tcp->u_arg[2], tcp->u_arg[3]);
 }

 int
diff --git a/strace.1 b/strace.1
index 2a24c38..89d7090 100644
--- a/strace.1
+++ b/strace.1
@@ -321,6 +321,9 @@ Print all strings in hexadecimal string format.
 .B \-y
 Print paths associated with file descriptor arguments.
 .TP
+.B \-A
+Print absolute paths instead of relative paths everywhere.
+.TP
 .BI "\-a " column
 Align return values in a specific column (default column 40).
 .TP
diff --git a/strace.c b/strace.c
index 2bc5c67..8b3adb2 100644
--- a/strace.c
+++ b/strace.c
@@ -129,7 +129,8 @@ static int post_attach_sigstop = TCB_IGNORE_ONE_SIGSTOP;
 bool not_failing_only = 0;

 /* Show path associated with fd arguments */
-unsigned int show_fd_path = 0;
+bool show_fd_path = 0;
+bool show_abs_path = 0;

 static bool detach_on_execve = 0;
 /* Are we "strace PROG" and need to skip detach on first execve? */
@@ -203,6 +204,7 @@ usage: strace [-CdffhiqrtttTvVxxy] [-I n] [-e expr]...\n\
               -p pid... / [-D] [-E var=val]... [-u username] PROG [ARGS]\n\
    or: strace -c[df] [-I n] [-e expr]... [-O overhead] [-S sortby]\n\
               -p pid... / [-D] [-E var=val]... [-u username] PROG [ARGS]\n\
+-A -- print absolute paths instead of relative paths everywhere\n\
 -c -- count time, calls, and errors for each syscall and report summary\n\
 -C -- like -c but also print regular output\n\
 -w -- summarise syscall latency (default is system time)\n\
@@ -216,6 +218,7 @@ usage: strace [-CdffhiqrtttTvVxxy] [-I n] [-e expr]...\n\
 -v -- verbose mode: print unabbreviated argv, stat, termios, etc. args\n\
 -x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
 -y -- print paths associated with file descriptor arguments\n\
+-yy -- print absolute paths instead of relative paths everywhere\n\
 -h -- print help message, -V -- print version\n\
 -a column -- alignment COLUMN for printing syscall results (default %d)\n\
 -b execve -- detach on this syscall\n\
@@ -1676,9 +1679,13 @@ init(int argc, char *argv[])
 #ifdef USE_LIBUNWIND
 		"k"
 #endif
+		"A"
 		"D"
 		"a:e:o:O:p:s:S:u:E:P:I:")) != EOF) {
 		switch (c) {
+		case 'A':
+			show_abs_path = 1;
+			break;
 		case 'b':
 			if (strcmp(optarg, "execve") != 0)
 				error_msg_and_die("Syscall '%s' for -b isn't supported",
@@ -1734,7 +1741,7 @@ init(int argc, char *argv[])
 			xflag++;
 			break;
 		case 'y':
-			show_fd_path++;
+			show_fd_path = 1;
 			break;
 		case 'v':
 			qualify("abbrev=none");
diff --git a/util.c b/util.c
index c78e962..587bbd4 100644
--- a/util.c
+++ b/util.c
@@ -405,7 +405,8 @@ printfd(struct tcb *tcp, int fd)
 {
 	char path[PATH_MAX + 1];

-	if (show_fd_path && getfdpath(tcp, fd, path, sizeof(path)) >= 0)
+	if ((show_fd_path || show_abs_path) &&
+	    getfdpath(tcp, fd, path, sizeof(path)) >= 0)
 		tprintf("%d<%s>", fd, path);
 	else
 		tprintf("%d", fd);
@@ -560,11 +561,64 @@ string_quote(const char *instr, char *outstr, long len, int size)
 }

 /*
- * Print path string specified by address `addr' and length `n'.
- * If path length exceeds `n', append `...' to the output.
+ * Encode a path(either cwd or fd path) in a manner fit for printing
+ * before a relative path.
  */
+static void
+encode_path(char *path, int n)
+{
+	char *outstr;
+
+	path[n++] = '/';
+	path[n++] = '\0';
+
+	/* path has n-1 characters followed by a null */
+	outstr = alloca(4 * n); /* 4*(n-1) + 3 for quotes and NUL */
+	string_quote(path, outstr, -1, n);
+	outstr[strlen(outstr)-1] = '\0'; /* Don't print the closing quotes */
+	tprints(outstr);
+}
+
+/*
+ * Print the current working directory of the tracee process
+ */
+static bool
+print_tracee_cwd(struct tcb *tcp)
+{
+	int link_size = sizeof("/proc//cwd") + sizeof(int) * 3;
+	char linkpath[link_size];
+	char cwd[MAXPATHLEN + 2];
+	ssize_t n;
+
+	snprintf(linkpath, link_size, "/proc/%u/cwd", tcp->pid);
+	n = readlink(linkpath, cwd, MAXPATHLEN);
+
+	if (n > 0) {
+		encode_path(cwd, n);
+		return true;
+	}
+	return false;
+}
+
+/*
+ * Print absolute path string corresponding to an `fd`.
+ */
+static bool
+print_tracee_fdpath(struct tcb *tcp, int fd)
+{
+	char path[PATH_MAX + 1];
+	int n;
+
+	n = getfdpath(tcp, fd, path, sizeof(path));
+	if (n > 0) {
+		encode_path(path, n);
+		return true;
+	}
+	return false;
+}
+
 void
-printpathn(struct tcb *tcp, long addr, int n)
+printpath_common(struct tcb *tcp, int fd, long addr, int n)
 {
 	char path[MAXPATHLEN + 1];
 	int nul_seen;
@@ -584,11 +638,29 @@ printpathn(struct tcb *tcp, long addr, int n)
 		tprintf("%#lx", addr);
 	else {
 		char *outstr;
+		bool prefix_printed = false;

 		path[n] = '\0';
+
+		/* If the call comes from `printpathn' and -y is used */
+		if (fd == -1 && show_fd_path && *path && *path != '/')
+			prefix_printed = print_tracee_cwd(tcp);
+
+		/* If the call comes from `printpathnat' and -A is used */
+		else if (show_abs_path && *path && *path != '/') {
+			if (fd == AT_FDCWD)
+				prefix_printed = print_tracee_cwd(tcp);
+			else
+				prefix_printed = print_tracee_fdpath(tcp, fd);
+		}
+
 		n++;
 		outstr = alloca(4 * n); /* 4*(n-1) + 3 for quotes and NUL */
 		string_quote(path, outstr, -1, n);
+
+		/* Dont print opening quotes if cwd/decoded dirfd is printed */
+		if (prefix_printed)
+			outstr += 1;
 		tprints(outstr);
 		if (!nul_seen)
 			tprints("...");
@@ -596,6 +668,18 @@ printpathn(struct tcb *tcp, long addr, int n)
 }

 void
+printpathat(struct tcb *tcp, int fd, long addr)
+{
+	printpath_common(tcp, fd, addr, MAXPATHLEN);
+}
+
+void
+printpathn(struct tcb *tcp, long addr, int n)
+{
+	printpath_common(tcp, -1, addr, n);
+}
+
+void
 printpath(struct tcb *tcp, long addr)
 {
 	/* Size must correspond to char path[] size in printpathn */


-- zm
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 496 bytes
Desc: Message signed with OpenPGP using GPGMail
URL: <http://lists.strace.io/pipermail/strace-devel/attachments/20140830/ae79e0e0/attachment.bin>


More information about the Strace-devel mailing list