diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2012-02-23 13:45:18 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2012-02-23 13:45:18 +0100 |
commit | 6111f967f5299d2eb82fb8eb4bf3b3a4272e3f44 (patch) | |
tree | 9fccf7ef8fdabd40aa048ae8a5048dd1035def13 | |
parent | af36ba206f7cf0eef77a82af741766a2d03c51ad (diff) | |
download | busybox-w32-6111f967f5299d2eb82fb8eb4bf3b3a4272e3f44.tar.gz busybox-w32-6111f967f5299d2eb82fb8eb4bf3b3a4272e3f44.tar.bz2 busybox-w32-6111f967f5299d2eb82fb8eb4bf3b3a4272e3f44.zip |
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.c | 8 | ||||
-rw-r--r-- | archival/libarchive/data_extract_to_command.c | 8 | ||||
-rw-r--r-- | archival/libarchive/get_header_tar.c | 65 | ||||
-rw-r--r-- | include/bb_archive.h | 9 |
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) | |||
13 | int res; | 13 | int res; |
14 | 14 | ||
15 | #if ENABLE_FEATURE_TAR_SELINUX | 15 | #if ENABLE_FEATURE_TAR_SELINUX |
16 | char *sctx = archive_handle->tar__next_file_sctx; | 16 | char *sctx = archive_handle->tar__sctx[PAX_NEXT_FILE]; |
17 | if (!sctx) | 17 | if (!sctx) |
18 | sctx = archive_handle->tar__global_sctx; | 18 | sctx = archive_handle->tar__sctx[PAX_GLOBAL]; |
19 | if (sctx) { /* setfscreatecon is 4 syscalls, avoid if possible */ | 19 | if (sctx) { /* setfscreatecon is 4 syscalls, avoid if possible */ |
20 | setfscreatecon(sctx); | 20 | setfscreatecon(sctx); |
21 | free(archive_handle->tar__next_file_sctx); | 21 | free(archive_handle->tar__sctx[PAX_NEXT_FILE]); |
22 | archive_handle->tar__next_file_sctx = NULL; | 22 | archive_handle->tar__sctx[PAX_NEXT_FILE] = NULL; |
23 | } | 23 | } |
24 | #endif | 24 | #endif |
25 | 25 | ||
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) | |||
64 | file_header_t *file_header = archive_handle->file_header; | 64 | file_header_t *file_header = archive_handle->file_header; |
65 | 65 | ||
66 | #if 0 /* do we need this? ENABLE_FEATURE_TAR_SELINUX */ | 66 | #if 0 /* do we need this? ENABLE_FEATURE_TAR_SELINUX */ |
67 | char *sctx = archive_handle->tar__next_file_sctx; | 67 | char *sctx = archive_handle->tar__sctx[PAX_NEXT_FILE]; |
68 | if (!sctx) | 68 | if (!sctx) |
69 | sctx = archive_handle->tar__global_sctx; | 69 | sctx = archive_handle->tar__sctx[PAX_GLOBAL]; |
70 | if (sctx) { /* setfscreatecon is 4 syscalls, avoid if possible */ | 70 | if (sctx) { /* setfscreatecon is 4 syscalls, avoid if possible */ |
71 | setfscreatecon(sctx); | 71 | setfscreatecon(sctx); |
72 | free(archive_handle->tar__next_file_sctx); | 72 | free(archive_handle->tar__sctx[PAX_NEXT_FILE]); |
73 | archive_handle->tar__next_file_sctx = NULL; | 73 | archive_handle->tar__sctx[PAX_NEXT_FILE] = NULL; |
74 | } | 74 | } |
75 | #endif | 75 | #endif |
76 | 76 | ||
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) | |||
90 | } | 90 | } |
91 | #define GET_OCTAL(a) getOctal((a), sizeof(a)) | 91 | #define GET_OCTAL(a) getOctal((a), sizeof(a)) |
92 | 92 | ||
93 | #if ENABLE_FEATURE_TAR_SELINUX | 93 | /* "global" is 0 or 1 */ |
94 | /* Scan a PAX header for SELinux contexts, via "RHT.security.selinux" keyword. | 94 | static void process_pax_hdr(archive_handle_t *archive_handle, unsigned sz, int global) |
95 | * This is what Red Hat's patched version of tar uses. | ||
96 | */ | ||
97 | # define SELINUX_CONTEXT_KEYWORD "RHT.security.selinux" | ||
98 | static char *get_selinux_sctx_from_pax_hdr(archive_handle_t *archive_handle, unsigned sz) | ||
99 | { | 95 | { |
100 | char *buf, *p; | 96 | char *buf, *p; |
101 | char *result; | 97 | unsigned blk_sz; |
98 | |||
99 | blk_sz = (sz + 511) & (~511); | ||
100 | p = buf = xmalloc(blk_sz + 1); | ||
101 | xread(archive_handle->src_fd, buf, blk_sz); | ||
102 | archive_handle->offset += blk_sz; | ||
102 | 103 | ||
103 | p = buf = xmalloc(sz + 1); | ||
104 | /* prevent bb_strtou from running off the buffer */ | 104 | /* prevent bb_strtou from running off the buffer */ |
105 | buf[sz] = '\0'; | 105 | buf[sz] = '\0'; |
106 | xread(archive_handle->src_fd, buf, sz); | ||
107 | archive_handle->offset += sz; | ||
108 | 106 | ||
109 | result = NULL; | ||
110 | while (sz != 0) { | 107 | while (sz != 0) { |
111 | char *end, *value; | 108 | char *end, *value; |
112 | unsigned len; | 109 | unsigned len; |
@@ -133,19 +130,33 @@ static char *get_selinux_sctx_from_pax_hdr(archive_handle_t *archive_handle, uns | |||
133 | * (we do not bother to check that it *was* a newline) | 130 | * (we do not bother to check that it *was* a newline) |
134 | */ | 131 | */ |
135 | p[-1] = '\0'; | 132 | p[-1] = '\0'; |
136 | /* Is it selinux security context? */ | ||
137 | value = end + 1; | 133 | value = end + 1; |
134 | |||
135 | #if ENABLE_FEATURE_TAR_GNU_EXTENSIONS | ||
136 | if (!global && strncmp(value, "path=", sizeof("path=") - 1) == 0) { | ||
137 | value += sizeof("path=") - 1; | ||
138 | free(archive_handle->tar__longname); | ||
139 | archive_handle->tar__longname = xstrdup(value); | ||
140 | continue; | ||
141 | } | ||
142 | #endif | ||
143 | |||
144 | #if ENABLE_FEATURE_TAR_SELINUX | ||
145 | /* Scan for SELinux contexts, via "RHT.security.selinux" keyword. | ||
146 | * This is what Red Hat's patched version of tar uses. | ||
147 | */ | ||
148 | # define SELINUX_CONTEXT_KEYWORD "RHT.security.selinux" | ||
138 | if (strncmp(value, SELINUX_CONTEXT_KEYWORD"=", sizeof(SELINUX_CONTEXT_KEYWORD"=") - 1) == 0) { | 149 | if (strncmp(value, SELINUX_CONTEXT_KEYWORD"=", sizeof(SELINUX_CONTEXT_KEYWORD"=") - 1) == 0) { |
139 | value += sizeof(SELINUX_CONTEXT_KEYWORD"=") - 1; | 150 | value += sizeof(SELINUX_CONTEXT_KEYWORD"=") - 1; |
140 | result = xstrdup(value); | 151 | free(archive_handle->tar__sctx[global]); |
141 | break; | 152 | archive_handle->tar__sctx[global] = xstrdup(value); |
153 | continue; | ||
142 | } | 154 | } |
155 | #endif | ||
143 | } | 156 | } |
144 | 157 | ||
145 | free(buf); | 158 | free(buf); |
146 | return result; | ||
147 | } | 159 | } |
148 | #endif | ||
149 | 160 | ||
150 | char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) | 161 | char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) |
151 | { | 162 | { |
@@ -418,12 +429,14 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) | |||
418 | case 'S': /* Sparse file */ | 429 | case 'S': /* Sparse file */ |
419 | case 'V': /* Volume header */ | 430 | case 'V': /* Volume header */ |
420 | #endif | 431 | #endif |
421 | #if !ENABLE_FEATURE_TAR_SELINUX | ||
422 | case 'g': /* pax global header */ | 432 | case 'g': /* pax global header */ |
423 | case 'x': /* pax extended header */ | 433 | case 'x': { /* pax extended header */ |
424 | #else | 434 | if ((uoff_t)file_header->size > 0xfffff) /* paranoia */ |
435 | goto skip_ext_hdr; | ||
436 | process_pax_hdr(archive_handle, file_header->size, (tar.typeflag == 'g')); | ||
437 | goto again_after_align; | ||
438 | } | ||
425 | skip_ext_hdr: | 439 | skip_ext_hdr: |
426 | #endif | ||
427 | { | 440 | { |
428 | off_t sz; | 441 | off_t sz; |
429 | bb_error_msg("warning: skipping header '%c'", tar.typeflag); | 442 | bb_error_msg("warning: skipping header '%c'", tar.typeflag); |
@@ -435,18 +448,6 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) | |||
435 | /* return get_header_tar(archive_handle); */ | 448 | /* return get_header_tar(archive_handle); */ |
436 | goto again_after_align; | 449 | goto again_after_align; |
437 | } | 450 | } |
438 | #if ENABLE_FEATURE_TAR_SELINUX | ||
439 | case 'g': /* pax global header */ | ||
440 | case 'x': { /* pax extended header */ | ||
441 | char **pp; | ||
442 | if ((uoff_t)file_header->size > 0xfffff) /* paranoia */ | ||
443 | goto skip_ext_hdr; | ||
444 | pp = (tar.typeflag == 'g') ? &archive_handle->tar__global_sctx : &archive_handle->tar__next_file_sctx; | ||
445 | free(*pp); | ||
446 | *pp = get_selinux_sctx_from_pax_hdr(archive_handle, file_header->size); | ||
447 | goto again; | ||
448 | } | ||
449 | #endif | ||
450 | default: | 451 | default: |
451 | bb_error_msg_and_die("unknown typeflag: 0x%x", tar.typeflag); | 452 | bb_error_msg_and_die("unknown typeflag: 0x%x", tar.typeflag); |
452 | } | 453 | } |
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 { | |||
77 | off_t offset; | 77 | off_t offset; |
78 | 78 | ||
79 | /* Archiver specific. Can make it a union if it ever gets big */ | 79 | /* Archiver specific. Can make it a union if it ever gets big */ |
80 | #define PAX_NEXT_FILE 0 | ||
81 | #define PAX_GLOBAL 1 | ||
80 | #if ENABLE_TAR || ENABLE_DPKG || ENABLE_DPKG_DEB | 82 | #if ENABLE_TAR || ENABLE_DPKG || ENABLE_DPKG_DEB |
81 | smallint tar__end; | 83 | smallint tar__end; |
82 | # if ENABLE_FEATURE_TAR_GNU_EXTENSIONS | 84 | # if ENABLE_FEATURE_TAR_GNU_EXTENSIONS |
83 | char* tar__longname; | 85 | char* tar__longname; |
84 | char* tar__linkname; | 86 | char* tar__linkname; |
85 | # endif | 87 | # endif |
86 | #if ENABLE_FEATURE_TAR_TO_COMMAND | 88 | # if ENABLE_FEATURE_TAR_TO_COMMAND |
87 | char* tar__to_command; | 89 | char* tar__to_command; |
88 | const char* tar__to_command_shell; | 90 | const char* tar__to_command_shell; |
89 | #endif | 91 | # endif |
90 | # if ENABLE_FEATURE_TAR_SELINUX | 92 | # if ENABLE_FEATURE_TAR_SELINUX |
91 | char* tar__global_sctx; | 93 | char* tar__sctx[2]; |
92 | char* tar__next_file_sctx; | ||
93 | # endif | 94 | # endif |
94 | #endif | 95 | #endif |
95 | #if ENABLE_CPIO || ENABLE_RPM2CPIO || ENABLE_RPM | 96 | #if ENABLE_CPIO || ENABLE_RPM2CPIO || ENABLE_RPM |