diff options
| author | Mark Adler <madler@alumni.caltech.edu> | 2011-09-09 23:23:45 -0700 |
|---|---|---|
| committer | Mark Adler <madler@alumni.caltech.edu> | 2011-09-09 23:23:45 -0700 |
| commit | 7a6955760ba950eb82f57929f8f6c9847c65f0af (patch) | |
| tree | e2cd657aca6d606e0b28bf57fe45e914717a334c /contrib/untgz | |
| parent | f0e76a6634eb26e3ddc6dfc6f2489553eff8c8f4 (diff) | |
| download | zlib-1.2.1.2.tar.gz zlib-1.2.1.2.tar.bz2 zlib-1.2.1.2.zip | |
zlib 1.2.1.2v1.2.1.2
Diffstat (limited to 'contrib/untgz')
| -rw-r--r-- | contrib/untgz/untgz.c | 135 |
1 files changed, 120 insertions, 15 deletions
diff --git a/contrib/untgz/untgz.c b/contrib/untgz/untgz.c index d748b690..3a30768b 100644 --- a/contrib/untgz/untgz.c +++ b/contrib/untgz/untgz.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * untgz.c -- Display contents and extract files from a gzip'd TAR file | 2 | * untgz.c -- Display contents and extract files from a gzip'd TAR file |
| 3 | * | 3 | * |
| 4 | * written by "Pedro A. Aranda Guti\irrez" <paag@tid.es> | 4 | * written by Pedro A. Aranda Gutierrez <paag@tid.es> |
| 5 | * adaptation to Unix by Jean-loup Gailly <jloup@gzip.org> | 5 | * adaptation to Unix by Jean-loup Gailly <jloup@gzip.org> |
| 6 | * various fixes by Cosmin Truta <cosmint@cs.ubbcluj.ro> | 6 | * various fixes by Cosmin Truta <cosmint@cs.ubbcluj.ro> |
| 7 | */ | 7 | */ |
| @@ -15,10 +15,10 @@ | |||
| 15 | #include "zlib.h" | 15 | #include "zlib.h" |
| 16 | 16 | ||
| 17 | #ifdef unix | 17 | #ifdef unix |
| 18 | # include <unistd.h> | 18 | # include <unistd.h> |
| 19 | #else | 19 | #else |
| 20 | # include <direct.h> | 20 | # include <direct.h> |
| 21 | # include <io.h> | 21 | # include <io.h> |
| 22 | #endif | 22 | #endif |
| 23 | 23 | ||
| 24 | #ifdef WIN32 | 24 | #ifdef WIN32 |
| @@ -28,8 +28,9 @@ | |||
| 28 | # endif | 28 | # endif |
| 29 | # define mkdir(dirname,mode) _mkdir(dirname) | 29 | # define mkdir(dirname,mode) _mkdir(dirname) |
| 30 | # ifdef _MSC_VER | 30 | # ifdef _MSC_VER |
| 31 | # define strdup(str) _strdup(str) | ||
| 32 | # define access(path,mode) _access(path,mode) | 31 | # define access(path,mode) _access(path,mode) |
| 32 | # define chmod(path,mode) _chmod(path,mode) | ||
| 33 | # define strdup(str) _strdup(str) | ||
| 33 | # endif | 34 | # endif |
| 34 | #else | 35 | #else |
| 35 | # include <utime.h> | 36 | # include <utime.h> |
| @@ -48,7 +49,21 @@ | |||
| 48 | #define FIFOTYPE '6' /* FIFO special */ | 49 | #define FIFOTYPE '6' /* FIFO special */ |
| 49 | #define CONTTYPE '7' /* reserved */ | 50 | #define CONTTYPE '7' /* reserved */ |
| 50 | 51 | ||
| 51 | #define BLOCKSIZE 512 | 52 | /* GNU tar extensions */ |
| 53 | |||
| 54 | #define GNUTYPE_DUMPDIR 'D' /* file names from dumped directory */ | ||
| 55 | #define GNUTYPE_LONGLINK 'K' /* long link name */ | ||
| 56 | #define GNUTYPE_LONGNAME 'L' /* long file name */ | ||
| 57 | #define GNUTYPE_MULTIVOL 'M' /* continuation of file from another volume */ | ||
| 58 | #define GNUTYPE_NAMES 'N' /* file name that does not fit into main hdr */ | ||
| 59 | #define GNUTYPE_SPARSE 'S' /* sparse file */ | ||
| 60 | #define GNUTYPE_VOLHDR 'V' /* tape/volume header */ | ||
| 61 | |||
| 62 | |||
| 63 | /* tar header */ | ||
| 64 | |||
| 65 | #define BLOCKSIZE 512 | ||
| 66 | #define SHORTNAMESIZE 100 | ||
| 52 | 67 | ||
| 53 | struct tar_header | 68 | struct tar_header |
| 54 | { /* byte offset */ | 69 | { /* byte offset */ |
| @@ -71,11 +86,20 @@ struct tar_header | |||
| 71 | /* 500 */ | 86 | /* 500 */ |
| 72 | }; | 87 | }; |
| 73 | 88 | ||
| 74 | union tar_buffer { | 89 | union tar_buffer |
| 90 | { | ||
| 75 | char buffer[BLOCKSIZE]; | 91 | char buffer[BLOCKSIZE]; |
| 76 | struct tar_header header; | 92 | struct tar_header header; |
| 77 | }; | 93 | }; |
| 78 | 94 | ||
| 95 | struct attr_item | ||
| 96 | { | ||
| 97 | struct attr_item *next; | ||
| 98 | char *fname; | ||
| 99 | int mode; | ||
| 100 | time_t time; | ||
| 101 | }; | ||
| 102 | |||
| 79 | enum { TGZ_EXTRACT, TGZ_LIST, TGZ_INVALID }; | 103 | enum { TGZ_EXTRACT, TGZ_LIST, TGZ_INVALID }; |
| 80 | 104 | ||
| 81 | char *TGZfname OF((const char *)); | 105 | char *TGZfname OF((const char *)); |
| @@ -84,6 +108,9 @@ void TGZnotfound OF((const char *)); | |||
| 84 | int getoct OF((char *, int)); | 108 | int getoct OF((char *, int)); |
| 85 | char *strtime OF((time_t *)); | 109 | char *strtime OF((time_t *)); |
| 86 | int setfiletime OF((char *, time_t)); | 110 | int setfiletime OF((char *, time_t)); |
| 111 | void push_attr OF((struct attr_item **, char *, int, time_t)); | ||
| 112 | void restore_attr OF((struct attr_item **)); | ||
| 113 | |||
| 87 | int ExprMatch OF((char *, char *)); | 114 | int ExprMatch OF((char *, char *)); |
| 88 | 115 | ||
| 89 | int makedir OF((char *)); | 116 | int makedir OF((char *)); |
| @@ -221,7 +248,42 @@ int setfiletime (char *fname,time_t ftime) | |||
| 221 | } | 248 | } |
| 222 | 249 | ||
| 223 | 250 | ||
| 224 | /* regular expression matching */ | 251 | /* push file attributes */ |
| 252 | |||
| 253 | void push_attr(struct attr_item **list,char *fname,int mode,time_t time) | ||
| 254 | { | ||
| 255 | struct attr_item *item; | ||
| 256 | |||
| 257 | item = (struct attr_item *)malloc(sizeof(struct attr_item)); | ||
| 258 | if (item == NULL) | ||
| 259 | error("Out of memory"); | ||
| 260 | item->fname = strdup(fname); | ||
| 261 | item->mode = mode; | ||
| 262 | item->time = time; | ||
| 263 | item->next = *list; | ||
| 264 | *list = item; | ||
| 265 | } | ||
| 266 | |||
| 267 | |||
| 268 | /* restore file attributes */ | ||
| 269 | |||
| 270 | void restore_attr(struct attr_item **list) | ||
| 271 | { | ||
| 272 | struct attr_item *item, *prev; | ||
| 273 | |||
| 274 | for (item = *list; item != NULL; ) | ||
| 275 | { | ||
| 276 | setfiletime(item->fname,item->time); | ||
| 277 | chmod(item->fname,item->mode); | ||
| 278 | prev = item; | ||
| 279 | item = item->next; | ||
| 280 | free(prev); | ||
| 281 | } | ||
| 282 | *list = NULL; | ||
| 283 | } | ||
| 284 | |||
| 285 | |||
| 286 | /* match regular expression */ | ||
| 225 | 287 | ||
| 226 | #define ISSPECIAL(c) (((c) == '*') || ((c) == '/')) | 288 | #define ISSPECIAL(c) (((c) == '*') || ((c) == '/')) |
| 227 | 289 | ||
| @@ -332,6 +394,7 @@ int tar (gzFile in,int action,int arg,int argc,char **argv) | |||
| 332 | char fname[BLOCKSIZE]; | 394 | char fname[BLOCKSIZE]; |
| 333 | int tarmode; | 395 | int tarmode; |
| 334 | time_t tartime; | 396 | time_t tartime; |
| 397 | struct attr_item *attributes = NULL; | ||
| 335 | 398 | ||
| 336 | if (action == TGZ_LIST) | 399 | if (action == TGZ_LIST) |
| 337 | printf(" date time size file\n" | 400 | printf(" date time size file\n" |
| @@ -354,14 +417,15 @@ int tar (gzFile in,int action,int arg,int argc,char **argv) | |||
| 354 | /* | 417 | /* |
| 355 | * If we have to get a tar header | 418 | * If we have to get a tar header |
| 356 | */ | 419 | */ |
| 357 | if (getheader == 1) | 420 | if (getheader >= 1) |
| 358 | { | 421 | { |
| 359 | /* | 422 | /* |
| 360 | * if we met the end of the tar | 423 | * if we met the end of the tar |
| 361 | * or the end-of-tar block, | 424 | * or the end-of-tar block, |
| 362 | * we are done | 425 | * we are done |
| 363 | */ | 426 | */ |
| 364 | if ((len == 0) || (buffer.header.name[0] == 0)) break; | 427 | if (len == 0 || buffer.header.name[0] == 0) |
| 428 | break; | ||
| 365 | 429 | ||
| 366 | tarmode = getoct(buffer.header.mode,8); | 430 | tarmode = getoct(buffer.header.mode,8); |
| 367 | tartime = (time_t)getoct(buffer.header.mtime,12); | 431 | tartime = (time_t)getoct(buffer.header.mtime,12); |
| @@ -371,8 +435,25 @@ int tar (gzFile in,int action,int arg,int argc,char **argv) | |||
| 371 | action = TGZ_INVALID; | 435 | action = TGZ_INVALID; |
| 372 | } | 436 | } |
| 373 | 437 | ||
| 374 | strcpy(fname,buffer.header.name); | 438 | if (getheader == 1) |
| 439 | { | ||
| 440 | strncpy(fname,buffer.header.name,SHORTNAMESIZE); | ||
| 441 | if (fname[SHORTNAMESIZE-1] != 0) | ||
| 442 | fname[SHORTNAMESIZE] = 0; | ||
| 443 | } | ||
| 444 | else | ||
| 445 | { | ||
| 446 | /* | ||
| 447 | * The file name is longer than SHORTNAMESIZE | ||
| 448 | */ | ||
| 449 | if (strncmp(fname,buffer.header.name,SHORTNAMESIZE-1) != 0) | ||
| 450 | error("bad long name"); | ||
| 451 | getheader = 1; | ||
| 452 | } | ||
| 375 | 453 | ||
| 454 | /* | ||
| 455 | * Act according to the type flag | ||
| 456 | */ | ||
| 376 | switch (buffer.header.typeflag) | 457 | switch (buffer.header.typeflag) |
| 377 | { | 458 | { |
| 378 | case DIRTYPE: | 459 | case DIRTYPE: |
| @@ -381,7 +462,7 @@ int tar (gzFile in,int action,int arg,int argc,char **argv) | |||
| 381 | if (action == TGZ_EXTRACT) | 462 | if (action == TGZ_EXTRACT) |
| 382 | { | 463 | { |
| 383 | makedir(fname); | 464 | makedir(fname); |
| 384 | setfiletime(fname,tartime); | 465 | push_attr(&attributes,fname,tarmode,tartime); |
| 385 | } | 466 | } |
| 386 | break; | 467 | break; |
| 387 | case REGTYPE: | 468 | case REGTYPE: |
| @@ -419,6 +500,24 @@ int tar (gzFile in,int action,int arg,int argc,char **argv) | |||
| 419 | } | 500 | } |
| 420 | getheader = 0; | 501 | getheader = 0; |
| 421 | break; | 502 | break; |
| 503 | case GNUTYPE_LONGLINK: | ||
| 504 | case GNUTYPE_LONGNAME: | ||
| 505 | remaining = getoct(buffer.header.size,12); | ||
| 506 | if (remaining < 0 || remaining >= BLOCKSIZE) | ||
| 507 | { | ||
| 508 | action = TGZ_INVALID; | ||
| 509 | break; | ||
| 510 | } | ||
| 511 | len = gzread(in, fname, BLOCKSIZE); | ||
| 512 | if (len < 0) | ||
| 513 | error(gzerror(in, &err)); | ||
| 514 | if (fname[BLOCKSIZE-1] != 0 || (int)strlen(fname) > remaining) | ||
| 515 | { | ||
| 516 | action = TGZ_INVALID; | ||
| 517 | break; | ||
| 518 | } | ||
| 519 | getheader = 2; | ||
| 520 | break; | ||
| 422 | default: | 521 | default: |
| 423 | if (action == TGZ_LIST) | 522 | if (action == TGZ_LIST) |
| 424 | printf(" %s <---> %s\n",strtime(&tartime),fname); | 523 | printf(" %s <---> %s\n",strtime(&tartime),fname); |
| @@ -433,7 +532,8 @@ int tar (gzFile in,int action,int arg,int argc,char **argv) | |||
| 433 | { | 532 | { |
| 434 | if (fwrite(&buffer,sizeof(char),bytes,outfile) != bytes) | 533 | if (fwrite(&buffer,sizeof(char),bytes,outfile) != bytes) |
| 435 | { | 534 | { |
| 436 | fprintf(stderr,"%s: Error writing %s -- skipping\n",prog,fname); | 535 | fprintf(stderr, |
| 536 | "%s: Error writing %s -- skipping\n",prog,fname); | ||
| 437 | fclose(outfile); | 537 | fclose(outfile); |
| 438 | outfile = NULL; | 538 | outfile = NULL; |
| 439 | remove(fname); | 539 | remove(fname); |
| @@ -450,7 +550,7 @@ int tar (gzFile in,int action,int arg,int argc,char **argv) | |||
| 450 | fclose(outfile); | 550 | fclose(outfile); |
| 451 | outfile = NULL; | 551 | outfile = NULL; |
| 452 | if (action != TGZ_INVALID) | 552 | if (action != TGZ_INVALID) |
| 453 | setfiletime(fname,tartime); | 553 | push_attr(&attributes,fname,tarmode,tartime); |
| 454 | } | 554 | } |
| 455 | } | 555 | } |
| 456 | 556 | ||
| @@ -464,6 +564,11 @@ int tar (gzFile in,int action,int arg,int argc,char **argv) | |||
| 464 | } | 564 | } |
| 465 | } | 565 | } |
| 466 | 566 | ||
| 567 | /* | ||
| 568 | * Restore file modes and time stamps | ||
| 569 | */ | ||
| 570 | restore_attr(&attributes); | ||
| 571 | |||
| 467 | if (gzclose(in) != Z_OK) | 572 | if (gzclose(in) != Z_OK) |
| 468 | error("failed gzclose"); | 573 | error("failed gzclose"); |
| 469 | 574 | ||
| @@ -475,7 +580,7 @@ int tar (gzFile in,int action,int arg,int argc,char **argv) | |||
| 475 | 580 | ||
| 476 | void help(int exitval) | 581 | void help(int exitval) |
| 477 | { | 582 | { |
| 478 | printf("untgz version 0.2\n" | 583 | printf("untgz version 0.2.1\n" |
| 479 | " using zlib version %s\n\n", | 584 | " using zlib version %s\n\n", |
| 480 | zlibVersion()); | 585 | zlibVersion()); |
| 481 | printf("Usage: untgz file.tgz extract all files\n" | 586 | printf("Usage: untgz file.tgz extract all files\n" |
