From 31aaaca68b15fab61bf8a5e2b0187111fae27f46 Mon Sep 17 00:00:00 2001 From: Thorsten Töpper Date: Sat, 2 Aug 2025 00:02:57 +0200 Subject: symlinks: destination can be resolved --- src/output.c | 140 +++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 108 insertions(+), 32 deletions(-) (limited to 'src/output.c') diff --git a/src/output.c b/src/output.c index f94e3c9..a928140 100644 --- a/src/output.c +++ b/src/output.c @@ -37,22 +37,26 @@ #define out_vsep() fputc(box_vsep, stdout) #define out_print_newline() fputc('\n', stdout) -#define out_print_fname(x) printf(" %s ", x->fname) -#define out_print_uid(x) printf(" %4u ", x->ln_stat.st_gid) -#define out_print_gid(x) printf(" %4u ", x->ln_stat.st_uid) +void out_print_fname(struct list_node *ptr, size_t longest_fname); +void out_print_gid(struct list_node *ptr); void out_print_group_name(struct list_node *ptr); void out_print_permissions(struct list_node *ptr); void out_print_size(struct list_node *ptr); +void out_print_symlink(struct list_node *ptr, size_t longest_fname); void out_print_time(time_t tv); void out_print_time_by_option(struct list_node *ptr); void out_print_type(struct list_node *ptr); +void out_print_uid(struct list_node *ptr); void out_print_user_name(struct list_node *ptr); -void out_print_format_string_header(const char *format, size_t longest_fname); +void out_print_format_string_header(const char *format, + size_t longest_fname, size_t longest_symlink); -size_t estimate_formatted_line_length(const char *format, size_t longest_fname); +size_t estimate_formatted_line_length(const char *format, + size_t longest_fname, size_t longest_symlink); size_t get_longest_filename(struct list_head *list); +size_t get_longest_symlink(struct list_head *list); char *global_sep_line = NULL; @@ -102,7 +106,7 @@ inline int fputc_width_x(char c, size_t x, FILE *fdout) { inline size_t get_longest_filename(struct list_head *list) { size_t rc = 4, tmp = 0; struct list_node *ptr = NULL; - if (list == NULL) { return 0; } + if (list == NULL) { return rc; } ptr = list->first; while (ptr != NULL) { tmp = strlen(ptr->fname); @@ -112,8 +116,66 @@ inline size_t get_longest_filename(struct list_head *list) { return rc; } +/* basic 7 due to formatted output */ +inline size_t get_longest_symlink(struct list_head *list) { + size_t rc = 7, tmp = 0; + struct list_node *ptr = NULL; + if (list == NULL) { return rc; } + ptr = list->first; + while(ptr != NULL) { + if (ptr->symlink_target != NULL) { + tmp = strlen(ptr->symlink_target); + } else { tmp = 0; } + if (tmp>rc) { rc = tmp; } + ptr = ptr->next; + } + return rc; +} + /* === FORMATTING RELATED FUNCTIONS === */ + +inline void out_print_uid(struct list_node *ptr) { + printf(" %4u ", ptr->ln_stat.st_gid); + if (option_print_boxed_table) { out_vsep(); } +} + + +inline void out_print_gid(struct list_node *ptr) { + printf(" %4u ", ptr->ln_stat.st_uid); + if (option_print_boxed_table) { out_vsep(); } +} + + +inline void out_print_fname(struct list_node *ptr, size_t longest_fname) { + size_t i = 0; + printf(" %s ", ptr->fname); + if (option_print_boxed_table) { + for (i=0; i<(longest_fname - strlen(ptr->fname)); i++) { + fputc(' ', stdout); + } + out_vsep(); + } +} + + +inline void out_print_symlink(struct list_node *ptr, size_t longest_symlink) { + size_t i = 0, sll = 0; + if (ptr->symlink_target != NULL) { + sll = strlen(ptr->symlink_target); + printf(" %s ", ptr->symlink_target); + } else { + printf(" "); + } + if (option_print_boxed_table) { + for (i=0; i<(longest_symlink - sll); i++) { + fputc(' ', stdout); + } + out_vsep(); + } +} + + /* Be aware: getting the name via uid takes a lot of time depending on the * systems setup. local, NIS, LDAP ... * Caching happens outside the executable, minimal here for skipping funcion calls. */ @@ -152,6 +214,7 @@ inline void out_print_group_name(struct list_node *ptr) { explicit_bzero(prev_group_name, 64); memcpy(prev_group_name, group->gr_name, group_name_length); printf(" %-10s ", prev_group_name); + if (option_print_boxed_table) { out_vsep(); } } /* Reminder: resolving may take some time even with cache in libraries, @@ -191,6 +254,7 @@ inline void out_print_user_name(struct list_node *ptr) { explicit_bzero(prev_user_name, 64); memcpy(prev_user_name, pwd->pw_name, user_name_length); printf(" %-10s ", prev_user_name); + if (option_print_boxed_table) { out_vsep(); } } inline void out_print_size(struct list_node *ptr) { @@ -208,6 +272,7 @@ inline void out_print_size(struct list_node *ptr) { } } printf(" %8ld %3s ", tmp, unit); + if (option_print_boxed_table) { out_vsep(); } } inline void out_print_time(time_t tv) { @@ -222,6 +287,7 @@ inline void out_print_time(time_t tv) { strftime(timestamp, sizeof(timestamp), "%H:%M:%S", tm); printf(" %-8s ", timestamp); } + if (option_print_boxed_table) { out_vsep(); } } inline void out_print_time_by_option(struct list_node *ptr) { @@ -282,6 +348,7 @@ inline void out_print_type(struct list_node *ptr) { } /* The ones longer than 12 characters are rare. */ printf(" %-12s ", entry); + if (option_print_boxed_table) { out_vsep(); } } inline void out_print_permissions(struct list_node *ptr) { @@ -327,11 +394,14 @@ inline void out_print_permissions(struct list_node *ptr) { mode |= S_ISUID; } printf(" %4o ", mode); + if (option_print_boxed_table) { out_vsep(); } } +/* === END OF FORMATTING FUNCTIONS === */ + /* Interpret the format string and based on it generate a size which will be * able to store everything including visual additions. Use strlen later. */ -inline size_t estimate_formatted_line_length(const char *format, size_t longest_fname) { +inline size_t estimate_formatted_line_length(const char *format, size_t longest_fname, size_t longest_symlink) { size_t rc = 0, i=0, format_len=0; static int login_name_max = -1; if (login_name_max < 0) { @@ -347,6 +417,7 @@ inline size_t estimate_formatted_line_length(const char *format, size_t longest_ format_len = strnlen(format, DM_OUT_FORMAT_MAX_LEN); for (i=0; ifirst; @@ -568,57 +656,45 @@ void print_list_formatted(const char *format, struct list_head *list) { for (i=0; i < format_len; i++) { switch (format[i]) { case 'n': - out_print_fname(ptr); - if (option_print_boxed_table) { - for (j=0; j<(longest_fname - strlen(ptr->fname)); j++) { - fputc(' ', stdout); - } - out_vsep(); + out_print_fname(ptr, longest_fname); + break; + case 'l': + if (option_resolve_symlinks) { + out_print_symlink(ptr, longest_symlink); } break; case 's': out_print_size(ptr); - if (option_print_boxed_table) { out_vsep(); } break; case 't': out_print_time_by_option(ptr); - if (option_print_boxed_table) { out_vsep(); } break; case 'A': out_print_time(ptr->ln_stat.st_atim.tv_sec); - if (option_print_boxed_table) { out_vsep(); } break; case 'C': out_print_time(ptr->ln_stat.st_ctim.tv_sec); - if (option_print_boxed_table) { out_vsep(); } break; case 'M': out_print_time(ptr->ln_stat.st_mtim.tv_sec); - if (option_print_boxed_table) { out_vsep(); } break; case 'T': out_print_type(ptr); - if (option_print_boxed_table) { out_vsep(); } break; case 'u': out_print_uid(ptr); - if (option_print_boxed_table) { out_vsep(); } break; case 'g': out_print_gid(ptr); - if (option_print_boxed_table) { out_vsep(); } break; case 'U': out_print_user_name(ptr); - if (option_print_boxed_table) { out_vsep(); } break; case 'G': out_print_group_name(ptr); - if (option_print_boxed_table) { out_vsep(); } break; case 'p': out_print_permissions(ptr); - if (option_print_boxed_table) { out_vsep(); } break; case ' ': /* just ignore this without warning */ break; -- cgit v1.2.3-70-g09d2