diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/io/src/unix/dir_iterator.c | 3 | ||||
-rw-r--r-- | lib/io/src/win32/dir_iterator.c | 3 | ||||
-rw-r--r-- | lib/io/src/xattr.c | 25 | ||||
-rw-r--r-- | lib/tar/Makemodule.am | 27 | ||||
-rw-r--r-- | lib/tar/src/istream.c | 240 | ||||
-rw-r--r-- | lib/tar/src/iterator.c | 339 | ||||
-rw-r--r-- | lib/tar/src/read_header.c | 11 | ||||
-rw-r--r-- | lib/tar/test/data/CREDITS | 4 | ||||
-rw-r--r-- | lib/tar/test/data/iterator/sparse.tar (renamed from lib/tar/test/data/istream/sparse.tar) | bin | 33792 -> 33792 bytes | |||
-rw-r--r-- | lib/tar/test/tar_istream.c | 73 | ||||
-rw-r--r-- | lib/tar/test/tar_istream2.c | 151 | ||||
-rw-r--r-- | lib/tar/test/tar_iterator.c | 139 | ||||
-rw-r--r-- | lib/tar/test/tar_iterator2.c (renamed from lib/tar/test/tar_istream3.c) | 40 | ||||
-rw-r--r-- | lib/tar/test/tar_iterator3.c | 173 |
14 files changed, 724 insertions, 504 deletions
diff --git a/lib/io/src/unix/dir_iterator.c b/lib/io/src/unix/dir_iterator.c index fb7edae..7154ec9 100644 --- a/lib/io/src/unix/dir_iterator.c +++ b/lib/io/src/unix/dir_iterator.c @@ -118,6 +118,9 @@ static int dir_next(dir_iterator_t *base, dir_entry_t **out) decoded->gid = it->sb.st_gid; decoded->mode = it->sb.st_mode; + if (S_ISREG(it->sb.st_mode)) + decoded->size = it->sb.st_size; + if (decoded->dev != it->device) decoded->flags |= DIR_ENTRY_FLAG_MOUNT_POINT; diff --git a/lib/io/src/win32/dir_iterator.c b/lib/io/src/win32/dir_iterator.c index c9defc7..f504b65 100644 --- a/lib/io/src/win32/dir_iterator.c +++ b/lib/io/src/win32/dir_iterator.c @@ -91,6 +91,9 @@ static int dir_iterator_next(dir_iterator_t *it, dir_entry_t **out) ent->mode = S_IFDIR | 0755; } else { ent->mode = S_IFREG | 0644; + ent->size = w32->ent.nFileSizeHigh; + ent->size <<= 32UL; + ent->size |= w32->ent.nFileSizeLow; } ent->mtime = w32time_to_unix(&(w32->ent.ftLastWriteTime)); diff --git a/lib/io/src/xattr.c b/lib/io/src/xattr.c index dd9a338..85b7e53 100644 --- a/lib/io/src/xattr.c +++ b/lib/io/src/xattr.c @@ -28,6 +28,31 @@ dir_entry_xattr_t *dir_entry_xattr_create(const char *key, const sqfs_u8 *value, return out; } +dir_entry_xattr_t *dir_entry_xattr_list_copy(const dir_entry_xattr_t *list) +{ + dir_entry_xattr_t *new, *copy = NULL, *copy_last = NULL; + const dir_entry_xattr_t *it; + + for (it = list; it != NULL; it = it->next) { + new = dir_entry_xattr_create(it->key, it->value, + it->value_len); + if (new == NULL) { + dir_entry_xattr_list_free(copy); + return NULL; + } + + if (copy_last == NULL) { + copy = new; + copy_last = new; + } else { + copy_last->next = new; + copy_last = new; + } + } + + return copy; +} + void dir_entry_xattr_list_free(dir_entry_xattr_t *list) { dir_entry_xattr_t *old; diff --git a/lib/tar/Makemodule.am b/lib/tar/Makemodule.am index 07eb497..7e58cc6 100644 --- a/lib/tar/Makemodule.am +++ b/lib/tar/Makemodule.am @@ -3,7 +3,8 @@ libtar_a_SOURCES = lib/tar/src/read_header.c lib/tar/src/write_header.c \ lib/tar/src/read_sparse_map_old.c lib/tar/src/internal.h \ lib/tar/src/padd_file.c lib/tar/src/record_to_memory.c \ lib/tar/src/pax_header.c lib/tar/src/read_sparse_map_new.c \ - lib/tar/src/istream.c include/tar/tar.h include/tar/format.h + lib/tar/src/iterator.c \ + include/tar/tar.h include/tar/format.h noinst_LIBRARIES += libtar.a @@ -162,19 +163,19 @@ test_tar_xattr_schily_bin_LDADD = libtar.a libio.a libutil.a libcompat.a test_tar_xattr_schily_bin_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR) test_tar_xattr_schily_bin_CPPFLAGS += -DTESTFILE=xattr/xattr-schily-binary.tar -test_tar_istream_SOURCES = lib/tar/test/tar_istream.c -test_tar_istream_LDADD = libtar.a libio.a libutil.a libcompat.a -test_tar_istream_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR) -test_tar_istream_CPPFLAGS += -DTESTFILE=format-acceptance/gnu.tar +test_tar_iterator_SOURCES = lib/tar/test/tar_iterator.c +test_tar_iterator_LDADD = libtar.a libio.a libutil.a libcompat.a +test_tar_iterator_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR) +test_tar_iterator_CPPFLAGS += -DTESTFILE=format-acceptance/gnu.tar -test_tar_istream2_SOURCES = lib/tar/test/tar_istream2.c -test_tar_istream2_LDADD = libtar.a libio.a libutil.a libcompat.a -test_tar_istream2_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR) +test_tar_iterator2_SOURCES = lib/tar/test/tar_iterator2.c +test_tar_iterator2_LDADD = libtar.a libio.a libutil.a libcompat.a +test_tar_iterator2_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR) +test_tar_iterator2_CPPFLAGS += -DTESTFILE=iterator/sparse.tar -test_tar_istream3_SOURCES = lib/tar/test/tar_istream3.c -test_tar_istream3_LDADD = libtar.a libio.a libutil.a libcompat.a -test_tar_istream3_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR) -test_tar_istream3_CPPFLAGS += -DTESTFILE=istream/sparse.tar +test_tar_iterator3_SOURCES = lib/tar/test/tar_iterator3.c +test_tar_iterator3_LDADD = libtar.a libio.a libutil.a libcompat.a +test_tar_iterator3_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR) tar_fuzz_SOURCES = lib/tar/test/tar_fuzz.c tar_fuzz_LDADD = libtar.a libio.a libutil.a libcompat.a @@ -195,7 +196,7 @@ LIBTAR_TESTS = \ test_tar_sparse_gnu2 test_tar_sparse_gnu3 \ test_tar_xattr_bsd test_tar_xattr_schily test_tar_xattr_schily_bin \ test_tar_target_filled \ - test_tar_istream test_tar_istream2 test_tar_istream3 \ + test_tar_iterator test_tar_iterator2 test_tar_iterator3 \ test_tar_write_simple check_PROGRAMS += $(LIBTAR_TESTS) diff --git a/lib/tar/src/istream.c b/lib/tar/src/istream.c deleted file mode 100644 index 80519b1..0000000 --- a/lib/tar/src/istream.c +++ /dev/null @@ -1,240 +0,0 @@ -/* SPDX-License-Identifier: GPL-3.0-or-later */ -/* - * istream.c - * - * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> - */ -#include "internal.h" - -#include <string.h> -#include <stdlib.h> - -typedef struct { - sqfs_u64 offset; - sqfs_u64 count; -} sparse_ent_t; - -typedef struct { - istream_t base; - - istream_t *parent; - - char *filename; - - sparse_ent_t *sparse; - size_t num_sparse; - - sqfs_u64 record_size; - sqfs_u64 file_size; - sqfs_u64 offset; - - size_t padding; - size_t last_chunk; - bool last_sparse; - - sqfs_u8 buffer[4096]; -} tar_istream_t; - -static bool is_sparse_region(tar_istream_t *tar, sqfs_u64 *count) -{ - size_t i; - - *count = tar->file_size - tar->offset; - if (tar->num_sparse == 0) - return false; - - for (i = 0; i < tar->num_sparse; ++i) { - if (tar->offset >= tar->sparse[i].offset) { - sqfs_u64 diff = tar->offset - tar->sparse[i].offset; - - if (diff < tar->sparse[i].count) { - *count = tar->sparse[i].count - diff; - return false; - } - } - } - - for (i = 0; i < tar->num_sparse; ++i) { - if (tar->offset < tar->sparse[i].offset) { - sqfs_u64 diff = tar->sparse[i].offset - tar->offset; - - if (diff < *count) - *count = diff; - } - } - - return true; -} - -static int precache(istream_t *strm) -{ - tar_istream_t *tar = (tar_istream_t *)strm; - sqfs_u64 diff, avail; - - tar->offset += tar->last_chunk; - - if (!tar->last_sparse) { - tar->parent->buffer_offset += tar->last_chunk; - tar->record_size -= tar->last_chunk; - } - - if (tar->offset >= tar->file_size) { - strm->eof = true; - strm->buffer_used = 0; - strm->buffer = tar->buffer; - if (tar->record_size > 0) - goto fail_rec_sz; - if (istream_skip(tar->parent, tar->padding)) - goto fail; - tar->padding = 0; - return 0; - } - - if (is_sparse_region(tar, &diff)) { - if (diff > sizeof(tar->buffer)) - diff = sizeof(tar->buffer); - - strm->buffer = tar->buffer; - strm->buffer_used = diff; - tar->last_chunk = diff; - tar->last_sparse = true; - - memset(tar->buffer, 0, diff); - } else { - if (diff > tar->record_size) - goto fail_rec_sz; - - avail = tar->parent->buffer_used - tar->parent->buffer_offset; - - if ((diff > avail) && - ((tar->parent->buffer_offset > 0) || avail == 0)) { - if (istream_precache(tar->parent)) - goto fail; - - if (tar->parent->buffer_used == 0 && tar->parent->eof) - goto fail_eof; - - avail = tar->parent->buffer_used; - } - - if (diff > avail) - diff = avail; - - strm->buffer = tar->parent->buffer + tar->parent->buffer_offset; - strm->buffer_used = diff; - tar->last_chunk = diff; - tar->last_sparse = false; - } - - return 0; -fail_rec_sz: - fprintf(stderr, - "%s: missmatch in tar record size vs file size for `%s`.\n", - istream_get_filename(tar->parent), istream_get_filename(strm)); - goto fail; -fail_eof: - fprintf(stderr, "%s: unexpected end-of-file while reading `%s`\n", - istream_get_filename(tar->parent), istream_get_filename(strm)); - goto fail; -fail: - tar->record_size = 0; - tar->padding = 0; - return -1; -} - -static const char *get_filename(istream_t *strm) -{ - return ((tar_istream_t *)strm)->filename; -} - -static void tar_istream_destroy(sqfs_object_t *obj) -{ - tar_istream_t *strm = (tar_istream_t *)obj; - - if (strm->record_size > 0) - istream_skip(strm->parent, strm->record_size); - - if (strm->padding > 0) - istream_skip(strm->parent, strm->padding); - - sqfs_drop(strm->parent); - free(strm->sparse); - free(strm->filename); - free(strm); -} - -istream_t *tar_record_istream_create(istream_t *parent, - const tar_header_decoded_t *hdr) -{ - tar_istream_t *strm; - sparse_map_t *it; - sqfs_u64 diff; - size_t idx; - - strm = calloc(1, sizeof(*strm)); - if (strm == NULL) - goto fail_oom; - - sqfs_object_init(strm, tar_istream_destroy, NULL); - - strm->filename = strdup(hdr->name); - if (strm->filename == NULL) - goto fail_oom; - - strm->num_sparse = 0; - for (it = hdr->sparse; it != NULL; it = it->next) - strm->num_sparse += 1; - - if (strm->num_sparse > 0) { - strm->sparse = alloc_array(sizeof(strm->sparse[0]), - strm->num_sparse); - if (strm->sparse == NULL) - goto fail_oom; - - idx = 0; - it = hdr->sparse; - while (it != NULL && idx < strm->num_sparse) { - strm->sparse[idx].offset = it->offset; - strm->sparse[idx].count = it->count; - ++idx; - it = it->next; - } - } - - for (idx = 1; idx < strm->num_sparse; ++idx) { - if (strm->sparse[idx].offset <= strm->sparse[idx - 1].offset) - goto fail_sparse; - - diff = strm->sparse[idx].offset - strm->sparse[idx - 1].offset; - - if (diff < strm->sparse[idx - 1].count) - goto fail_sparse; - } - - strm->padding = hdr->record_size % 512; - if (strm->padding > 0) - strm->padding = 512 - strm->padding; - - strm->record_size = hdr->record_size; - strm->file_size = hdr->actual_size; - strm->parent = sqfs_grab(parent); - - ((istream_t *)strm)->precache = precache; - ((istream_t *)strm)->get_filename = get_filename; - ((istream_t *)strm)->buffer = strm->buffer; - ((istream_t *)strm)->eof = false; - return (istream_t *)strm; -fail_sparse: - fprintf(stderr, "%s: sparse map is not ordered or overlapping!\n", - hdr->name); - goto fail; -fail_oom: - fputs("tar istream create: out-of-memory\n", stderr); - goto fail; -fail: - if (strm != NULL) { - free(strm->filename); - free(strm); - } - return NULL; -} diff --git a/lib/tar/src/iterator.c b/lib/tar/src/iterator.c new file mode 100644 index 0000000..9a6b9f7 --- /dev/null +++ b/lib/tar/src/iterator.c @@ -0,0 +1,339 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * iterator.c + * + * Copyright (C) 2023 David Oberhollenzer <goliath@infraroot.at> + */ +#include "tar/tar.h" +#include "sqfs/error.h" +#include "util/util.h" + +#include <stdlib.h> +#include <string.h> +#include <stdbool.h> + +typedef struct { + dir_iterator_t base; + tar_header_decoded_t current; + istream_t *stream; + int state; + + /* File I/O wrapper related */ + bool locked; + + sqfs_u64 record_size; + sqfs_u64 file_size; + sqfs_u64 offset; + + size_t padding; + size_t last_chunk; + bool last_sparse; +} tar_iterator_t; + +typedef struct { + istream_t base; + + tar_iterator_t *parent; + + sqfs_u8 buffer[4096]; +} tar_istream_t; + +static bool is_sparse_region(const tar_iterator_t *tar, sqfs_u64 *count) +{ + const sparse_map_t *it; + + *count = tar->file_size - tar->offset; + if (tar->current.sparse == NULL) + return false; + + for (it = tar->current.sparse; it != NULL; it = it->next) { + if (tar->offset >= it->offset) { + sqfs_u64 diff = tar->offset - it->offset; + + if (diff < it->count) { + *count = it->count - diff; + return false; + } + } + } + + for (it = tar->current.sparse; it != NULL; it = it->next) { + if (tar->offset < it->offset) { + sqfs_u64 diff = it->offset - tar->offset; + + if (diff < *count) + *count = diff; + } + } + + return true; +} + +static int data_available(tar_iterator_t *tar, sqfs_u64 want, sqfs_u64 *out) +{ + sqfs_u64 avail = tar->stream->buffer_used - tar->stream->buffer_offset; + + if ((want > avail) && + ((tar->stream->buffer_offset > 0) || avail == 0)) { + if (istream_precache(tar->stream)) { + tar->state = SQFS_ERROR_IO; + return -1; + } + + if (tar->stream->buffer_used == 0 && tar->stream->eof) { + tar->state = SQFS_ERROR_CORRUPTED; + return -1; + } + + avail = tar->stream->buffer_used; + } + + *out = avail <= want ? avail : want; + return 0; +} + +/*****************************************************************************/ + +static const char *strm_get_filename(istream_t *strm) +{ + return ((tar_istream_t *)strm)->parent->current.name; +} + +static int strm_precache(istream_t *strm) +{ + tar_istream_t *tar = (tar_istream_t *)strm; + sqfs_u64 diff; + + tar->parent->offset += tar->parent->last_chunk; + + if (!tar->parent->last_sparse) { + tar->parent->stream->buffer_offset += tar->parent->last_chunk; + tar->parent->record_size -= tar->parent->last_chunk; + } + + if (tar->parent->offset >= tar->parent->file_size) + goto out_eof; + + if (is_sparse_region(tar->parent, &diff)) { + if (diff > sizeof(tar->buffer)) + diff = sizeof(tar->buffer); + + strm->buffer = tar->buffer; + strm->buffer_used = diff; + tar->parent->last_chunk = diff; + tar->parent->last_sparse = true; + + memset(tar->buffer, 0, diff); + } else { + if (data_available(tar->parent, diff, &diff)) + goto out_eof; + + strm->buffer = tar->parent->stream->buffer + + tar->parent->stream->buffer_offset; + strm->buffer_used = diff; + tar->parent->last_chunk = diff; + tar->parent->last_sparse = false; + } + + return 0; +out_eof: + strm->eof = true; + strm->buffer_used = 0; + strm->buffer = tar->buffer; + tar->parent->locked = false; + return tar->parent->state < 0 ? -1 : 0; +} + +static void strm_destroy(sqfs_object_t *obj) +{ + tar_istream_t *tar = (tar_istream_t *)obj; + + tar->parent->locked = false; + sqfs_drop(tar->parent); + free(tar); +} + +/*****************************************************************************/ + +static int it_next(dir_iterator_t *it, dir_entry_t **out) +{ + tar_iterator_t *tar = (tar_iterator_t *)it; + dir_entry_t *ent; + int ret; + + *out = NULL; + if (tar->locked) + return SQFS_ERROR_SEQUENCE; + + if (tar->state != 0) + return tar->state; +retry: + if (tar->record_size > 0) { + ret = istream_skip(tar->stream, tar->record_size); + if (ret) + goto fail; + } + + if (tar->padding > 0) { + ret = istream_skip(tar->stream, tar->padding); + if (ret) + goto fail; + } + + clear_header(&(tar->current)); + ret = read_header(tar->stream, &(tar->current)); + if (ret != 0) + goto fail; + + tar->offset = 0; + tar->last_chunk = 0; + tar->last_sparse = false; + tar->record_size = tar->current.record_size; + tar->file_size = tar->current.actual_size; + tar->padding = tar->current.record_size % 512; + if (tar->padding > 0) + tar->padding = 512 - tar->padding; + + if (tar->current.unknown_record) + goto retry; + + if (canonicalize_name(tar->current.name) != 0) { + tar->state = SQFS_ERROR_CORRUPTED; + return tar->state; + } + + ent = calloc(1, sizeof(*ent) + strlen(tar->current.name) + 1); + if (ent == NULL) { + tar->state = SQFS_ERROR_ALLOC; + return tar->state; + } + + ent->mtime = tar->current.mtime; + ent->rdev = tar->current.devno; + ent->uid = tar->current.uid; + ent->gid = tar->current.gid; + ent->mode = tar->current.mode; + strcpy(ent->name, tar->current.name); + + if (tar->current.is_hard_link) { + ent->mode = (S_IFLNK | 0777); + ent->flags |= DIR_ENTRY_FLAG_HARD_LINK; + } + + if (S_ISREG(ent->mode)) + ent->size = tar->current.actual_size; + + *out = ent; + return 0; +fail: + tar->state = ret < 0 ? SQFS_ERROR_IO : 1; + return tar->state; +} + +static int it_read_link(dir_iterator_t *it, char **out) +{ + tar_iterator_t *tar = (tar_iterator_t *)it; + + *out = NULL; + if (tar->locked) + return SQFS_ERROR_SEQUENCE; + + if (tar->state != 0 || tar->current.link_target == NULL) + return tar->state < 0 ? tar->state : SQFS_ERROR_NO_ENTRY; + + *out = strdup(tar->current.link_target); + return (*out == NULL) ? SQFS_ERROR_ALLOC : 0; +} + +static int it_open_subdir(dir_iterator_t *it, dir_iterator_t **out) +{ + (void)it; + *out = NULL; + return SQFS_ERROR_UNSUPPORTED; +} + +static void it_ignore_subdir(dir_iterator_t *it) +{ + (void)it; + /* TODO: skip list */ +} + +static int it_open_file_ro(dir_iterator_t *it, istream_t **out) +{ + tar_iterator_t *tar = (tar_iterator_t *)it; + tar_istream_t *strm; + + *out = NULL; + if (tar->locked) + return SQFS_ERROR_SEQUENCE; + + if (tar->state != 0) + return tar->state < 0 ? tar->state : SQFS_ERROR_NO_ENTRY; + + if (!S_ISREG(tar->current.mode)) + return SQFS_ERROR_NOT_FILE; + + strm = calloc(1, sizeof(*strm)); + if (strm == NULL) + return SQFS_ERROR_ALLOC; + + sqfs_object_init(strm, strm_destroy, NULL); + strm->parent = sqfs_grab(tar); + + ((istream_t *)strm)->precache = strm_precache; + ((istream_t *)strm)->get_filename = strm_get_filename; + ((istream_t *)strm)->buffer = strm->buffer; + + tar->locked = true; + *out = (istream_t *)strm; + return 0; +} + +static int it_read_xattr(dir_iterator_t *it, dir_entry_xattr_t **out) +{ + tar_iterator_t *tar = (tar_iterator_t *)it; + + *out = NULL; + if (tar->locked) + return SQFS_ERROR_SEQUENCE; + + if (tar->state != 0) + return tar->state < 0 ? tar->state : SQFS_ERROR_NO_ENTRY; + + if (tar->current.xattr != NULL) { + *out = dir_entry_xattr_list_copy(tar->current.xattr); + if (*out == NULL) + return SQFS_ERROR_ALLOC; + } + + return 0; +} + +static void it_destroy(sqfs_object_t *obj) +{ + tar_iterator_t *tar = (tar_iterator_t *)obj; + + clear_header(&(tar->current)); + sqfs_drop(tar->stream); + free(tar); +} + +dir_iterator_t *tar_open_stream(istream_t *stream) +{ + tar_iterator_t *tar = calloc(1, sizeof(*tar)); + dir_iterator_t *it = (dir_iterator_t *)tar; + + if (tar == NULL) + return NULL; + + sqfs_object_init(it, it_destroy, NULL); + tar->stream = sqfs_grab(stream); + it->next = it_next; + it->read_link = it_read_link; + it->open_subdir = it_open_subdir; + it->ignore_subdir = it_ignore_subdir; + it->open_file_ro = it_open_file_ro; + it->read_xattr = it_read_xattr; + + return it; +} diff --git a/lib/tar/src/read_header.c b/lib/tar/src/read_header.c index 8d3145b..751c5dc 100644 --- a/lib/tar/src/read_header.c +++ b/lib/tar/src/read_header.c @@ -224,7 +224,9 @@ int read_header(istream_t *fp, tar_header_decoded_t *out) case TAR_TYPE_PAX_GLOBAL: if (read_number(hdr.size, sizeof(hdr.size), &pax_size)) goto fail; - skip_entry(fp, pax_size); + if (pax_size % 512) + pax_size += 512 - (pax_size % 512); + istream_skip(fp, pax_size); continue; case TAR_TYPE_PAX: clear_header(out); @@ -291,10 +293,3 @@ fail: clear_header(out); return -1; } - -int skip_entry(istream_t *fp, sqfs_u64 size) -{ - size_t tail = size % 512; - - return istream_skip(fp, tail ? (size + 512 - tail) : size); -} diff --git a/lib/tar/test/data/CREDITS b/lib/tar/test/data/CREDITS index 1e7fb32..4c20256 100644 --- a/lib/tar/test/data/CREDITS +++ b/lib/tar/test/data/CREDITS @@ -33,9 +33,9 @@ The following addtional files have been added: Contributed in GitHub issue #64. A tar ball that contains a hard link where the 100 byte target field is completely filled without containing a null-terminator. - - istream/sparse.tar + - iterator/sparse.tar Derived from sparse/gnu.tar and contains some test data for testing the - tar istream implementation. + tar iterator implementation. - write/simple.tar Created using the tar writer to verify that it works as intended. Used for testing the tar writer to check if it still produces identical diff --git a/lib/tar/test/data/istream/sparse.tar b/lib/tar/test/data/iterator/sparse.tar Binary files differindex 7f4700d..7f4700d 100644 --- a/lib/tar/test/data/istream/sparse.tar +++ b/lib/tar/test/data/iterator/sparse.tar diff --git a/lib/tar/test/tar_istream.c b/lib/tar/test/tar_istream.c deleted file mode 100644 index cc31282..0000000 --- a/lib/tar/test/tar_istream.c +++ /dev/null @@ -1,73 +0,0 @@ -/* SPDX-License-Identifier: GPL-3.0-or-later */ -/* - * tar_istream.c - * - * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> - */ -#include "config.h" -#include "io/file.h" -#include "tar/tar.h" -#include "util/test.h" - -#ifndef TESTUID -#define TESTUID 1000 -#endif - -#ifndef TESTGID -#define TESTGID TESTUID -#endif - -#ifndef TESTFNAME -#define TESTFNAME input.txt -#endif - -#ifndef TESTTS -#define TESTTS 1542905892 -#endif - -static const char *fname = STRVALUE(TESTFNAME); - -int main(int argc, char **argv) -{ - tar_header_decoded_t hdr; - char buffer[100]; - sqfs_s64 ts; - istream_t *fp; - istream_t *ti; - sqfs_s32 ret; - (void)argc; (void)argv; - - fp = istream_open_file(STRVALUE(TESTPATH) "/" STRVALUE(TESTFILE)); - TEST_NOT_NULL(fp); - TEST_EQUAL_UI(((sqfs_object_t *)fp)->refcount, 1); - TEST_ASSERT(read_header(fp, &hdr) == 0); - TEST_EQUAL_UI(((sqfs_object_t *)fp)->refcount, 1); - TEST_EQUAL_UI(hdr.mode, S_IFREG | 0644); - TEST_EQUAL_UI(hdr.uid, TESTUID); - TEST_EQUAL_UI(hdr.gid, TESTGID); - TEST_EQUAL_UI(hdr.actual_size, 5); - - ts = TESTTS; - TEST_EQUAL_UI(hdr.mtime, ts); - TEST_STR_EQUAL(hdr.name, fname); - TEST_ASSERT(!hdr.unknown_record); - - ti = tar_record_istream_create(fp, &hdr); - TEST_NOT_NULL(ti); - TEST_EQUAL_UI(((sqfs_object_t *)fp)->refcount, 2); - TEST_EQUAL_UI(((sqfs_object_t *)ti)->refcount, 1); - - ret = istream_read(ti, buffer, sizeof(buffer)); - TEST_EQUAL_I(ret, 5); - buffer[5] = '\0'; - TEST_STR_EQUAL(buffer, "test\n"); - - ret = istream_read(ti, buffer, sizeof(buffer)); - TEST_EQUAL_I(ret, 0); - - clear_header(&hdr); - sqfs_drop(ti); - TEST_EQUAL_UI(((sqfs_object_t *)fp)->refcount, 1); - sqfs_drop(fp); - return EXIT_SUCCESS; -} diff --git a/lib/tar/test/tar_istream2.c b/lib/tar/test/tar_istream2.c deleted file mode 100644 index e5cdca8..0000000 --- a/lib/tar/test/tar_istream2.c +++ /dev/null @@ -1,151 +0,0 @@ -/* SPDX-License-Identifier: GPL-3.0-or-later */ -/* - * tar_istream2.c - * - * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> - */ -#include "config.h" -#include "io/file.h" -#include "tar/tar.h" -#include "util/test.h" - -int main(int argc, char **argv) -{ - tar_header_decoded_t hdr; - char buffer[100]; - istream_t *fp; - istream_t *ti; - (void)argc; (void)argv; - - TEST_ASSERT(chdir(TEST_PATH) == 0); - - fp = istream_open_file("format-acceptance/link_filled.tar"); - TEST_NOT_NULL(fp); - TEST_EQUAL_UI(((sqfs_object_t *)fp)->refcount, 1); - - /* "deep" directory hierarchy containg 2 files */ - TEST_EQUAL_UI(((sqfs_object_t *)fp)->refcount, 1); - TEST_ASSERT(read_header(fp, &hdr) == 0); - TEST_EQUAL_UI(((sqfs_object_t *)fp)->refcount, 1); - TEST_EQUAL_UI(hdr.mode, S_IFDIR | 0777); - TEST_STR_EQUAL(hdr.name, "20_characters_here01/"); - clear_header(&hdr); - - TEST_EQUAL_UI(((sqfs_object_t *)fp)->refcount, 1); - TEST_ASSERT(read_header(fp, &hdr) == 0); - TEST_EQUAL_UI(((sqfs_object_t *)fp)->refcount, 1); - TEST_EQUAL_UI(hdr.mode, S_IFDIR | 0777); - TEST_STR_EQUAL(hdr.name, "20_characters_here01/20_characters_here02/"); - clear_header(&hdr); - - TEST_EQUAL_UI(((sqfs_object_t *)fp)->refcount, 1); - TEST_ASSERT(read_header(fp, &hdr) == 0); - TEST_EQUAL_UI(((sqfs_object_t *)fp)->refcount, 1); - TEST_EQUAL_UI(hdr.mode, S_IFDIR | 0777); - TEST_STR_EQUAL(hdr.name, "20_characters_here01/20_characters_here02/" - "20_characters_here03/"); - clear_header(&hdr); - - TEST_EQUAL_UI(((sqfs_object_t *)fp)->refcount, 1); - TEST_ASSERT(read_header(fp, &hdr) == 0); - TEST_EQUAL_UI(((sqfs_object_t *)fp)->refcount, 1); - TEST_EQUAL_UI(hdr.mode, S_IFDIR | 0777); - TEST_STR_EQUAL(hdr.name, "20_characters_here01/20_characters_here02/" - "20_characters_here03/20_characters_here04/"); - clear_header(&hdr); - - TEST_EQUAL_UI(((sqfs_object_t *)fp)->refcount, 1); - TEST_ASSERT(read_header(fp, &hdr) == 0); - TEST_EQUAL_UI(((sqfs_object_t *)fp)->refcount, 1); - TEST_EQUAL_UI(hdr.mode, S_IFREG | 0777); - TEST_STR_EQUAL(hdr.name, "20_characters_here01/20_characters_here02/" - "20_characters_here03/20_characters_here04/" - "errored_file_tst"); - TEST_EQUAL_UI(hdr.actual_size, 5); - - ti = tar_record_istream_create(fp, &hdr); - TEST_NOT_NULL(ti); - TEST_EQUAL_UI(((sqfs_object_t *)fp)->refcount, 2); - TEST_EQUAL_UI(((sqfs_object_t *)ti)->refcount, 1); - clear_header(&hdr); - - TEST_ASSERT(istream_read(ti, buffer, sizeof(buffer)) == 5); - buffer[5] = '\0'; - TEST_STR_EQUAL(buffer, "test\n"); - TEST_ASSERT(istream_read(ti, buffer, sizeof(buffer)) == 0); - - ti = sqfs_drop(ti); - TEST_EQUAL_UI(((sqfs_object_t *)fp)->refcount, 1); - - TEST_EQUAL_UI(((sqfs_object_t *)fp)->refcount, 1); - TEST_ASSERT(read_header(fp, &hdr) == 0); - TEST_EQUAL_UI(((sqfs_object_t *)fp)->refcount, 1); - TEST_EQUAL_UI(hdr.mode, S_IFREG | 0777); - TEST_STR_EQUAL(hdr.name, "20_characters_here01/20_characters_here02/" - "20_characters_here03/20_characters_here04/" - "some_test_file"); - TEST_EQUAL_UI(hdr.actual_size, 5); - - ti = tar_record_istream_create(fp, &hdr); - TEST_NOT_NULL(ti); - TEST_EQUAL_UI(((sqfs_object_t *)fp)->refcount, 2); - TEST_EQUAL_UI(((sqfs_object_t *)ti)->refcount, 1); - clear_header(&hdr); - - TEST_ASSERT(istream_read(ti, buffer, sizeof(buffer)) == 5); - buffer[5] = '\0'; - TEST_STR_EQUAL(buffer, "test\n"); - TEST_ASSERT(istream_read(ti, buffer, sizeof(buffer)) == 0); - - ti = sqfs_drop(ti); - TEST_EQUAL_UI(((sqfs_object_t *)fp)->refcount, 1); - - /* "deep" directory hierarchy containg a hard link */ - TEST_EQUAL_UI(((sqfs_object_t *)fp)->refcount, 1); - TEST_ASSERT(read_header(fp, &hdr) == 0); - TEST_EQUAL_UI(((sqfs_object_t *)fp)->refcount, 1); - TEST_EQUAL_UI(hdr.mode, S_IFDIR | 0777); - TEST_STR_EQUAL(hdr.name, "20CharsForLnkTest001/"); - clear_header(&hdr); - - TEST_EQUAL_UI(((sqfs_object_t *)fp)->refcount, 1); - TEST_ASSERT(read_header(fp, &hdr) == 0); - TEST_EQUAL_UI(((sqfs_object_t *)fp)->refcount, 1); - TEST_EQUAL_UI(hdr.mode, S_IFDIR | 0777); - TEST_STR_EQUAL(hdr.name, "20CharsForLnkTest001/20CharsForLnkTest002/"); - clear_header(&hdr); - - TEST_EQUAL_UI(((sqfs_object_t *)fp)->refcount, 1); - TEST_ASSERT(read_header(fp, &hdr) == 0); - TEST_EQUAL_UI(((sqfs_object_t *)fp)->refcount, 1); - TEST_EQUAL_UI(hdr.mode, S_IFDIR | 0777); - TEST_STR_EQUAL(hdr.name, "20CharsForLnkTest001/20CharsForLnkTest002/" - "20CharsForLnkTest003/"); - clear_header(&hdr); - - TEST_EQUAL_UI(((sqfs_object_t *)fp)->refcount, 1); - TEST_ASSERT(read_header(fp, &hdr) == 0); - TEST_EQUAL_UI(((sqfs_object_t *)fp)->refcount, 1); - TEST_EQUAL_UI(hdr.mode, S_IFDIR | 0777); - TEST_STR_EQUAL(hdr.name, "20CharsForLnkTest001/20CharsForLnkTest002/" - "20CharsForLnkTest003/20CharsForLnkTest004/"); - clear_header(&hdr); - - TEST_EQUAL_UI(((sqfs_object_t *)fp)->refcount, 1); - TEST_ASSERT(read_header(fp, &hdr) == 0); - TEST_EQUAL_UI(((sqfs_object_t *)fp)->refcount, 1); - TEST_STR_EQUAL(hdr.name, "20CharsForLnkTest001/20CharsForLnkTest002/" - "20CharsForLnkTest003/20CharsForLnkTest004/" - "01234567890123456789"); - TEST_ASSERT(hdr.is_hard_link); - - TEST_STR_EQUAL(hdr.link_target, "20_characters_here01/" - "20_characters_here02/20_characters_here03/" - "20_characters_here04/errored_file_tst"); - clear_header(&hdr); - - /* end of file */ - TEST_ASSERT(read_header(fp, &hdr) > 0); - sqfs_drop(fp); - return EXIT_SUCCESS; -} diff --git a/lib/tar/test/tar_iterator.c b/lib/tar/test/tar_iterator.c new file mode 100644 index 0000000..21bd3e6 --- /dev/null +++ b/lib/tar/test/tar_iterator.c @@ -0,0 +1,139 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * tar_iterator.c + * + * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> + */ +#include "config.h" +#include "io/file.h" +#include "tar/tar.h" +#include "util/test.h" +#include "sqfs/error.h" + +#ifndef TESTUID +#define TESTUID 1000 +#endif + +#ifndef TESTGID +#define TESTGID TESTUID +#endif + +#ifndef TESTFNAME +#define TESTFNAME input.txt +#endif + +#ifndef TESTTS +#define TESTTS 1542905892 +#endif + +static const char *fname = STRVALUE(TESTFNAME); + +int main(int argc, char **argv) +{ + istream_t *fp, *ti, *ti2; + dir_iterator_t *it; + dir_entry_t *ent; + char buffer[100]; + sqfs_s32 ret; + sqfs_s64 ts; + (void)argc; (void)argv; + + /* Open the file, create an iterator */ + fp = istream_open_file(STRVALUE(TESTPATH) "/" STRVALUE(TESTFILE)); + TEST_NOT_NULL(fp); + TEST_EQUAL_UI(((sqfs_object_t *)fp)->refcount, 1); + it = tar_open_stream(fp); + TEST_NOT_NULL(it); + TEST_EQUAL_UI(((sqfs_object_t *)fp)->refcount, 2); + TEST_EQUAL_UI(((sqfs_object_t *)it)->refcount, 1); + + /* read entry */ + ret = it->next(it, &ent); + TEST_EQUAL_I(ret, 0); + TEST_NOT_NULL(ent); + TEST_EQUAL_UI(((sqfs_object_t *)fp)->refcount, 2); + TEST_EQUAL_UI(((sqfs_object_t *)it)->refcount, 1); + + ts = TESTTS; + TEST_EQUAL_UI(ent->mode, S_IFREG | 0644); + TEST_EQUAL_UI(ent->uid, TESTUID); + TEST_EQUAL_UI(ent->gid, TESTGID); + TEST_EQUAL_UI(ent->mtime, ts); + TEST_STR_EQUAL(ent->name, fname); + free(ent); + ent = NULL; + + /* Open file stream */ + ret = it->open_file_ro(it, &ti); + TEST_EQUAL_I(ret, 0); + TEST_NOT_NULL(ti); + TEST_EQUAL_UI(((sqfs_object_t *)fp)->refcount, 2); + TEST_EQUAL_UI(((sqfs_object_t *)it)->refcount, 2); + TEST_EQUAL_UI(((sqfs_object_t *)ti)->refcount, 1); + + /* test that the iterator is now "locked" */ + ret = it->open_file_ro(it, &ti2); + TEST_EQUAL_I(ret, SQFS_ERROR_SEQUENCE); + TEST_NULL(ti2); + ret = it->next(it, &ent); + TEST_EQUAL_I(ret, SQFS_ERROR_SEQUENCE); + TEST_NULL(ent); + TEST_EQUAL_UI(((sqfs_object_t *)fp)->refcount, 2); + TEST_EQUAL_UI(((sqfs_object_t *)it)->refcount, 2); + TEST_EQUAL_UI(((sqfs_object_t *)ti)->refcount, 1); + + /* read the data from the stream */ + ret = istream_read(ti, buffer, sizeof(buffer)); + TEST_EQUAL_I(ret, 5); + buffer[5] = '\0'; + TEST_STR_EQUAL(buffer, "test\n"); + + ret = istream_read(ti, buffer, sizeof(buffer)); + TEST_EQUAL_I(ret, 0); + + sqfs_drop(ti); + TEST_EQUAL_UI(((sqfs_object_t *)fp)->refcount, 2); + TEST_EQUAL_UI(((sqfs_object_t *)it)->refcount, 1); + + /* read past EOF on the iterator */ + ret = it->next(it, &ent); + TEST_ASSERT(ret > 0); + TEST_NULL(ent); + + /* cleanup */ + sqfs_drop(it); + TEST_EQUAL_UI(((sqfs_object_t *)fp)->refcount, 1); + sqfs_drop(fp); + + /* re-open the tar iterator */ + fp = istream_open_file(STRVALUE(TESTPATH) "/" STRVALUE(TESTFILE)); + TEST_NOT_NULL(fp); + it = tar_open_stream(fp); + TEST_NOT_NULL(it); + + /* read entry */ + ret = it->next(it, &ent); + TEST_EQUAL_I(ret, 0); + TEST_NOT_NULL(ent); + + ts = TESTTS; + TEST_EQUAL_UI(ent->mode, S_IFREG | 0644); + TEST_EQUAL_UI(ent->uid, TESTUID); + TEST_EQUAL_UI(ent->gid, TESTGID); + TEST_EQUAL_UI(ent->mtime, ts); + TEST_STR_EQUAL(ent->name, fname); + free(ent); + ent = NULL; + + /* read next entry, mus treturn EOF */ + ret = it->next(it, &ent); + TEST_ASSERT(ret > 0); + TEST_NULL(ent); + + /* cleanup */ + sqfs_drop(it); + TEST_EQUAL_UI(((sqfs_object_t *)fp)->refcount, 1); + sqfs_drop(fp); + + return EXIT_SUCCESS; +} diff --git a/lib/tar/test/tar_istream3.c b/lib/tar/test/tar_iterator2.c index d287081..7f1f3bf 100644 --- a/lib/tar/test/tar_istream3.c +++ b/lib/tar/test/tar_iterator2.c @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-3.0-or-later */ /* - * tar_istream3.c + * tar_iterator2.c * * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> */ @@ -44,27 +44,34 @@ static int byte_from_offset(uint64_t offset) int main(int argc, char **argv) { unsigned char buffer[941]; - tar_header_decoded_t hdr; + dir_iterator_t *it; istream_t *fp, *ti; + dir_entry_t *ent; uint64_t offset; sqfs_s32 i, ret; (void)argc; (void)argv; fp = istream_open_file(STRVALUE(TESTPATH) "/" STRVALUE(TESTFILE)); TEST_NOT_NULL(fp); - TEST_ASSERT(read_header(fp, &hdr) == 0); - TEST_EQUAL_UI(hdr.mode, S_IFREG | 0644); - TEST_EQUAL_UI(hdr.uid, 01750); - TEST_EQUAL_UI(hdr.gid, 01750); - TEST_EQUAL_UI(hdr.actual_size, 2097152); - TEST_EQUAL_UI(hdr.record_size, 32768); - TEST_STR_EQUAL(hdr.name, "input.bin"); - TEST_ASSERT(!hdr.unknown_record); - - ti = tar_record_istream_create(fp, &hdr); - TEST_EQUAL_UI(((sqfs_object_t *)fp)->refcount, 2); - TEST_EQUAL_UI(((sqfs_object_t *)ti)->refcount, 1); - clear_header(&hdr); + it = tar_open_stream(fp); + TEST_NOT_NULL(it); + sqfs_drop(fp); + + ret = it->next(it, &ent); + TEST_EQUAL_I(ret, 0); + TEST_NOT_NULL(ent); + + TEST_EQUAL_UI(ent->mode, S_IFREG | 0644); + TEST_EQUAL_UI(ent->uid, 01750); + TEST_EQUAL_UI(ent->gid, 01750); + TEST_EQUAL_UI(ent->size, 2097152); + //TEST_EQUAL_UI(ent->on_disk_size, 32768); + TEST_STR_EQUAL(ent->name, "input.bin"); + free(ent); + + ret = it->open_file_ro(it, &ti); + TEST_EQUAL_I(ret, 0); + TEST_NOT_NULL(ti); offset = 0; @@ -93,8 +100,7 @@ int main(int argc, char **argv) TEST_EQUAL_UI(offset, 2097152); + sqfs_drop(it); sqfs_drop(ti); - TEST_EQUAL_UI(((sqfs_object_t *)fp)->refcount, 1); - sqfs_drop(fp); return EXIT_SUCCESS; } diff --git a/lib/tar/test/tar_iterator3.c b/lib/tar/test/tar_iterator3.c new file mode 100644 index 0000000..b2ad6f9 --- /dev/null +++ b/lib/tar/test/tar_iterator3.c @@ -0,0 +1,173 @@ + +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * tar_iterator3.c + * + * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> + */ +#include "config.h" +#include "io/file.h" +#include "tar/tar.h" +#include "util/test.h" +#include "sqfs/error.h" + +int main(int argc, char **argv) +{ + dir_iterator_t *it; + istream_t *fp, *ti; + char buffer[100]; + dir_entry_t *ent; + char *link; + int ret; + (void)argc; (void)argv; + + TEST_ASSERT(chdir(TEST_PATH) == 0); + + fp = istream_open_file("format-acceptance/link_filled.tar"); + TEST_NOT_NULL(fp); + TEST_EQUAL_UI(((sqfs_object_t *)fp)->refcount, 1); + it = tar_open_stream(fp); + TEST_NOT_NULL(it); + TEST_EQUAL_UI(((sqfs_object_t *)fp)->refcount, 2); + TEST_EQUAL_UI(((sqfs_object_t *)it)->refcount, 1); + sqfs_drop(fp); + + /* "deep" directory hierarchy containg 2 files */ + ret = it->next(it, &ent); + TEST_EQUAL_I(ret, 0); + TEST_NOT_NULL(ent); + TEST_EQUAL_UI(ent->mode, S_IFDIR | 0777); + TEST_STR_EQUAL(ent->name, "20_characters_here01"); + free(ent); + + ret = it->read_link(it, &link); + TEST_EQUAL_I(ret, SQFS_ERROR_NO_ENTRY); + TEST_NULL(link); + ret = it->open_file_ro(it, &ti); + TEST_EQUAL_I(ret, SQFS_ERROR_NOT_FILE); + TEST_NULL(ti); + + ret = it->next(it, &ent); + TEST_EQUAL_I(ret, 0); + TEST_NOT_NULL(ent); + TEST_EQUAL_UI(ent->mode, S_IFDIR | 0777); + TEST_STR_EQUAL(ent->name, "20_characters_here01/20_characters_here02"); + free(ent); + + ret = it->next(it, &ent); + TEST_EQUAL_I(ret, 0); + TEST_NOT_NULL(ent); + TEST_EQUAL_UI(ent->mode, S_IFDIR | 0777); + TEST_STR_EQUAL(ent->name, "20_characters_here01/20_characters_here02/" + "20_characters_here03"); + free(ent); + + ret = it->next(it, &ent); + TEST_EQUAL_I(ret, 0); + TEST_NOT_NULL(ent); + TEST_EQUAL_UI(ent->mode, S_IFDIR | 0777); + TEST_STR_EQUAL(ent->name, "20_characters_here01/20_characters_here02/" + "20_characters_here03/20_characters_here04"); + free(ent); + + ret = it->next(it, &ent); + TEST_EQUAL_I(ret, 0); + TEST_NOT_NULL(ent); + TEST_EQUAL_UI(ent->mode, S_IFREG | 0777); + TEST_STR_EQUAL(ent->name, "20_characters_here01/20_characters_here02/" + "20_characters_here03/20_characters_here04/" + "errored_file_tst"); + free(ent); + + ret = it->read_link(it, &link); + TEST_EQUAL_I(ret, SQFS_ERROR_NO_ENTRY); + TEST_NULL(link); + ret = it->open_file_ro(it, &ti); + TEST_EQUAL_I(ret, 0); + TEST_NOT_NULL(ti); + + TEST_ASSERT(istream_read(ti, buffer, sizeof(buffer)) == 5); + buffer[5] = '\0'; + TEST_STR_EQUAL(buffer, "test\n"); + TEST_ASSERT(istream_read(ti, buffer, sizeof(buffer)) == 0); + ti = sqfs_drop(ti); + + ret = it->next(it, &ent); + TEST_EQUAL_I(ret, 0); + TEST_NOT_NULL(ent); + TEST_EQUAL_UI(ent->mode, S_IFREG | 0777); + TEST_STR_EQUAL(ent->name, "20_characters_here01/20_characters_here02/" + "20_characters_here03/20_characters_here04/" + "some_test_file"); + free(ent); + + ret = it->open_file_ro(it, &ti); + TEST_EQUAL_I(ret, 0); + TEST_NOT_NULL(ti); + + TEST_ASSERT(istream_read(ti, buffer, sizeof(buffer)) == 5); + buffer[5] = '\0'; + TEST_STR_EQUAL(buffer, "test\n"); + TEST_ASSERT(istream_read(ti, buffer, sizeof(buffer)) == 0); + ti = sqfs_drop(ti); + + /* "deep" directory hierarchy containg a hard link */ + ret = it->next(it, &ent); + TEST_EQUAL_I(ret, 0); + TEST_NOT_NULL(ent); + TEST_EQUAL_UI(ent->mode, S_IFDIR | 0777); + TEST_STR_EQUAL(ent->name, "20CharsForLnkTest001"); + free(ent); + + ret = it->next(it, &ent); + TEST_EQUAL_I(ret, 0); + TEST_NOT_NULL(ent); + TEST_EQUAL_UI(ent->mode, S_IFDIR | 0777); + TEST_STR_EQUAL(ent->name, "20CharsForLnkTest001/20CharsForLnkTest002"); + free(ent); + + ret = it->next(it, &ent); + TEST_EQUAL_I(ret, 0); + TEST_NOT_NULL(ent); + TEST_EQUAL_UI(ent->mode, S_IFDIR | 0777); + TEST_STR_EQUAL(ent->name, "20CharsForLnkTest001/20CharsForLnkTest002/" + "20CharsForLnkTest003"); + free(ent); + + ret = it->next(it, &ent); + TEST_EQUAL_I(ret, 0); + TEST_NOT_NULL(ent); + TEST_EQUAL_UI(ent->mode, S_IFDIR | 0777); + TEST_STR_EQUAL(ent->name, "20CharsForLnkTest001/20CharsForLnkTest002/" + "20CharsForLnkTest003/20CharsForLnkTest004"); + free(ent); + + ret = it->next(it, &ent); + TEST_EQUAL_I(ret, 0); + TEST_NOT_NULL(ent); + TEST_STR_EQUAL(ent->name, "20CharsForLnkTest001/20CharsForLnkTest002/" + "20CharsForLnkTest003/20CharsForLnkTest004/" + "01234567890123456789"); + TEST_EQUAL_UI(ent->mode, S_IFLNK | 0777); + TEST_ASSERT((ent->flags & DIR_ENTRY_FLAG_HARD_LINK) != 0); + free(ent); + + ret = it->read_link(it, &link); + TEST_EQUAL_I(ret, 0); + TEST_NOT_NULL(link); + ret = it->open_file_ro(it, &ti); + TEST_EQUAL_I(ret, SQFS_ERROR_NOT_FILE); + TEST_NULL(ti); + + TEST_STR_EQUAL(link, "20_characters_here01/" + "20_characters_here02/20_characters_here03/" + "20_characters_here04/errored_file_tst"); + free(link); + + /* end of file */ + ret = it->next(it, &ent); + TEST_ASSERT(ret > 0); + TEST_NULL(ent); + sqfs_drop(it); + return EXIT_SUCCESS; +} |