summaryrefslogtreecommitdiff
path: root/unpack/list_files.c
diff options
context:
space:
mode:
authorDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2019-05-03 19:53:57 +0200
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2019-05-03 21:45:46 +0200
commit11163f69106c88736499ca3ec3a9972bcdcd0c26 (patch)
tree36431c4e88e6523f8cca2448ca2a4370a2ba2527 /unpack/list_files.c
parent4dc4c6bf50155550c0b83e433fef8c7c19462853 (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>
Diffstat (limited to 'unpack/list_files.c')
-rw-r--r--unpack/list_files.c75
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);
+ }
}
}