annotate src/zlib-1.2.7/contrib/untgz/untgz.c @ 23:619f715526df sv_v2.1

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