bore

basic core utilities (PD)
git clone git://bvnf.space/bore.git
Log | Files | Refs | README

commit 97a531b65e79984b130d359b3bcb7fc37f270853
parent 05429c0040ad1a642daca41782338ea751638764
Author: phoebos <ben@bvnf.space>
Date:   Mon, 14 Mar 2022 04:01:54 +0000

ls: sort files given as args

put all the entries into one overall array, which is then sorted.
this has the problem of mixing entries from different directories -
make separate arrays for each directory? or just do it separately for
each directory?

Diffstat:
Mls.c | 76+++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------
1 file changed, 57 insertions(+), 19 deletions(-)

diff --git a/ls.c b/ls.c @@ -233,15 +233,15 @@ free_all(struct ent *entries, size_t num_entries) { } int -ls(const char *path) { +add_entries(const char *path, struct ent **entr, size_t *nentr) { struct stat st; if (lstat(path, &st) == -1) { fprintf(stderr, "ls: %s: %s\n", path, strerror(errno)); return 1; } - size_t num_entries = 0; - struct ent *entries = NULL; + size_t num_entries = *nentr; + struct ent *entries = *entr; DIR *dirp = NULL; struct dirent *dp = NULL; @@ -291,6 +291,7 @@ ls(const char *path) { /* add entry to entries */ num_entries++; + (*nentr)++; struct ent *tmp = realloc(entries, num_entries * sizeof(struct ent)); if (tmp == NULL) { fprintf(stderr, "ls: realloc: %s\n", strerror(errno)); @@ -298,6 +299,7 @@ ls(const char *path) { goto closedir_and_die; } entries = tmp; + *entr = entries; entries[num_entries - 1].name = strdup(dp->d_name); entries[num_entries - 1].ino = stt.st_ino; entries[num_entries - 1].mode = stt.st_mode; @@ -323,6 +325,7 @@ ls(const char *path) { } else { /* file */ num_entries++; + (*nentr)++; struct ent *tmp = realloc(entries, num_entries * sizeof(struct ent)); if (tmp == NULL) { fprintf(stderr, "ls: realloc: %s\n", strerror(errno)); @@ -330,6 +333,7 @@ ls(const char *path) { return 1; } entries = tmp; + *entr = entries; entries[num_entries - 1].name = strdup(path); entries[num_entries - 1].ino = st.st_ino; entries[num_entries - 1].mode = st.st_mode; @@ -346,13 +350,6 @@ ls(const char *path) { } finished_scan: - if (~flags & FLAG_f) - qsort(entries, num_entries, sizeof(struct ent), sort); - for (size_t i = 0; i < num_entries; i++) { - printname(&entries[i]); - } - - free_all(entries, num_entries); return 0; closedir_and_die: @@ -367,6 +364,52 @@ closedir_and_die: } int +ls(char **paths, int num) { + size_t num_entries = 0; + struct ent *entries = NULL; + + /* This puts all the struct ents into one array, which is then sorted. + * Solves problem of sorting individual files given as arguments (ls -tr foo.bar foo.baz) + * but we should not mix these files with files from other directories (ls foo.bar dir/ ) + */ + if (num == 0) { + if (add_entries(".", &entries, &num_entries) != 0) + return 1; + } else { + for (int i = 0; i < num; i++) { + if (add_entries(paths[i], &entries, &num_entries) != 0) + return 1; + } + } + + if (~flags & FLAG_f) + /* is this wrong if num > 1, because argument order dictates order in entries? + * but POSIX does say that -f is only about directory entries. + * Best to write args separately, and then directories according to -f etc with a dir: prefix. + * Like: + * $ ls -1f foo.txt bar.txt dir/ + * . + * foo.txt + * .. + * bar.txt + * + * dir: + * a.txt + * . + * .. + * b.txt + * + */ + qsort(entries, num_entries, sizeof(struct ent), sort); + for (size_t i = 0; i < num_entries; i++) { + printname(&entries[i]); + } + + free_all(entries, num_entries); + return 0; +} + +int main(int argc, char **argv) { int c, ret_val; flags = ret_val = 0; @@ -441,19 +484,14 @@ main(int argc, char **argv) { return 1; } } - argv += optind - 1; + argv += optind; + argc -= optind; if(!isatty(1)) flags |= FLAG_1; - if (argc == optind) { - if (ls(".") != 0) - ret_val = 1; - } - // TODO: if multiple separate files are given, they are not sorted (eg ls -lSr *.c) - else while (*++argv) - if (ls(*argv) != 0) - ret_val = 1; + if (ls(argv, argc) != 0) + ret_val = 1; if (!(flags & FLAG_1)) puts(""); /* final newline */