summaryrefslogtreecommitdiff
path: root/ls.c
diff options
context:
space:
mode:
authorJakob Kaivo <jkk@ung.org>2022-04-11 18:31:03 -0400
committerJakob Kaivo <jkk@ung.org>2022-04-11 18:31:03 -0400
commitab17e87f7becf9f3e7e48c554a1644c5a0271280 (patch)
treee389cbc135bf90e232d0a018bcdec79675b8f6a8 /ls.c
parent7e6af0686393dd9d46cc501f7f5a07eaa35663ad (diff)
show symlink destinations and proper character suffixes in -l
Diffstat (limited to 'ls.c')
-rw-r--r--ls.c62
1 files changed, 44 insertions, 18 deletions
diff --git a/ls.c b/ls.c
index 5575738..e9d9d85 100644
--- a/ls.c
+++ b/ls.c
@@ -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);