From: Junio C Hamano Date: Sun, 06 Jan 2013 06:54:24 GMT Subject: Re: [PATCH] archive-tar: split long paths more carefully Message-ID: <7v7gnqpzrz.fsf@alter.siamese.dyndns.org> In-Reply-To: <50E8AE12.8040102@lsrfire.ath.cx> René Scharfe writes: > The name field of a tar header has a size of 100 characters. This limit > was extended long ago in a backward compatible way by providing the > additional prefix field, which can hold 155 additional characters. The > actual path is constructed at extraction time by concatenating the prefix > field, a slash and the name field. > > get_path_prefix() is used to determine which slash in the path is used as > the cutting point and thus which part of it is placed into the field > prefix and which into the field name. It tries to cram as much into the > prefix field as possible. (And only if we can't fit a path into the > provided 255 characters we use a pax extended header to store it.) > > If a path is longer than 100 but shorter than 156 characters and ends > with a slash (i.e. is for a directory) then get_path_prefix() puts the > whole path in the prefix field and leaves the name field empty. GNU tar > reconstructs the path without complaint, but the tar included with > NetBSD 6 does not: It reports the header to be invalid. > > For compatibility with this version of tar, make sure to never leave the > name field empty. In order to do that, trim the trailing slash from the > part considered as possible prefix, if it exists -- that way the last > path component (or more, but not less) will end up in the name field. Nicely explained; thanks. Makes me wonder what we should do for a file inside a directory whose name is 10 bytes long, and whose filename is 120 bytes long, though. Sounds like people on NetBSD are SOL due to the 155+'/'+100 in such a case and there is nothing we can do, I guess. > Signed-off-by: Rene Scharfe > --- > archive-tar.c | 2 ++ > 1 file changed, 2 insertions(+) > > diff --git a/archive-tar.c b/archive-tar.c > index 0ba3f25..923daf5 100644 > --- a/archive-tar.c > +++ b/archive-tar.c > @@ -153,6 +153,8 @@ static unsigned int ustar_header_chksum(const struct ustar_header *header) > static size_t get_path_prefix(const char *path, size_t pathlen, size_t maxlen) > { > size_t i = pathlen; > + if (i > 1 && path[i - 1] == '/') > + i--; > if (i > maxlen) > i = maxlen; > do {