aboutsummaryrefslogtreecommitdiff
path: root/extras/list_files.c
diff options
context:
space:
mode:
Diffstat (limited to 'extras/list_files.c')
-rw-r--r--extras/list_files.c160
1 files changed, 115 insertions, 45 deletions
diff --git a/extras/list_files.c b/extras/list_files.c
index 89a1f30..55b94e2 100644
--- a/extras/list_files.c
+++ b/extras/list_files.c
@@ -6,6 +6,7 @@
*/
#include "sqfs/compressor.h"
#include "sqfs/dir_reader.h"
+#include "sqfs/dir_entry.h"
#include "sqfs/id_table.h"
#include "sqfs/inode.h"
#include "sqfs/super.h"
@@ -16,52 +17,114 @@
#include <errno.h>
#include <stdio.h>
-static void write_tree_dfs(const sqfs_tree_node_t *n)
+static int count_entries(sqfs_dir_iterator_t *it, unsigned int *out)
{
- const sqfs_tree_node_t *p;
- unsigned int mask, level;
- int i;
-
- for (n = n->children; n != NULL; n = n->next) {
- level = 0;
- mask = 0;
-
- for (p = n->parent; p->parent != NULL; p = p->parent) {
- if (p->next != NULL)
- mask |= 1 << level;
- ++level;
+ sqfs_dir_entry_t *ent;
+ int ret;
+
+ *out = 0;
+
+ for (;;) {
+ ret = it->next(it, &ent);
+ if (ret < 0) {
+ *out = 0;
+ return -1;
}
+ if (ret > 0)
+ break;
- for (i = level - 1; i >= 0; --i)
+ *out += 1;
+ free(ent);
+ }
+
+ return 0;
+}
+
+static void write_tree_dfs(sqfs_dir_iterator_t *it,
+ unsigned int mask, unsigned int level,
+ unsigned int count)
+{
+ sqfs_dir_entry_t *ent;
+ unsigned int i;
+ sqfs_u16 type;
+
+ while (count--) {
+ for (i = 0; i < level; ++i)
fputs(mask & (1 << i) ? "│ " : " ", stdout);
- fputs(n->next == NULL ? "└─ " : "├─ ", stdout);
- fputs((const char *)n->name, stdout);
-
- if (n->inode->base.type == SQFS_INODE_SLINK) {
- printf(" ⭢ %.*s",
- (int)n->inode->data.slink.target_size,
- (const char *)n->inode->extra);
- } else if (n->inode->base.type == SQFS_INODE_EXT_SLINK) {
- printf(" ⭢ %.*s",
- (int)n->inode->data.slink_ext.target_size,
- (const char *)n->inode->extra);
+ if (it->next(it, &ent) != 0)
+ break;
+
+ fputs(count == 0 ? "└─ " : "├─ ", stdout);
+ fputs(ent->name, stdout);
+
+ type = ent->mode & SQFS_INODE_MODE_MASK;
+ free(ent);
+
+ if (type == SQFS_INODE_MODE_LNK) {
+ char *target;
+
+ if (it->read_link(it, &target) == 0)
+ printf(" ⭢ %s", target);
+
+ free(target);
}
fputc('\n', stdout);
- write_tree_dfs(n);
+
+ if (type == SQFS_INODE_MODE_DIR) {
+ sqfs_dir_iterator_t *sub;
+ unsigned int sub_count;
+
+ it->open_subdir(it, &sub);
+ count_entries(sub, &sub_count);
+ sub = sqfs_drop(sub);
+
+ it->open_subdir(it, &sub);
+ write_tree_dfs(sub,
+ mask | (count > 0 ? (1 << level) : 0),
+ level + 1, sub_count);
+ sqfs_drop(sub);
+ }
}
}
+static sqfs_dir_iterator_t *create_root_iterator(sqfs_dir_reader_t *dr,
+ sqfs_id_table_t *idtbl,
+ const char *filename)
+{
+ sqfs_inode_generic_t *iroot;
+ sqfs_dir_iterator_t *it;
+ int ret;
+
+ if (sqfs_dir_reader_get_root_inode(dr, &iroot)) {
+ fprintf(stderr, "%s: error reading root inode.\n",
+ filename);
+ return NULL;
+ }
+
+ ret = sqfs_dir_iterator_create(dr, idtbl, NULL, NULL, iroot, &it);
+ free(iroot);
+
+ if (ret) {
+ fprintf(stderr, "%s: error creating root iterator.\n",
+ filename);
+ return NULL;
+ }
+
+ return it;
+}
+
int main(int argc, char **argv)
{
int ret, status = EXIT_FAILURE;
+ sqfs_dir_iterator_t *it = NULL;
+ sqfs_compressor_t *cmp = NULL;
+ sqfs_id_table_t *idtbl = NULL;
+ sqfs_dir_reader_t *dr = NULL;
sqfs_compressor_config_t cfg;
- sqfs_compressor_t *cmp;
- sqfs_tree_node_t *root = NULL;
- sqfs_id_table_t *idtbl;
- sqfs_dir_reader_t *dr;
- sqfs_file_t *file;
+ sqfs_file_t *file = NULL;
+ unsigned int root_count;
sqfs_super_t super;
/* open the SquashFS file we want to read */
@@ -79,7 +142,7 @@ int main(int argc, char **argv)
process the compressor options */
if (sqfs_super_read(&super, file)) {
fprintf(stderr, "%s: error reading super block.\n", argv[1]);
- goto out_fd;
+ goto out;
}
sqfs_compressor_config_init(&cfg, super.compression_id,
@@ -90,50 +153,57 @@ int main(int argc, char **argv)
if (ret != 0) {
fprintf(stderr, "%s: error creating compressor: %d.\n",
argv[1], ret);
- goto out_fd;
+ goto out;
}
/* Create and read the UID/GID mapping table */
idtbl = sqfs_id_table_create(0);
if (idtbl == NULL) {
fputs("Error creating ID table.\n", stderr);
- goto out_cmp;
+ goto out;
}
if (sqfs_id_table_read(idtbl, file, &super, cmp)) {
fprintf(stderr, "%s: error loading ID table.\n", argv[1]);
- goto out_id;
+ goto out;
}
- /* create a directory reader and scan the entire directory hiearchy */
+ /* create a directory reader */
dr = sqfs_dir_reader_create(&super, cmp, file, 0);
if (dr == NULL) {
fprintf(stderr, "%s: error creating directory reader.\n",
argv[1]);
- goto out_id;
+ goto out;
}
- if (sqfs_dir_reader_get_full_hierarchy(dr, idtbl, NULL, 0, &root)) {
- fprintf(stderr, "%s: error loading directory tree.\n",
+ /* create a directory iterator for the root inode */
+ it = create_root_iterator(dr, idtbl, argv[1]);
+ if (it == NULL)
+ goto out;
+
+ if (count_entries(it, &root_count)) {
+ fprintf(stderr, "%s: error counting root iterator entries.\n",
argv[1]);
goto out;
}
+ it = sqfs_drop(it);
+
+ it = create_root_iterator(dr, idtbl, argv[1]);
+ if (it == NULL)
+ goto out;
+
/* fancy print the hierarchy */
printf("/\n");
- write_tree_dfs(root);
+ write_tree_dfs(it, 0, 0, root_count);
/* cleanup */
status = EXIT_SUCCESS;
out:
- if (root != NULL)
- sqfs_dir_tree_destroy(root);
+ sqfs_drop(it);
sqfs_drop(dr);
-out_id:
sqfs_drop(idtbl);
-out_cmp:
sqfs_drop(cmp);
-out_fd:
sqfs_drop(file);
return status;
}