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-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.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)
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. 94static 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"
98static 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
150char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) 161char 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