annotate src/zlib-1.2.8/contrib/untgz/untgz.c @ 79:91c729825bca pa_catalina

Update build for AUDIO_COMPONENT_FIX
author Chris Cannam
date Wed, 30 Oct 2019 12:40:34 +0000
parents 5ea0608b923f
children
rev   line source
Chris@43 1 /*
Chris@43 2 * untgz.c -- Display contents and extract files from a gzip'd TAR file
Chris@43 3 *
Chris@43 4 * written by Pedro A. Aranda Gutierrez <paag@tid.es>
Chris@43 5 * adaptation to Unix by Jean-loup Gailly <jloup@gzip.org>
Chris@43 6 * various fixes by Cosmin Truta <cosmint@cs.ubbcluj.ro>
Chris@43 7 */
Chris@43 8
Chris@43 9 #include <stdio.h>
Chris@43 10 #include <stdlib.h>
Chris@43 11 #include <string.h>
Chris@43 12 #include <time.h>
Chris@43 13 #include <errno.h>
Chris@43 14
Chris@43 15 #include "zlib.h"
Chris@43 16
Chris@43 17 #ifdef unix
Chris@43 18 # include <unistd.h>
Chris@43 19 #else
Chris@43 20 # include <direct.h>
Chris@43 21 # include <io.h>
Chris@43 22 #endif
Chris@43 23
Chris@43 24 #ifdef WIN32
Chris@43 25 #include <windows.h>
Chris@43 26 # ifndef F_OK
Chris@43 27 # define F_OK 0
Chris@43 28 # endif
Chris@43 29 # define mkdir(dirname,mode) _mkdir(dirname)
Chris@43 30 # ifdef _MSC_VER
Chris@43 31 # define access(path,mode) _access(path,mode)
Chris@43 32 # define chmod(path,mode) _chmod(path,mode)
Chris@43 33 # define strdup(str) _strdup(str)
Chris@43 34 # endif
Chris@43 35 #else
Chris@43 36 # include <utime.h>
Chris@43 37 #endif
Chris@43 38
Chris@43 39
Chris@43 40 /* values used in typeflag field */
Chris@43 41
Chris@43 42 #define REGTYPE '0' /* regular file */
Chris@43 43 #define AREGTYPE '\0' /* regular file */
Chris@43 44 #define LNKTYPE '1' /* link */
Chris@43 45 #define SYMTYPE '2' /* reserved */
Chris@43 46 #define CHRTYPE '3' /* character special */
Chris@43 47 #define BLKTYPE '4' /* block special */
Chris@43 48 #define DIRTYPE '5' /* directory */
Chris@43 49 #define FIFOTYPE '6' /* FIFO special */
Chris@43 50 #define CONTTYPE '7' /* reserved */
Chris@43 51
Chris@43 52 /* GNU tar extensions */
Chris@43 53
Chris@43 54 #define GNUTYPE_DUMPDIR 'D' /* file names from dumped directory */
Chris@43 55 #define GNUTYPE_LONGLINK 'K' /* long link name */
Chris@43 56 #define GNUTYPE_LONGNAME 'L' /* long file name */
Chris@43 57 #define GNUTYPE_MULTIVOL 'M' /* continuation of file from another volume */
Chris@43 58 #define GNUTYPE_NAMES 'N' /* file name that does not fit into main hdr */
Chris@43 59 #define GNUTYPE_SPARSE 'S' /* sparse file */
Chris@43 60 #define GNUTYPE_VOLHDR 'V' /* tape/volume header */
Chris@43 61
Chris@43 62
Chris@43 63 /* tar header */
Chris@43 64
Chris@43 65 #define BLOCKSIZE 512
Chris@43 66 #define SHORTNAMESIZE 100
Chris@43 67
Chris@43 68 struct tar_header
Chris@43 69 { /* byte offset */
Chris@43 70 char name[100]; /* 0 */
Chris@43 71 char mode[8]; /* 100 */
Chris@43 72 char uid[8]; /* 108 */
Chris@43 73 char gid[8]; /* 116 */
Chris@43 74 char size[12]; /* 124 */
Chris@43 75 char mtime[12]; /* 136 */
Chris@43 76 char chksum[8]; /* 148 */
Chris@43 77 char typeflag; /* 156 */
Chris@43 78 char linkname[100]; /* 157 */
Chris@43 79 char magic[6]; /* 257 */
Chris@43 80 char version[2]; /* 263 */
Chris@43 81 char uname[32]; /* 265 */
Chris@43 82 char gname[32]; /* 297 */
Chris@43 83 char devmajor[8]; /* 329 */
Chris@43 84 char devminor[8]; /* 337 */
Chris@43 85 char prefix[155]; /* 345 */
Chris@43 86 /* 500 */
Chris@43 87 };
Chris@43 88
Chris@43 89 union tar_buffer
Chris@43 90 {
Chris@43 91 char buffer[BLOCKSIZE];
Chris@43 92 struct tar_header header;
Chris@43 93 };
Chris@43 94
Chris@43 95 struct attr_item
Chris@43 96 {
Chris@43 97 struct attr_item *next;
Chris@43 98 char *fname;
Chris@43 99 int mode;
Chris@43 100 time_t time;
Chris@43 101 };
Chris@43 102
Chris@43 103 enum { TGZ_EXTRACT, TGZ_LIST, TGZ_INVALID };
Chris@43 104
Chris@43 105 char *TGZfname OF((const char *));
Chris@43 106 void TGZnotfound OF((const char *));
Chris@43 107
Chris@43 108 int getoct OF((char *, int));
Chris@43 109 char *strtime OF((time_t *));
Chris@43 110 int setfiletime OF((char *, time_t));
Chris@43 111 void push_attr OF((struct attr_item **, char *, int, time_t));
Chris@43 112 void restore_attr OF((struct attr_item **));
Chris@43 113
Chris@43 114 int ExprMatch OF((char *, char *));
Chris@43 115
Chris@43 116 int makedir OF((char *));
Chris@43 117 int matchname OF((int, int, char **, char *));
Chris@43 118
Chris@43 119 void error OF((const char *));
Chris@43 120 int tar OF((gzFile, int, int, int, char **));
Chris@43 121
Chris@43 122 void help OF((int));
Chris@43 123 int main OF((int, char **));
Chris@43 124
Chris@43 125 char *prog;
Chris@43 126
Chris@43 127 const char *TGZsuffix[] = { "\0", ".tar", ".tar.gz", ".taz", ".tgz", NULL };
Chris@43 128
Chris@43 129 /* return the file name of the TGZ archive */
Chris@43 130 /* or NULL if it does not exist */
Chris@43 131
Chris@43 132 char *TGZfname (const char *arcname)
Chris@43 133 {
Chris@43 134 static char buffer[1024];
Chris@43 135 int origlen,i;
Chris@43 136
Chris@43 137 strcpy(buffer,arcname);
Chris@43 138 origlen = strlen(buffer);
Chris@43 139
Chris@43 140 for (i=0; TGZsuffix[i]; i++)
Chris@43 141 {
Chris@43 142 strcpy(buffer+origlen,TGZsuffix[i]);
Chris@43 143 if (access(buffer,F_OK) == 0)
Chris@43 144 return buffer;
Chris@43 145 }
Chris@43 146 return NULL;
Chris@43 147 }
Chris@43 148
Chris@43 149
Chris@43 150 /* error message for the filename */
Chris@43 151
Chris@43 152 void TGZnotfound (const char *arcname)
Chris@43 153 {
Chris@43 154 int i;
Chris@43 155
Chris@43 156 fprintf(stderr,"%s: Couldn't find ",prog);
Chris@43 157 for (i=0;TGZsuffix[i];i++)
Chris@43 158 fprintf(stderr,(TGZsuffix[i+1]) ? "%s%s, " : "or %s%s\n",
Chris@43 159 arcname,
Chris@43 160 TGZsuffix[i]);
Chris@43 161 exit(1);
Chris@43 162 }
Chris@43 163
Chris@43 164
Chris@43 165 /* convert octal digits to int */
Chris@43 166 /* on error return -1 */
Chris@43 167
Chris@43 168 int getoct (char *p,int width)
Chris@43 169 {
Chris@43 170 int result = 0;
Chris@43 171 char c;
Chris@43 172
Chris@43 173 while (width--)
Chris@43 174 {
Chris@43 175 c = *p++;
Chris@43 176 if (c == 0)
Chris@43 177 break;
Chris@43 178 if (c == ' ')
Chris@43 179 continue;
Chris@43 180 if (c < '0' || c > '7')
Chris@43 181 return -1;
Chris@43 182 result = result * 8 + (c - '0');
Chris@43 183 }
Chris@43 184 return result;
Chris@43 185 }
Chris@43 186
Chris@43 187
Chris@43 188 /* convert time_t to string */
Chris@43 189 /* use the "YYYY/MM/DD hh:mm:ss" format */
Chris@43 190
Chris@43 191 char *strtime (time_t *t)
Chris@43 192 {
Chris@43 193 struct tm *local;
Chris@43 194 static char result[32];
Chris@43 195
Chris@43 196 local = localtime(t);
Chris@43 197 sprintf(result,"%4d/%02d/%02d %02d:%02d:%02d",
Chris@43 198 local->tm_year+1900, local->tm_mon+1, local->tm_mday,
Chris@43 199 local->tm_hour, local->tm_min, local->tm_sec);
Chris@43 200 return result;
Chris@43 201 }
Chris@43 202
Chris@43 203
Chris@43 204 /* set file time */
Chris@43 205
Chris@43 206 int setfiletime (char *fname,time_t ftime)
Chris@43 207 {
Chris@43 208 #ifdef WIN32
Chris@43 209 static int isWinNT = -1;
Chris@43 210 SYSTEMTIME st;
Chris@43 211 FILETIME locft, modft;
Chris@43 212 struct tm *loctm;
Chris@43 213 HANDLE hFile;
Chris@43 214 int result;
Chris@43 215
Chris@43 216 loctm = localtime(&ftime);
Chris@43 217 if (loctm == NULL)
Chris@43 218 return -1;
Chris@43 219
Chris@43 220 st.wYear = (WORD)loctm->tm_year + 1900;
Chris@43 221 st.wMonth = (WORD)loctm->tm_mon + 1;
Chris@43 222 st.wDayOfWeek = (WORD)loctm->tm_wday;
Chris@43 223 st.wDay = (WORD)loctm->tm_mday;
Chris@43 224 st.wHour = (WORD)loctm->tm_hour;
Chris@43 225 st.wMinute = (WORD)loctm->tm_min;
Chris@43 226 st.wSecond = (WORD)loctm->tm_sec;
Chris@43 227 st.wMilliseconds = 0;
Chris@43 228 if (!SystemTimeToFileTime(&st, &locft) ||
Chris@43 229 !LocalFileTimeToFileTime(&locft, &modft))
Chris@43 230 return -1;
Chris@43 231
Chris@43 232 if (isWinNT < 0)
Chris@43 233 isWinNT = (GetVersion() < 0x80000000) ? 1 : 0;
Chris@43 234 hFile = CreateFile(fname, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
Chris@43 235 (isWinNT ? FILE_FLAG_BACKUP_SEMANTICS : 0),
Chris@43 236 NULL);
Chris@43 237 if (hFile == INVALID_HANDLE_VALUE)
Chris@43 238 return -1;
Chris@43 239 result = SetFileTime(hFile, NULL, NULL, &modft) ? 0 : -1;
Chris@43 240 CloseHandle(hFile);
Chris@43 241 return result;
Chris@43 242 #else
Chris@43 243 struct utimbuf settime;
Chris@43 244
Chris@43 245 settime.actime = settime.modtime = ftime;
Chris@43 246 return utime(fname,&settime);
Chris@43 247 #endif
Chris@43 248 }
Chris@43 249
Chris@43 250
Chris@43 251 /* push file attributes */
Chris@43 252
Chris@43 253 void push_attr(struct attr_item **list,char *fname,int mode,time_t time)
Chris@43 254 {
Chris@43 255 struct attr_item *item;
Chris@43 256
Chris@43 257 item = (struct attr_item *)malloc(sizeof(struct attr_item));
Chris@43 258 if (item == NULL)
Chris@43 259 error("Out of memory");
Chris@43 260 item->fname = strdup(fname);
Chris@43 261 item->mode = mode;
Chris@43 262 item->time = time;
Chris@43 263 item->next = *list;
Chris@43 264 *list = item;
Chris@43 265 }
Chris@43 266
Chris@43 267
Chris@43 268 /* restore file attributes */
Chris@43 269
Chris@43 270 void restore_attr(struct attr_item **list)
Chris@43 271 {
Chris@43 272 struct attr_item *item, *prev;
Chris@43 273
Chris@43 274 for (item = *list; item != NULL; )
Chris@43 275 {
Chris@43 276 setfiletime(item->fname,item->time);
Chris@43 277 chmod(item->fname,item->mode);
Chris@43 278 prev = item;
Chris@43 279 item = item->next;
Chris@43 280 free(prev);
Chris@43 281 }
Chris@43 282 *list = NULL;
Chris@43 283 }
Chris@43 284
Chris@43 285
Chris@43 286 /* match regular expression */
Chris@43 287
Chris@43 288 #define ISSPECIAL(c) (((c) == '*') || ((c) == '/'))
Chris@43 289
Chris@43 290 int ExprMatch (char *string,char *expr)
Chris@43 291 {
Chris@43 292 while (1)
Chris@43 293 {
Chris@43 294 if (ISSPECIAL(*expr))
Chris@43 295 {
Chris@43 296 if (*expr == '/')
Chris@43 297 {
Chris@43 298 if (*string != '\\' && *string != '/')
Chris@43 299 return 0;
Chris@43 300 string ++; expr++;
Chris@43 301 }
Chris@43 302 else if (*expr == '*')
Chris@43 303 {
Chris@43 304 if (*expr ++ == 0)
Chris@43 305 return 1;
Chris@43 306 while (*++string != *expr)
Chris@43 307 if (*string == 0)
Chris@43 308 return 0;
Chris@43 309 }
Chris@43 310 }
Chris@43 311 else
Chris@43 312 {
Chris@43 313 if (*string != *expr)
Chris@43 314 return 0;
Chris@43 315 if (*expr++ == 0)
Chris@43 316 return 1;
Chris@43 317 string++;
Chris@43 318 }
Chris@43 319 }
Chris@43 320 }
Chris@43 321
Chris@43 322
Chris@43 323 /* recursive mkdir */
Chris@43 324 /* abort on ENOENT; ignore other errors like "directory already exists" */
Chris@43 325 /* return 1 if OK */
Chris@43 326 /* 0 on error */
Chris@43 327
Chris@43 328 int makedir (char *newdir)
Chris@43 329 {
Chris@43 330 char *buffer = strdup(newdir);
Chris@43 331 char *p;
Chris@43 332 int len = strlen(buffer);
Chris@43 333
Chris@43 334 if (len <= 0) {
Chris@43 335 free(buffer);
Chris@43 336 return 0;
Chris@43 337 }
Chris@43 338 if (buffer[len-1] == '/') {
Chris@43 339 buffer[len-1] = '\0';
Chris@43 340 }
Chris@43 341 if (mkdir(buffer, 0755) == 0)
Chris@43 342 {
Chris@43 343 free(buffer);
Chris@43 344 return 1;
Chris@43 345 }
Chris@43 346
Chris@43 347 p = buffer+1;
Chris@43 348 while (1)
Chris@43 349 {
Chris@43 350 char hold;
Chris@43 351
Chris@43 352 while(*p && *p != '\\' && *p != '/')
Chris@43 353 p++;
Chris@43 354 hold = *p;
Chris@43 355 *p = 0;
Chris@43 356 if ((mkdir(buffer, 0755) == -1) && (errno == ENOENT))
Chris@43 357 {
Chris@43 358 fprintf(stderr,"%s: Couldn't create directory %s\n",prog,buffer);
Chris@43 359 free(buffer);
Chris@43 360 return 0;
Chris@43 361 }
Chris@43 362 if (hold == 0)
Chris@43 363 break;
Chris@43 364 *p++ = hold;
Chris@43 365 }
Chris@43 366 free(buffer);
Chris@43 367 return 1;
Chris@43 368 }
Chris@43 369
Chris@43 370
Chris@43 371 int matchname (int arg,int argc,char **argv,char *fname)
Chris@43 372 {
Chris@43 373 if (arg == argc) /* no arguments given (untgz tgzarchive) */
Chris@43 374 return 1;
Chris@43 375
Chris@43 376 while (arg < argc)
Chris@43 377 if (ExprMatch(fname,argv[arg++]))
Chris@43 378 return 1;
Chris@43 379
Chris@43 380 return 0; /* ignore this for the moment being */
Chris@43 381 }
Chris@43 382
Chris@43 383
Chris@43 384 /* tar file list or extract */
Chris@43 385
Chris@43 386 int tar (gzFile in,int action,int arg,int argc,char **argv)
Chris@43 387 {
Chris@43 388 union tar_buffer buffer;
Chris@43 389 int len;
Chris@43 390 int err;
Chris@43 391 int getheader = 1;
Chris@43 392 int remaining = 0;
Chris@43 393 FILE *outfile = NULL;
Chris@43 394 char fname[BLOCKSIZE];
Chris@43 395 int tarmode;
Chris@43 396 time_t tartime;
Chris@43 397 struct attr_item *attributes = NULL;
Chris@43 398
Chris@43 399 if (action == TGZ_LIST)
Chris@43 400 printf(" date time size file\n"
Chris@43 401 " ---------- -------- --------- -------------------------------------\n");
Chris@43 402 while (1)
Chris@43 403 {
Chris@43 404 len = gzread(in, &buffer, BLOCKSIZE);
Chris@43 405 if (len < 0)
Chris@43 406 error(gzerror(in, &err));
Chris@43 407 /*
Chris@43 408 * Always expect complete blocks to process
Chris@43 409 * the tar information.
Chris@43 410 */
Chris@43 411 if (len != BLOCKSIZE)
Chris@43 412 {
Chris@43 413 action = TGZ_INVALID; /* force error exit */
Chris@43 414 remaining = 0; /* force I/O cleanup */
Chris@43 415 }
Chris@43 416
Chris@43 417 /*
Chris@43 418 * If we have to get a tar header
Chris@43 419 */
Chris@43 420 if (getheader >= 1)
Chris@43 421 {
Chris@43 422 /*
Chris@43 423 * if we met the end of the tar
Chris@43 424 * or the end-of-tar block,
Chris@43 425 * we are done
Chris@43 426 */
Chris@43 427 if (len == 0 || buffer.header.name[0] == 0)
Chris@43 428 break;
Chris@43 429
Chris@43 430 tarmode = getoct(buffer.header.mode,8);
Chris@43 431 tartime = (time_t)getoct(buffer.header.mtime,12);
Chris@43 432 if (tarmode == -1 || tartime == (time_t)-1)
Chris@43 433 {
Chris@43 434 buffer.header.name[0] = 0;
Chris@43 435 action = TGZ_INVALID;
Chris@43 436 }
Chris@43 437
Chris@43 438 if (getheader == 1)
Chris@43 439 {
Chris@43 440 strncpy(fname,buffer.header.name,SHORTNAMESIZE);
Chris@43 441 if (fname[SHORTNAMESIZE-1] != 0)
Chris@43 442 fname[SHORTNAMESIZE] = 0;
Chris@43 443 }
Chris@43 444 else
Chris@43 445 {
Chris@43 446 /*
Chris@43 447 * The file name is longer than SHORTNAMESIZE
Chris@43 448 */
Chris@43 449 if (strncmp(fname,buffer.header.name,SHORTNAMESIZE-1) != 0)
Chris@43 450 error("bad long name");
Chris@43 451 getheader = 1;
Chris@43 452 }
Chris@43 453
Chris@43 454 /*
Chris@43 455 * Act according to the type flag
Chris@43 456 */
Chris@43 457 switch (buffer.header.typeflag)
Chris@43 458 {
Chris@43 459 case DIRTYPE:
Chris@43 460 if (action == TGZ_LIST)
Chris@43 461 printf(" %s <dir> %s\n",strtime(&tartime),fname);
Chris@43 462 if (action == TGZ_EXTRACT)
Chris@43 463 {
Chris@43 464 makedir(fname);
Chris@43 465 push_attr(&attributes,fname,tarmode,tartime);
Chris@43 466 }
Chris@43 467 break;
Chris@43 468 case REGTYPE:
Chris@43 469 case AREGTYPE:
Chris@43 470 remaining = getoct(buffer.header.size,12);
Chris@43 471 if (remaining == -1)
Chris@43 472 {
Chris@43 473 action = TGZ_INVALID;
Chris@43 474 break;
Chris@43 475 }
Chris@43 476 if (action == TGZ_LIST)
Chris@43 477 printf(" %s %9d %s\n",strtime(&tartime),remaining,fname);
Chris@43 478 else if (action == TGZ_EXTRACT)
Chris@43 479 {
Chris@43 480 if (matchname(arg,argc,argv,fname))
Chris@43 481 {
Chris@43 482 outfile = fopen(fname,"wb");
Chris@43 483 if (outfile == NULL) {
Chris@43 484 /* try creating directory */
Chris@43 485 char *p = strrchr(fname, '/');
Chris@43 486 if (p != NULL) {
Chris@43 487 *p = '\0';
Chris@43 488 makedir(fname);
Chris@43 489 *p = '/';
Chris@43 490 outfile = fopen(fname,"wb");
Chris@43 491 }
Chris@43 492 }
Chris@43 493 if (outfile != NULL)
Chris@43 494 printf("Extracting %s\n",fname);
Chris@43 495 else
Chris@43 496 fprintf(stderr, "%s: Couldn't create %s",prog,fname);
Chris@43 497 }
Chris@43 498 else
Chris@43 499 outfile = NULL;
Chris@43 500 }
Chris@43 501 getheader = 0;
Chris@43 502 break;
Chris@43 503 case GNUTYPE_LONGLINK:
Chris@43 504 case GNUTYPE_LONGNAME:
Chris@43 505 remaining = getoct(buffer.header.size,12);
Chris@43 506 if (remaining < 0 || remaining >= BLOCKSIZE)
Chris@43 507 {
Chris@43 508 action = TGZ_INVALID;
Chris@43 509 break;
Chris@43 510 }
Chris@43 511 len = gzread(in, fname, BLOCKSIZE);
Chris@43 512 if (len < 0)
Chris@43 513 error(gzerror(in, &err));
Chris@43 514 if (fname[BLOCKSIZE-1] != 0 || (int)strlen(fname) > remaining)
Chris@43 515 {
Chris@43 516 action = TGZ_INVALID;
Chris@43 517 break;
Chris@43 518 }
Chris@43 519 getheader = 2;
Chris@43 520 break;
Chris@43 521 default:
Chris@43 522 if (action == TGZ_LIST)
Chris@43 523 printf(" %s <---> %s\n",strtime(&tartime),fname);
Chris@43 524 break;
Chris@43 525 }
Chris@43 526 }
Chris@43 527 else
Chris@43 528 {
Chris@43 529 unsigned int bytes = (remaining > BLOCKSIZE) ? BLOCKSIZE : remaining;
Chris@43 530
Chris@43 531 if (outfile != NULL)
Chris@43 532 {
Chris@43 533 if (fwrite(&buffer,sizeof(char),bytes,outfile) != bytes)
Chris@43 534 {
Chris@43 535 fprintf(stderr,
Chris@43 536 "%s: Error writing %s -- skipping\n",prog,fname);
Chris@43 537 fclose(outfile);
Chris@43 538 outfile = NULL;
Chris@43 539 remove(fname);
Chris@43 540 }
Chris@43 541 }
Chris@43 542 remaining -= bytes;
Chris@43 543 }
Chris@43 544
Chris@43 545 if (remaining == 0)
Chris@43 546 {
Chris@43 547 getheader = 1;
Chris@43 548 if (outfile != NULL)
Chris@43 549 {
Chris@43 550 fclose(outfile);
Chris@43 551 outfile = NULL;
Chris@43 552 if (action != TGZ_INVALID)
Chris@43 553 push_attr(&attributes,fname,tarmode,tartime);
Chris@43 554 }
Chris@43 555 }
Chris@43 556
Chris@43 557 /*
Chris@43 558 * Abandon if errors are found
Chris@43 559 */
Chris@43 560 if (action == TGZ_INVALID)
Chris@43 561 {
Chris@43 562 error("broken archive");
Chris@43 563 break;
Chris@43 564 }
Chris@43 565 }
Chris@43 566
Chris@43 567 /*
Chris@43 568 * Restore file modes and time stamps
Chris@43 569 */
Chris@43 570 restore_attr(&attributes);
Chris@43 571
Chris@43 572 if (gzclose(in) != Z_OK)
Chris@43 573 error("failed gzclose");
Chris@43 574
Chris@43 575 return 0;
Chris@43 576 }
Chris@43 577
Chris@43 578
Chris@43 579 /* ============================================================ */
Chris@43 580
Chris@43 581 void help(int exitval)
Chris@43 582 {
Chris@43 583 printf("untgz version 0.2.1\n"
Chris@43 584 " using zlib version %s\n\n",
Chris@43 585 zlibVersion());
Chris@43 586 printf("Usage: untgz file.tgz extract all files\n"
Chris@43 587 " untgz file.tgz fname ... extract selected files\n"
Chris@43 588 " untgz -l file.tgz list archive contents\n"
Chris@43 589 " untgz -h display this help\n");
Chris@43 590 exit(exitval);
Chris@43 591 }
Chris@43 592
Chris@43 593 void error(const char *msg)
Chris@43 594 {
Chris@43 595 fprintf(stderr, "%s: %s\n", prog, msg);
Chris@43 596 exit(1);
Chris@43 597 }
Chris@43 598
Chris@43 599
Chris@43 600 /* ============================================================ */
Chris@43 601
Chris@43 602 #if defined(WIN32) && defined(__GNUC__)
Chris@43 603 int _CRT_glob = 0; /* disable argument globbing in MinGW */
Chris@43 604 #endif
Chris@43 605
Chris@43 606 int main(int argc,char **argv)
Chris@43 607 {
Chris@43 608 int action = TGZ_EXTRACT;
Chris@43 609 int arg = 1;
Chris@43 610 char *TGZfile;
Chris@43 611 gzFile *f;
Chris@43 612
Chris@43 613 prog = strrchr(argv[0],'\\');
Chris@43 614 if (prog == NULL)
Chris@43 615 {
Chris@43 616 prog = strrchr(argv[0],'/');
Chris@43 617 if (prog == NULL)
Chris@43 618 {
Chris@43 619 prog = strrchr(argv[0],':');
Chris@43 620 if (prog == NULL)
Chris@43 621 prog = argv[0];
Chris@43 622 else
Chris@43 623 prog++;
Chris@43 624 }
Chris@43 625 else
Chris@43 626 prog++;
Chris@43 627 }
Chris@43 628 else
Chris@43 629 prog++;
Chris@43 630
Chris@43 631 if (argc == 1)
Chris@43 632 help(0);
Chris@43 633
Chris@43 634 if (strcmp(argv[arg],"-l") == 0)
Chris@43 635 {
Chris@43 636 action = TGZ_LIST;
Chris@43 637 if (argc == ++arg)
Chris@43 638 help(0);
Chris@43 639 }
Chris@43 640 else if (strcmp(argv[arg],"-h") == 0)
Chris@43 641 {
Chris@43 642 help(0);
Chris@43 643 }
Chris@43 644
Chris@43 645 if ((TGZfile = TGZfname(argv[arg])) == NULL)
Chris@43 646 TGZnotfound(argv[arg]);
Chris@43 647
Chris@43 648 ++arg;
Chris@43 649 if ((action == TGZ_LIST) && (arg != argc))
Chris@43 650 help(1);
Chris@43 651
Chris@43 652 /*
Chris@43 653 * Process the TGZ file
Chris@43 654 */
Chris@43 655 switch(action)
Chris@43 656 {
Chris@43 657 case TGZ_LIST:
Chris@43 658 case TGZ_EXTRACT:
Chris@43 659 f = gzopen(TGZfile,"rb");
Chris@43 660 if (f == NULL)
Chris@43 661 {
Chris@43 662 fprintf(stderr,"%s: Couldn't gzopen %s\n",prog,TGZfile);
Chris@43 663 return 1;
Chris@43 664 }
Chris@43 665 exit(tar(f, action, arg, argc, argv));
Chris@43 666 break;
Chris@43 667
Chris@43 668 default:
Chris@43 669 error("Unknown option");
Chris@43 670 exit(1);
Chris@43 671 }
Chris@43 672
Chris@43 673 return 0;
Chris@43 674 }