diff options
author | kientzle <kientzle@FreeBSD.org> | 2006-02-14 04:05:03 +0000 |
---|---|---|
committer | kientzle <kientzle@FreeBSD.org> | 2006-02-14 04:05:03 +0000 |
commit | 68f2d4ef56930e2c1f2f4d0055545a5b07d3d580 (patch) | |
tree | e919c97cc67a7c1c4f506eea68becaae7e72e989 /lib/libarchive | |
parent | ad0af0f7049c1284c09f5390d8ed7323b1d4b073 (diff) | |
download | FreeBSD-src-68f2d4ef56930e2c1f2f4d0055545a5b07d3d580.zip FreeBSD-src-68f2d4ef56930e2c1f2f4d0055545a5b07d3d580.tar.gz |
Minor fixes to the code that generates an internal ustar filename
for Pax extended attribute entries.
Diffstat (limited to 'lib/libarchive')
-rw-r--r-- | lib/libarchive/archive_write_set_format_pax.c | 43 |
1 files changed, 22 insertions, 21 deletions
diff --git a/lib/libarchive/archive_write_set_format_pax.c b/lib/libarchive/archive_write_set_format_pax.c index ce9a13a..4e9857b 100644 --- a/lib/libarchive/archive_write_set_format_pax.c +++ b/lib/libarchive/archive_write_set_format_pax.c @@ -67,7 +67,8 @@ static int archive_write_pax_finish_entry(struct archive *); static int archive_write_pax_header(struct archive *, struct archive_entry *); static char *build_pax_attribute_name(char *dest, const char *src); -static char *build_ustar_entry_name(char *dest, const char *src, const char *insert); +static char *build_ustar_entry_name(char *dest, const char *src, + size_t src_length, const char *insert); static char *format_int(char *dest, int64_t); static int has_non_ASCII(const wchar_t *); static int write_nulls(struct archive *, size_t); @@ -390,7 +391,7 @@ archive_write_pax_header(struct archive *a, if (suffix_start == NULL || suffix_start - p > 155 || has_non_ASCII(wp)) { add_pax_attr_w(&(pax->pax_header), "path", wp); archive_entry_set_pathname(entry_main, - build_ustar_entry_name(ustar_entry_name, p, NULL)); + build_ustar_entry_name(ustar_entry_name, p, strlen(p), NULL)); need_extension = 1; } @@ -787,13 +788,13 @@ archive_write_pax_header(struct archive *a, * parts 1 & 2, but does store the '/' separating parts 2 & 3. */ static char * -build_ustar_entry_name(char *dest, const char *src, const char *insert) +build_ustar_entry_name(char *dest, const char *src, size_t src_length, + const char *insert) { const char *prefix, *prefix_end; const char *suffix, *suffix_end; const char *filename, *filename_end; char *p; - size_t s; int need_slash = 0; /* Was there a trailing slash? */ size_t suffix_length = 99; int insert_length; @@ -806,14 +807,14 @@ build_ustar_entry_name(char *dest, const char *src, const char *insert) insert_length = strlen(insert) + 2; /* Step 0: Quick bailout in a common case. */ - s = strlen(src); - if (s < 100 && insert == NULL) { - strcpy(dest, src); + if (src_length < 100 && insert == NULL) { + strncpy(dest, src, src_length); + dest[src_length] = '\0'; return (dest); } /* Step 1: Locate filename and enforce the length restriction. */ - filename_end = src + s; + filename_end = src + src_length; /* Remove trailing '/' chars and '/.' pairs. */ for (;;) { if (filename_end > src && filename_end[-1] == '/') { @@ -881,8 +882,7 @@ build_ustar_entry_name(char *dest, const char *src, const char *insert) p += suffix_end - suffix; } if (insert != NULL) { - if (prefix_end > prefix || suffix_end > suffix) - *p++ = '/'; + /* Note: assume insert does not have leading or trailing '/' */ strcpy(p, insert); p += strlen(insert); *p++ = '/'; @@ -915,7 +915,7 @@ build_ustar_entry_name(char *dest, const char *src, const char *insert) static char * build_pax_attribute_name(char *dest, const char *src) { - char *p; + const char *p; /* Handle the null filename case. */ if (src == NULL || *src == '\0') { @@ -924,36 +924,37 @@ build_pax_attribute_name(char *dest, const char *src) } /* Prune final '/' and other unwanted final elements. */ - p = dest + strlen(dest); + p = src + strlen(src); for (;;) { /* Ends in "/", remove the '/' */ - if (p > dest && p[-1] == '/') { - *--p = '\0'; + if (p > src && p[-1] == '/') { + --p; continue; } /* Ends in "/.", remove the '.' */ - if (p > dest + 1 && p[-1] == '.' + if (p > src + 1 && p[-1] == '.' && p[-2] == '/') { - *--p = '\0'; + --p; continue; } break; } - /* Pathological case: After above, there was nothing left. */ - if (p == dest) { + /* Pathological case: After above, there was nothing left. + * This includes "/." "/./." "/.//./." etc. */ + if (p == src) { strcpy(dest, "/PaxHeader/rootdir"); return (dest); } - /* Convert unadorned "." into "dot" */ - if (*src == '.' && src[1] == '\0') { + /* Convert unadorned "." into a suitable filename. */ + if (*src == '.' && p == src + 1) { strcpy(dest, "PaxHeader/currentdir"); return (dest); } /* General case: build a ustar-compatible name adding "/PaxHeader/". */ - build_ustar_entry_name(dest, src, "PaxHeader"); + build_ustar_entry_name(dest, src, p - src, "PaxHeader"); return (dest); } |