Skip to content

Commit

Permalink
easy: add xattr API.
Browse files Browse the repository at this point in the history
This commit adds an easy API to read extended attributes from a
squashfs. It also adds two new examples that show how to use both the
new easy API and the low level API to read extended attributes.
  • Loading branch information
Gottox committed Aug 29, 2023
1 parent 08b0fce commit b3f811a
Show file tree
Hide file tree
Showing 6 changed files with 276 additions and 2 deletions.
34 changes: 34 additions & 0 deletions examples/list_xattrs.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/**
* @author Enno Boland (mail@eboland.de)
* @file read_file.c
*
* This is an example program that prints the content of a file in a squashfs
* archive.
*/

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

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

char **keys = sqsh_easy_xattr_keys(archive, argv[2], NULL);
assert(keys != NULL);
for (int i = 0; keys[i] != NULL; i++) {
char *value = sqsh_easy_xattr_get(archive, argv[2], keys[i], NULL);
printf("%s=%s\n", keys[i], value);
free(value);
}
free(keys);

sqsh_archive_close(archive);
return 0;
}
70 changes: 70 additions & 0 deletions examples/list_xattrs_ll.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/**
* @author Enno Boland (mail@eboland.de)
* @file read_file_ll.c
*
* This is an example program that prints the content of a file in a squashfs
* archive. It uses low level variants of the API.
*/

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

int
main(int argc, char *argv[]) {
int error_code = 0;
if (argc != 3) {
printf("Usage: %s <sqsh-file> <path>\n", argv[0]);
return 1;
}
struct SqshConfig config = {
// Read the header file to find documentation on these fields.
// It's safe to set them all to 0.
.source_mapper = sqsh_mapper_impl_mmap,
.source_size = 0,
.mapper_block_size = 0,
.mapper_lru_size = 0,
.compression_lru_size = 0,
.archive_offset = 0,
.max_symlink_depth = 0,
};
struct SqshArchive *archive =
sqsh_archive_open(argv[1], &config, &error_code);
if (error_code != 0) {
sqsh_perror(error_code, "sqsh_archive_new");
return 1;
}
struct SqshFile *file = sqsh_open(archive, argv[2], &error_code);
if (error_code != 0) {
sqsh_perror(error_code, "sqsh_open");
return 1;
}

struct SqshXattrIterator *iterator =
sqsh_xattr_iterator_new(file, &error_code);
if (error_code != 0) {
sqsh_perror(error_code, "sqsh_xattr_iterator_new");
return 1;
}

while (sqsh_xattr_iterator_next(iterator, &error_code)) {
const char *prefix = sqsh_xattr_iterator_prefix(iterator);
const size_t prefix_size = sqsh_xattr_iterator_prefix_size(iterator);
const char *name = sqsh_xattr_iterator_name(iterator);
const size_t name_size = sqsh_xattr_iterator_name_size(iterator);
const char *value = sqsh_xattr_iterator_value(iterator);
const size_t value_size = sqsh_xattr_iterator_value_size(iterator);

printf("%.*s%.*s=%.*s\n", (int)prefix_size, prefix, (int)name_size,
name, (int)value_size, value);
}
if (error_code < 0) {
sqsh_perror(error_code, "sqsh_xattr_iterator_next");
return 1;
}

sqsh_xattr_iterator_free(iterator);
sqsh_close(file);
sqsh_archive_close(archive);
return 0;
}
12 changes: 12 additions & 0 deletions examples/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,18 @@ executable(
install: false,
dependencies: libsqsh_dep,
)
executable(
'list_xattrs',
'list_xattrs.c',
install: false,
dependencies: libsqsh_dep,
)
executable(
'list_xattrs_ll',
'list_xattrs_ll.c',
install: false,
dependencies: libsqsh_dep,
)
executable(
'readme_example',
'readme_example.c',
Expand Down
38 changes: 36 additions & 2 deletions include/sqsh_easy.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ struct SqshArchive;
struct SqshFile;

/***************************************
* chrome/file.c
* easy/file.c
*/

/**
Expand Down Expand Up @@ -115,7 +115,7 @@ time_t
sqsh_easy_file_mtime(struct SqshArchive *archive, const char *path, int *err);

/***************************************
* chrome/directory.c
* easy/directory.c
*/

/**
Expand All @@ -132,6 +132,40 @@ sqsh_easy_file_mtime(struct SqshArchive *archive, const char *path, int *err);
char **sqsh_easy_directory_list(
struct SqshArchive *archive, const char *path, int *err);

/***************************************
* easy/xattr.c
*/

/**
* @brief retrieves all xattr keys of a file or directory.
*
* The returned list needs to be released with `free()`.
*
* @param[in] archive The sqsh archive context.
* @param[in] path The path the file or directory.
* @param[out] err Pointer to an int where the error code will be stored.
*
* @return A list of xattr keys on success, NULL on error.
*/
char **
sqsh_easy_xattr_keys(struct SqshArchive *archive, const char *path, int *err);

/**
* @brief retrieves the value of a xattr key of a file or directory.
*
* The returned pointer needs to be released with `free()`.
*
* @param[in] archive The sqsh archive context.
* @param[in] path The path the file or directory.
* @param[in] key The xattr key.
* @param[out] err Pointer to an int where the error code will be stored.
*
* @return The value of the given xattr key on success, NULL on error.
*/
char *sqsh_easy_xattr_get(
struct SqshArchive *archive, const char *path, const char *key,
int *err);

#ifdef __cplusplus
}
#endif
Expand Down
123 changes: 123 additions & 0 deletions lib/easy/xattr.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
/******************************************************************************
* *
* Copyright (c) 2023, Enno Boland <g@s01.de> *
* *
* 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 (mail@eboland.de)
* @file xattr.c
*/

#define _DEFAULT_SOURCE

#include "../../include/sqsh_easy.h"

#include <cextras/collection.h>
#include <errno.h>
#include <pthread.h>
#include <stdatomic.h>
#include <stdlib.h>
#include <string.h>

#include "../../include/sqsh_error.h"
#include "../../include/sqsh_tree_private.h"
#include "../../include/sqsh_xattr_private.h"

char *
sqsh_easy_xattr_get(
struct SqshArchive *archive, const char *path, const char *key,
int *err) {
int rv = 0;
struct SqshFile *file = NULL;
struct SqshXattrIterator iterator = {0};
char *xattr_value = NULL;

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

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

rv = sqsh_xattr_iterator_lookup(&iterator, key);
if (rv < 0) {
goto out;
}

xattr_value = sqsh_xattr_iterator_value_dup(&iterator);

out:
sqsh__xattr_iterator_cleanup(&iterator);
sqsh_close(file);
if (err) {
*err = rv;
}
return xattr_value;
}

static int
xattr_collector_next(void *iterator, const char **value, size_t *size) {
int rv = 0;
if (sqsh_xattr_iterator_next(iterator, &rv)) {
*value = sqsh_xattr_iterator_value(iterator);
*size = (size_t)sqsh_xattr_iterator_value_size(iterator);
}
return rv;
}

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

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

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

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

out:
sqsh__xattr_iterator_cleanup(&iterator);
sqsh_close(file);
if (err) {
*err = rv;
}
return list;
}
1 change: 1 addition & 0 deletions lib/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ libsqsh_sources = files(
'directory/directory_iterator.c',
'easy/directory.c',
'easy/file.c',
'easy/xattr.c',
'extract/extract_manager.c',
'extract/extract_view.c',
'extract/extractor.c',
Expand Down

0 comments on commit b3f811a

Please sign in to comment.