diff options
author | Jakob Kaivo <jkk@ung.org> | 2022-04-11 18:31:03 -0400 |
---|---|---|
committer | Jakob Kaivo <jkk@ung.org> | 2022-04-11 18:31:03 -0400 |
commit | ab17e87f7becf9f3e7e48c554a1644c5a0271280 (patch) | |
tree | e389cbc135bf90e232d0a018bcdec79675b8f6a8 /ls.c | |
parent | 7e6af0686393dd9d46cc501f7f5a07eaa35663ad (diff) |
show symlink destinations and proper character suffixes in -l
Diffstat (limited to 'ls.c')
-rw-r--r-- | ls.c | 62 |
1 files changed, 44 insertions, 18 deletions
@@ -71,32 +71,36 @@ static int stat_flags = AT_SYMLINK_NOFOLLOW; struct file_info { char *path; + char link[PATH_MAX]; struct stat st; + struct stat lstat; }; static void (*ls_print)(size_t n, struct file_info[static n]); -static char * ls_filename(struct file_info *f) +static char * ls_getmark(mode_t mode) { - static char name[PATH_MAX + 2]; - char *suffix = ""; - - /* TODO: only if requested */ - if (ls_mark != MARK_NONE && S_ISDIR(f->st.st_mode)) { - suffix = "/"; + if (ls_mark != MARK_NONE && S_ISDIR(mode)) { + return "/"; } else if (ls_mark == MARK_ALL) { - if (S_ISFIFO(f->st.st_mode)) { - suffix = "|"; - } else if (S_ISLNK(f->st.st_mode)) { - suffix = "@"; - } else if (S_ISREG(f->st.st_mode)) { - if ((S_IXUSR & f->st.st_mode) || (S_IXGRP & f->st.st_mode) || (S_IXOTH & f->st.st_mode)) { - suffix = "*"; + if (S_ISFIFO(mode)) { + return "|"; + } else if (S_ISLNK(mode)) { + return "@"; + } else if (S_ISREG(mode)) { + if ((S_IXUSR & mode) || (S_IXGRP & mode) || (S_IXOTH & mode)) { + return "*"; } } } - snprintf(name, sizeof(name), "%s%s", f->path, suffix); + return ""; +} + +static char * ls_filename(struct file_info *f) +{ + static char name[PATH_MAX + 2]; + snprintf(name, sizeof(name), "%s%s", f->path, ls_getmark(f->st.st_mode)); return name; } @@ -185,8 +189,13 @@ static int ls_dir(char *dir, int showdirname) files[nfiles].path = NULL; ret = 1; } else { - nfiles++; blocks += files[nfiles].st.st_blocks; + if (S_ISLNK(files[nfiles].st.st_mode)) { + readlinkat(dfd, de->d_name, files[nfiles].link, + sizeof(files[nfiles].link)); + fstatat(dfd, de->d_name, &files[nfiles].lstat, 0); + } + nfiles++; } } closedir(d); @@ -202,6 +211,10 @@ static int ls_dir(char *dir, int showdirname) qsort(files, nfiles, sizeof(*files), ls_compare_files); ls_print(nfiles, files); + + for (size_t i = 0; i < nfiles; i++) { + free(files[i].path); + } free(files); return ret; @@ -341,10 +354,18 @@ static void ls_print_long(size_t n, struct file_info files[static n]) } printf("%s ", ls_file_time(st.st_mtim)); - printf("%s", ls_filename(files + i)); + + char * name = ls_filename(files + i); if (S_ISLNK(st.st_mode)) { - printf(" -> %s\n", "LINK_DESTINATION"); + if (ls_mark == MARK_ALL) { + name[strlen(name) - 1] = '\0'; + } + printf("%s -> %s", name, files[i].link); + printf("%s", ls_getmark(files[i].lstat.st_mode)); + } else { + printf("%s", name); } + printf("\n"); } } @@ -620,6 +641,11 @@ int main(int argc, char *argv[]) fprintf(stderr, "ls: %s: %s\n", argv[i], strerror(errno)); ret = 1; } + if (S_ISLNK(operands[i].st.st_mode)) { + readlinkat(AT_FDCWD, argv[i], operands[i].link, + sizeof(operands[i].link)); + fstatat(AT_FDCWD, argv[i], &operands[i].lstat, 0); + } } operands[argc].path = NULL; qsort(operands, argc, sizeof(operands[0]), ls_compare_operands); |