[PATCH 2/2] ls: fix -q with -tSFilpRn and -U

From: Alexandre Niveau <alexandre.niveau_AT_gmail.com>
Date: Fri, 15 May 2015 00:15:39 +0200

Handling of -q was modifying ent->name 'in place', which was
preventing further stat-ing (and opendir-ing) when filenames
contained non-printable chars. With this commit, those chars
are replaced with '?' in the output only. It also incidentally
makes -q work with -U.
---
 ls.c | 47 +++++++++++++++++++++++++----------------------
 1 file changed, 25 insertions(+), 22 deletions(-)
diff --git a/ls.c b/ls.c
index cdfce4d..2ca12ac 100644
--- a/ls.c
+++ b/ls.c
_AT_@ -97,6 +97,21 @@ indicator(mode_t mode)
 }
 
 static void
+putname(const char *name)
+{
+	Rune r;
+
+	if (qflag)
+		while (*name)
+			if (name += chartorune(&r, name), isprintrune(r))
+				efputrune(&r, stdout, "<stdout>");
+			else
+				putchar('?');
+	else
+		fputs(name, stdout);
+}
+
+static void
 output(const struct entry *ent)
 {
 	struct group *gr;
_AT_@ -109,7 +124,8 @@ output(const struct entry *ent)
 	if (iflag)
 		printf("%lu ", (unsigned long)ent->ino);
 	if (!lflag) {
-		printf("%s%s\n", ent->name, indicator(ent->mode));
+		putname(ent->name);
+		puts(indicator(ent->mode));
 		return;
 	}
 	if (S_ISREG(ent->mode))
_AT_@ -165,7 +181,9 @@ output(const struct entry *ent)
 		printf("%10s ", humansize(ent->size));
 	else
 		printf("%10lu ", (unsigned long)ent->size);
-	printf("%s %s%s", buf, ent->name, indicator(ent->mode));
+	printf("%s ", buf);
+	putname(ent->name);
+	fputs(indicator(ent->mode), stdout);
 	if (S_ISLNK(ent->mode)) {
 		if ((len = readlink(ent->name, buf, sizeof(buf) - 1)) < 0)
 			eprintf("readlink %s:", ent->name);
_AT_@ -193,11 +211,10 @@ static void
 lsdir(const char *path)
 {
 	DIR *dp;
-	Rune r;
 	struct entry ent, *ents = NULL;
 	struct dirent *d;
-	size_t i, n = 0, len;
-	char cwd[PATH_MAX], *p, *q, *name;
+	size_t i, n = 0;
+	char cwd[PATH_MAX];
 
 	if (!getcwd(cwd, sizeof(cwd)))
 		eprintf("getcwd:");
_AT_@ -209,7 +226,8 @@ lsdir(const char *path)
 	if (many || Rflag) {
 		if (!first)
 			putchar('\n');
-		printf("%s:\n", path);
+		putname(path);
+		puts(":");
 	}
 	first = 0;
 
_AT_@ -224,22 +242,7 @@ lsdir(const char *path)
 			ls(&ent, Rflag);
 		} else {
 			ents = ereallocarray(ents, ++n, sizeof(*ents));
-			name = p = estrdup(d->d_name);
-			if (qflag) {
-				q = d->d_name;
-				while (*q) {
-					len = chartorune(&r, q);
-					if (isprintrune(r)) {
-						memcpy(p, q, len);
-						p += len, q += len;
-					} else {
-						*p++ = '?';
-						q += len;
-					}
-				}
-				*p = '\0';
-			}
-			mkent(&ents[n - 1], name, tflag || Sflag || Fflag || iflag || lflag || pflag || Rflag, Lflag);
+			mkent(&ents[n - 1], estrdup(d->d_name), tflag || Sflag || Fflag || iflag || lflag || pflag || Rflag, Lflag);
 		}
 	}
 	closedir(dp);
-- 
2.1.4
--------------080204010409080804050902--
Received on Mon Sep 17 2001 - 00:00:00 CEST

This archive was generated by hypermail 2.3.0 : Fri May 15 2015 - 07:00:05 CEST