From 0cf63744a754b1c03efc50f53cbfc13fa53a2d77 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?P=C5=99emysl=20Janouch?=
Date: Sat, 15 Jul 2017 22:18:45 +0200
Subject: [PATCH] Factor out ls_format(), comments
---
sdn.cpp | 110 +++++++++++++++++++++++++++++++-------------------------
1 file changed, 61 insertions(+), 49 deletions(-)
diff --git a/sdn.cpp b/sdn.cpp
index cb841c8..1ba094e 100644
--- a/sdn.cpp
+++ b/sdn.cpp
@@ -318,6 +318,60 @@ static struct {
map ls_exts; // LS_COLORS file extensions
} g;
+fun ls_format (const string &filename, const struct stat &info) -> chtype {
+ int type = LS_ORPHAN;
+ auto set = [&](int t) { if (g.ls_colors.count (t)) type = t; };
+ // TODO: LS_MISSING if available and this is a missing symlink target
+ // TODO: go by readdir() information when stat() isn't available yet
+ if (S_ISREG (info.st_mode)) {
+ type = LS_FILE;
+ if (info.st_nlink > 1)
+ set (LS_MULTIHARDLINK);
+ if ((info.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)))
+ set (LS_EXECUTABLE);
+ if (lgetxattr (filename.c_str (), "security.capability", NULL, 0) >= 0)
+ set (LS_CAPABILITY);
+ if ((info.st_mode & S_ISGID))
+ set (LS_SETGID);
+ if ((info.st_mode & S_ISUID))
+ set (LS_SETUID);
+ } else if (S_ISDIR (info.st_mode)) {
+ type = LS_DIRECTORY;
+ if ((info.st_mode & S_ISVTX))
+ set (LS_STICKY);
+ if ((info.st_mode & S_IWOTH))
+ set (LS_OTHER_WRITABLE);
+ if ((info.st_mode & S_ISVTX) && (info.st_mode & S_IWOTH))
+ set (LS_STICKY_OTHER_WRITABLE);
+ } else if (S_ISLNK (info.st_mode)) {
+ // TODO: LS_ORPHAN when symlink target is missing and either
+ // a/ "li" is "target", or
+ // b/ LS_ORPHAN is available
+ type = LS_SYMLINK;
+ } else if (S_ISFIFO (info.st_mode)) {
+ type = LS_FIFO;
+ } else if (S_ISSOCK (info.st_mode)) {
+ type = LS_SOCKET;
+ } else if (S_ISBLK (info.st_mode)) {
+ type = LS_BLOCK;
+ } else if (S_ISCHR (info.st_mode)) {
+ type = LS_CHARACTER;
+ }
+
+ chtype format = 0;
+ const auto x = g.ls_colors.find (type);
+ if (x != g.ls_colors.end ())
+ format = x->second;
+
+ auto dot = filename.find_last_of ('.');
+ if (dot != string::npos && type == LS_FILE) {
+ const auto x = g.ls_exts.find (filename.substr (++dot));
+ if (x != g.ls_exts.end ())
+ format = x->second;
+ }
+ return format;
+}
+
// XXX: this will probably have to be changed to make_entry and run lstat itself
fun make_row (const string &filename, const struct stat &info) -> row {
row r;
@@ -353,55 +407,8 @@ fun make_row (const string &filename, const struct stat &info) -> row {
(tm->tm_year == now_year) ? "%b %e %H:%M" : "%b %e %Y", tm);
r.cols[row::MTIME] = apply_attrs (to_wide (buf), 0);
- int type = LS_ORPHAN;
- auto set = [&](int t) { if (g.ls_colors.count (t)) type = t; };
- // TODO: LS_MISSING
- if (S_ISREG (info.st_mode)) {
- type = LS_FILE;
- if (info.st_nlink > 1)
- set (LS_MULTIHARDLINK);
- if ((info.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)))
- set (LS_EXECUTABLE);
- if (lgetxattr (filename.c_str (), "security.capability", NULL, 0) >= 0)
- set (LS_CAPABILITY);
- if ((info.st_mode & S_ISGID))
- set (LS_SETGID);
- if ((info.st_mode & S_ISUID))
- set (LS_SETUID);
- } else if (S_ISDIR (info.st_mode)) {
- type = LS_DIRECTORY;
- if ((info.st_mode & S_ISVTX))
- set (LS_STICKY);
- if ((info.st_mode & S_IWOTH))
- set (LS_OTHER_WRITABLE);
- if ((info.st_mode & S_ISVTX) && (info.st_mode & S_IWOTH))
- set (LS_STICKY_OTHER_WRITABLE);
- } else if (S_ISLNK (info.st_mode)) {
- // TODO: LS_ORPHAN
- type = LS_SYMLINK;
- } else if (S_ISFIFO (info.st_mode)) {
- type = LS_FIFO;
- } else if (S_ISSOCK (info.st_mode)) {
- type = LS_SOCKET;
- } else if (S_ISBLK (info.st_mode)) {
- type = LS_BLOCK;
- } else if (S_ISCHR (info.st_mode)) {
- type = LS_CHARACTER;
- }
-
- chtype format = 0;
- const auto x = g.ls_colors.find (type);
- if (x != g.ls_colors.end ())
- format = x->second;
-
- auto dot = filename.find_last_of ('.');
- if (dot != string::npos && type == LS_FILE) {
- const auto x = g.ls_exts.find (filename.substr (++dot));
- if (x != g.ls_exts.end ())
- format = x->second;
- }
-
- // TODO: show symlink target
+ // TODO: show symlink target: check st_mode/DT_*, readlink
+ auto format = ls_format (filename, info);
r.cols[row::FILENAME] = apply_attrs (to_wide (filename), format);
return r;
}
@@ -462,6 +469,10 @@ fun reload () {
if (f->d_name == string ("."))
continue;
+ // TODO: check lstat() return value
+ // TODO: benchmark just readdir() vs. lstat(), also on dead mounts;
+ // it might make sense to stat asynchronously in threads
+ // http://lkml.iu.edu/hypermail//linux/kernel/0804.3/1616.html
struct stat sb = {};
lstat (f->d_name, &sb);
g.entries.push_back ({ f->d_name, sb, make_row (f->d_name, sb) });
@@ -527,6 +538,7 @@ fun handle_editor (wint_t c, bool is_char) {
fun choose (const entry &entry) -> bool {
bool is_dir = S_ISDIR (entry.info.st_mode) != 0;
// Dive into directories and accessible symlinks to them
+ // TODO: we probably want to use a preread readlink value
if (S_ISLNK (entry.info.st_mode)) {
char buf[PATH_MAX];
struct stat sb = {};