aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2012-02-23 13:45:18 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2012-02-23 13:45:18 +0100
commit6111f967f5299d2eb82fb8eb4bf3b3a4272e3f44 (patch)
tree9fccf7ef8fdabd40aa048ae8a5048dd1035def13
parentaf36ba206f7cf0eef77a82af741766a2d03c51ad (diff)
downloadbusybox-6111f967f5299d2eb82fb8eb4bf3b3a4272e3f44.tar.gz
tar: add support for PAX-encoded path=LONGFILENAME
function old new delta get_header_tar 1478 1759 +281 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--archival/libarchive/data_extract_all.c8
-rw-r--r--archival/libarchive/data_extract_to_command.c8
-rw-r--r--archival/libarchive/get_header_tar.c65
-rw-r--r--include/bb_archive.h9
4 files changed, 46 insertions, 44 deletions
diff --git a/archival/libarchive/data_extract_all.c b/archival/libarchive/data_extract_all.c
index f565e5471..3f67b835f 100644
--- a/archival/libarchive/data_extract_all.c
+++ b/archival/libarchive/data_extract_all.c
@@ -13,13 +13,13 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
int res;
#if ENABLE_FEATURE_TAR_SELINUX
- char *sctx = archive_handle->tar__next_file_sctx;
+ char *sctx = archive_handle->tar__sctx[PAX_NEXT_FILE];
if (!sctx)
- sctx = archive_handle->tar__global_sctx;
+ sctx = archive_handle->tar__sctx[PAX_GLOBAL];
if (sctx) { /* setfscreatecon is 4 syscalls, avoid if possible */
setfscreatecon(sctx);
- free(archive_handle->tar__next_file_sctx);
- archive_handle->tar__next_file_sctx = NULL;
+ free(archive_handle->tar__sctx[PAX_NEXT_FILE]);
+ archive_handle->tar__sctx[PAX_NEXT_FILE] = NULL;
}
#endif
diff --git a/archival/libarchive/data_extract_to_command.c b/archival/libarchive/data_extract_to_command.c
index cc2ff7798..a2ce33b51 100644
--- a/archival/libarchive/data_extract_to_command.c
+++ b/archival/libarchive/data_extract_to_command.c
@@ -64,13 +64,13 @@ void FAST_FUNC data_extract_to_command(archive_handle_t *archive_handle)
file_header_t *file_header = archive_handle->file_header;
#if 0 /* do we need this? ENABLE_FEATURE_TAR_SELINUX */
- char *sctx = archive_handle->tar__next_file_sctx;
+ char *sctx = archive_handle->tar__sctx[PAX_NEXT_FILE];
if (!sctx)
- sctx = archive_handle->tar__global_sctx;
+ sctx = archive_handle->tar__sctx[PAX_GLOBAL];
if (sctx) { /* setfscreatecon is 4 syscalls, avoid if possible */
setfscreatecon(sctx);
- free(archive_handle->tar__next_file_sctx);
- archive_handle->tar__next_file_sctx = NULL;
+ free(archive_handle->tar__sctx[PAX_NEXT_FILE]);
+ archive_handle->tar__sctx[PAX_NEXT_FILE] = NULL;
}
#endif
diff --git a/archival/libarchive/get_header_tar.c b/archival/libarchive/get_header_tar.c
index a63c0fb01..8c699754b 100644
--- a/archival/libarchive/get_header_tar.c
+++ b/archival/libarchive/get_header_tar.c
@@ -90,23 +90,20 @@ static unsigned long long getOctal(char *str, int len)
}
#define GET_OCTAL(a) getOctal((a), sizeof(a))
-#if ENABLE_FEATURE_TAR_SELINUX
-/* Scan a PAX header for SELinux contexts, via "RHT.security.selinux" keyword.
- * This is what Red Hat's patched version of tar uses.
- */
-# define SELINUX_CONTEXT_KEYWORD "RHT.security.selinux"
-static char *get_selinux_sctx_from_pax_hdr(archive_handle_t *archive_handle, unsigned sz)
+/* "global" is 0 or 1 */
+static void process_pax_hdr(archive_handle_t *archive_handle, unsigned sz, int global)
{
char *buf, *p;
- char *result;
+ unsigned blk_sz;
+
+ blk_sz = (sz + 511) & (~511);
+ p = buf = xmalloc(blk_sz + 1);
+ xread(archive_handle->src_fd, buf, blk_sz);
+ archive_handle->offset += blk_sz;
- p = buf = xmalloc(sz + 1);
/* prevent bb_strtou from running off the buffer */
buf[sz] = '\0';
- xread(archive_handle->src_fd, buf, sz);
- archive_handle->offset += sz;
- result = NULL;
while (sz != 0) {
char *end, *value;
unsigned len;
@@ -133,19 +130,33 @@ static char *get_selinux_sctx_from_pax_hdr(archive_handle_t *archive_handle, uns
* (we do not bother to check that it *was* a newline)
*/
p[-1] = '\0';
- /* Is it selinux security context? */
value = end + 1;
+
+#if ENABLE_FEATURE_TAR_GNU_EXTENSIONS
+ if (!global && strncmp(value, "path=", sizeof("path=") - 1) == 0) {
+ value += sizeof("path=") - 1;
+ free(archive_handle->tar__longname);
+ archive_handle->tar__longname = xstrdup(value);
+ continue;
+ }
+#endif
+
+#if ENABLE_FEATURE_TAR_SELINUX
+ /* Scan for SELinux contexts, via "RHT.security.selinux" keyword.
+ * This is what Red Hat's patched version of tar uses.
+ */
+# define SELINUX_CONTEXT_KEYWORD "RHT.security.selinux"
if (strncmp(value, SELINUX_CONTEXT_KEYWORD"=", sizeof(SELINUX_CONTEXT_KEYWORD"=") - 1) == 0) {
value += sizeof(SELINUX_CONTEXT_KEYWORD"=") - 1;
- result = xstrdup(value);
- break;
+ free(archive_handle->tar__sctx[global]);
+ archive_handle->tar__sctx[global] = xstrdup(value);
+ continue;
}
+#endif
}
free(buf);
- return result;
}
-#endif
char FAST_FUNC get_header_tar(archive_handle_t *archive_handle)
{
@@ -418,12 +429,14 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle)
case 'S': /* Sparse file */
case 'V': /* Volume header */
#endif
-#if !ENABLE_FEATURE_TAR_SELINUX
case 'g': /* pax global header */
- case 'x': /* pax extended header */
-#else
+ case 'x': { /* pax extended header */
+ if ((uoff_t)file_header->size > 0xfffff) /* paranoia */
+ goto skip_ext_hdr;
+ process_pax_hdr(archive_handle, file_header->size, (tar.typeflag == 'g'));
+ goto again_after_align;
+ }
skip_ext_hdr:
-#endif
{
off_t sz;
bb_error_msg("warning: skipping header '%c'", tar.typeflag);
@@ -435,18 +448,6 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle)
/* return get_header_tar(archive_handle); */
goto again_after_align;
}
-#if ENABLE_FEATURE_TAR_SELINUX
- case 'g': /* pax global header */
- case 'x': { /* pax extended header */
- char **pp;
- if ((uoff_t)file_header->size > 0xfffff) /* paranoia */
- goto skip_ext_hdr;
- pp = (tar.typeflag == 'g') ? &archive_handle->tar__global_sctx : &archive_handle->tar__next_file_sctx;
- free(*pp);
- *pp = get_selinux_sctx_from_pax_hdr(archive_handle, file_header->size);
- goto again;
- }
-#endif
default:
bb_error_msg_and_die("unknown typeflag: 0x%x", tar.typeflag);
}
diff --git a/include/bb_archive.h b/include/bb_archive.h
index d1a9a34ec..4987de6cf 100644
--- a/include/bb_archive.h
+++ b/include/bb_archive.h
@@ -77,19 +77,20 @@ typedef struct archive_handle_t {
off_t offset;
/* Archiver specific. Can make it a union if it ever gets big */
+#define PAX_NEXT_FILE 0
+#define PAX_GLOBAL 1
#if ENABLE_TAR || ENABLE_DPKG || ENABLE_DPKG_DEB
smallint tar__end;
# if ENABLE_FEATURE_TAR_GNU_EXTENSIONS
char* tar__longname;
char* tar__linkname;
# endif
-#if ENABLE_FEATURE_TAR_TO_COMMAND
+# if ENABLE_FEATURE_TAR_TO_COMMAND
char* tar__to_command;
const char* tar__to_command_shell;
-#endif
+# endif
# if ENABLE_FEATURE_TAR_SELINUX
- char* tar__global_sctx;
- char* tar__next_file_sctx;
+ char* tar__sctx[2];
# endif
#endif
#if ENABLE_CPIO || ENABLE_RPM2CPIO || ENABLE_RPM