Skip to content

Commit

Permalink
Merge pull request #226 from Gottox/add/easy-traversal
Browse files Browse the repository at this point in the history
Add/easy traversal
  • Loading branch information
Gottox committed May 28, 2024
2 parents a657fad + f413079 commit f396654
Show file tree
Hide file tree
Showing 7 changed files with 199 additions and 1 deletion.
6 changes: 6 additions & 0 deletions examples/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ executable(
install: false,
dependencies: libsqsh_dep,
)
executable(
'traverse_dir',
'traverse_dir.c',
install: false,
dependencies: libsqsh_dep,
)
executable(
'traverse_dir_ll',
'traverse_dir_ll.c',
Expand Down
33 changes: 33 additions & 0 deletions examples/traverse_dir.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/**
* @author Enno Boland ([email protected])
* @file list_dir.c
*
* This is an example program that lists the top level files in a squashfs
* archive.
*/

#include <assert.h>
#include <sqsh.h>
#include <stdio.h>
#include <stdlib.h>

int
main(int argc, char *argv[]) {
if (argc != 2) {
printf("Usage: %s <sqsh-file>\n", argv[0]);
return 1;
}
struct SqshArchive *archive = sqsh_archive_open(argv[1], NULL, NULL);
assert(archive != NULL);

char **dir_list = sqsh_easy_tree_traversal(archive, "/xfce-extra", NULL);
assert(dir_list != NULL);

for (int i = 0; dir_list[i] != NULL; i++) {
puts(dir_list[i]);
}

free(dir_list);
sqsh_archive_close(archive);
return 0;
}
7 changes: 7 additions & 0 deletions include/sqsh_easy.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,13 @@ char **sqsh_easy_directory_list(
char **sqsh_easy_directory_list_path(
struct SqshArchive *archive, const char *path, int *err);

/***************************************
* easy/traversal.c
*/

char **sqsh_easy_tree_traversal(
struct SqshArchive *archive, const char *path, int *err);

/***************************************
* easy/xattr.c
*/
Expand Down
122 changes: 122 additions & 0 deletions libsqsh/src/easy/traversal.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/******************************************************************************
* *
* Copyright (c) 2023-2024, Enno Boland <[email protected]> *
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions are *
* met: *
* *
* * Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* * Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS *
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, *
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR *
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR *
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
******************************************************************************/

/**
* @author Enno Boland ([email protected])
* @file directory.c
*/

#include "sqsh_tree.h"
#define _DEFAULT_SOURCE

#include <sqsh_easy.h>

#include <pthread.h>
#include <stdlib.h>
#include <string.h>

#include <sqsh_error.h>
#include <sqsh_tree_private.h>

struct TreeTraversalIterator {
struct SqshTreeTraversal traversal;
char *value;
};

static int
tree_traversal_collector_next(
void *iterator, const char **value, size_t *size) {
struct TreeTraversalIterator *it = iterator;
int rv = 0;
free(it->value);

while (sqsh_tree_traversal_next(&it->traversal, &rv)) {
enum SqshTreeTraversalState state =
sqsh_tree_traversal_state(&it->traversal);
if (state != SQSH_TREE_TRAVERSAL_STATE_FILE &&
state != SQSH_TREE_TRAVERSAL_STATE_DIRECTORY_BEGIN) {
continue;
}

it->value = sqsh_tree_traversal_path_dup(&it->traversal);
if (it->value == NULL) {
rv = -SQSH_ERROR_MALLOC_FAILED;
goto out;
}
*value = it->value;
*size = strlen(*value);
break;
}

out:
return rv;
}

char **
sqsh_easy_tree_traversal(
struct SqshArchive *archive, const char *path, int *err) {
int rv = 0;
struct SqshFile *file = NULL;
struct TreeTraversalIterator iterator = {0};
char **list = NULL;

file = sqsh_open(archive, path, &rv);
if (rv < 0) {
goto out;
}

if (sqsh_file_type(file) != SQSH_FILE_TYPE_DIRECTORY) {
rv = -SQSH_ERROR_NOT_A_DIRECTORY;
goto out;
}

rv = sqsh__tree_traversal_init(&iterator.traversal, 0, file);
if (rv < 0) {
goto out;
}

// Drop the root path
bool has_next = sqsh_tree_traversal_next(&iterator.traversal, &rv);
if (has_next == false) {
rv = -SQSH_ERROR_INTERNAL;
goto out;
}

rv = cx_collect(&list, tree_traversal_collector_next, &iterator);
if (rv < 0) {
goto out;
}

out:
sqsh__tree_traversal_cleanup(&iterator.traversal);
sqsh_close(file);
if (err) {
*err = rv;
}
return list;
}
1 change: 1 addition & 0 deletions libsqsh/src/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ libsqsh_sources = files(
'directory/directory_iterator.c',
'easy/directory.c',
'easy/file.c',
'easy/traversal.c',
'easy/xattr.c',
'extract/extract_manager.c',
'extract/extract_view.c',
Expand Down
4 changes: 3 additions & 1 deletion libsqsh/src/tree/traversal.c
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,9 @@ sqsh_tree_traversal_path_dup(const struct SqshTreeTraversal *traversal) {

const size_t count = sqsh_tree_traversal_depth(traversal);
for (sqsh_index_t i = 0; i < count; i++) {
rv = cx_buffer_append(&buffer, (const uint8_t *)"/", 1);
if (i > 0) {
rv = cx_buffer_append(&buffer, (const uint8_t *)"/", 1);
}
if (rv < 0) {
goto out;
}
Expand Down
27 changes: 27 additions & 0 deletions test/libsqsh/integration.c
Original file line number Diff line number Diff line change
Expand Up @@ -638,4 +638,31 @@ UTEST(integration, test_tree_traversal) {
ASSERT_EQ(0, rv);
}

UTEST(integration, test_easy_traversal) {
int rv;
struct SqshArchive sqsh = {0};
struct SqshFile *file = NULL;
char **traversal = NULL;

struct SqshConfig config = DEFAULT_CONFIG(TEST_SQUASHFS_IMAGE_LEN);
config.archive_offset = 1010;
rv = sqsh__archive_init(&sqsh, (char *)TEST_SQUASHFS_IMAGE, &config);
ASSERT_EQ(0, rv);

traversal = sqsh_easy_tree_traversal(&sqsh, "/", &rv);
ASSERT_EQ(0, rv);

ASSERT_STREQ("a", traversal[0]);
ASSERT_STREQ("b", traversal[1]);
ASSERT_STREQ("large_dir", traversal[2]);
ASSERT_STREQ("large_dir/1", traversal[3]);
ASSERT_STREQ("large_dir/10", traversal[4]);

free(traversal);
rv = sqsh_close(file);

rv = sqsh__archive_cleanup(&sqsh);
ASSERT_EQ(0, rv);
}

UTEST_MAIN()

0 comments on commit f396654

Please sign in to comment.