diff options
Diffstat (limited to 'src/output.c')
| -rw-r--r-- | src/output.c | 57 |
1 files changed, 52 insertions, 5 deletions
diff --git a/src/output.c b/src/output.c index 3cf68af..4c660d6 100644 --- a/src/output.c +++ b/src/output.c @@ -51,6 +51,7 @@ void out_print_user_name(struct list_node *ptr); void out_print_format_string_header(const char *format, size_t longest_fname); +size_t estimate_formatted_line_length(const char *format, size_t longest_fname); size_t get_longest_filename(struct list_head *list); @@ -314,18 +315,62 @@ inline void out_print_permissions(struct list_node *ptr) { printf(" %4o ", mode); } +/* 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) { + size_t rc = 0, i=0, format_len=0; + static int login_name_max = -1; + if (login_name_max < 0) { + /* TODO: Check whether all UNIX likes use this for user and group name*/ + if ((login_name_max=(int)sysconf(_SC_LOGIN_NAME_MAX)) < 0) { + LOGERR("ERROR: sysconf(_SC_LOGIN_NAME_MAX) failed: %s (errno %d)\n", + strerror(errno), errno); + return 0; + } + DBGTRC("DEBUG: sysconf(_SC_LOGIN_NAME_MAX) = %d\n", login_name_max); + login_name_max += 4; /* formatting additions */ + } + format_len = strnlen(format, DM_OUT_FORMAT_MAX_LEN); + for (i=0; i<format_len; i++) { + switch (format[i]) { + case 'n': rc += longest_fname+4; break; + case 'G': + case 'U': rc += ((unsigned int)login_name_max); break; + case 'g': /* Short ones */ + case 'p': + case 'u': rc += 8; break; + case ' ': break; + default: rc += 28; /* time, and strings >10 in format*/ + }; + } + DBGTRC("DEBUG: format string '%s' estimated with %lu bytes\n", format, rc); + return rc; +} + inline void out_print_format_string_header(const char *format, size_t longest_fname) { - size_t i=0, j=0, k=0, format_len=0, tmp = 0; - char header[4096] = "", sep_line[4096] = ""; - char *pos = header; + size_t i=0, j=0, k=0, format_len=0, est_length=0, tmp = 0; + char *header = NULL, *sep_line = NULL; + char *pos = NULL; - if (format == NULL || longest_fname == 0) return; + if (format == NULL || format[0] == '\0' || longest_fname == 0) return; DBGTRC("DEBUG: format string: \"%s\"\n", format); - format_len = strnlen(format, DM_OUT_FORMAT_MAX_LEN); + est_length = estimate_formatted_line_length(format, longest_fname); + if ((header=calloc(est_length, sizeof(char))) == NULL) { + LOGERR("ERROR: Failed to allocate memory for header\n"); + return; + } + + pos = header; + if (option_print_boxed_table) { + if ((sep_line=calloc(est_length, sizeof(char))) == NULL) { + free(header); + LOGERR("ERROR: Failed to allocate memory for sep line\n"); + return; + } if (global_sep_line != NULL) { free(global_sep_line); } pos[0] = box_vsep; pos++; @@ -429,11 +474,13 @@ inline void out_print_format_string_header(const char *format, size_t longest_fn fputs(sep_line, stdout); if ((global_sep_line = calloc(tmp+1, sizeof(char))) != NULL) { memcpy(global_sep_line, sep_line, tmp); + free(sep_line); } } else { fputc_width_x('-', strlen(header), stdout); } out_print_newline(); + free(header); #undef LOCAL_EXTEND_SEP_LINE } /* === END OF FORMATTING FUNCTIONS === */ |
