diff options
author | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2020-01-08 13:53:02 +0100 |
---|---|---|
committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2020-01-08 13:53:02 +0100 |
commit | c835ac7dc3286ee77547e385a3420c42e8f535b9 (patch) | |
tree | 70d743576dcf2bdf61c54c21ac31cc2df1a5e082 /tar/sqfs2tar.c | |
parent | d053eb8096a790d81b67c844d918341e797c2659 (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/sqfs2tar.c')
-rw-r--r-- | tar/sqfs2tar.c | 57 |
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; } } |