aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/output.c57
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 === */