diff options
author | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2019-05-03 19:53:57 +0200 |
---|---|---|
committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2019-05-03 21:45:46 +0200 |
commit | 11163f69106c88736499ca3ec3a9972bcdcd0c26 (patch) | |
tree | 36431c4e88e6523f8cca2448ca2a4370a2ba2527 | |
parent | 4dc4c6bf50155550c0b83e433fef8c7c19462853 (diff) |
unsquashfs: print file size and symlink targets
Behave somewhat like `ls -l' does by printing the size of the
entry (or major/minor device number for devices) between the UID/GID
column and the name column.
For symlinks, print and arrow and the symlink target after the name.
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
-rw-r--r-- | unpack/list_files.c | 75 |
1 files changed, 69 insertions, 6 deletions
diff --git a/unpack/list_files.c b/unpack/list_files.c index aaf0652..86bc185 100644 --- a/unpack/list_files.c +++ b/unpack/list_files.c @@ -1,6 +1,8 @@ /* SPDX-License-Identifier: GPL-3.0-or-later */ #include "unsquashfs.h" +#include <sys/sysmacros.h> + static void mode_to_str(uint16_t mode, char *p) { switch (mode & S_IFMT) { @@ -59,10 +61,51 @@ static int count_int_chars(unsigned int i) return count; } +static void print_size(uint64_t size, char *buffer) +{ + static const char *suffices = "kMGTPEZY"; + int suffix = -1; + + while (size > 1024) { + ++suffix; + size /= 1024; + } + + if (suffix >= 0) { + sprintf(buffer, "%u%c", (unsigned int)size, suffices[suffix]); + } else { + sprintf(buffer, "%u", (unsigned int)size); + } +} + +static void print_node_size(tree_node_t *n, char *buffer) +{ + switch (n->mode & S_IFMT) { + case S_IFLNK: + print_size(strlen(n->data.slink_target), buffer); + break; + case S_IFREG: + print_size(n->data.file->size, buffer); + break; + case S_IFDIR: + print_size(n->data.dir->size, buffer); + break; + case S_IFBLK: + case S_IFCHR: + sprintf(buffer, "%u:%u", major(n->data.devno), + minor(n->data.devno)); + break; + default: + buffer[0] = '0'; + buffer[1] = '\0'; + break; + } +} + void list_files(tree_node_t *node) { - int i, max_uid_chars = 0, max_gid_chars = 0; - char modestr[12]; + int i, max_uid_chars = 0, max_gid_chars = 0, max_sz_chars = 0; + char modestr[12], sizestr[32]; tree_node_t *n; if (S_ISDIR(node->mode)) { @@ -72,19 +115,39 @@ void list_files(tree_node_t *node) i = count_int_chars(n->gid); max_gid_chars = i > max_gid_chars ? i : max_gid_chars; + + print_node_size(n, sizestr); + i = strlen(sizestr); + max_sz_chars = i > max_sz_chars ? i : max_sz_chars; } for (n = node->data.dir->children; n != NULL; n = n->next) { mode_to_str(n->mode, modestr); + print_node_size(n, sizestr); - printf("%s %*u/%-*u %s\n", modestr, + printf("%s %*u/%-*u %*s %s", modestr, max_uid_chars, n->uid, - max_gid_chars, n->gid, n->name); + max_gid_chars, n->gid, + max_sz_chars, sizestr, + n->name); + + if (S_ISLNK(n->mode)) { + printf(" -> %s\n", n->data.slink_target); + } else { + fputc('\n', stdout); + } } } else { mode_to_str(node->mode, modestr); + print_node_size(node, sizestr); - printf("%s %u/%u %s\n", modestr, - node->uid, node->gid, node->name); + printf("%s %u/%u %s %s", modestr, + node->uid, node->gid, sizestr, node->name); + + if (S_ISLNK(node->mode)) { + printf(" -> %s\n", node->data.slink_target); + } else { + fputc('\n', stdout); + } } } |