Changeset 3621 in MondoRescue for branches/3.3/mindi-busybox/archival/libarchive/open_transformer.c
- Timestamp:
- Dec 20, 2016, 4:07:32 PM (7 years ago)
- Location:
- branches/3.3
- Files:
-
- 1 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
branches/3.3/mindi-busybox/archival/libarchive/open_transformer.c
r3232 r3621 7 7 #include "bb_archive.h" 8 8 9 void FAST_FUNC init_transformer_ aux_data(transformer_aux_data_t *aux)10 { 11 memset( aux, 0, sizeof(*aux));12 } 13 14 int FAST_FUNC check_signature16(transformer_ aux_data_t *aux, int src_fd, unsigned magic16)15 { 16 if ( aux && aux->check_signature) {9 void FAST_FUNC init_transformer_state(transformer_state_t *xstate) 10 { 11 memset(xstate, 0, sizeof(*xstate)); 12 } 13 14 int FAST_FUNC check_signature16(transformer_state_t *xstate, unsigned magic16) 15 { 16 if (!xstate->signature_skipped) { 17 17 uint16_t magic2; 18 if (full_read( src_fd, &magic2, 2) != 2 || magic2 != magic16) {18 if (full_read(xstate->src_fd, &magic2, 2) != 2 || magic2 != magic16) { 19 19 bb_error_msg("invalid magic"); 20 #if 0 /* possible future extension */21 if (aux->check_signature > 1)22 xfunc_die();23 #endif24 20 return -1; 25 21 } 22 xstate->signature_skipped = 2; 26 23 } 27 24 return 0; 25 } 26 27 ssize_t FAST_FUNC transformer_write(transformer_state_t *xstate, const void *buf, size_t bufsize) 28 { 29 ssize_t nwrote; 30 31 if (xstate->mem_output_size_max != 0) { 32 size_t pos = xstate->mem_output_size; 33 size_t size; 34 35 size = (xstate->mem_output_size += bufsize); 36 if (size > xstate->mem_output_size_max) { 37 free(xstate->mem_output_buf); 38 xstate->mem_output_buf = NULL; 39 bb_perror_msg("buffer %u too small", (unsigned)xstate->mem_output_size_max); 40 nwrote = -1; 41 goto ret; 42 } 43 xstate->mem_output_buf = xrealloc(xstate->mem_output_buf, size + 1); 44 memcpy(xstate->mem_output_buf + pos, buf, bufsize); 45 xstate->mem_output_buf[size] = '\0'; 46 nwrote = bufsize; 47 } else { 48 nwrote = full_write(xstate->dst_fd, buf, bufsize); 49 if (nwrote != (ssize_t)bufsize) { 50 bb_perror_msg("write"); 51 nwrote = -1; 52 goto ret; 53 } 54 } 55 ret: 56 return nwrote; 57 } 58 59 ssize_t FAST_FUNC xtransformer_write(transformer_state_t *xstate, const void *buf, size_t bufsize) 60 { 61 ssize_t nwrote = transformer_write(xstate, buf, bufsize); 62 if (nwrote != (ssize_t)bufsize) { 63 xfunc_die(); 64 } 65 return nwrote; 28 66 } 29 67 … … 35 73 /* block waiting for any child */ 36 74 if (wait(&status) < 0) 75 //FIXME: check EINTR? 37 76 return; /* probably there are no children */ 38 77 goto check_status; … … 42 81 for (;;) { 43 82 if (wait_any_nohang(&status) < 0) 83 //FIXME: check EINTR? 44 84 /* wait failed?! I'm confused... */ 45 85 return; 46 86 check_status: 47 if (WIFEXITED(status) && WEXITSTATUS(status) == 0) 87 /*if (WIFEXITED(status) && WEXITSTATUS(status) == 0)*/ 88 /* On Linux, the above can be checked simply as: */ 89 if (status == 0) 48 90 /* this child exited with 0 */ 49 91 continue; 50 /* Cannot happen? 51 if (!WIFSIGNALED(status) && !WIFEXITED(status)) ???; */ 92 /* Cannot happen: 93 if (!WIFSIGNALED(status) && !WIFEXITED(status)) ???; 94 */ 52 95 bb_got_signal = 1; 53 96 } … … 56 99 /* transformer(), more than meets the eye */ 57 100 #if BB_MMU 58 void FAST_FUNC open_transformer(int fd,59 int check_signature,60 IF_DESKTOP(long long) int FAST_FUNC (*transformer)(transformer_ aux_data_t *aux, int src_fd, int dst_fd)101 void FAST_FUNC fork_transformer(int fd, 102 int signature_skipped, 103 IF_DESKTOP(long long) int FAST_FUNC (*transformer)(transformer_state_t *xstate) 61 104 ) 62 105 #else 63 void FAST_FUNC open_transformer(int fd, const char *transform_prog)106 void FAST_FUNC fork_transformer(int fd, const char *transform_prog) 64 107 #endif 65 108 { … … 75 118 #if BB_MMU 76 119 { 77 transformer_aux_data_t aux; 78 init_transformer_aux_data(&aux); 79 aux.check_signature = check_signature; 80 transformer(&aux, fd, fd_pipe.wr); 120 IF_DESKTOP(long long) int r; 121 transformer_state_t xstate; 122 init_transformer_state(&xstate); 123 xstate.signature_skipped = signature_skipped; 124 xstate.src_fd = fd; 125 xstate.dst_fd = fd_pipe.wr; 126 r = transformer(&xstate); 81 127 if (ENABLE_FEATURE_CLEAN_UP) { 82 128 close(fd_pipe.wr); /* send EOF */ … … 84 130 } 85 131 /* must be _exit! bug was actually seen here */ 86 _exit( EXIT_SUCCESS);132 _exit(/*error if:*/ r < 0); 87 133 } 88 134 #else … … 113 159 * thus we can't guess the format from filename's extension. 114 160 */ 115 int FAST_FUNC setup_unzip_on_fd(int fd, int fail_if_not_detected)161 static transformer_state_t *setup_transformer_on_fd(int fd, int fail_if_not_compressed) 116 162 { 117 163 union { … … 120 166 uint32_t b32[1]; 121 167 } magic; 122 int offset = -2; 123 USE_FOR_MMU(IF_DESKTOP(long long) int FAST_FUNC (*xformer)(transformer_aux_data_t *aux, int src_fd, int dst_fd);) 124 USE_FOR_NOMMU(const char *xformer_prog;) 168 transformer_state_t *xstate; 169 170 xstate = xzalloc(sizeof(*xstate)); 171 xstate->src_fd = fd; 172 xstate->signature_skipped = 2; 125 173 126 174 /* .gz and .bz2 both have 2-byte signature, and their … … 130 178 && magic.b16[0] == GZIP_MAGIC 131 179 ) { 132 USE_FOR_MMU(xformer = unpack_gz_stream;) 133 USE_FOR_NOMMU(xformer_prog = "gunzip";) 180 xstate->xformer = unpack_gz_stream; 181 USE_FOR_NOMMU(xstate->xformer_prog = "gunzip";) 182 goto found_magic; 183 } 184 if (ENABLE_FEATURE_SEAMLESS_Z 185 && magic.b16[0] == COMPRESS_MAGIC 186 ) { 187 xstate->xformer = unpack_Z_stream; 188 USE_FOR_NOMMU(xstate->xformer_prog = "uncompress";) 134 189 goto found_magic; 135 190 } … … 137 192 && magic.b16[0] == BZIP2_MAGIC 138 193 ) { 139 USE_FOR_MMU(xformer = unpack_bz2_stream;)140 USE_FOR_NOMMU(x former_prog = "bunzip2";)194 xstate->xformer = unpack_bz2_stream; 195 USE_FOR_NOMMU(xstate->xformer_prog = "bunzip2";) 141 196 goto found_magic; 142 197 } … … 144 199 && magic.b16[0] == XZ_MAGIC1 145 200 ) { 146 offset = -6;201 xstate->signature_skipped = 6; 147 202 xread(fd, magic.b32, sizeof(magic.b32[0])); 148 203 if (magic.b32[0] == XZ_MAGIC2) { 149 USE_FOR_MMU(xformer = unpack_xz_stream;)150 USE_FOR_NOMMU(x former_prog = "unxz";)204 xstate->xformer = unpack_xz_stream; 205 USE_FOR_NOMMU(xstate->xformer_prog = "unxz";) 151 206 goto found_magic; 152 207 } … … 154 209 155 210 /* No known magic seen */ 156 if (fail_if_not_ detected)211 if (fail_if_not_compressed) 157 212 bb_error_msg_and_die("no gzip" 158 213 IF_FEATURE_SEAMLESS_BZ2("/bzip2") 159 214 IF_FEATURE_SEAMLESS_XZ("/xz") 160 215 " magic"); 161 xlseek(fd, offset, SEEK_CUR); 162 return 1; 216 217 /* Some callers expect this function to "consume" fd 218 * even if data is not compressed. In this case, 219 * we return a state with trivial transformer. 220 */ 221 // USE_FOR_MMU(xstate->xformer = copy_stream;) 222 // USE_FOR_NOMMU(xstate->xformer_prog = "cat";) 163 223 164 224 found_magic: 225 return xstate; 226 } 227 228 /* Used by e.g. rpm which gives us a fd without filename, 229 * thus we can't guess the format from filename's extension. 230 */ 231 int FAST_FUNC setup_unzip_on_fd(int fd, int fail_if_not_compressed) 232 { 233 transformer_state_t *xstate = setup_transformer_on_fd(fd, fail_if_not_compressed); 234 235 if (!xstate || !xstate->xformer) { 236 free(xstate); 237 return 1; 238 } 239 165 240 # if BB_MMU 166 open_transformer_with_no_sig(fd,xformer);241 fork_transformer_with_no_sig(xstate->src_fd, xstate->xformer); 167 242 # else 168 /* NOMMU version of open_transformer execs243 /* NOMMU version of fork_transformer execs 169 244 * an external unzipper that wants 170 * file position at the start of the file */ 171 xlseek(fd, offset, SEEK_CUR); 172 open_transformer_with_sig(fd, xformer, xformer_prog); 245 * file position at the start of the file. 246 */ 247 xlseek(fd, - xstate->signature_skipped, SEEK_CUR); 248 xstate->signature_skipped = 0; 249 fork_transformer_with_sig(xstate->src_fd, xstate->xformer, xstate->xformer_prog); 173 250 # endif 251 free(xstate); 174 252 return 0; 175 253 } 176 254 177 int FAST_FUNC open_zipped(const char *fname)178 { 179 char *sfx;255 static transformer_state_t *open_transformer(const char *fname, int fail_if_not_compressed) 256 { 257 transformer_state_t *xstate; 180 258 int fd; 181 259 182 260 fd = open(fname, O_RDONLY); 183 261 if (fd < 0) 184 return fd; 185 186 sfx = strrchr(fname, '.'); 187 if (sfx) { 188 sfx++; 189 if (ENABLE_FEATURE_SEAMLESS_LZMA && strcmp(sfx, "lzma") == 0) 190 /* .lzma has no header/signature, just trust it */ 191 open_transformer_with_sig(fd, unpack_lzma_stream, "unlzma"); 192 else 193 if ((ENABLE_FEATURE_SEAMLESS_GZ && strcmp(sfx, "gz") == 0) 194 || (ENABLE_FEATURE_SEAMLESS_BZ2 && strcmp(sfx, "bz2") == 0) 195 || (ENABLE_FEATURE_SEAMLESS_XZ && strcmp(sfx, "xz") == 0) 196 ) { 197 setup_unzip_on_fd(fd, /*fail_if_not_detected:*/ 1); 198 } 199 } 200 262 return NULL; 263 264 if (ENABLE_FEATURE_SEAMLESS_LZMA) { 265 /* .lzma has no header/signature, can only detect it by extension */ 266 char *sfx = strrchr(fname, '.'); 267 if (sfx && strcmp(sfx+1, "lzma") == 0) { 268 xstate = xzalloc(sizeof(*xstate)); 269 xstate->src_fd = fd; 270 xstate->xformer = unpack_lzma_stream; 271 USE_FOR_NOMMU(xstate->xformer_prog = "unlzma";) 272 return xstate; 273 } 274 } 275 276 xstate = setup_transformer_on_fd(fd, fail_if_not_compressed); 277 278 return xstate; 279 } 280 281 int FAST_FUNC open_zipped(const char *fname, int fail_if_not_compressed) 282 { 283 int fd; 284 transformer_state_t *xstate; 285 286 xstate = open_transformer(fname, fail_if_not_compressed); 287 if (!xstate) 288 return -1; 289 290 fd = xstate->src_fd; 291 # if BB_MMU 292 if (xstate->xformer) { 293 fork_transformer_with_no_sig(fd, xstate->xformer); 294 } else { 295 /* the file is not compressed */ 296 xlseek(fd, - xstate->signature_skipped, SEEK_CUR); 297 xstate->signature_skipped = 0; 298 } 299 # else 300 /* NOMMU can't avoid the seek :( */ 301 xlseek(fd, - xstate->signature_skipped, SEEK_CUR); 302 xstate->signature_skipped = 0; 303 if (xstate->xformer) { 304 fork_transformer_with_sig(fd, xstate->xformer, xstate->xformer_prog); 305 } /* else: the file is not compressed */ 306 # endif 307 308 free(xstate); 201 309 return fd; 202 310 } 203 311 204 #endif /* SEAMLESS_COMPRESSION */205 206 312 void* FAST_FUNC xmalloc_open_zipped_read_close(const char *fname, size_t *maxsz_p) 207 313 { 314 # if 1 315 transformer_state_t *xstate; 316 char *image; 317 318 xstate = open_transformer(fname, /*fail_if_not_compressed:*/ 0); 319 if (!xstate) /* file open error */ 320 return NULL; 321 322 image = NULL; 323 if (xstate->xformer) { 324 /* In-memory decompression */ 325 xstate->mem_output_size_max = maxsz_p ? *maxsz_p : (size_t)(INT_MAX - 4095); 326 xstate->xformer(xstate); 327 if (xstate->mem_output_buf) { 328 image = xstate->mem_output_buf; 329 if (maxsz_p) 330 *maxsz_p = xstate->mem_output_size; 331 } 332 } else { 333 /* File is not compressed */ 334 //FIXME: avoid seek 335 xlseek(xstate->src_fd, - xstate->signature_skipped, SEEK_CUR); 336 xstate->signature_skipped = 0; 337 image = xmalloc_read(xstate->src_fd, maxsz_p); 338 } 339 340 if (!image) 341 bb_perror_msg("read error from '%s'", fname); 342 close(xstate->src_fd); 343 free(xstate); 344 return image; 345 # else 346 /* This version forks a subprocess - much more expensive */ 208 347 int fd; 209 348 char *image; 210 349 211 fd = open_zipped(fname );350 fd = open_zipped(fname, /*fail_if_not_compressed:*/ 0); 212 351 if (fd < 0) 213 352 return NULL; … … 217 356 bb_perror_msg("read error from '%s'", fname); 218 357 close(fd); 219 220 358 return image; 221 } 359 # endif 360 } 361 362 #endif /* SEAMLESS_COMPRESSION */
Note:
See TracChangeset
for help on using the changeset viewer.