summaryrefslogtreecommitdiffstats
path: root/lib/libarchive/archive_write_set_format_pax.c
diff options
context:
space:
mode:
authorkientzle <kientzle@FreeBSD.org>2008-05-26 17:00:24 +0000
committerkientzle <kientzle@FreeBSD.org>2008-05-26 17:00:24 +0000
commita24d28f8e3d3892010c91baad77e2178c6a16ba2 (patch)
treed200bbdabe22d32b68a61172999be232d0c31d75 /lib/libarchive/archive_write_set_format_pax.c
parent268a4c430f25bc479b5e1e097f51394aa0f1fffb (diff)
downloadFreeBSD-src-a24d28f8e3d3892010c91baad77e2178c6a16ba2.zip
FreeBSD-src-a24d28f8e3d3892010c91baad77e2178c6a16ba2.tar.gz
MFp4: libarchive 2.5.4b. (Still 'b' until I get a bit more
feedback, but the 2.5 branch is shaping up nicely.) In addition to many small bug fixes and code improvements: * Another iteration of versioning; I think I've got it right now. * Portability: A lot of progress on Windows support (though I'm not committing all of the Windows support files to FreeBSD CVS) * Explicit tracking of MBS, WCS, and UTF-8 versions of strings in archive_entry; the archive_entry routines now correctly return NULL only when something is unset, setting NULL properly clears string values. Most charset conversions have been pushed down to archive_string. * Better handling of charset conversion failure when writing or reading UTF-8 headers in pax archives * archive_entry_linkify() provides multiple strategies for hardlink matching to suit different format expectations * More accurate bzip2 format detection * Joerg Sonnenberger's extensive improvements to mtree support * Rough support for self-extracting ZIP archives. Not an ideal approach, but it works for the archives I've tried. * New "sparsify" option in archive_write_disk converts blocks of nulls into seeks. * Better default behavior for the test harness; it now reports all failures by default instead of coredumping at the first one.
Diffstat (limited to 'lib/libarchive/archive_write_set_format_pax.c')
-rw-r--r--lib/libarchive/archive_write_set_format_pax.c75
1 files changed, 58 insertions, 17 deletions
diff --git a/lib/libarchive/archive_write_set_format_pax.c b/lib/libarchive/archive_write_set_format_pax.c
index 6f05a99..b40aec5 100644
--- a/lib/libarchive/archive_write_set_format_pax.c
+++ b/lib/libarchive/archive_write_set_format_pax.c
@@ -386,7 +386,7 @@ archive_write_pax_header(struct archive_write *a,
const char *p;
char *t;
const wchar_t *wp;
- const char *suffix_start;
+ const char *suffix;
int need_extension, r, ret;
struct pax *pax;
const char *hdrcharset = NULL;
@@ -496,34 +496,73 @@ archive_write_pax_header(struct archive_write *a,
if (hdrcharset != NULL)
add_pax_attr(&(pax->pax_header), "hdrcharset", hdrcharset);
- /*
- * Determining whether or not the name is too big is ugly
- * because of the rules for dividing names between 'name' and
- * 'prefix' fields. Here, I pick out the longest possible
- * suffix, then test whether the remaining prefix is too long.
- */
- if (strlen(path) <= 100) /* Short enough for just 'name' field */
- suffix_start = path; /* Record a zero-length prefix */
- else
- /* Find the largest suffix that fits in 'name' field. */
- suffix_start = strchr(path + strlen(path) - 100 - 1, '/');
/*
* If name is too long, or has non-ASCII characters, add
* 'path' to pax extended attrs. (Note that an unconvertible
* name must have non-ASCII characters.)
*/
- if (suffix_start == NULL || suffix_start - path > 155
- || path_w == NULL || has_non_ASCII(path_w)) {
- if (path_w == NULL || hdrcharset != NULL)
+ if (path == NULL) {
+ /* We don't have a narrow version, so we have to store
+ * the wide version. */
+ add_pax_attr_w(&(pax->pax_header), "path", path_w);
+ archive_entry_set_pathname(entry_main, "@WidePath");
+ need_extension = 1;
+ } else if (has_non_ASCII(path_w)) {
+ /* We have non-ASCII characters. */
+ if (path_w == NULL || hdrcharset != NULL) {
/* Can't do UTF-8, so store it raw. */
add_pax_attr(&(pax->pax_header), "path", path);
- else
- add_pax_attr_w(&(pax->pax_header), "path", path_w);
+ } else {
+ /* Store UTF-8 */
+ add_pax_attr_w(&(pax->pax_header),
+ "path", path_w);
+ }
archive_entry_set_pathname(entry_main,
build_ustar_entry_name(ustar_entry_name,
path, strlen(path), NULL));
need_extension = 1;
+ } else {
+ /* We have an all-ASCII path; we'd like to just store
+ * it in the ustar header if it will fit. Yes, this
+ * duplicates some of the logic in
+ * write_set_format_ustar.c
+ */
+ if (strlen(path) <= 100) {
+ /* Fits in the old 100-char tar name field. */
+ } else {
+ /* Find largest suffix that will fit. */
+ /* Note: strlen() > 100, so strlen() - 100 - 1 >= 0 */
+ suffix = strchr(path + strlen(path) - 100 - 1, '/');
+ /* Don't attempt an empty prefix. */
+ if (suffix == path)
+ suffix = strchr(suffix + 1, '/');
+ /* We can put it in the ustar header if it's
+ * all ASCII and it's either <= 100 characters
+ * or can be split at a '/' into a prefix <=
+ * 155 chars and a suffix <= 100 chars. (Note
+ * the strchr() above will return NULL exactly
+ * when the path can't be split.)
+ */
+ if (suffix == NULL /* Suffix > 100 chars. */
+ || suffix[1] == '\0' /* empty suffix */
+ || suffix - path > 155) /* Prefix > 155 chars */
+ {
+ if (path_w == NULL || hdrcharset != NULL) {
+ /* Can't do UTF-8, so store it raw. */
+ add_pax_attr(&(pax->pax_header),
+ "path", path);
+ } else {
+ /* Store UTF-8 */
+ add_pax_attr_w(&(pax->pax_header),
+ "path", path_w);
+ }
+ archive_entry_set_pathname(entry_main,
+ build_ustar_entry_name(ustar_entry_name,
+ path, strlen(path), NULL));
+ need_extension = 1;
+ }
+ }
}
if (linkpath != NULL) {
@@ -1215,6 +1254,8 @@ archive_write_pax_data(struct archive_write *a, const void *buff, size_t s)
static int
has_non_ASCII(const wchar_t *wp)
{
+ if (wp == NULL)
+ return (1);
while (*wp != L'\0' && *wp < 128)
wp++;
return (*wp != L'\0');
OpenPOWER on IntegriCloud