aboutsummaryrefslogtreecommitdiff
path: root/bin/sqfs2tar/src/sqfs2tar.c
diff options
context:
space:
mode:
Diffstat (limited to 'bin/sqfs2tar/src/sqfs2tar.c')
-rw-r--r--bin/sqfs2tar/src/sqfs2tar.c287
1 files changed, 103 insertions, 184 deletions
diff --git a/bin/sqfs2tar/src/sqfs2tar.c b/bin/sqfs2tar/src/sqfs2tar.c
index e21cd7a..786182c 100644
--- a/bin/sqfs2tar/src/sqfs2tar.c
+++ b/bin/sqfs2tar/src/sqfs2tar.c
@@ -6,113 +6,96 @@
*/
#include "sqfs2tar.h"
-sqfs_xattr_reader_t *xr;
-sqfs_data_reader_t *data;
-sqfs_super_t super;
-sqfs_ostream_t *out_file = NULL;
+static sqfs_ostream_t *out_file = NULL;
-static sqfs_file_t *file;
-
-char *assemble_tar_path(char *name, bool is_dir)
+static int terminate_archive(void)
{
- size_t len, new_len;
- char *temp;
- (void)is_dir;
-
- if (root_becomes == NULL && !is_dir)
- return name;
-
- new_len = strlen(name);
- if (root_becomes != NULL)
- new_len += strlen(root_becomes) + 1;
- if (is_dir)
- new_len += 1;
-
- temp = realloc(name, new_len + 1);
- if (temp == NULL) {
- perror("assembling tar entry filename");
- free(name);
- return NULL;
- }
-
- name = temp;
+ char buffer[1024];
- if (root_becomes != NULL) {
- len = strlen(root_becomes);
+ memset(buffer, '\0', sizeof(buffer));
- memmove(name + len + 1, name, strlen(name) + 1);
- memcpy(name, root_becomes, len);
- name[len] = '/';
- }
+ return out_file->append(out_file, buffer, sizeof(buffer));
+}
- if (is_dir) {
- len = strlen(name);
+static int write_file_data(sqfs_dir_iterator_t *it, const sqfs_dir_entry_t *ent)
+{
+ sqfs_istream_t *in;
+ int ret;
- if (len == 0 || name[len - 1] != '/') {
- name[len++] = '/';
- name[len] = '\0';
- }
- }
+ ret = it->open_file_ro(it, &in);
+ if (ret)
+ return ret;
- return name;
-}
+ do {
+ ret = sqfs_istream_splice(in, out_file,
+ SQFS_DEFAULT_BLOCK_SIZE);
+ } while (ret > 0);
-static int terminate_archive(void)
-{
- char buffer[1024];
+ in = sqfs_drop(in);
- memset(buffer, '\0', sizeof(buffer));
+ if (ret == 0)
+ ret = padd_file(out_file, ent->size);
- return out_file->append(out_file, buffer, sizeof(buffer));
+ return ret;
}
-static sqfs_tree_node_t *tree_merge(sqfs_tree_node_t *lhs,
- sqfs_tree_node_t *rhs)
+static int write_entry(sqfs_dir_iterator_t *it, const sqfs_dir_entry_t *ent)
{
- sqfs_tree_node_t *head = NULL, **next_ptr = &head;
- sqfs_tree_node_t *it, *l, *r;
- int diff;
-
- while (lhs->children != NULL && rhs->children != NULL) {
- diff = strcmp((const char *)lhs->children->name,
- (const char *)rhs->children->name);
-
- if (diff < 0) {
- it = lhs->children;
- lhs->children = lhs->children->next;
- } else if (diff > 0) {
- it = rhs->children;
- rhs->children = rhs->children->next;
- } else {
- l = lhs->children;
- lhs->children = lhs->children->next;
-
- r = rhs->children;
- rhs->children = rhs->children->next;
-
- it = tree_merge(l, r);
+ static unsigned int record_counter;
+ sqfs_xattr_t *xattr = NULL;
+ char *target = NULL;
+ struct stat sb;
+ int ret;
+
+ if (S_ISLNK(ent->mode) ||
+ (ent->flags & SQFS_DIR_ENTRY_FLAG_HARD_LINK)) {
+ ret = it->read_link(it, &target);
+
+ if (ret != 0) {
+ sqfs_perror(ent->name, "reading link target", ret);
+ return ret;
}
+ }
- *next_ptr = it;
- next_ptr = &it->next;
+ ret = it->read_xattr(it, &xattr);
+ if (ret != 0) {
+ sqfs_perror(ent->name, "reading xattr data", ret);
+ sqfs_free(target);
+ return ret;
+ }
+
+ memset(&sb, 0, sizeof(sb));
+ sb.st_mode = ent->mode;
+ sb.st_uid = ent->uid;
+ sb.st_gid = ent->gid;
+ sb.st_mtime = ent->mtime;
+ sb.st_rdev = ent->rdev;
+ sb.st_size = ent->size;
+
+ if (ent->flags & SQFS_DIR_ENTRY_FLAG_HARD_LINK) {
+ ret = write_hard_link(out_file, &sb, ent->name, target,
+ record_counter++);
+ if (ret)
+ sqfs_perror(ent->name, "writing tar hard link", ret);
+ } else {
+ ret = write_tar_header(out_file, &sb, ent->name, target,
+ xattr, record_counter++);
+ if (ret)
+ sqfs_perror(ent->name, "writing tar header", ret);
}
- it = (lhs->children != NULL ? lhs->children : rhs->children);
- *next_ptr = it;
+ if (S_ISREG(ent->mode) && ret == 0)
+ ret = write_file_data(it, ent);
- sqfs_dir_tree_destroy(rhs);
- lhs->children = head;
- return lhs;
+ sqfs_xattr_list_free(xattr);
+ sqfs_free(target);
+ return ret;
}
int main(int argc, char **argv)
{
- sqfs_tree_node_t *root = NULL, *subtree = NULL;
- int flags, ret, status = EXIT_FAILURE;
- sqfs_compressor_t *cmp = NULL;
- sqfs_id_table_t *idtbl = NULL;
- sqfs_dir_reader_t *dr = NULL;
- sqfs_compressor_config_t cfg;
+ int ret, status = EXIT_FAILURE;
+ sqfs_dir_iterator_t *it = NULL;
size_t i;
process_args(argc, argv);
@@ -139,117 +122,59 @@ int main(int argc, char **argv)
goto out;
}
- ret = sqfs_file_open(&file, filename, SQFS_FILE_OPEN_READ_ONLY);
- if (ret) {
- sqfs_perror(filename, "open", ret);
- goto out;
- }
-
- ret = sqfs_super_read(&super, file);
- if (ret) {
- sqfs_perror(filename, "reading super block", ret);
- goto out;
- }
-
- sqfs_compressor_config_init(&cfg, super.compression_id,
- super.block_size,
- SQFS_COMP_FLAG_UNCOMPRESS);
-
- ret = sqfs_compressor_create(&cfg, &cmp);
-
-#ifdef WITH_LZO
- if (super.compression_id == SQFS_COMP_LZO && ret != 0)
- ret = lzo_compressor_create(&cfg, &cmp);
-#endif
-
- if (ret != 0) {
- sqfs_perror(filename, "creating compressor", ret);
+ it = tar_compat_iterator_create(filename);
+ if (it == NULL)
goto out;
- }
- idtbl = sqfs_id_table_create(0);
+ if (!no_links) {
+ sqfs_dir_iterator_t *hl;
- if (idtbl == NULL) {
- perror("creating ID table");
- goto out;
- }
+ ret = sqfs_hard_link_filter_create(&hl, it);
+ it = sqfs_drop(it);
- ret = sqfs_id_table_read(idtbl, file, &super, cmp);
- if (ret) {
- sqfs_perror(filename, "loading ID table", ret);
- goto out;
- }
-
- data = sqfs_data_reader_create(file, super.block_size, cmp, 0);
- if (data == NULL) {
- sqfs_perror(filename, "creating data reader",
- SQFS_ERROR_ALLOC);
- goto out;
- }
+ if (ret != 0) {
+ sqfs_perror(filename, "creating hard link filter", ret);
+ goto out;
+ }
- ret = sqfs_data_reader_load_fragment_table(data, &super);
- if (ret) {
- sqfs_perror(filename, "loading fragment table", ret);
- goto out;
+ it = hl;
}
- dr = sqfs_dir_reader_create(&super, cmp, file, 0);
- if (dr == NULL) {
- sqfs_perror(filename, "creating dir reader",
- SQFS_ERROR_ALLOC);
- goto out;
- }
+ for (;;) {
+ sqfs_dir_entry_t *ent;
- if (!no_xattr && !(super.flags & SQFS_FLAG_NO_XATTRS)) {
- xr = sqfs_xattr_reader_create(0);
- if (xr == NULL) {
- sqfs_perror(filename, "creating xattr reader",
- SQFS_ERROR_ALLOC);
+ ret = it->next(it, &ent);
+ if (ret > 0)
+ break;
+ if (ret < 0) {
+ sqfs_perror(filename, "reading directory entry", ret);
goto out;
}
- ret = sqfs_xattr_reader_load(xr, &super, file, cmp);
- if (ret) {
- sqfs_perror(filename, "loading xattr table", ret);
- goto out;
+ ret = write_entry(it, ent);
+ if (ret == SQFS_ERROR_UNSUPPORTED) {
+ fprintf(stderr, "WARNING: %s: unsupported file type\n",
+ ent->name);
+ if (dont_skip) {
+ fputs("Not allowed to skip files, aborting!\n",
+ stderr);
+ sqfs_free(ent);
+ goto out;
+ }
+ fprintf(stderr, "Skipping %s\n", ent->name);
+ sqfs_free(ent);
+ continue;
}
- }
- if (num_subdirs == 0) {
- ret = sqfs_dir_reader_get_full_hierarchy(dr, idtbl, NULL,
- 0, &root);
if (ret) {
- sqfs_perror(filename, "loading filesystem tree", ret);
+ sqfs_perror(ent->name, NULL, ret);
+ sqfs_free(ent);
goto out;
}
- } else {
- flags = 0;
-
- if (keep_as_dir || num_subdirs > 1)
- flags = SQFS_TREE_STORE_PARENTS;
-
- for (i = 0; i < num_subdirs; ++i) {
- ret = sqfs_dir_reader_get_full_hierarchy(dr, idtbl,
- subdirs[i],
- flags,
- &subtree);
- if (ret) {
- sqfs_perror(subdirs[i], "loading filesystem "
- "tree", ret);
- goto out;
- }
- if (root == NULL) {
- root = subtree;
- } else {
- root = tree_merge(root, subtree);
- }
- }
+ sqfs_free(ent);
}
- if (write_tree(root))
- goto out;
-
if (terminate_archive())
goto out;
@@ -261,13 +186,7 @@ int main(int argc, char **argv)
status = EXIT_SUCCESS;
out:
- sqfs_dir_tree_destroy(root);
- sqfs_drop(xr);
- sqfs_drop(dr);
- sqfs_drop(data);
- sqfs_drop(idtbl);
- sqfs_drop(cmp);
- sqfs_drop(file);
+ sqfs_drop(it);
sqfs_drop(out_file);
for (i = 0; i < num_subdirs; ++i)
free(subdirs[i]);