+void destroy_entry_list(struct entry_node *node) {
+ struct entry_node *next;
+ while(node) {
+ next = node->next;
+ free(node->name);
+ free(node);
+ node = next;
+ }
+}
+
+/**********************************************************************/
+
+int compare_files(const void *x1, const void *x2) {
+ const struct entry_node **f1, **f2;
+
+ f1 = (const struct entry_node **) x1;
+ f2 = (const struct entry_node **) x2;
+
+ if(reverse_sorting) {
+ if((*f1)->size < (*f2)->size) {
+ return 1;
+ } else if((*f1)->size > (*f2)->size) {
+ return -1;
+ } else {
+ return 0;
+ }
+ } else {
+ if((*f1)->size < (*f2)->size) {
+ return -1;
+ } else if((*f1)->size > (*f2)->size) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+}
+
+void raw_print(char *buffer, size_t buffer_size, char *filename, size_sum_t size) {
+ char *a, *b, *c, u;
+
+ b = buffer;
+ do {
+ if(b >= buffer + buffer_size) {
+ fprintf(stderr, "Buffer overflow in raw_print (hu?!).\n");
+ exit(EXIT_FAILURE);
+ }
+ *(b++) = size%10 + '0';
+ size /= 10;
+ } while(size);
+
+ a = buffer;
+ c = b;
+ while(a < c) {
+ u = *a;
+ *(a++) = *(--c);
+ *c = u;
+ }
+
+ *(b++) = ' ';
+
+ snprintf(b, buffer_size - (b - buffer), "%s\n", filename);
+}
+
+void fancy_print(char *buffer, size_t buffer_size, char *filename, size_sum_t size) {
+ if(size < 1024) {
+ snprintf(buffer,
+ buffer_size,
+ "% 7d -- %s\n",
+ ((int) size),
+ filename);
+ } else if(size < 1024 * 1024) {
+ snprintf(buffer,
+ buffer_size,
+ "% 6.1fK -- %s\n",
+ ((double) (size))/(1024.0),
+ filename);
+ } else if(size < 1024 * 1024 * 1024) {
+ snprintf(buffer,
+ buffer_size,
+ "% 6.1fM -- %s\n",
+ ((double) (size))/(1024.0 * 1024),
+ filename);
+ } else {
+ snprintf(buffer,
+ buffer_size,
+ "% 6.1fG -- %s\n",
+ ((double) (size))/(1024.0 * 1024.0 * 1024.0),
+ filename);
+ }
+}
+
+void print_sorted(struct entry_node *root, int width, int height) {
+ char line[BUFFER_SIZE];
+ struct entry_node *node;
+ struct entry_node **nodes;
+ int nb_nodes, n, first, last;
+
+ nb_nodes = 0;
+ for(node = root; node; node = node->next) {
+ if(size_min < 0 || node->size >= size_min) {
+ nb_nodes++;
+ }
+ }
+
+ nodes = safe_malloc(nb_nodes * sizeof(struct entry_node *));
+
+ n = 0;
+ for(node = root; node; node = node->next) {
+ if(size_min < 0 || node->size >= size_min) {
+ nodes[n++] = node;
+ }
+ }
+
+ qsort(nodes, nb_nodes, sizeof(struct entry_node *), compare_files);
+
+ first = 0;
+ last = nb_nodes;
+
+ if(forced_height) {
+ height = forced_height;
+ }
+
+ if(forced_width) {
+ width = forced_width;
+ }
+
+ if(height >= 0 && nb_nodes > height && !show_top && !forced_height) {
+ printf("...\n");
+ }
+
+ if(height > 0 && height < nb_nodes) {
+ first = nb_nodes - height;
+ }
+
+ if(show_top) {
+ n = last;
+ last = nb_nodes - first;
+ first = nb_nodes - n;
+ }
+
+ /* I do not like valgrind to complain about uninitialized data */
+ if(width < BUFFER_SIZE) {
+ line[width] = '\0';
+ }
+
+ for(n = first; n < last; n++) {
+ if(fancy_size_display) {
+ fancy_print(line, BUFFER_SIZE, nodes[n]->name, nodes[n]->size);
+ } else {
+ raw_print(line, BUFFER_SIZE, nodes[n]->name, nodes[n]->size);
+ }
+ if(width >= 1 && width + 1 < BUFFER_SIZE && line[width]) {
+ line[width] = '\n';
+ line[width + 1] = '\0';
+ }
+ printf(line);
+ }
+
+ if(height >= 0 && nb_nodes > height && show_top && !forced_height) {
+ printf("...\n");
+ }
+
+ free(nodes);
+}
+
+/**********************************************************************/
+
+void usage(FILE *out) {
+ fprintf(out, "Usage: dus [OPTION]... [FILE]...\n");
+ fprintf(out, "Version %s (%s)\n", VERSION_NUMBER, UNAME);
+ fprintf(out, "List files and directories sorted according to their size or content size. Take the content of the current directory as argument if none is provided.\n");
+ fprintf(out, "\n");
+ /* 01234567890123456789012345678901234567890123456789012345678901234567890123456789*/
+ fprintf(out, " -d, --ignore-dots ignore files and directories starting with a '.'\n");
+ fprintf(out, " -f, --fancy display size with float values and K, M and G\n");
+ fprintf(out, " units.\n");
+ fprintf(out, " -r, --reverse-order reverse the sorting order.\n");
+ fprintf(out, " -t, --show-top show the top of the list.\n");
+ fprintf(out, " -c <cols>, --nb-columns <cols>\n");
+ fprintf(out, " specificy the number of columns to display. The\n");
+ fprintf(out, " value -1 corresponds to no constraint. By default\n");
+ fprintf(out, " the command uses the tty width, or no constraint\n");
+ fprintf(out, " if the stdout is not a tty.\n");
+ fprintf(out, " -l <lines>, --nb-lines <lines>\n");
+ fprintf(out, " same as -c for number of lines.\n");
+ fprintf(out, " -h, --help show this help.\n");
+ fprintf(out, " -m <size>, --size-min <size>\n");
+ fprintf(out, " set the listed entries minimum size.\n");
+ fprintf(out, "\n");
+ fprintf(out, "Report bugs and comments to <francois@fleuret.org>.\n");
+}
+
+/**********************************************************************/
+
+static struct option long_options[] = {
+ { "ignore-dots", no_argument, 0, 'd' },
+ { "reverse-order", no_argument, 0, 'r' },
+ { "show-top", no_argument, 0, 't' },
+ { "help", no_argument, 0, 'h' },
+ { "fancy", no_argument, 0, 'f' },
+ { "nb-columns", 1, 0, 'c' },
+ { "nb-lines", 1, 0, 'l' },
+ { "size-min", 1, 0, 'm' },
+ { 0, 0, 0, 0 }
+};
+