ls: print filenames on the fly rather than in a buffer

This commit is contained in:
Quentin Rameau 2016-10-06 11:16:32 +02:00 committed by Evan Gates
parent 60da4fb049
commit 441f73a518

48
ls.c
View File

@ -113,25 +113,20 @@ indicator(mode_t mode)
return ""; return "";
} }
static char * static void
makeprint(char *name) printname(const char *name)
{ {
char *c, *u, *print = emalloc(strlen(name) + 1); const char *c;
Rune r; Rune r;
size_t l; size_t l;
for (c = print, u = name; *u; u += l) { for (c = name; *c; c += l) {
l = chartorune(&r, u); l = chartorune(&r, c);
if (isprintrune(r)) { if (!qflag || isprintrune(r))
memcpy(c, u, l); fwrite(c, 1, l, stdout);
c += l; else
} else { putchar('?');
*c++ = '?';
} }
}
*c = '\0';
return print;
} }
static void static void
@ -142,14 +137,14 @@ output(const struct entry *ent)
struct tm *tm; struct tm *tm;
ssize_t len; ssize_t len;
char *fmt, buf[BUFSIZ], pwname[_SC_LOGIN_NAME_MAX], char *fmt, buf[BUFSIZ], pwname[_SC_LOGIN_NAME_MAX],
grname[_SC_LOGIN_NAME_MAX], mode[] = "----------", grname[_SC_LOGIN_NAME_MAX], mode[] = "----------";
*name = qflag ? makeprint(ent->name) : ent->name;
if (iflag) if (iflag)
printf("%lu ", (unsigned long)ent->ino); printf("%lu ", (unsigned long)ent->ino);
if (!lflag) { if (!lflag) {
printf("%s%s\n", name, indicator(ent->mode)); printname(ent->name);
goto cleanup; puts(indicator(ent->mode));
return;
} }
if (S_ISREG(ent->mode)) if (S_ISREG(ent->mode))
mode[0] = '-'; mode[0] = '-';
@ -209,7 +204,9 @@ output(const struct entry *ent)
printf("%10s ", humansize(ent->size)); printf("%10s ", humansize(ent->size));
else else
printf("%10lu ", (unsigned long)ent->size); printf("%10lu ", (unsigned long)ent->size);
printf("%s %s%s", buf, name, indicator(ent->mode)); printf("%s ", buf);
printname(ent->name);
fputs(indicator(ent->mode), stdout);
if (S_ISLNK(ent->mode)) { if (S_ISLNK(ent->mode)) {
if ((len = readlink(ent->name, buf, sizeof(buf) - 1)) < 0) if ((len = readlink(ent->name, buf, sizeof(buf) - 1)) < 0)
eprintf("readlink %s:", ent->name); eprintf("readlink %s:", ent->name);
@ -217,10 +214,6 @@ output(const struct entry *ent)
printf(" -> %s%s", buf, indicator(ent->tmode)); printf(" -> %s%s", buf, indicator(ent->tmode));
} }
putchar('\n'); putchar('\n');
cleanup:
if (qflag)
free(name);
} }
static int static int
@ -252,7 +245,7 @@ lsdir(const char *path, const struct entry *dir)
struct entry *ent, *ents = NULL; struct entry *ent, *ents = NULL;
struct dirent *d; struct dirent *d;
size_t i, n = 0; size_t i, n = 0;
char prefix[PATH_MAX], *name; char prefix[PATH_MAX];
if (!(dp = opendir(dir->name))) { if (!(dp = opendir(dir->name))) {
ret = 1; ret = 1;
@ -280,10 +273,9 @@ lsdir(const char *path, const struct entry *dir)
qsort(ents, n, sizeof(*ents), entcmp); qsort(ents, n, sizeof(*ents), entcmp);
if (path[0] || showdirs) { if (path[0] || showdirs) {
name = qflag ? makeprint(dir->name) : dir->name; fputs(path, stdout);
printf("%s%s:\n", path, name); printname(dir->name);
if (qflag) puts(":");
free(name);
} }
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
output(&ents[i]); output(&ents[i]);