Skip to content

Commit

Permalink
tar-tree: Use the prefix field of a tar header
Browse files Browse the repository at this point in the history
... to store parts of the path, if possible.  This allows us to avoid
writing extended headers in certain cases (long pathes can only be
split at '/' chars).

Also adds a file to the test repo with a 100 chars long directory name.
Even old versions of tar that don't understand POSIX extended headers
should be able to handle this testcase.

Btw.: The longest path in the kernel tree currently has 70 chars.
Together with a 30 chars long prefix this would already cross the
field limit of 100 chars.

Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>
Signed-off-by: Junio C Hamano <junkio@cox.net>
  • Loading branch information
Rene Scharfe authored and Junio C Hamano committed Mar 26, 2006
1 parent 86da1c5 commit 4c69172
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 3 deletions.
3 changes: 3 additions & 0 deletions t/t5000-tar-tree.sh
Expand Up @@ -34,6 +34,9 @@ test_expect_success \
mkdir a/bin &&
cp /bin/sh a/bin &&
ln -s a a/l1 &&
(p=long_path_to_a_file && cd a &&
for depth in 1 2 3 4 5; do mkdir $p && cd $p; done &&
echo text >file_with_long_path) &&
(cd a && find .) | sort >a.lst'

test_expect_success \
Expand Down
24 changes: 21 additions & 3 deletions tar-tree.c
Expand Up @@ -161,6 +161,16 @@ static unsigned int ustar_header_chksum(const struct ustar_header *header)
return chksum;
}

static int get_path_prefix(const struct strbuf *path, int maxlen)
{
int i = path->len;
if (i > maxlen)
i = maxlen;
while (i > 0 && path->buf[i] != '/')
i--;
return i;
}

static void write_entry(const unsigned char *sha1, struct strbuf *path,
unsigned int mode, void *buffer, unsigned long size)
{
Expand Down Expand Up @@ -195,9 +205,17 @@ static void write_entry(const unsigned char *sha1, struct strbuf *path,
return;
}
if (path->len > sizeof(header.name)) {
sprintf(header.name, "%s.data", sha1_to_hex(sha1));
strbuf_append_ext_header(&ext_header, "path",
path->buf, path->len);
int plen = get_path_prefix(path, sizeof(header.prefix));
int rest = path->len - plen - 1;
if (plen > 0 && rest <= sizeof(header.name)) {
memcpy(header.prefix, path->buf, plen);
memcpy(header.name, path->buf + plen + 1, rest);
} else {
sprintf(header.name, "%s.data",
sha1_to_hex(sha1));
strbuf_append_ext_header(&ext_header, "path",
path->buf, path->len);
}
} else
memcpy(header.name, path->buf, path->len);
}
Expand Down

0 comments on commit 4c69172

Please sign in to comment.