annotate src/zlib-1.2.8/contrib/untgz/untgz.c @ 155:54abead6ecce

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