From c835ac7dc3286ee77547e385a3420c42e8f535b9 Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Wed, 8 Jan 2020 13:53:02 +0100 Subject: 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 --- tar/sqfs2tar.c | 57 ++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 40 insertions(+), 17 deletions(-) (limited to 'tar') 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; } } -- cgit v1.2.3