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/untgz.c | |
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/untgz.c')
-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 d748b69..3a30768 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" |