aboutsummaryrefslogtreecommitdiff
path: root/tar
diff options
context:
space:
mode:
authorDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2020-01-08 13:53:02 +0100
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2020-01-08 13:53:02 +0100
commitc835ac7dc3286ee77547e385a3420c42e8f535b9 (patch)
tree70d743576dcf2bdf61c54c21ac31cc2df1a5e082 /tar
parentd053eb8096a790d81b67c844d918341e797c2659 (diff)
Always append '/' to names of directories
In the distant past, the first versions of tar did not have any header field to indicate the type of the file being packed. Instead, they used to append a '/' to the filename to indicate that an entry is a actually a directory. GNU tar still does this today, despite having a header field for file type. This commit modifies sqfs2tar to append slashes to directory names for compatibillity and to mimic GNU tar behaviour more closely. Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
Diffstat (limited to 'tar')
-rw-r--r--tar/sqfs2tar.c57
1 files changed, 40 insertions, 17 deletions
diff --git a/tar/sqfs2tar.c b/tar/sqfs2tar.c
index 6e22621..4d31fbe 100644
--- a/tar/sqfs2tar.c
+++ b/tar/sqfs2tar.c
@@ -297,20 +297,47 @@ fail:
return -1;
}
-static char *prepend_prefix(char *name)
+static char *assemble_tar_path(char *name, bool is_dir)
{
- size_t len = strlen(root_becomes);
- char *temp = realloc(name, strlen(name) + len + 2);
+ 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;
- memmove(name + len + 1, name, strlen(name) + 1);
- memcpy(name, root_becomes, len);
- name[len] = '/';
+
+ if (root_becomes != NULL) {
+ len = strlen(root_becomes);
+
+ memmove(name + len + 1, name, strlen(name) + 1);
+ memcpy(name, root_becomes, len);
+ name[len] = '/';
+ }
+
+ if (is_dir) {
+ len = strlen(name);
+
+ if (len == 0 || name[len - 1] != '/') {
+ name[len++] = '/';
+ name[len] = '\0';
+ }
+ }
+
return name;
}
@@ -366,11 +393,9 @@ static int write_tree_dfs(const sqfs_tree_node_t *n)
}
}
- if (root_becomes != NULL) {
- name = prepend_prefix(name);
- if (name == NULL)
- return -1;
- }
+ name = assemble_tar_path(name, n->children != NULL);
+ if (name == NULL)
+ return -1;
}
inode_stat(n, &sb);
@@ -636,12 +661,10 @@ int main(int argc, char **argv)
if (sqfs_tree_find_hard_links(root, &links))
goto out_tree;
- if (root_becomes != NULL) {
- for (lnk = links; lnk != NULL; lnk = lnk->next) {
- lnk->target = prepend_prefix(lnk->target);
- if (lnk->target == NULL)
- goto out;
- }
+ for (lnk = links; lnk != NULL; lnk = lnk->next) {
+ lnk->target = assemble_tar_path(lnk->target, false);
+ if (lnk->target == NULL)
+ goto out;
}
}