getdents, getdents64: quote filenames
* dirent.c (print_old_dirent): Fix quoting.
(sys_getdents): Print d_name using print_quoted_string.
(sys_getdents64): Likewise.
* tests/getdents.test: Test it.
* tests/getdents.awk: Update.
diff --git a/dirent.c b/dirent.c
index cbebdb7..d30e0d2 100644
--- a/dirent.c
+++ b/dirent.c
@@ -1,6 +1,8 @@
#include "defs.h"
#include <dirent.h>
+#define D_NAME_LEN_MAX 256
+
struct kernel_dirent {
unsigned long d_ino;
unsigned long d_off;
@@ -28,12 +30,12 @@
return;
}
- tprintf("{d_ino=%lu, d_off=%lu, d_reclen=%u, d_name=\"",
+ tprintf("{d_ino=%lu, d_off=%lu, d_reclen=%u, d_name=",
(unsigned long) d.d_ino, (unsigned long) d.d_off, d.d_reclen);
- if (d.d_reclen > 256)
- d.d_reclen = 256;
+ 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);
- tprints("\"}");
+ tprints("}");
}
int
@@ -103,11 +105,18 @@
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;
+ if (d_name_len > D_NAME_LEN_MAX)
+ d_name_len = D_NAME_LEN_MAX;
- tprintf("%s{d_ino=%lu, d_off=%lu, ",
- i ? " " : "", d->d_ino, d->d_off);
- tprintf("d_reclen=%u, d_name=\"%.*s\", d_type=",
- d->d_reclen, d_name_len, d->d_name);
+ tprintf("%s{d_ino=%lu, d_off=%lu, d_reclen=%u, d_name=",
+ i ? " " : "", d->d_ino, d->d_off, d->d_reclen);
+
+ if (print_quoted_string(d->d_name, d_name_len,
+ QUOTE_0_TERMINATED) > 0) {
+ tprints("...");
+ }
+
+ tprints(", d_type=");
if (oob)
tprints("?");
else
@@ -182,6 +191,8 @@
} 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=",
@@ -190,8 +201,14 @@
d->d_off,
d->d_reclen);
printxval(direnttypes, d->d_type, "DT_???");
- tprintf(", d_name=\"%.*s\"}",
- d_name_len, d->d_name);
+
+ 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) */");
diff --git a/tests/getdents.awk b/tests/getdents.awk
index 686d578..904c5c0 100644
--- a/tests/getdents.awk
+++ b/tests/getdents.awk
@@ -8,17 +8,25 @@
d_ino = "d_ino=" i
d_off = "d_off=" i
d_reclen = "d_reclen=" len
- d_name1 = "d_name=\"\\.\""
- d_name2 = "d_name=\"\\.\\.\""
- d_type = "d_type=DT_DIR"
+ d_name_1 = "d_name=\"\\.\""
+ d_name_2 = "d_name=\"\\.\\.\""
+ d_name_3 = "d_name=\"(A\\\\n){127}Z\""
+ d_type_dir = "d_type=DT_DIR"
+ d_type_reg = "d_type=DT_REG"
- d1_1 = "\\{" d_ino ", " d_off ", " d_reclen ", " d_name1 ", " d_type "\\}"
- d1_2 = "\\{" d_ino ", " d_off ", " d_reclen ", " d_name2 ", " d_type "\\}"
- d2_1 = "\\{" d_ino ", " d_off ", " d_reclen ", " d_type ", " d_name1 "\\}"
- d2_2 = "\\{" d_ino ", " d_off ", " d_reclen ", " d_type ", " d_name2 "\\}"
+ dirent_1 = "\\{" d_ino ", " d_off ", " d_reclen ", " d_name_1 ", " d_type_dir "\\}"
+ dirent_2 = "\\{" d_ino ", " d_off ", " d_reclen ", " d_name_2 ", " d_type_dir "\\}"
+ dirent_3 = "\\{" d_ino ", " d_off ", " d_reclen ", " d_name_3 ", " d_type_reg "\\}"
- getdents = "^getdents\\(" i ", \\{(" d1_1 " " d1_2 "|" d1_2 " " d1_1 ")\\}, " len "\\) += " len "$"
- getdents64 = "^getdents64\\(" i ", \\{(" d2_1 " " d2_2 "|" d2_2 " " d2_1 ")\\}, " len "\\) += " len "$"
+ dirent64_1 = "\\{" d_ino ", " d_off ", " d_reclen ", " d_type_dir ", " d_name_1 "\\}"
+ dirent64_2 = "\\{" d_ino ", " d_off ", " d_reclen ", " d_type_dir ", " d_name_2 "\\}"
+ dirent64_3 = "\\{" d_ino ", " d_off ", " d_reclen ", " d_type_reg ", " d_name_3 "\\}"
+
+ dents = "\\{(" dirent_1 " " dirent_2 "|" dirent_2 " " dirent_1 ") " dirent_3 "\\}"
+ dents64 = "\\{(" dirent64_1 " " dirent64_2 "|" dirent64_2 " " dirent64_1 ") " dirent64_3 "\\}"
+
+ getdents = "^getdents\\(" i ", " dents ", " len "\\) += " len "$"
+ getdents64 = "^getdents64\\(" i ", " dents64 ", " len "\\) += " len "$"
}
NR == 1 {if (match($0, getdents) || match($0, getdents64)) next}
diff --git a/tests/getdents.test b/tests/getdents.test
index 5f86ac1..e6f8fee 100755
--- a/tests/getdents.test
+++ b/tests/getdents.test
@@ -5,25 +5,36 @@
. "${srcdir=.}/init.sh"
check_prog awk
-check_prog grep
check_prog ls
check_prog mkdir
-check_prog rmdir
+check_prog rm
+check_prog seq
+check_prog touch
-mkdir emptydir ||
- framework_skip_ 'failed to create an empty directory'
+dir="$LOG.dir"
+mkdir -- "$dir" ||
+ framework_skip_ 'failed to create a directory'
-ls emptydir ||
- { rmdir emptydir; framework_skip_ 'failed to list an empty directory'; }
+touch -- "$dir/$(for i in $(seq 1 127); do echo A; done; echo Z)" ||
+ framework_skip_ 'failed to create a file'
+
+ls -- "$dir" > /dev/null || {
+ rm -rf -- "$dir"
+ framework_skip_ 'failed to list a directory'
+}
args='-vegetdents,getdents64'
-$STRACE $args -o $LOG ls emptydir
+$STRACE -o "$LOG" $args ls -- "$dir" > /dev/null
rc=$?
-rmdir emptydir
-[ $rc -eq 0 ] ||
- { cat $LOG; fail_ "strace $args failed"; }
+rm -rf -- "$dir"
+[ $rc -eq 0 ] || {
+ cat "$LOG"
+ fail_ "strace $args failed"
+}
-awk -f "$srcdir"/getdents.awk $LOG ||
- { cat $LOG; fail_ "strace $args failed to trace getdents/getdents64 properly"; }
+awk -f "$srcdir"/getdents.awk "$LOG" || {
+ cat "$LOG"
+ fail_ "strace $args failed to trace getdents/getdents64 properly"
+}
exit 0