1/* 2 fileio.c - Zip 3 3 4 Copyright (c) 1990-2008 Info-ZIP. All rights reserved. 5 6 See the accompanying file LICENSE, version 2007-Mar-4 or later 7 (the contents of which are also included in zip.h) for terms of use. 8 If, for some reason, all these files are missing, the Info-ZIP license 9 also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html 10*/ 11/* 12 * fileio.c by Mark Adler 13 */ 14#define __FILEIO_C 15 16#include "zip.h" 17#include "crc32.h" 18 19#ifdef MACOS 20# include "helpers.h" 21#endif 22 23#ifdef VMS 24# include "vms/vms.h" 25#endif /* def VMS */ 26 27#include <time.h> 28 29#ifdef NO_MKTIME 30time_t mktime OF((struct tm *)); 31#endif 32 33#ifdef OSF 34#define EXDEV 18 /* avoid a bug in the DEC OSF/1 header files. */ 35#else 36#include <errno.h> 37#endif 38 39#ifdef NO_ERRNO 40extern int errno; 41#endif 42 43/* ----------------------- 44 For long option support 45 ----------------------- */ 46#include <ctype.h> 47 48 49#if defined(VMS) || defined(TOPS20) 50# define PAD 5 51#else 52# define PAD 0 53#endif 54 55#ifdef NO_RENAME 56int rename OF((ZCONST char *, ZCONST char *)); 57#endif 58 59 60/* Local functions */ 61local int optionerr OF((char *, ZCONST char *, int, int)); 62local unsigned long get_shortopt OF((char **, int, int *, int *, char **, int *, int)); 63local unsigned long get_longopt OF((char **, int, int *, int *, char **, int *, int)); 64 65#ifdef UNICODE_SUPPORT 66local int utf8_char_bytes OF((ZCONST char *utf8)); 67local long ucs4_char_from_utf8 OF((ZCONST char **utf8 )); 68local int utf8_from_ucs4_char OF((char *utf8buf, ulg ch)); 69local int utf8_to_ucs4_string OF((ZCONST char *utf8, ulg *usc4buf, 70 int buflen)); 71local int ucs4_string_to_utf8 OF((ZCONST ulg *ucs4, char *utf8buf, 72 int buflen)); 73#if 0 74 local int utf8_chars OF((ZCONST char *utf8)); 75#endif 76#endif /* UNICODE_SUPPORT */ 77 78#ifndef UTIL /* the companion #endif is a bit of ways down ... */ 79 80local int fqcmp OF((ZCONST zvoid *, ZCONST zvoid *)); 81local int fqcmpz OF((ZCONST zvoid *, ZCONST zvoid *)); 82 83 84/* Local module level variables. */ 85char *label = NULL; /* global, but only used in `system'.c */ 86local z_stat zipstatb; /* now use z_stat globally - 7/24/04 EG */ 87#if defined(UNICODE_SUPPORT) && defined(WIN32) 88 local zw_stat zipstatbw; 89#endif 90#if (!defined(MACOS) && !defined(WINDLL)) 91local int zipstate = -1; 92#else 93int zipstate; 94#endif 95/* -1 unknown, 0 old zip file exists, 1 new zip file */ 96 97#if 0 98char *getnam(n, fp) 99char *n; /* where to put name (must have >=FNMAX+1 bytes) */ 100#endif 101 102/* converted to return string pointer from malloc to avoid 103 size limitation - 11/8/04 EG */ 104#define GETNAM_MAX 9000 /* hopefully big enough for now */ 105char *getnam(fp) 106 FILE *fp; 107 /* Read a \n or \r delimited name from stdin into n, and return 108 n. If EOF, then return NULL. Also, if problem return NULL. */ 109{ 110 char name[GETNAM_MAX + 1]; 111 int c; /* last character read */ 112 char *p; /* pointer into name area */ 113 114 115 p = name; 116 while ((c = getc(fp)) == '\n' || c == '\r') 117 ; 118 if (c == EOF) 119 return NULL; 120 do { 121 if (p - name >= GETNAM_MAX) 122 return NULL; 123 *p++ = (char) c; 124 c = getc(fp); 125 } while (c != EOF && (c != '\n' && c != '\r')); 126#ifdef WIN32 127/* 128 * WIN32 strips off trailing spaces and periods in filenames 129 * XXX what about a filename that only consists of spaces ? 130 * Answer: on WIN32, a filename must contain at least one non-space char 131 */ 132 while (p > name) { 133 if ((c = p[-1]) != ' ' && c != '.') 134 break; 135 --p; 136 } 137#endif 138 *p = 0; 139 /* malloc a copy */ 140 if ((p = malloc(strlen(name) + 1)) == NULL) { 141 return NULL; 142 } 143 strcpy(p, name); 144 return p; 145} 146 147struct flist far *fexpel(f) 148struct flist far *f; /* entry to delete */ 149/* Delete the entry *f in the doubly-linked found list. Return pointer to 150 next entry to allow stepping through list. */ 151{ 152 struct flist far *t; /* temporary variable */ 153 154 t = f->nxt; 155 *(f->lst) = t; /* point last to next, */ 156 if (t != NULL) 157 t->lst = f->lst; /* and next to last */ 158 if (f->name != NULL) /* free memory used */ 159 free((zvoid *)(f->name)); 160 if (f->zname != NULL) 161 free((zvoid *)(f->zname)); 162 if (f->iname != NULL) 163 free((zvoid *)(f->iname)); 164#ifdef UNICODE_SUPPORT 165 if (f->uname) 166 free((zvoid *)f->uname); 167# ifdef WIN32 168 if (f->namew) 169 free((zvoid *)f->namew); 170 if (f->inamew) 171 free((zvoid *)f->inamew); 172 if (f->znamew) 173 free((zvoid *)f->znamew); 174# endif 175#endif 176 farfree((zvoid far *)f); 177 fcount--; /* decrement count */ 178 return t; /* return pointer to next */ 179} 180 181local int fqcmp(a, b) 182 ZCONST zvoid *a, *b; /* pointers to pointers to found entries */ 183/* Used by qsort() to compare entries in the found list by name. */ 184{ 185 return strcmp((*(struct flist far **)a)->name, 186 (*(struct flist far **)b)->name); 187} 188 189local int fqcmpz(a, b) 190 ZCONST zvoid *a, *b; /* pointers to pointers to found entries */ 191/* Used by qsort() to compare entries in the found list by iname. */ 192{ 193 return strcmp((*(struct flist far **)a)->iname, 194 (*(struct flist far **)b)->iname); 195} 196 197char *last(p, c) 198 char *p; /* sequence of path components */ 199 int c; /* path components separator character */ 200/* Return a pointer to the start of the last path component. For a directory 201 * name terminated by the character in c, the return value is an empty string. 202 */ 203{ 204 char *t; /* temporary variable */ 205 206 if ((t = strrchr(p, c)) != NULL) 207 return t + 1; 208 else 209#ifndef AOS_VS 210 return p; 211#else 212/* We want to allow finding of end of path in either AOS/VS-style pathnames 213 * or Unix-style pathnames. This presents a few little problems ... 214 */ 215 { 216 if (*p == '=' || *p == '^') /* like ./ and ../ respectively */ 217 return p + 1; 218 else 219 return p; 220 } 221#endif 222} 223 224#if defined(UNICODE_SUPPORT) && defined(WIN32) 225wchar_t *lastw(pw, c) 226 wchar_t *pw; /* sequence of path components */ 227 wchar_t c; /* path components separator character */ 228/* Return a pointer to the start of the last path component. For a directory 229 * name terminated by the character in c, the return value is an empty string. 230 */ 231{ 232 wchar_t *tw; /* temporary variable */ 233 234 if ((tw = wcsrchr(pw, c)) != NULL) 235 return tw + 1; 236 else 237# ifndef AOS_VS 238 return pw; 239# else 240/* We want to allow finding of end of path in either AOS/VS-style pathnames 241 * or Unix-style pathnames. This presents a few little problems ... 242 */ 243 { 244 if (*pw == (wchar_t)'=' || *pw == (wchar_t)'^') /* like ./ and ../ respectively */ 245 return pw + 1; 246 else 247 return pw; 248 } 249# endif 250} 251#endif 252 253 254char *msname(n) 255 char *n; 256/* Reduce all path components to MSDOS upper case 8.3 style names. */ 257{ 258 int c; /* current character */ 259 int f; /* characters in current component */ 260 char *p; /* source pointer */ 261 char *q; /* destination pointer */ 262 263 p = q = n; 264 f = 0; 265 while ((c = (unsigned char)*POSTINCSTR(p)) != 0) 266 if (c == ' ' || c == ':' || c == '"' || c == '*' || c == '+' || 267 c == ',' || c == ';' || c == '<' || c == '=' || c == '>' || 268 c == '?' || c == '[' || c == ']' || c == '|') 269 continue; /* char is discarded */ 270 else if (c == '/') 271 { 272 *POSTINCSTR(q) = (char)c; 273 f = 0; /* new component */ 274 } 275#ifdef __human68k__ 276 else if (ismbblead(c) && *p) 277 { 278 if (f == 7 || f == 11) 279 f++; 280 else if (*p && f < 12 && f != 8) 281 { 282 *q++ = c; 283 *q++ = *p++; 284 f += 2; 285 } 286 } 287#endif /* __human68k__ */ 288 else if (c == '.') 289 { 290 if (f == 0) 291 continue; /* leading dots are discarded */ 292 else if (f < 9) 293 { 294 *POSTINCSTR(q) = (char)c; 295 f = 9; /* now in file type */ 296 } 297 else 298 f = 12; /* now just excess characters */ 299 } 300 else 301 if (f < 12 && f != 8) 302 { 303 f += CLEN(p); /* do until end of name or type */ 304 *POSTINCSTR(q) = (char)(to_up(c)); 305 } 306 *q = 0; 307 return n; 308} 309 310#ifdef UNICODE_SUPPORT 311wchar_t *msnamew(nw) 312 wchar_t *nw; 313/* Reduce all path components to MSDOS upper case 8.3 style names. */ 314{ 315 wchar_t c; /* current character */ 316 int f; /* characters in current component */ 317 wchar_t *pw; /* source pointer */ 318 wchar_t *qw; /* destination pointer */ 319 320 pw = qw = nw; 321 f = 0; 322 while ((c = (unsigned char)*pw++) != 0) 323 if (c == ' ' || c == ':' || c == '"' || c == '*' || c == '+' || 324 c == ',' || c == ';' || c == '<' || c == '=' || c == '>' || 325 c == '?' || c == '[' || c == ']' || c == '|') 326 continue; /* char is discarded */ 327 else if (c == '/') 328 { 329 *qw++ = c; 330 f = 0; /* new component */ 331 } 332#ifdef __human68k__ 333 else if (ismbblead(c) && *pw) 334 { 335 if (f == 7 || f == 11) 336 f++; 337 else if (*pw && f < 12 && f != 8) 338 { 339 *qw++ = c; 340 *qw++ = *pw++; 341 f += 2; 342 } 343 } 344#endif /* __human68k__ */ 345 else if (c == '.') 346 { 347 if (f == 0) 348 continue; /* leading dots are discarded */ 349 else if (f < 9) 350 { 351 *qw++ = c; 352 f = 9; /* now in file type */ 353 } 354 else 355 f = 12; /* now just excess characters */ 356 } 357 else 358 if (f < 12 && f != 8) 359 { 360 f++; /* do until end of name or type */ 361 *qw++ = towupper(c); 362 } 363 *qw = 0; 364 return nw; 365} 366#endif 367 368 369int proc_archive_name(n, caseflag) 370 char *n; /* name to process */ 371 int caseflag; /* true to force case-sensitive match */ 372/* Process a name or sh expression in existing archive to operate 373 on (or exclude). Return an error code in the ZE_ class. */ 374{ 375 int m; /* matched flag */ 376 char *p; /* path for recursion */ 377 struct zlist far *z; /* steps through zfiles list */ 378 379 if (strcmp(n, "-") == 0) { /* if compressing stdin */ 380 zipwarn("Cannot select stdin when selecting archive entries", ""); 381 return ZE_MISS; 382 } 383 else 384 { 385 /* Search for shell expression in zip file */ 386 p = ex2in(n, 0, (int *)NULL); /* shouldn't affect matching chars */ 387 m = 1; 388 for (z = zfiles; z != NULL; z = z->nxt) { 389 if (MATCH(p, z->iname, caseflag)) 390 { 391 z->mark = pcount ? filter(z->zname, caseflag) : 1; 392 if (verbose) 393 fprintf(mesg, "zip diagnostic: %scluding %s\n", 394 z->mark ? "in" : "ex", z->oname); 395 m = 0; 396 } 397 } 398#ifdef UNICODE_SUPPORT 399 /* also check escaped Unicode names */ 400 for (z = zfiles; z != NULL; z = z->nxt) { 401 if (z->zuname) { 402#ifdef WIN32 403 /* It seems something is lost in going from a listed 404 name from zip -su in a console window to using that 405 name in a command line. This kluge may fix it 406 and just takes zuname, converts to oem (i.e. ouname), 407 then converts it back which ends up not the same as 408 started with. 409 */ 410 char *zuname = z->wuname; 411#else 412 char *zuname = z->zuname; 413#endif 414 if (MATCH(p, zuname, caseflag)) 415 { 416 z->mark = pcount ? filter(zuname, caseflag) : 1; 417 if (verbose) { 418 fprintf(mesg, "zip diagnostic: %scluding %s\n", 419 z->mark ? "in" : "ex", z->oname); 420 fprintf(mesg, " Escaped Unicode: %s\n", 421 z->ouname); 422 } 423 m = 0; 424 } 425 } 426 } 427#endif 428 free((zvoid *)p); 429 return m ? ZE_MISS : ZE_OK; 430 } 431} 432 433 434int check_dup() 435/* Sort the found list and remove duplicates. 436 Return an error code in the ZE_ class. */ 437{ 438 struct flist far *f; /* steps through found linked list */ 439 extent j, k; /* indices for s */ 440 struct flist far **s; /* sorted table */ 441 struct flist far **nodup; /* sorted table without duplicates */ 442 443 /* sort found list, remove duplicates */ 444 if (fcount) 445 { 446 extent fl_size = fcount * sizeof(struct flist far *); 447 if ((fl_size / sizeof(struct flist far *)) != fcount || 448 (s = (struct flist far **)malloc(fl_size)) == NULL) 449 return ZE_MEM; 450 for (j = 0, f = found; f != NULL; f = f->nxt) 451 s[j++] = f; 452 /* Check names as given (f->name) */ 453 qsort((char *)s, fcount, sizeof(struct flist far *), fqcmp); 454 for (k = j = fcount - 1; j > 0; j--) 455 if (strcmp(s[j - 1]->name, s[j]->name) == 0) 456 /* remove duplicate entry from list */ 457 fexpel(s[j]); /* fexpel() changes fcount */ 458 else 459 /* copy valid entry into destination position */ 460 s[k--] = s[j]; 461 s[k] = s[0]; /* First entry is always valid */ 462 nodup = &s[k]; /* Valid entries are at end of array s */ 463 464 /* sort only valid items and check for unique internal names (f->iname) */ 465 qsort((char *)nodup, fcount, sizeof(struct flist far *), fqcmpz); 466 for (j = 1; j < fcount; j++) 467 if (strcmp(nodup[j - 1]->iname, nodup[j]->iname) == 0) 468 { 469 char tempbuf[FNMAX+4081]; 470 471 sprintf(errbuf, " first full name: %s\n", nodup[j - 1]->name); 472 sprintf(tempbuf, " second full name: %s\n", nodup[j]->name); 473 strcat(errbuf, " "); 474 strcat(errbuf, tempbuf); 475#ifdef EBCDIC 476 strtoebc(nodup[j]->iname, nodup[j]->iname); 477#endif 478 sprintf(tempbuf, "name in zip file repeated: %s", nodup[j]->iname); 479 strcat(errbuf, " "); 480 strcat(errbuf, tempbuf); 481 if (pathput == 0) { 482 strcat(errbuf, "\n this may be a result of using -j"); 483 } 484#ifdef EBCDIC 485 strtoasc(nodup[j]->iname, nodup[j]->iname); 486#endif 487 zipwarn(errbuf, ""); 488 return ZE_PARMS; 489 } 490 free((zvoid *)s); 491 } 492 return ZE_OK; 493} 494 495int filter(name, casesensitive) 496 char *name; 497 int casesensitive; 498 /* Scan the -R, -i and -x lists for matches to the given name. 499 Return TRUE if the name must be included, FALSE otherwise. 500 Give precedence to -x over -i and -R. 501 Note that if both R and i patterns are given then must 502 have a match for both. 503 This routine relies on the following global variables: 504 patterns array of match pattern structures 505 pcount total number of patterns 506 icount number of -i patterns 507 Rcount number of -R patterns 508 These data are set up by the command line parsing code. 509 */ 510{ 511 unsigned int n; 512 int slashes; 513 char *p, *q; 514 /* without -i patterns, every name matches the "-i select rules" */ 515 int imatch = (icount == 0); 516 /* without -R patterns, every name matches the "-R select rules" */ 517 int Rmatch = (Rcount == 0); 518 519 if (pcount == 0) return TRUE; 520 521 for (n = 0; n < pcount; n++) { 522 if (!patterns[n].zname[0]) /* it can happen... */ 523 continue; 524 p = name; 525 switch (patterns[n].select) { 526 case 'R': 527 if (Rmatch) 528 /* one -R match is sufficient, skip this pattern */ 529 continue; 530 /* With -R patterns, if the pattern has N path components (that is, 531 N-1 slashes), then we test only the last N components of name. 532 */ 533 slashes = 0; 534 for (q = patterns[n].zname; (q = MBSCHR(q, '/')) != NULL; MB_NEXTCHAR(q)) 535 slashes++; 536 /* The name may have M path components (M-1 slashes) */ 537 for (q = p; (q = MBSCHR(q, '/')) != NULL; MB_NEXTCHAR(q)) 538 slashes--; 539 /* Now, "slashes" contains the difference "N-M" between the number 540 of path components in the pattern (N) and in the name (M). 541 */ 542 if (slashes < 0) 543 /* We found "M > N" 544 --> skip the first (M-N) path components of the name. 545 */ 546 for (q = p; (q = MBSCHR(q, '/')) != NULL; MB_NEXTCHAR(q)) 547 if (++slashes == 0) { 548 p = q + 1; /* q points at '/', mblen("/") is 1 */ 549 break; 550 } 551 break; 552 case 'i': 553 if (imatch) 554 /* one -i match is sufficient, skip this pattern */ 555 continue; 556 break; 557 } 558 if (MATCH(patterns[n].zname, p, casesensitive)) { 559 switch (patterns[n].select) { 560 case 'x': 561 /* The -x match takes precedence over everything else */ 562 return FALSE; 563 case 'R': 564 Rmatch = TRUE; 565 break; 566 default: 567 /* this must be a type -i match */ 568 imatch = TRUE; 569 break; 570 } 571 } 572 } 573 return imatch && Rmatch; 574} 575 576 577#ifdef UNICODE_SUPPORT 578# ifdef WIN32 579 580int newnamew(namew, isdir, casesensitive) 581 wchar_t *namew; /* name to add (or exclude) */ 582 int isdir; /* true for a directory */ 583 int casesensitive; /* true for case-sensitive matching */ 584/* Add (or exclude) the name of an existing disk file. Return an error 585 code in the ZE_ class. */ 586{ 587 wchar_t *inamew = NULL; /* internal name */ 588 wchar_t *znamew = NULL; /* external version of iname */ 589 wchar_t *undosmw = NULL; /* zname version with "-j" and "-k" options disabled */ 590 char *oname = NULL; /* iname converted for display */ 591 char *name = NULL; 592 char *iname = NULL; 593 char *zname = NULL; 594 char *zuname = NULL; 595 char *undosm = NULL; 596 struct flist far *f; /* where in found, or new found entry */ 597 struct zlist far *z; /* where in zfiles (if found) */ 598 int dosflag; 599 600 /* Scanning files ... 601 * 602 * After 5 seconds output Scanning files... 603 * then a dot every 2 seconds 604 */ 605 if (noisy) { 606 /* If find files then output message after delay */ 607 if (scan_count == 0) { 608 time_t current = time(NULL); 609 scan_start = current; 610 } 611 scan_count++; 612 if (scan_count % 100 == 0) { 613 time_t current = time(NULL); 614 615 if (current - scan_start > scan_delay) { 616 if (scan_last == 0) { 617 zipmessage_nl("Scanning files ", 0); 618 scan_last = current; 619 } 620 if (current - scan_last > scan_dot_time) { 621 scan_last = current; 622 fprintf(mesg, "."); 623 fflush(mesg); 624 } 625 } 626 } 627 } 628 629 /* Search for name in zip file. If there, mark it, else add to 630 list of new names to do (or remove from that list). */ 631 if ((inamew = ex2inw(namew, isdir, &dosflag)) == NULL) 632 return ZE_MEM; 633 634 /* Discard directory names with zip -rj */ 635 if (*inamew == (wchar_t)'\0') { 636 637 /* If extensions needs to be swapped, we will have empty directory names 638 instead of the original directory. For example, zipping 'c.', 'c.main' 639 should zip only 'main.c' while 'c.' will be converted to '\0' by ex2in. */ 640 641 if (pathput && !recurse) error("empty name without -j or -r"); 642 free((zvoid *)inamew); 643 return ZE_OK; 644 } 645 646 if (dosflag || !pathput) { 647 int save_dosify = dosify, save_pathput = pathput; 648 dosify = 0; 649 pathput = 1; 650 /* zname is temporarly mis-used as "undosmode" iname pointer */ 651 if ((znamew = ex2inw(namew, isdir, NULL)) != NULL) { 652 undosmw = in2exw(znamew); 653 free(znamew); 654 } 655 dosify = save_dosify; 656 pathput = save_pathput; 657 } 658 if ((znamew = in2exw(inamew)) == NULL) 659 return ZE_MEM; 660 661 /* Convert names from wchar_t to char */ 662 663 name = wchar_to_local_string(namew); 664 iname = wchar_to_local_string(inamew); 665 zname = wchar_to_local_string(znamew); 666 667 oname = local_to_display_string(zname); 668 669 zuname = wchar_to_local_string(znamew); 670 671 if (undosmw == NULL) 672 undosmw = znamew; 673 undosm = wchar_to_local_string(undosmw); 674 675 if ((z = zsearch(zuname)) != NULL) { 676 if (pcount && !filter(undosm, casesensitive)) { 677 /* Do not clear z->mark if "exclude", because, when "dosify || !pathput" 678 * is in effect, two files with different filter options may hit the 679 * same z entry. 680 */ 681 if (verbose) 682 fprintf(mesg, "excluding %s\n", oname); 683 } else { 684 z->mark = 1; 685 if ((z->name = malloc(strlen(name) + 1 + PAD)) == NULL) { 686 if (undosmw != znamew) 687 free(undosmw); 688 if (undosm) free(undosm); 689 if (inamew) free(inamew); 690 if (znamew) free(znamew); 691 if (name) free(name); 692 if (iname) free(iname); 693 if (zname) free(zname); 694 if (oname) free(oname); 695 if (zuname) free(zuname); 696 return ZE_MEM; 697 } 698 strcpy(z->name, name); 699 z->oname = oname; 700 oname = NULL; 701 z->dosflag = dosflag; 702 703#ifdef FORCE_NEWNAME 704 free((zvoid *)(z->iname)); 705 z->iname = iname; 706 iname = NULL; 707#else 708 /* Better keep the old name. Useful when updating on MSDOS a zip file 709 * made on Unix. 710 */ 711#endif /* ? FORCE_NEWNAME */ 712 } 713 714 if ((z->namew = (wchar_t *)malloc((wcslen(namew) + 1) * sizeof(wchar_t))) == NULL) { 715 if (undosmw != znamew) 716 free(undosmw); 717 if (undosm) free(undosm); 718 if (inamew) free(inamew); 719 if (znamew) free(znamew); 720 if (name) free(name); 721 if (iname) free(iname); 722 if (zname) free(zname); 723 if (oname) free(oname); 724 if (zuname) free(zuname); 725 return ZE_MEM; 726 } 727 wcscpy(z->namew, namew); 728 z->inamew = inamew; 729 inamew = NULL; 730 z->znamew = znamew; 731 znamew = NULL; 732 z->uname = wchar_to_utf8_string(z->inamew); 733 if (name == label) { 734 label = z->name; 735 } 736 } else if (pcount == 0 || filter(undosm, casesensitive)) { 737 738 /* Check that we are not adding the zip file to itself. This 739 * catches cases like "zip -m foo ../dir/foo.zip". 740 */ 741/* Version of stat() for CMS/MVS isn't complete enough to see if */ 742/* files match. Just let ZIP.C compare the filenames. That's good */ 743/* enough for CMS anyway since there aren't paths to worry about. */ 744 zw_stat statbw; /* need for wide stat */ 745 wchar_t *zipfilew = local_to_wchar_string(zipfile); 746 747 if (zipstate == -1) 748 zipstate = strcmp(zipfile, "-") != 0 && 749 zwstat(zipfilew, &zipstatbw) == 0; 750 free(zipfilew); 751 752 if (zipstate == 1 && (statbw = zipstatbw, zwstat(namew, &statbw) == 0 753 && zipstatbw.st_mode == statbw.st_mode 754 && zipstatbw.st_ino == statbw.st_ino 755 && zipstatbw.st_dev == statbw.st_dev 756 && zipstatbw.st_uid == statbw.st_uid 757 && zipstatbw.st_gid == statbw.st_gid 758 && zipstatbw.st_size == statbw.st_size 759 && zipstatbw.st_mtime == statbw.st_mtime 760 && zipstatbw.st_ctime == statbw.st_ctime)) { 761 /* Don't compare a_time since we are reading the file */ 762 if (verbose) 763 fprintf(mesg, "file matches zip file -- skipping\n"); 764 if (undosmw != znamew) 765 free(undosmw); 766 if (undosm) free(undosm); 767 if (inamew) free(inamew); 768 if (znamew) free(znamew); 769 if (name) free(name); 770 if (iname) free(iname); 771 if (zname) free(zname); 772 if (oname) free(oname); 773 if (zuname) free(zuname); 774 return ZE_OK; 775 } 776 777 /* allocate space and add to list */ 778 if ((f = (struct flist far *)farmalloc(sizeof(struct flist))) == NULL || 779 fcount + 1 < fcount || 780 (f->name = malloc(strlen(name) + 1 + PAD)) == NULL) 781 { 782 if (f != NULL) 783 farfree((zvoid far *)f); 784 if (undosmw != znamew) 785 free(undosmw); 786 if (undosm) free(undosm); 787 if (inamew) free(inamew); 788 if (znamew) free(znamew); 789 if (name) free(name); 790 if (iname) free(iname); 791 if (zname) free(zname); 792 if (oname) free(oname); 793 if (zuname) free(zuname); 794 return ZE_MEM; 795 } 796 if (undosmw != znamew) 797 free((zvoid *)undosmw); 798 strcpy(f->name, name); 799 f->iname = iname; 800 iname = NULL; 801 f->zname = zname; 802 zname = NULL; 803 /* Unicode */ 804 if ((f->namew = (wchar_t *)malloc((wcslen(namew) + 1) * sizeof(wchar_t))) == NULL) { 805 if (f != NULL) 806 farfree((zvoid far *)f); 807 if (undosmw != znamew) 808 free(undosmw); 809 if (undosm) free(undosm); 810 if (inamew) free(inamew); 811 if (znamew) free(znamew); 812 if (name) free(name); 813 if (iname) free(iname); 814 if (zname) free(zname); 815 if (oname) free(oname); 816 if (zuname) free(zuname); 817 return ZE_MEM; 818 } 819 wcscpy(f->namew, namew); 820 f->znamew = znamew; 821 znamew = NULL; 822 f->uname = wchar_to_utf8_string(inamew); 823 f->inamew = inamew; 824 inamew = NULL; 825 f->oname = oname; 826 oname = NULL; 827 f->dosflag = dosflag; 828 *fnxt = f; 829 f->lst = fnxt; 830 f->nxt = NULL; 831 fnxt = &f->nxt; 832 fcount++; 833 if (name == label) { 834 label = f->name; 835 } 836 } 837 if (undosm) free(undosm); 838 if (inamew) free(inamew); 839 if (znamew) free(znamew); 840 if (name) free(name); 841 if (iname) free(iname); 842 if (zname) free(zname); 843 if (oname) free(oname); 844 if (zuname) free(zuname); 845 return ZE_OK; 846} 847 848# endif 849#endif 850 851int newname(name, isdir, casesensitive) 852 char *name; /* name to add (or exclude) */ 853 int isdir; /* true for a directory */ 854 int casesensitive; /* true for case-sensitive matching */ 855/* Add (or exclude) the name of an existing disk file. Return an error 856 code in the ZE_ class. */ 857{ 858 char *iname, *zname; /* internal name, external version of iname */ 859 char *undosm; /* zname version with "-j" and "-k" options disabled */ 860 char *oname; /* iname converted for display */ 861 struct flist far *f; /* where in found, or new found entry */ 862 struct zlist far *z; /* where in zfiles (if found) */ 863 int dosflag; 864 865 /* Scanning files ... 866 * 867 * After 5 seconds output Scanning files... 868 * then a dot every 2 seconds 869 */ 870 if (noisy) { 871 /* If find files then output message after delay */ 872 if (scan_count == 0) { 873 time_t current = time(NULL); 874 scan_start = current; 875 } 876 scan_count++; 877 if (scan_count % 100 == 0) { 878 time_t current = time(NULL); 879 880 if (current - scan_start > scan_delay) { 881 if (scan_last == 0) { 882 zipmessage_nl("Scanning files ", 0); 883 scan_last = current; 884 } 885 if (current - scan_last > scan_dot_time) { 886 scan_last = current; 887 fprintf(mesg, "."); 888 fflush(mesg); 889 } 890 } 891 } 892 } 893 894 /* Search for name in zip file. If there, mark it, else add to 895 list of new names to do (or remove from that list). */ 896 if ((iname = ex2in(name, isdir, &dosflag)) == NULL) 897 return ZE_MEM; 898 899 /* Discard directory names with zip -rj */ 900 if (*iname == '\0') { 901#ifndef AMIGA 902/* A null string is a legitimate external directory name in AmigaDOS; also, 903 * a command like "zip -r zipfile FOO:" produces an empty internal name. 904 */ 905# ifndef RISCOS 906 /* If extensions needs to be swapped, we will have empty directory names 907 instead of the original directory. For example, zipping 'c.', 'c.main' 908 should zip only 'main.c' while 'c.' will be converted to '\0' by ex2in. */ 909 910 if (pathput && !recurse) error("empty name without -j or -r"); 911 912# endif /* !RISCOS */ 913#endif /* !AMIGA */ 914 free((zvoid *)iname); 915 return ZE_OK; 916 } 917 undosm = NULL; 918 if (dosflag || !pathput) { 919 int save_dosify = dosify, save_pathput = pathput; 920 dosify = 0; 921 pathput = 1; 922 /* zname is temporarly mis-used as "undosmode" iname pointer */ 923 if ((zname = ex2in(name, isdir, NULL)) != NULL) { 924 undosm = in2ex(zname); 925 free(zname); 926 } 927 dosify = save_dosify; 928 pathput = save_pathput; 929 } 930 if ((zname = in2ex(iname)) == NULL) 931 return ZE_MEM; 932#ifdef UNICODE_SUPPORT 933 /* Convert name to display or OEM name */ 934 oname = local_to_display_string(iname); 935#else 936 if ((oname = malloc(strlen(zname) + 1)) == NULL) 937 return ZE_MEM; 938 strcpy(oname, zname); 939#endif 940 if (undosm == NULL) 941 undosm = zname; 942 if ((z = zsearch(zname)) != NULL) { 943 if (pcount && !filter(undosm, casesensitive)) { 944 /* Do not clear z->mark if "exclude", because, when "dosify || !pathput" 945 * is in effect, two files with different filter options may hit the 946 * same z entry. 947 */ 948 if (verbose) 949 fprintf(mesg, "excluding %s\n", oname); 950 free((zvoid *)iname); 951 free((zvoid *)zname); 952 } else { 953 z->mark = 1; 954 if ((z->name = malloc(strlen(name) + 1 + PAD)) == NULL) { 955 if (undosm != zname) 956 free((zvoid *)undosm); 957 free((zvoid *)iname); 958 free((zvoid *)zname); 959 return ZE_MEM; 960 } 961 strcpy(z->name, name); 962 z->oname = oname; 963 z->dosflag = dosflag; 964 965#ifdef FORCE_NEWNAME 966 free((zvoid *)(z->iname)); 967 z->iname = iname; 968#else 969 /* Better keep the old name. Useful when updating on MSDOS a zip file 970 * made on Unix. 971 */ 972 free((zvoid *)iname); 973 free((zvoid *)zname); 974#endif /* ? FORCE_NEWNAME */ 975 } 976#if defined(UNICODE_SUPPORT) && defined(WIN32) 977 z->namew = NULL; 978 z->inamew = NULL; 979 z->znamew = NULL; 980#endif 981 if (name == label) { 982 label = z->name; 983 } 984 } else if (pcount == 0 || filter(undosm, casesensitive)) { 985 986 /* Check that we are not adding the zip file to itself. This 987 * catches cases like "zip -m foo ../dir/foo.zip". 988 */ 989#ifndef CMS_MVS 990/* Version of stat() for CMS/MVS isn't complete enough to see if */ 991/* files match. Just let ZIP.C compare the filenames. That's good */ 992/* enough for CMS anyway since there aren't paths to worry about. */ 993 z_stat statb; /* now use structure z_stat and function zstat globally 7/24/04 EG */ 994 995 if (zipstate == -1) 996 zipstate = strcmp(zipfile, "-") != 0 && 997 zstat(zipfile, &zipstatb) == 0; 998 999 if (zipstate == 1 && (statb = zipstatb, zstat(name, &statb) == 0 1000 && zipstatb.st_mode == statb.st_mode 1001#ifdef VMS 1002 && memcmp(zipstatb.st_ino, statb.st_ino, sizeof(statb.st_ino)) == 0 1003 && strcmp(zipstatb.st_dev, statb.st_dev) == 0 1004 && zipstatb.st_uid == statb.st_uid 1005#else /* !VMS */ 1006 && zipstatb.st_ino == statb.st_ino 1007 && zipstatb.st_dev == statb.st_dev 1008 && zipstatb.st_uid == statb.st_uid 1009 && zipstatb.st_gid == statb.st_gid 1010#endif /* ?VMS */ 1011 && zipstatb.st_size == statb.st_size 1012 && zipstatb.st_mtime == statb.st_mtime 1013 && zipstatb.st_ctime == statb.st_ctime)) { 1014 /* Don't compare a_time since we are reading the file */ 1015 if (verbose) 1016 fprintf(mesg, "file matches zip file -- skipping\n"); 1017 if (undosm != zname) 1018 free((zvoid *)zname); 1019 if (undosm != iname) 1020 free((zvoid *)undosm); 1021 free((zvoid *)iname); 1022 free(oname); 1023 return ZE_OK; 1024 } 1025#endif /* CMS_MVS */ 1026 1027 /* allocate space and add to list */ 1028 if ((f = (struct flist far *)farmalloc(sizeof(struct flist))) == NULL || 1029 fcount + 1 < fcount || 1030 (f->name = malloc(strlen(name) + 1 + PAD)) == NULL) 1031 { 1032 if (f != NULL) 1033 farfree((zvoid far *)f); 1034 if (undosm != zname) 1035 free((zvoid *)undosm); 1036 free((zvoid *)iname); 1037 free((zvoid *)zname); 1038 free(oname); 1039 return ZE_MEM; 1040 } 1041 strcpy(f->name, name); 1042 f->iname = iname; 1043 f->zname = zname; 1044#ifdef UNICODE_SUPPORT 1045 /* Unicode */ 1046 f->uname = local_to_utf8_string(iname); 1047#ifdef WIN32 1048 f->namew = NULL; 1049 f->inamew = NULL; 1050 f->znamew = NULL; 1051 if (strcmp(f->name, "-") == 0) { 1052 f->namew = local_to_wchar_string(f->name); 1053 } 1054#endif 1055 1056#endif 1057 f->oname = oname; 1058 f->dosflag = dosflag; 1059 1060 *fnxt = f; 1061 f->lst = fnxt; 1062 f->nxt = NULL; 1063 fnxt = &f->nxt; 1064 fcount++; 1065 if (name == label) { 1066 label = f->name; 1067 } 1068 } 1069 if (undosm != zname) 1070 free((zvoid *)undosm); 1071 return ZE_OK; 1072} 1073 1074ulg dostime(y, n, d, h, m, s) 1075int y; /* year */ 1076int n; /* month */ 1077int d; /* day */ 1078int h; /* hour */ 1079int m; /* minute */ 1080int s; /* second */ 1081/* Convert the date y/n/d and time h:m:s to a four byte DOS date and 1082 time (date in high two bytes, time in low two bytes allowing magnitude 1083 comparison). */ 1084{ 1085 return y < 1980 ? DOSTIME_MINIMUM /* dostime(1980, 1, 1, 0, 0, 0) */ : 1086 (((ulg)y - 1980) << 25) | ((ulg)n << 21) | ((ulg)d << 16) | 1087 ((ulg)h << 11) | ((ulg)m << 5) | ((ulg)s >> 1); 1088} 1089 1090 1091ulg unix2dostime(t) 1092time_t *t; /* unix time to convert */ 1093/* Return the Unix time t in DOS format, rounded up to the next two 1094 second boundary. */ 1095{ 1096 time_t t_even; 1097 struct tm *s; /* result of localtime() */ 1098 1099 t_even = (time_t)(((unsigned long)(*t) + 1) & (~1)); 1100 /* Round up to even seconds. */ 1101 s = localtime(&t_even); /* Use local time since MSDOS does. */ 1102 if (s == (struct tm *)NULL) { 1103 /* time conversion error; use current time as emergency value 1104 (assuming that localtime() does at least accept this value!) */ 1105 t_even = (time_t)(((unsigned long)time(NULL) + 1) & (~1)); 1106 s = localtime(&t_even); 1107 } 1108 return dostime(s->tm_year + 1900, s->tm_mon + 1, s->tm_mday, 1109 s->tm_hour, s->tm_min, s->tm_sec); 1110} 1111 1112int issymlnk(a) 1113ulg a; /* Attributes returned by filetime() */ 1114/* Return true if the attributes are those of a symbolic link */ 1115{ 1116#ifndef QDOS 1117#ifdef S_IFLNK 1118#ifdef __human68k__ 1119 int *_dos_importlnenv(void); 1120 1121 if (_dos_importlnenv() == NULL) 1122 return 0; 1123#endif 1124 return ((a >> 16) & S_IFMT) == S_IFLNK; 1125#else /* !S_IFLNK */ 1126 return (int)a & 0; /* avoid warning on unused parameter */ 1127#endif /* ?S_IFLNK */ 1128#else 1129 return 0; 1130#endif 1131} 1132 1133#endif /* !UTIL */ 1134 1135 1136#if (!defined(UTIL) && !defined(ZP_NEED_GEN_D2U_TIME)) 1137 /* There is no need for dos2unixtime() in the ZipUtils' code. */ 1138# define ZP_NEED_GEN_D2U_TIME 1139#endif 1140#if ((defined(OS2) || defined(VMS)) && defined(ZP_NEED_GEN_D2U_TIME)) 1141 /* OS/2 and VMS use a special solution to handle time-stams of files. */ 1142# undef ZP_NEED_GEN_D2U_TIME 1143#endif 1144#if (defined(W32_STATROOT_FIX) && !defined(ZP_NEED_GEN_D2U_TIME)) 1145 /* The Win32 stat()-bandaid to fix stat'ing root directories needs 1146 * dos2unixtime() to calculate the time-stamps. */ 1147# define ZP_NEED_GEN_D2U_TIME 1148#endif 1149 1150#ifdef ZP_NEED_GEN_D2U_TIME 1151 1152time_t dos2unixtime(dostime) 1153ulg dostime; /* DOS time to convert */ 1154/* Return the Unix time_t value (GMT/UTC time) for the DOS format (local) 1155 * time dostime, where dostime is a four byte value (date in most significant 1156 * word, time in least significant word), see dostime() function. 1157 */ 1158{ 1159 struct tm *t; /* argument for mktime() */ 1160 ZCONST time_t clock = time(NULL); 1161 1162 t = localtime(&clock); 1163 t->tm_isdst = -1; /* let mktime() determine if DST is in effect */ 1164 /* Convert DOS time to UNIX time_t format */ 1165 t->tm_sec = (((int)dostime) << 1) & 0x3e; 1166 t->tm_min = (((int)dostime) >> 5) & 0x3f; 1167 t->tm_hour = (((int)dostime) >> 11) & 0x1f; 1168 t->tm_mday = (int)(dostime >> 16) & 0x1f; 1169 t->tm_mon = ((int)(dostime >> 21) & 0x0f) - 1; 1170 t->tm_year = ((int)(dostime >> 25) & 0x7f) + 80; 1171 1172 return mktime(t); 1173} 1174 1175#undef ZP_NEED_GEN_D2U_TIME 1176#endif /* ZP_NEED_GEN_D2U_TIME */ 1177 1178 1179#ifndef MACOS 1180int destroy(f) 1181 char *f; /* file to delete */ 1182/* Delete the file *f, returning non-zero on failure. */ 1183{ 1184 return unlink(f); 1185} 1186 1187 1188int replace(d, s) 1189char *d, *s; /* destination and source file names */ 1190/* Replace file *d by file *s, removing the old *s. Return an error code 1191 in the ZE_ class. This function need not preserve the file attributes, 1192 this will be done by setfileattr() later. 1193 */ 1194{ 1195 z_stat t; /* results of stat() */ 1196#if defined(CMS_MVS) 1197 /* cmsmvs.h defines FOPW_TEMP as memory(hiperspace). Since memory is 1198 * lost at end of run, always do copy instead of rename. 1199 */ 1200 int copy = 1; 1201#else 1202 int copy = 0; 1203#endif 1204 int d_exists; 1205 1206#if defined(VMS) || defined(CMS_MVS) 1207 /* stat() is broken on VMS remote files (accessed through Decnet). 1208 * This patch allows creation of remote zip files, but is not sufficient 1209 * to update them or compress remote files */ 1210 unlink(d); 1211#else /* !(VMS || CMS_MVS) */ 1212 d_exists = (LSTAT(d, &t) == 0); 1213 if (d_exists) 1214 { 1215 /* 1216 * respect existing soft and hard links! 1217 */ 1218 if (t.st_nlink > 1 1219# ifdef S_IFLNK 1220 || (t.st_mode & S_IFMT) == S_IFLNK 1221# endif 1222 ) 1223 copy = 1; 1224 else if (unlink(d)) 1225 return ZE_CREAT; /* Can't erase zip file--give up */ 1226 } 1227#endif /* ?(VMS || CMS_MVS) */ 1228#ifndef CMS_MVS 1229 if (!copy) { 1230 if (rename(s, d)) { /* Just move s on top of d */ 1231 copy = 1; /* failed ? */ 1232#if !defined(VMS) && !defined(ATARI) && !defined(AZTEC_C) 1233#if !defined(CMS_MVS) && !defined(RISCOS) && !defined(QDOS) 1234 /* For VMS, ATARI, AMIGA Aztec, VM_CMS, MVS, RISCOS, 1235 always assume that failure is EXDEV */ 1236 if (errno != EXDEV 1237# ifdef THEOS 1238 && errno != EEXIST 1239# else 1240# ifdef ENOTSAM 1241 && errno != ENOTSAM /* Used at least on Turbo C */ 1242# endif 1243# endif 1244 ) return ZE_CREAT; 1245#endif /* !CMS_MVS && !RISCOS */ 1246#endif /* !VMS && !ATARI && !AZTEC_C */ 1247 } 1248 } 1249#endif /* !CMS_MVS */ 1250 1251 if (copy) { 1252 FILE *f, *g; /* source and destination files */ 1253 int r; /* temporary variable */ 1254 1255#ifdef RISCOS 1256 if (SWI_OS_FSControl_26(s,d,0xA1)!=NULL) { 1257#endif 1258 1259 /* Use zfopen for almost all opens where fopen is used. For 1260 most OS that support large files we use the 64-bit file 1261 environment and zfopen maps to fopen, but this allows 1262 tweeking ports that don't do that. 7/24/04 */ 1263 if ((f = zfopen(s, FOPR)) == NULL) { 1264 fprintf(mesg," replace: can't open %s\n", s); 1265 return ZE_TEMP; 1266 } 1267 if ((g = zfopen(d, FOPW)) == NULL) 1268 { 1269 fclose(f); 1270 return ZE_CREAT; 1271 } 1272 1273 r = fcopy(f, g, (ulg)-1L); 1274 fclose(f); 1275 if (fclose(g) || r != ZE_OK) 1276 { 1277 unlink(d); 1278 return r ? (r == ZE_TEMP ? ZE_WRITE : r) : ZE_WRITE; 1279 } 1280 unlink(s); 1281#ifdef RISCOS 1282 } 1283#endif 1284 } 1285 return ZE_OK; 1286} 1287#endif /* !MACOS */ 1288 1289 1290int getfileattr(f) 1291char *f; /* file path */ 1292/* Return the file attributes for file f or 0 if failure */ 1293{ 1294#ifdef __human68k__ 1295 struct _filbuf buf; 1296 1297 return _dos_files(&buf, f, 0xff) < 0 ? 0x20 : buf.atr; 1298#else 1299 z_stat s; 1300 1301 return SSTAT(f, &s) == 0 ? (int) s.st_mode : 0; 1302#endif 1303} 1304 1305 1306int setfileattr(f, a) 1307char *f; /* file path */ 1308int a; /* attributes returned by getfileattr() */ 1309/* Give the file f the attributes a, return non-zero on failure */ 1310{ 1311#if defined(TOPS20) || defined (CMS_MVS) 1312 return 0; 1313#else 1314#ifdef __human68k__ 1315 return _dos_chmod(f, a) < 0 ? -1 : 0; 1316#else 1317 return chmod(f, a); 1318#endif 1319#endif 1320} 1321 1322 1323/* tempname */ 1324 1325#ifndef VMS /* VMS-specific function is in VMS.C. */ 1326 1327char *tempname(zip) 1328 char *zip; /* path name of zip file to generate temp name for */ 1329 1330/* Return a temporary file name in its own malloc'ed space, using tempath. */ 1331{ 1332 char *t = zip; /* malloc'ed space for name (use zip to avoid warning) */ 1333 1334# ifdef CMS_MVS 1335 if ((t = malloc(strlen(tempath) + L_tmpnam + 2)) == NULL) 1336 return NULL; 1337 1338# ifdef VM_CMS 1339 tmpnam(t); 1340 /* Remove filemode and replace with tempath, if any. */ 1341 /* Otherwise A-disk is used by default */ 1342 *(strrchr(t, ' ')+1) = '\0'; 1343 if (tempath!=NULL) 1344 strcat(t, tempath); 1345 return t; 1346# else /* !VM_CMS */ 1347 /* For MVS */ 1348 tmpnam(t); 1349 if (tempath != NULL) 1350 { 1351 int l1 = strlen(t); 1352 char *dot; 1353 if (*t == '\'' && *(t+l1-1) == '\'' && (dot = strchr(t, '.'))) 1354 { 1355 /* MVS and not OE. tmpnam() returns quoted string of 5 qualifiers. 1356 * First is HLQ, rest are timestamps. User can only replace HLQ. 1357 */ 1358 int l2 = strlen(tempath); 1359 if (strchr(tempath, '.') || l2 < 1 || l2 > 8) 1360 ziperr(ZE_PARMS, "On MVS and not OE, tempath (-b) can only be HLQ"); 1361 memmove(t+1+l2, dot, l1+1-(dot-t)); /* shift dot ready for new hlq */ 1362 memcpy(t+1, tempath, l2); /* insert new hlq */ 1363 } 1364 else 1365 { 1366 /* MVS and probably OE. tmpnam() returns filename based on TMPDIR, 1367 * no point in even attempting to change it. User should modify TMPDIR 1368 * instead. 1369 */ 1370 zipwarn("MVS, assumed to be OE, change TMPDIR instead of option -b: ", 1371 tempath); 1372 } 1373 } 1374 return t; 1375# endif /* !VM_CMS */ 1376 1377# else /* !CMS_MVS */ 1378 1379# ifdef TANDEM 1380 char cur_subvol [FILENAME_MAX]; 1381 char temp_subvol [FILENAME_MAX]; 1382 char *zptr; 1383 char *ptr; 1384 char *cptr = &cur_subvol[0]; 1385 char *tptr = &temp_subvol[0]; 1386 short err; 1387 FILE *tempf; 1388 int attempts; 1389 1390 t = (char *)malloc(NAMELEN); /* malloc here as you cannot free */ 1391 /* tmpnam allocated storage later */ 1392 1393 zptr = strrchr(zip, TANDEM_DELIMITER); 1394 1395 if (zptr != NULL) { 1396 /* ZIP file specifies a Subvol so make temp file there so it can just 1397 be renamed at end */ 1398 1399 *tptr = *cptr = '\0'; 1400 strcat(cptr, getenv("DEFAULTS")); 1401 1402 strncat(tptr, zip, _min(FILENAME_MAX, (zptr - zip)) ); /* temp subvol */ 1403 strncat(t, zip, _min(NAMELEN, ((zptr - zip) + 1)) ); /* temp stem */ 1404 1405 err = chvol(tptr); 1406 ptr = t + strlen(t); /* point to end of stem */ 1407 } 1408 else 1409 ptr = t; 1410 1411 /* If two zips are running in same subvol then we can get contention problems 1412 with the temporary filename. As a work around we attempt to create 1413 the file here, and if it already exists we get a new temporary name */ 1414 1415 attempts = 0; 1416 do { 1417 attempts++; 1418 tmpnam(ptr); /* Add filename */ 1419 tempf = zfopen(ptr, FOPW_TMP); /* Attempt to create file */ 1420 } while (tempf == NULL && attempts < 100); 1421 1422 if (attempts >= 100) { 1423 ziperr(ZE_TEMP, "Could not get unique temp file name"); 1424 } 1425 1426 fclose(tempf); 1427 1428 if (zptr != NULL) { 1429 err = chvol(cptr); /* Put ourself back to where we came in */ 1430 } 1431 1432 return t; 1433 1434# else /* !CMS_MVS && !TANDEM */ 1435/* 1436 * Do something with TMPDIR, TMP, TEMP ???? 1437 */ 1438 if (tempath != NULL) 1439 { 1440 if ((t = malloc(strlen(tempath) + 12)) == NULL) 1441 return NULL; 1442 strcpy(t, tempath); 1443 1444# if (!defined(VMS) && !defined(TOPS20)) 1445# ifdef MSDOS 1446 { 1447 char c = (char)lastchar(t); 1448 if (c != '/' && c != ':' && c != '\\') 1449 strcat(t, "/"); 1450 } 1451# else 1452 1453# ifdef AMIGA 1454 { 1455 char c = (char)lastchar(t); 1456 if (c != '/' && c != ':') 1457 strcat(t, "/"); 1458 } 1459# else /* !AMIGA */ 1460# ifdef RISCOS 1461 if (lastchar(t) != '.') 1462 strcat(t, "."); 1463# else /* !RISCOS */ 1464 1465# ifdef QDOS 1466 if (lastchar(t) != '_') 1467 strcat(t, "_"); 1468# else 1469 if (lastchar(t) != '/') 1470 strcat(t, "/"); 1471# endif /* ?QDOS */ 1472# endif /* ?RISCOS */ 1473# endif /* ?AMIGA */ 1474# endif /* ?MSDOS */ 1475# endif /* !VMS && !TOPS20 */ 1476 } 1477 else 1478 { 1479 if ((t = malloc(12)) == NULL) 1480 return NULL; 1481 *t = 0; 1482 } 1483# ifdef NO_MKTEMP 1484 { 1485 char *p = t + strlen(t); 1486 sprintf(p, "%08lx", (ulg)time(NULL)); 1487 return t; 1488 } 1489# else 1490 strcat(t, "ziXXXXXX"); /* must use lowercase for Linux dos file system */ 1491# if defined(UNIX) && !defined(NO_MKSTEMP) 1492 /* tempname should not be called */ 1493 return t; 1494# else 1495 return mktemp(t); 1496# endif 1497# endif /* NO_MKTEMP */ 1498# endif /* TANDEM */ 1499# endif /* CMS_MVS */ 1500} 1501#endif /* !VMS */ 1502 1503int fcopy(f, g, n) 1504 FILE *f, *g; /* source and destination files */ 1505 /* now use uzoff_t for all file sizes 5/14/05 CS */ 1506 uzoff_t n; /* number of bytes to copy or -1 for all */ 1507/* Copy n bytes from file *f to file *g, or until EOF if (zoff_t)n == -1. 1508 Return an error code in the ZE_ class. */ 1509{ 1510 char *b; /* malloc'ed buffer for copying */ 1511 extent k; /* result of fread() */ 1512 uzoff_t m; /* bytes copied so far */ 1513 1514 if ((b = malloc(CBSZ)) == NULL) 1515 return ZE_MEM; 1516 m = 0; 1517 while (n == (uzoff_t)(-1L) || m < n) 1518 { 1519 if ((k = fread(b, 1, n == (uzoff_t)(-1) ? 1520 CBSZ : (n - m < CBSZ ? (extent)(n - m) : CBSZ), f)) == 0) 1521 { 1522 if (ferror(f)) 1523 { 1524 free((zvoid *)b); 1525 return ZE_READ; 1526 } 1527 else 1528 break; 1529 } 1530 if (fwrite(b, 1, k, g) != k) 1531 { 1532 free((zvoid *)b); 1533 fprintf(mesg," fcopy: write error\n"); 1534 return ZE_TEMP; 1535 } 1536 m += k; 1537 } 1538 free((zvoid *)b); 1539 return ZE_OK; 1540} 1541 1542 1543/* from zipfile.c */ 1544 1545#ifdef THEOS 1546 /* Macros cause stack overflow in compiler */ 1547 ush SH(uch* p) { return ((ush)(uch)((p)[0]) | ((ush)(uch)((p)[1]) << 8)); } 1548 ulg LG(uch* p) { return ((ulg)(SH(p)) | ((ulg)(SH((p)+2)) << 16)); } 1549#else /* !THEOS */ 1550 /* Macros for converting integers in little-endian to machine format */ 1551# define SH(a) ((ush)(((ush)(uch)(a)[0]) | (((ush)(uch)(a)[1]) << 8))) 1552# define LG(a) ((ulg)SH(a) | ((ulg)SH((a)+2) << 16)) 1553# ifdef ZIP64_SUPPORT /* zip64 support 08/31/2003 R.Nausedat */ 1554# define LLG(a) ((zoff_t)LG(a) | ((zoff_t)LG((a)+4) << 32)) 1555# endif 1556#endif /* ?THEOS */ 1557 1558 1559/* always copies from global in_file to global output file y */ 1560int bfcopy(n) 1561 /* now use uzoff_t for all file sizes 5/14/05 CS */ 1562 uzoff_t n; /* number of bytes to copy or -1 for all */ 1563/* Copy n bytes from in_file to out_file, or until EOF if (zoff_t)n == -1. 1564 1565 Normally we have the compressed size from either the central directory 1566 entry or the local header. 1567 1568 If n != -1 and EOF, close current split and open next and continue 1569 copying. 1570 1571 If n == -2, copy until find the extended header (data descriptor). Only 1572 used for -FF when no size available. 1573 1574 If fix == 1 calculate CRC of input entry and verify matches. 1575 1576 If fix == 2 and this entry using data descriptor keep a sliding 1577 window in the buffer for looking for signature. 1578 1579 Return an error code in the ZE_ class. */ 1580{ 1581 char *b; /* malloc'ed buffer for copying */ 1582 extent k; /* result of fread() */ 1583 uzoff_t m; /* bytes copied so far */ 1584 extent brd; /* bytes to read */ 1585 zoff_t data_start = 0; 1586 zoff_t des_start = 0; 1587 char *split_path; 1588 extent kk; 1589 int i; 1590 char sbuf[4]; /* buffer for sliding signature window for fix = 2 */ 1591 int des = 0; /* this entry has data descriptor to find */ 1592 1593 if ((b = malloc(CBSZ)) == NULL) 1594 return ZE_MEM; 1595 1596 if (copy_only && !display_globaldots) { 1597 /* initialize dot count */ 1598 dot_count = -1; 1599 } 1600 1601 if (fix == 2 && n == (uzoff_t) -2) { 1602 data_start = zftello(in_file); 1603 for (kk = 0; kk < 4; kk++) 1604 sbuf[kk] = 0; 1605 des = 1; 1606 } 1607 1608 des_good = 0; 1609 1610 m = 0; 1611 while (des || n == (uzoff_t)(-1L) || m < n) 1612 { 1613 if (des || n == (uzoff_t)(-1)) 1614 brd = CBSZ; 1615 else 1616 brd = (n - m < CBSZ ? (extent)(n - m) : CBSZ); 1617 1618 des_start = zftello(in_file); 1619 1620 if ((k = fread(b, 1, brd, in_file)) == 0) 1621 { 1622 if (fix == 2 && k < brd) { 1623 free((zvoid *)b); 1624 return ZE_READ; 1625 } 1626 else if (ferror(in_file)) 1627 { 1628 free((zvoid *)b); 1629 return ZE_READ; 1630 } 1631 else { 1632 break; 1633 } 1634 } 1635 1636 1637 /* end at extended local header (data descriptor) signature */ 1638 if (des) { 1639 des_crc = 0; 1640 des_csize = 0; 1641 des_usize = 0; 1642 1643 /* If first 4 bytes in buffer are data descriptor signature then 1644 try to read the data descriptor. 1645 If not, scan for signature and break if found, let bfwrite flush 1646 the data and then next read should put the data descriptor at 1647 the beginning of the buffer. 1648 */ 1649 1650 if ( 1651 (b[0] != 0x50 /*'P' except EBCDIC*/ || 1652 b[1] != 0x4b /*'K' except EBCDIC*/ || 1653 b[2] != '\07' || 1654 b[3] != '\010')) { 1655 /* buffer is not start of data descriptor */ 1656 1657 for (kk = 0; kk < k; kk++) { 1658 /* add byte to end of sbuf */ 1659 for (i = 0; i < 3; i++) 1660 sbuf[i] = sbuf[i + 1]; 1661 sbuf[3] = b[kk]; 1662 1663 /* see if this is signature */ 1664 if ( 1665 (sbuf[0] == 0x50 /*'P' except EBCDIC*/ && 1666 sbuf[1] == 0x4b /*'K' except EBCDIC*/ && 1667 sbuf[2] == '\07' && 1668 sbuf[3] == '\010')) { 1669 kk -= 3; 1670 if (zfseeko(in_file, bytes_this_split + kk, SEEK_SET) != 0) { 1671 /* seek error */ 1672 ZIPERR(ZE_READ, "seek failed reading descriptor"); 1673 } 1674 des_start = zftello(in_file); 1675 k = kk; 1676 break; 1677 } 1678 } 1679 } 1680 else 1681 1682 /* signature at start of buffer */ 1683 { 1684 des_good = 0; 1685 1686#ifdef ZIP64_SUPPORT 1687 if (zip64_entry) { 1688 1689 /* read Zip64 data descriptor */ 1690 if (k < 24) { 1691 /* not enough bytes, so can't be data descriptor 1692 as data descriptors can't be split across splits 1693 */ 1694 } 1695 else 1696 { 1697 /* read the Zip64 descriptor */ 1698 1699 des_crc = LG(b + 4); 1700 des_csize = LLG(b + 8); 1701 des_usize = LLG(b + 16); 1702 1703 /* if this is the right data descriptor then the sizes should match */ 1704 if ((uzoff_t)des_start - (uzoff_t)data_start != des_csize) { 1705 /* apparently this signature does not go with this data so skip */ 1706 1707 /* write out signature as data */ 1708 k = 4; 1709 if (zfseeko(in_file, des_start + k, SEEK_SET) != 0) { 1710 /* seek error */ 1711 ZIPERR(ZE_READ, "seek failed reading descriptor"); 1712 } 1713 if (bfwrite(b, 1, k, BFWRITE_DATA) != k) 1714 { 1715 free((zvoid *)b); 1716 fprintf(mesg," fcopy: write error\n"); 1717 return ZE_TEMP; 1718 } 1719 m += k; 1720 continue; 1721 } 1722 else 1723 { 1724 /* apparently this is the correct data descriptor */ 1725 1726 /* we should check the CRC but would need to inflate 1727 the data */ 1728 1729 /* skip descriptor as will write out later */ 1730 des_good = 1; 1731 k = 24; 1732 data_start = zftello(in_file); 1733 if (zfseeko(in_file, des_start + k, SEEK_SET) != 0) { 1734 /* seek error */ 1735 ZIPERR(ZE_READ, "seek failed reading descriptor"); 1736 } 1737 data_start = zftello(in_file); 1738 } 1739 } 1740 1741 } 1742 else 1743#endif 1744 { 1745 /* read standard data descriptor */ 1746 1747 if (k < 16) { 1748 /* not enough bytes, so can't be data descriptor 1749 as data descriptors can't be split across splits 1750 */ 1751 } 1752 else 1753 { 1754 /* read the descriptor */ 1755 1756 des_crc = LG(b + 4); 1757 des_csize = LG(b + 8); 1758 des_usize = LG(b + 12); 1759 1760 /* if this is the right data descriptor then the sizes should match */ 1761 if ((uzoff_t)des_start - (uzoff_t)data_start != des_csize) { 1762 /* apparently this signature does not go with this data so skip */ 1763 1764 /* write out signature as data */ 1765 k = 4; 1766 if (zfseeko(in_file, des_start + k, SEEK_SET) != 0) { 1767 /* seek error */ 1768 ZIPERR(ZE_READ, "seek failed reading descriptor"); 1769 } 1770 if (bfwrite(b, 1, k, BFWRITE_DATA) != k) 1771 { 1772 free((zvoid *)b); 1773 fprintf(mesg," fcopy: write error\n"); 1774 return ZE_TEMP; 1775 } 1776 m += k; 1777 continue; 1778 } 1779 else 1780 { 1781 /* apparently this is the correct data descriptor */ 1782 1783 /* we should check the CRC but this does not work for 1784 encrypted data */ 1785 1786 /* skip descriptor as will write out later */ 1787 des_good = 1; 1788 data_start = zftello(in_file); 1789 k = 16; 1790 if (zfseeko(in_file, des_start + k, SEEK_SET) != 0) { 1791 /* seek error */ 1792 ZIPERR(ZE_READ, "seek failed reading descriptor"); 1793 } 1794 data_start = zftello(in_file); 1795 } 1796 } 1797 1798 1799 } 1800 } 1801 } 1802 1803 1804 if (des_good) { 1805 /* skip descriptor as will write out later */ 1806 } else { 1807 /* write out apparently wrong descriptor as data */ 1808 if (bfwrite(b, 1, k, BFWRITE_DATA) != k) 1809 { 1810 free((zvoid *)b); 1811 fprintf(mesg," fcopy: write error\n"); 1812 return ZE_TEMP; 1813 } 1814 m += k; 1815 } 1816 1817 if (copy_only && !display_globaldots) { 1818 if (dot_size > 0) { 1819 /* initial space */ 1820 if (noisy && dot_count == -1) { 1821#ifndef WINDLL 1822 putc(' ', mesg); 1823 fflush(mesg); 1824#else 1825 fprintf(stdout,"%c",' '); 1826#endif 1827 dot_count++; 1828 } 1829 dot_count += k; 1830 if (dot_size <= dot_count) dot_count = 0; 1831 } 1832 if ((verbose || noisy) && dot_size && !dot_count) { 1833#ifndef WINDLL 1834 putc('.', mesg); 1835 fflush(mesg); 1836#else 1837 fprintf(stdout,"%c",'.'); 1838#endif 1839 mesg_line_started = 1; 1840 } 1841 } 1842 1843 if (des_good) 1844 break; 1845 1846 if (des) 1847 continue; 1848 1849 if ((des || n != (uzoff_t)(-1L)) && m < n && feof(in_file)) { 1850 /* open next split */ 1851 current_in_disk++; 1852 1853 if (current_in_disk >= total_disks) { 1854 /* done */ 1855 break; 1856 1857 } else if (current_in_disk == total_disks - 1) { 1858 /* last disk is archive.zip */ 1859 if ((split_path = malloc(strlen(in_path) + 1)) == NULL) { 1860 zipwarn("reading archive: ", in_path); 1861 return ZE_MEM; 1862 } 1863 strcpy(split_path, in_path); 1864 } else { 1865 /* other disks are archive.z01, archive.z02, ... */ 1866 split_path = get_in_split_path(in_path, current_in_disk); 1867 } 1868 1869 fclose(in_file); 1870 1871 /* open the split */ 1872 while ((in_file = zfopen(split_path, FOPR)) == NULL) { 1873 int r = 0; 1874 1875 /* could not open split */ 1876 1877 if (fix == 1 && skip_this_disk) { 1878 free(split_path); 1879 free((zvoid *)b); 1880 return ZE_FORM; 1881 } 1882 1883 /* Ask for directory with split. Updates in_path */ 1884 r = ask_for_split_read_path(current_in_disk); 1885 if (r == ZE_ABORT) { 1886 zipwarn("could not find split: ", split_path); 1887 free(split_path); 1888 free((zvoid *)b); 1889 return ZE_ABORT; 1890 } 1891 if (r == ZE_EOF) { 1892 zipmessage_nl("", 1); 1893 zipwarn("user ended reading - closing archive", ""); 1894 free(split_path); 1895 free((zvoid *)b); 1896 return ZE_EOF; 1897 } 1898 if (fix == 2 && skip_this_disk) { 1899 /* user asked to skip this disk */ 1900 zipwarn("skipping split file: ", split_path); 1901 current_in_disk++; 1902 } 1903 1904 if (current_in_disk == total_disks - 1) { 1905 /* last disk is archive.zip */ 1906 if ((split_path = malloc(strlen(in_path) + 1)) == NULL) { 1907 zipwarn("reading archive: ", in_path); 1908 return ZE_MEM; 1909 } 1910 strcpy(split_path, in_path); 1911 } else { 1912 /* other disks are archive.z01, archive.z02, ... */ 1913 split_path = get_in_split_path(zipfile, current_in_disk); 1914 } 1915 } 1916 if (fix == 2 && skip_this_disk) { 1917 /* user asked to skip this disk */ 1918 free(split_path); 1919 free((zvoid *)b); 1920 return ZE_FORM; 1921 } 1922 free(split_path); 1923 } 1924 } 1925 free((zvoid *)b); 1926 return ZE_OK; 1927} 1928 1929 1930 1931#ifdef NO_RENAME 1932int rename(from, to) 1933ZCONST char *from; 1934ZCONST char *to; 1935{ 1936 unlink(to); 1937 if (link(from, to) == -1) 1938 return -1; 1939 if (unlink(from) == -1) 1940 return -1; 1941 return 0; 1942} 1943 1944#endif /* NO_RENAME */ 1945 1946 1947#ifdef ZMEM 1948 1949/************************/ 1950/* Function memset() */ 1951/************************/ 1952 1953/* 1954 * memset - for systems without it 1955 * bill davidsen - March 1990 1956 */ 1957 1958char * 1959memset(buf, init, len) 1960register char *buf; /* buffer loc */ 1961register int init; /* initializer */ 1962register unsigned int len; /* length of the buffer */ 1963{ 1964 char *start; 1965 1966 start = buf; 1967 while (len--) *(buf++) = init; 1968 return(start); 1969} 1970 1971 1972/************************/ 1973/* Function memcpy() */ 1974/************************/ 1975 1976char * 1977memcpy(dst,src,len) /* v2.0f */ 1978register char *dst, *src; 1979register unsigned int len; 1980{ 1981 char *start; 1982 1983 start = dst; 1984 while (len--) 1985 *dst++ = *src++; 1986 return(start); 1987} 1988 1989 1990/************************/ 1991/* Function memcmp() */ 1992/************************/ 1993 1994int 1995memcmp(b1,b2,len) /* jpd@usl.edu -- 11/16/90 */ 1996register char *b1, *b2; 1997register unsigned int len; 1998{ 1999 2000 if (len) do { /* examine each byte (if any) */ 2001 if (*b1++ != *b2++) 2002 return (*((uch *)b1-1) - *((uch *)b2-1)); /* exit when miscompare */ 2003 } while (--len); 2004 2005 return(0); /* no miscompares, yield 0 result */ 2006} 2007 2008#endif /* ZMEM */ 2009 2010 2011/*------------------------------------------------------------------ 2012 * Split archives 2013 */ 2014 2015 2016/* ask_for_split_read_path 2017 * 2018 * If the next split file is not in the current directory, ask 2019 * the user where it is. 2020 * 2021 * in_path is the base path for reading splits and is usually 2022 * the same as zipfile. The path in in_path must be the archive 2023 * file ending in .zip as this is assumed by get_in_split_path(). 2024 * 2025 * Updates in_path if changed. Returns ZE_OK if OK or ZE_ABORT if 2026 * user cancels reading archive. 2027 * 2028 * If fix = 1 then allow skipping disk (user may not have it). 2029 */ 2030 2031#define SPLIT_MAXPATH (FNMAX + 4010) 2032 2033int ask_for_split_read_path(current_disk) 2034 ulg current_disk; 2035{ 2036 FILE *f; 2037 int is_readable = 0; 2038 int i; 2039 char *split_dir = NULL; 2040 char *archive_name = NULL; 2041 char *split_name = NULL; 2042 char *split_path = NULL; 2043 char buf[SPLIT_MAXPATH + 100]; 2044 2045 /* get split path */ 2046 split_path = get_in_split_path(in_path, current_disk); 2047 2048 /* get the directory */ 2049 if ((split_dir = malloc(strlen(in_path) + 40)) == NULL) { 2050 ZIPERR(ZE_MEM, "split path"); 2051 } 2052 strcpy(split_dir, in_path); 2053 2054 /* remove any name at end */ 2055 for (i = strlen(split_dir) - 1; i >= 0; i--) { 2056 if (split_dir[i] == '/' || split_dir[i] == '\\' 2057 || split_dir[i] == ':') { 2058 split_dir[i + 1] = '\0'; 2059 break; 2060 } 2061 } 2062 if (i < 0) 2063 split_dir[0] = '\0'; 2064 2065 /* get the name of the archive */ 2066 if ((archive_name = malloc(strlen(in_path) + 1)) == NULL) { 2067 ZIPERR(ZE_MEM, "split path"); 2068 } 2069 if (strlen(in_path) == strlen(split_dir)) { 2070 archive_name[0] = '\0'; 2071 } else { 2072 strcpy(archive_name, in_path + strlen(split_dir)); 2073 } 2074 2075 /* get the name of the split */ 2076 if ((split_name = malloc(strlen(split_path) + 1)) == NULL) { 2077 ZIPERR(ZE_MEM, "split path"); 2078 } 2079 if (strlen(in_path) == strlen(split_dir)) { 2080 split_name[0] = '\0'; 2081 } else { 2082 strcpy(split_name, split_path + strlen(split_dir)); 2083 } 2084 if (i < 0) { 2085 strcpy(split_dir, "(current directory)"); 2086 } 2087 2088 fprintf(mesg, "\n\nCould not find:\n"); 2089 fprintf(mesg, " %s\n", split_path); 2090 /* 2091 fprintf(mesg, "Please enter the path directory (. for cur dir) where\n"); 2092 fprintf(mesg, " %s\n", split_name); 2093 fprintf(mesg, "is located\n"); 2094 */ 2095 for (;;) { 2096 if (is_readable) { 2097 fprintf(mesg, "\nHit c (change path to where this split file is)"); 2098 fprintf(mesg, "\n q (abort archive - quit)"); 2099 fprintf(mesg, "\n or ENTER (continue with this split): "); 2100 } else { 2101 if (fix == 1) { 2102 fprintf(mesg, "\nHit c (change path to where this split file is)"); 2103 fprintf(mesg, "\n s (skip this split)"); 2104 fprintf(mesg, "\n q (abort archive - quit)"); 2105 fprintf(mesg, "\n or ENTER (try reading this split again): "); 2106 } else if (fix == 2) { 2107 fprintf(mesg, "\nHit c (change path to where this split file is)"); 2108 fprintf(mesg, "\n s (skip this split)"); 2109 fprintf(mesg, "\n q (abort archive - quit)"); 2110 fprintf(mesg, "\n e (end this archive - no more splits)"); 2111 fprintf(mesg, "\n z (look for .zip split - the last split)"); 2112 fprintf(mesg, "\n or ENTER (try reading this split again): "); 2113 } else { 2114 fprintf(mesg, "\nHit c (change path to where this split file is)"); 2115 fprintf(mesg, "\n q (abort archive - quit)"); 2116 fprintf(mesg, "\n or ENTER (try reading this split again): "); 2117 } 2118 } 2119 fflush(mesg); 2120 fgets(buf, SPLIT_MAXPATH, stdin); 2121 /* remove any newline */ 2122 for (i = 0; buf[i]; i++) { 2123 if (buf[i] == '\n') { 2124 buf[i] = '\0'; 2125 break; 2126 } 2127 } 2128 if (toupper(buf[0]) == 'Q') { 2129 return ZE_ABORT; 2130 } else if ((fix == 1 || fix == 2) && toupper(buf[0]) == 'S') { 2131 /* 2132 fprintf(mesg, "\nSkip this split/disk? (files in this split will not be recovered) [n/y] "); 2133 fflush(mesg); 2134 fgets(buf, SPLIT_MAXPATH, stdin); 2135 if (buf[0] == 'y' || buf[0] == 'Y') { 2136 */ 2137 skip_this_disk = current_in_disk + 1; 2138 return ZE_FORM; 2139 } else if (toupper(buf[0]) == 'C') { 2140 fprintf(mesg, "\nEnter path where this split is (ENTER = same dir, . = current dir)"); 2141 fprintf(mesg, "\n: "); 2142 fflush(mesg); 2143 fgets(buf, SPLIT_MAXPATH, stdin); 2144 is_readable = 0; 2145 /* remove any newline */ 2146 for (i = 0; buf[i]; i++) { 2147 if (buf[i] == '\n') { 2148 buf[i] = '\0'; 2149 break; 2150 } 2151 } 2152 if (buf[0] == '\0') { 2153 /* Hit ENTER so try old path again - could be removable media was changed */ 2154 strcpy(buf, split_path); 2155 } 2156 } else if (fix == 2 && toupper(buf[0]) == 'E') { 2157 /* no more splits to read */ 2158 return ZE_EOF; 2159 } else if (fix == 2 && toupper(buf[0]) == 'Z') { 2160 total_disks = current_disk + 1; 2161 free(split_path); 2162 split_path = get_in_split_path(in_path, current_disk); 2163 buf[0] = '\0'; 2164 strncat(buf, split_path, SPLIT_MAXPATH); 2165 } 2166 if (strlen(buf) > 0) { 2167 /* changing path */ 2168 2169 /* check if user wants current directory */ 2170 if (buf[0] == '.' && buf[1] == '\0') { 2171 buf[0] = '\0'; 2172 } 2173 /* remove any name at end */ 2174 for (i = strlen(buf); i >= 0; i--) { 2175 if (buf[i] == '/' || buf[i] == '\\' 2176 || buf[i] == ':') { 2177 buf[i + 1] = '\0'; 2178 break; 2179 } 2180 } 2181 /* update base_path to newdir/split_name - in_path is the .zip file path */ 2182 free(in_path); 2183 if (i < 0) { 2184 /* just name so current directory */ 2185 strcpy(buf, "(current directory)"); 2186 if (archive_name == NULL) { 2187 i = 0; 2188 } else { 2189 i = strlen(archive_name); 2190 } 2191 if ((in_path = malloc(strlen(archive_name) + 40)) == NULL) { 2192 ZIPERR(ZE_MEM, "split path"); 2193 } 2194 strcpy(in_path, archive_name); 2195 } else { 2196 /* not the current directory */ 2197 /* remove any name at end */ 2198 for (i = strlen(buf); i >= 0; i--) { 2199 if (buf[i] == '/') { 2200 buf[i + 1] = '\0'; 2201 break; 2202 } 2203 } 2204 if (i < 0) { 2205 buf[0] = '\0'; 2206 } 2207 if ((in_path = malloc(strlen(buf) + strlen(archive_name) + 40)) == NULL) { 2208 ZIPERR(ZE_MEM, "split path"); 2209 } 2210 strcpy(in_path, buf); 2211 strcat(in_path, archive_name); 2212 } 2213 2214 free(split_path); 2215 2216 /* get split path */ 2217 split_path = get_in_split_path(in_path, current_disk); 2218 2219 free(split_dir); 2220 if ((split_dir = malloc(strlen(in_path) + 40)) == NULL) { 2221 ZIPERR(ZE_MEM, "split path"); 2222 } 2223 strcpy(split_dir, in_path); 2224 /* remove any name at end */ 2225 for (i = strlen(split_dir); i >= 0; i--) { 2226 if (split_dir[i] == '/') { 2227 split_dir[i + 1] = '\0'; 2228 break; 2229 } 2230 } 2231 2232 /* try to open it */ 2233 if ((f = fopen(split_path, "r")) == NULL) { 2234 fprintf(mesg, "\nCould not find or open\n"); 2235 fprintf(mesg, " %s\n", split_path); 2236 /* 2237 fprintf(mesg, "Please enter the path (. for cur dir) where\n"); 2238 fprintf(mesg, " %s\n", split_name); 2239 fprintf(mesg, "is located\n"); 2240 */ 2241 continue; 2242 } 2243 fclose(f); 2244 is_readable = 1; 2245 fprintf(mesg, "Found: %s\n", split_path); 2246 } else { 2247 /* try to open it */ 2248 if ((f = fopen(split_path, "r")) == NULL) { 2249 fprintf(mesg, "\nCould not find or open\n"); 2250 fprintf(mesg, " %s\n", split_path); 2251 /* 2252 fprintf(mesg, "Please enter the path (. for cur dir) where\n"); 2253 fprintf(mesg, " %s\n", split_name); 2254 fprintf(mesg, "is located\n"); 2255 */ 2256 continue; 2257 } 2258 fclose(f); 2259 is_readable = 1; 2260 fprintf(mesg, "\nFound: %s\n", split_path); 2261 break; 2262 } 2263 } 2264 free(archive_name); 2265 free(split_dir); 2266 free(split_name); 2267 2268 return ZE_OK; 2269} 2270 2271 2272/* ask_for_split_write_path 2273 * 2274 * Verify the directory for the next split. Called 2275 * when -sp is used to pause between writing splits. 2276 * 2277 * Updates out_path and return 1 if OK or 0 if cancel 2278 */ 2279int ask_for_split_write_path(current_disk) 2280 ulg current_disk; 2281{ 2282 unsigned int num = (unsigned int)current_disk + 1; 2283 int i; 2284 char *split_dir = NULL; 2285 char *split_name = NULL; 2286 char buf[FNMAX + 40]; 2287 2288 /* get the directory */ 2289 if ((split_dir = malloc(strlen(out_path) + 40)) == NULL) { 2290 ZIPERR(ZE_MEM, "split path"); 2291 } 2292 strcpy(split_dir, out_path); 2293 2294 /* remove any name at end */ 2295 for (i = strlen(split_dir); i >= 0; i--) { 2296 if (split_dir[i] == '/' || split_dir[i] == '\\' 2297 || split_dir[i] == ':') { 2298 split_dir[i + 1] = '\0'; 2299 break; 2300 } 2301 } 2302 2303 /* get the name of the split */ 2304 if ((split_name = malloc(strlen(out_path) + 1)) == NULL) { 2305 ZIPERR(ZE_MEM, "split path"); 2306 } 2307 if (strlen(out_path) == strlen(split_dir)) { 2308 split_name[0] = '\0'; 2309 } else { 2310 strcpy(split_name, out_path + strlen(split_dir)); 2311 } 2312 if (i < 0) { 2313 strcpy(split_dir, "(current directory)"); 2314 } 2315 if (mesg_line_started) 2316 fprintf(mesg, "\n"); 2317 fprintf(mesg, "\nOpening disk %d\n", num); 2318 fprintf(mesg, "Hit ENTER to write to default path of\n"); 2319 fprintf(mesg, " %s\n", split_dir); 2320 fprintf(mesg, "or enter a new directory path (. for cur dir) and hit ENTER\n"); 2321 for (;;) { 2322 fprintf(mesg, "\nPath (or hit ENTER to continue): "); 2323 fflush(mesg); 2324 fgets(buf, FNMAX, stdin); 2325 /* remove any newline */ 2326 for (i = 0; buf[i]; i++) { 2327 if (buf[i] == '\n') { 2328 buf[i] = '\0'; 2329 break; 2330 } 2331 } 2332 if (strlen(buf) > 0) { 2333 /* changing path */ 2334 2335 /* current directory */ 2336 if (buf[0] == '.' && buf[1] == '\0') { 2337 buf[0] = '\0'; 2338 } 2339 /* remove any name at end */ 2340 for (i = strlen(buf); i >= 0; i--) { 2341 if (buf[i] == '/' || buf[i] == '\\' 2342 || buf[i] == ':') { 2343 buf[i + 1] = '\0'; 2344 break; 2345 } 2346 } 2347 /* update out_path to newdir/split_name */ 2348 free(out_path); 2349 if (i < 0) { 2350 /* just name so current directory */ 2351 strcpy(buf, "(current directory)"); 2352 if (split_name == NULL) { 2353 i = 0; 2354 } else { 2355 i = strlen(split_name); 2356 } 2357 if ((out_path = malloc(strlen(split_name) + 40)) == NULL) { 2358 ZIPERR(ZE_MEM, "split path"); 2359 } 2360 strcpy(out_path, split_name); 2361 } else { 2362 /* not the current directory */ 2363 /* remove any name at end */ 2364 for (i = strlen(buf); i >= 0; i--) { 2365 if (buf[i] == '/') { 2366 buf[i + 1] = '\0'; 2367 break; 2368 } 2369 } 2370 if (i < 0) { 2371 buf[0] = '\0'; 2372 } 2373 if ((out_path = malloc(strlen(buf) + strlen(split_name) + 40)) == NULL) { 2374 ZIPERR(ZE_MEM, "split path"); 2375 } 2376 strcpy(out_path, buf); 2377 strcat(out_path, split_name); 2378 } 2379 fprintf(mesg, "Writing to:\n %s\n", buf); 2380 free(split_name); 2381 free(split_dir); 2382 if ((split_dir = malloc(strlen(out_path) + 40)) == NULL) { 2383 ZIPERR(ZE_MEM, "split path"); 2384 } 2385 strcpy(split_dir, out_path); 2386 /* remove any name at end */ 2387 for (i = strlen(split_dir); i >= 0; i--) { 2388 if (split_dir[i] == '/') { 2389 split_dir[i + 1] = '\0'; 2390 break; 2391 } 2392 } 2393 if ((split_name = malloc(strlen(out_path) + 1)) == NULL) { 2394 ZIPERR(ZE_MEM, "split path"); 2395 } 2396 strcpy(split_name, out_path + strlen(split_dir)); 2397 } else { 2398 break; 2399 } 2400 } 2401 free(split_dir); 2402 free(split_name); 2403 2404 /* for now no way out except Ctrl C */ 2405 return 1; 2406} 2407 2408 2409/* split_name 2410 * 2411 * get name of split being read 2412 */ 2413char *get_in_split_path(base_path, disk_number) 2414 char *base_path; 2415 ulg disk_number; 2416{ 2417 char *split_path = NULL; 2418 int base_len = 0; 2419 int path_len = 0; 2420 ulg num = disk_number + 1; 2421 char ext[6]; 2422#ifdef VMS 2423 int vers_len; /* File version length. */ 2424 char *vers_ptr; /* File version string. */ 2425#endif /* def VMS */ 2426 2427 /* 2428 * A split has extension z01, z02, ..., z99, z100, z101, ... z999 2429 * We currently support up to .z99999 2430 * WinZip will also read .100, .101, ... but AppNote 6.2.2 uses above 2431 * so use that. Means on DOS can only have 100 splits. 2432 */ 2433 2434 if (num == total_disks) { 2435 /* last disk is base path */ 2436 if ((split_path = malloc(strlen(base_path) + 1)) == NULL) { 2437 ZIPERR(ZE_MEM, "base path"); 2438 } 2439 strcpy(split_path, base_path); 2440 2441 return split_path; 2442 } else { 2443 if (num > 99999) { 2444 ZIPERR(ZE_BIG, "More than 99999 splits needed"); 2445 } 2446 sprintf(ext, "z%02lu", num); 2447 } 2448 2449 /* create path for this split - zip.c checked for .zip extension */ 2450 base_len = strlen(base_path) - 3; 2451 path_len = base_len + strlen(ext); 2452 2453#ifdef VMS 2454 /* On VMS, locate the file version, and adjust base_len accordingly. 2455 Note that path_len is correct, as-is. 2456 */ 2457 vers_ptr = vms_file_version( base_path); 2458 vers_len = strlen( vers_ptr); 2459 base_len -= vers_len; 2460#endif /* def VMS */ 2461 2462 if ((split_path = malloc(path_len + 1)) == NULL) { 2463 ZIPERR(ZE_MEM, "split path"); 2464 } 2465 /* copy base_path except for end zip */ 2466 strcpy(split_path, base_path); 2467 split_path[base_len] = '\0'; 2468 /* add extension */ 2469 strcat(split_path, ext); 2470 2471#ifdef VMS 2472 /* On VMS, append (preserve) the file version. */ 2473 strcat(split_path, vers_ptr); 2474#endif /* def VMS */ 2475 2476 return split_path; 2477} 2478 2479 2480/* split_name 2481 * 2482 * get name of split being written 2483 */ 2484char *get_out_split_path(base_path, disk_number) 2485 char *base_path; 2486 ulg disk_number; 2487{ 2488 char *split_path = NULL; 2489 int base_len = 0; 2490 int path_len = 0; 2491 ulg num = disk_number + 1; 2492 char ext[6]; 2493#ifdef VMS 2494 int vers_len; /* File version length. */ 2495 char *vers_ptr; /* File version string. */ 2496#endif /* def VMS */ 2497 2498 /* 2499 * A split has extension z01, z02, ..., z99, z100, z101, ... z999 2500 * We currently support up to .z99999 2501 * WinZip will also read .100, .101, ... but AppNote 6.2.2 uses above 2502 * so use that. Means on DOS can only have 100 splits. 2503 */ 2504 2505 if (num > 99999) { 2506 ZIPERR(ZE_BIG, "More than 99999 splits needed"); 2507 } 2508 sprintf(ext, "z%02lu", num); 2509 2510 /* create path for this split - zip.c checked for .zip extension */ 2511 base_len = strlen(base_path) - 3; 2512 path_len = base_len + strlen(ext); 2513 2514#ifdef VMS 2515 /* On VMS, locate the file version, and adjust base_len accordingly. 2516 Note that path_len is correct, as-is. 2517 */ 2518 vers_ptr = vms_file_version( base_path); 2519 vers_len = strlen( vers_ptr); 2520 base_len -= vers_len; 2521#endif /* def VMS */ 2522 2523 if ((split_path = malloc(path_len + 1)) == NULL) { 2524 ZIPERR(ZE_MEM, "split path"); 2525 } 2526 /* copy base_path except for end zip */ 2527 strcpy(split_path, base_path); 2528 split_path[base_len] = '\0'; 2529 /* add extension */ 2530 strcat(split_path, ext); 2531 2532#ifdef VMS 2533 /* On VMS, append (preserve) the file version. */ 2534 strcat(split_path, vers_ptr); 2535#endif /* def VMS */ 2536 2537 return split_path; 2538} 2539 2540/* close_split 2541 * 2542 * close a split - assume that the paths needed for the splits are 2543 * available. 2544 */ 2545int close_split(disk_number, tempfile, temp_name) 2546 ulg disk_number; 2547 FILE *tempfile; 2548 char *temp_name; 2549{ 2550 char *split_path = NULL; 2551 2552 split_path = get_out_split_path(out_path, disk_number); 2553 2554 if (noisy_splits) { 2555 zipmessage("\tClosing split ", split_path); 2556 } 2557 2558 fclose(tempfile); 2559 2560 rename_split(temp_name, split_path); 2561 set_filetype(split_path); 2562 2563 return ZE_OK; 2564} 2565 2566/* bfwrite 2567 Does the fwrite but also counts bytes and does splits */ 2568size_t bfwrite(buffer, size, count, mode) 2569 ZCONST void *buffer; 2570 size_t size; 2571 size_t count; 2572 int mode; 2573{ 2574 size_t bytes_written = 0; 2575 size_t r; 2576 size_t b = size * count; 2577 uzoff_t bytes_left_in_split = 0; 2578 size_t bytes_to_write = b; 2579 2580 2581 /* -------------------------------- */ 2582 /* local header */ 2583 if (mode == BFWRITE_LOCALHEADER) { 2584 /* writing local header - reset entry data count */ 2585 bytes_this_entry = 0; 2586 /* save start of local header so we can rewrite later */ 2587 current_local_file = y; 2588 current_local_disk = current_disk; 2589 current_local_offset = bytes_this_split; 2590 } 2591 2592 if (split_size == 0) 2593 bytes_left_in_split = bytes_to_write; 2594 else 2595 bytes_left_in_split = split_size - bytes_this_split; 2596 2597 if (bytes_to_write > bytes_left_in_split) { 2598 if (mode == BFWRITE_HEADER || 2599 mode == BFWRITE_LOCALHEADER || 2600 mode == BFWRITE_CENTRALHEADER) { 2601 /* if can't write entire header save for next split */ 2602 bytes_to_write = 0; 2603 } else { 2604 /* normal data so fill the split */ 2605 bytes_to_write = (size_t)bytes_left_in_split; 2606 } 2607 } 2608 2609 /* -------------------------------- */ 2610 /* central header */ 2611 if (mode == BFWRITE_CENTRALHEADER) { 2612 /* set start disk for CD */ 2613 if (cd_start_disk == (ulg)-1) { 2614 cd_start_disk = current_disk; 2615 cd_start_offset = bytes_this_split; 2616 } 2617 cd_entries_this_disk++; 2618 total_cd_entries++; 2619 } 2620 2621 /* -------------------------------- */ 2622 if (bytes_to_write > 0) { 2623 /* write out the bytes for this split */ 2624 r = fwrite(buffer, size, bytes_to_write, y); 2625 bytes_written += r; 2626 bytes_to_write = b - r; 2627 bytes_this_split += r; 2628 if (mode == BFWRITE_DATA) 2629 /* if data descriptor do not include in count */ 2630 bytes_this_entry += r; 2631 } else { 2632 bytes_to_write = b; 2633 } 2634 2635 if (bytes_to_write > 0) { 2636 if (split_method) { 2637 /* still bytes to write so close split and open next split */ 2638 bytes_prev_splits += bytes_this_split; 2639 2640 if (split_method == 1 && ferror(y)) { 2641 /* if writing all splits to same place and have problem then bad */ 2642 ZIPERR(ZE_WRITE, "Could not write split"); 2643 } 2644 2645 if (split_method == 2 && ferror(y)) { 2646 /* A split must be at least 64K except last .zip split */ 2647 if (bytes_this_split < 64 * (uzoff_t)0x400) { 2648 ZIPERR(ZE_WRITE, "Not enough space to write split"); 2649 } 2650 } 2651 2652 /* close this split */ 2653 if (split_method == 1 && current_local_disk == current_disk) { 2654 /* keep split open so can update it */ 2655 current_local_tempname = tempzip; 2656 } else { 2657 /* close split */ 2658 close_split(current_disk, y, tempzip); 2659 y = NULL; 2660 free(tempzip); 2661 tempzip = NULL; 2662 } 2663 cd_entries_this_disk = 0; 2664 bytes_this_split = 0; 2665 2666 /* increment disk - disks are numbered 0, 1, 2, ... and 2667 splits are 01, 02, ... */ 2668 current_disk++; 2669 2670 if (split_method == 2 && split_bell) { 2671 /* bell when pause to ask for next split */ 2672 putc('\007', mesg); 2673 fflush(mesg); 2674 } 2675 2676 for (;;) { 2677 /* if method 2 pause and allow changing path */ 2678 if (split_method == 2) { 2679 if (ask_for_split_write_path(current_disk) == 0) { 2680 ZIPERR(ZE_ABORT, "could not write split"); 2681 } 2682 } 2683 2684 /* open next split */ 2685#if defined(UNIX) && !defined(NO_MKSTEMP) 2686 { 2687 int yd; 2688 int i; 2689 2690 /* use mkstemp to avoid race condition and compiler warning */ 2691 2692 if (tempath != NULL) 2693 { 2694 /* if -b used to set temp file dir use that for split temp */ 2695 if ((tempzip = malloc(strlen(tempath) + 12)) == NULL) { 2696 ZIPERR(ZE_MEM, "allocating temp filename"); 2697 } 2698 strcpy(tempzip, tempath); 2699 if (lastchar(tempzip) != '/') 2700 strcat(tempzip, "/"); 2701 } 2702 else 2703 { 2704 /* create path by stripping name and appending template */ 2705 if ((tempzip = malloc(strlen(zipfile) + 12)) == NULL) { 2706 ZIPERR(ZE_MEM, "allocating temp filename"); 2707 } 2708 strcpy(tempzip, zipfile); 2709 for(i = strlen(tempzip); i > 0; i--) { 2710 if (tempzip[i - 1] == '/') 2711 break; 2712 } 2713 tempzip[i] = '\0'; 2714 } 2715 strcat(tempzip, "ziXXXXXX"); 2716 2717 if ((yd = mkstemp(tempzip)) == EOF) { 2718 ZIPERR(ZE_TEMP, tempzip); 2719 } 2720 if ((y = fdopen(yd, FOPW_TMP)) == NULL) { 2721 ZIPERR(ZE_TEMP, tempzip); 2722 } 2723 } 2724#else 2725 if ((tempzip = tempname(zipfile)) == NULL) { 2726 ZIPERR(ZE_MEM, "allocating temp filename"); 2727 } 2728 if ((y = zfopen(tempzip, FOPW_TMP)) == NULL) { 2729 ZIPERR(ZE_TEMP, tempzip); 2730 } 2731#endif 2732 2733 r = fwrite((char *)buffer + bytes_written, 1, bytes_to_write, y); 2734 bytes_written += r; 2735 bytes_this_split += r; 2736 if (!(mode == BFWRITE_HEADER || 2737 mode == BFWRITE_LOCALHEADER || 2738 mode == BFWRITE_CENTRALHEADER)) { 2739 bytes_this_entry += r; 2740 } 2741 if (bytes_to_write > r) { 2742 /* buffer bigger than split */ 2743 if (split_method == 2) { 2744 /* let user choose another disk */ 2745 zipwarn("Not enough room on disk", ""); 2746 continue; 2747 } else { 2748 ZIPERR(ZE_WRITE, "Not enough room on disk"); 2749 } 2750 } 2751 if (mode == BFWRITE_LOCALHEADER || 2752 mode == BFWRITE_HEADER || 2753 mode == BFWRITE_CENTRALHEADER) { 2754 if (split_method == 1 && current_local_file && 2755 current_local_disk != current_disk) { 2756 /* We're opening a new split because the next header 2757 did not fit on the last split. We need to now close 2758 the last split and update the pointers for 2759 the current split. */ 2760 close_split(current_local_disk, current_local_file, 2761 current_local_tempname); 2762 free(current_local_tempname); 2763 } 2764 current_local_tempname = tempzip; 2765 current_local_file = y; 2766 current_local_offset = 0; 2767 current_local_disk = current_disk; 2768 } 2769 break; 2770 } 2771 } 2772 else 2773 { 2774 /* likely have more than fits but no splits */ 2775 2776 /* probably already have error "no space left on device" */ 2777 /* could let flush_outbuf() handle error but bfwrite() is called for 2778 headers also */ 2779 if (ferror(y)) 2780 ziperr(ZE_WRITE, "write error on zip file"); 2781 } 2782 } 2783 2784 2785 /* display dots for archive instead of for each file */ 2786 if (display_globaldots) { 2787 if (dot_size > 0) { 2788 /* initial space */ 2789 if (dot_count == -1) { 2790#ifndef WINDLL 2791 putc(' ', mesg); 2792 fflush(mesg); 2793#else 2794 fprintf(stdout,"%c",' '); 2795#endif 2796 /* assume a header will be written first, so avoid 0 */ 2797 dot_count = 1; 2798 } 2799 /* skip incrementing dot count for small buffers like for headers */ 2800 if (size * count > 1000) { 2801 dot_count++; 2802 if (dot_size <= dot_count * (zoff_t)size * (zoff_t)count) dot_count = 0; 2803 } 2804 } 2805 if (dot_size && !dot_count) { 2806 dot_count++; 2807#ifndef WINDLL 2808 putc('.', mesg); 2809 fflush(mesg); 2810#else 2811 fprintf(stdout,"%c",'.'); 2812#endif 2813 mesg_line_started = 1; 2814 } 2815 } 2816 2817 2818 return bytes_written; 2819} 2820 2821 2822#ifdef UNICODE_SUPPORT 2823 2824/*--------------------------------------------- 2825 * Unicode conversion functions 2826 * 2827 * Provided by Paul Kienitz 2828 * 2829 * Some modifications to work with Zip 2830 * 2831 *--------------------------------------------- 2832 */ 2833 2834/* 2835 NOTES APPLICABLE TO ALL STRING FUNCTIONS: 2836 2837 All of the x_to_y functions take parameters for an output buffer and 2838 its available length, and return an int. The value returned is the 2839 length of the string that the input produces, which may be larger than 2840 the provided buffer length. If the returned value is less than the 2841 buffer length, then the contents of the buffer will be null-terminated; 2842 otherwise, it will not be terminated and may be invalid, possibly 2843 stopping in the middle of a multibyte sequence. 2844 2845 In all cases you may pass NULL as the buffer and/or 0 as the length, if 2846 you just want to learn how much space the string is going to require. 2847 2848 The functions will return -1 if the input is invalid UTF-8 or cannot be 2849 encoded as UTF-8. 2850*/ 2851 2852/* utility functions for managing UTF-8 and UCS-4 strings */ 2853 2854 2855/* utf8_char_bytes 2856 * 2857 * Returns the number of bytes used by the first character in a UTF-8 2858 * string, or -1 if the UTF-8 is invalid or null. 2859 */ 2860local int utf8_char_bytes(utf8) 2861 ZCONST char *utf8; 2862{ 2863 int t, r; 2864 unsigned lead; 2865 2866 if (!utf8) 2867 return -1; /* no input */ 2868 lead = (unsigned char) *utf8; 2869 if (lead < 0x80) 2870 r = 1; /* an ascii-7 character */ 2871 else if (lead < 0xC0) 2872 return -1; /* error: trailing byte without lead byte */ 2873 else if (lead < 0xE0) 2874 r = 2; /* an 11 bit character */ 2875 else if (lead < 0xF0) 2876 r = 3; /* a 16 bit character */ 2877 else if (lead < 0xF8) 2878 r = 4; /* a 21 bit character (the most currently used) */ 2879 else if (lead < 0xFC) 2880 r = 5; /* a 26 bit character (shouldn't happen) */ 2881 else if (lead < 0xFE) 2882 r = 6; /* a 31 bit character (shouldn't happen) */ 2883 else 2884 return -1; /* error: invalid lead byte */ 2885 for (t = 1; t < r; t++) 2886 if ((unsigned char) utf8[t] < 0x80 || (unsigned char) utf8[t] >= 0xC0) 2887 return -1; /* error: not enough valid trailing bytes */ 2888 return r; 2889} 2890 2891 2892/* ucs4_char_from_utf8 2893 * 2894 * Given a reference to a pointer into a UTF-8 string, returns the next 2895 * UCS-4 character and advances the pointer to the next character sequence. 2896 * Returns ~0 and does not advance the pointer when input is ill-formed. 2897 * 2898 * Since the Unicode standard says 32-bit values won't be used (just 2899 * up to the current 21-bit mappings) changed this to signed to allow -1 to 2900 * be returned. 2901 */ 2902long ucs4_char_from_utf8(utf8) 2903 ZCONST char **utf8; 2904{ 2905 ulg ret; 2906 int t, bytes; 2907 2908 if (!utf8) 2909 return -1; /* no input */ 2910 bytes = utf8_char_bytes(*utf8); 2911 if (bytes <= 0) 2912 return -1; /* invalid input */ 2913 if (bytes == 1) 2914 ret = **utf8; /* ascii-7 */ 2915 else 2916 ret = **utf8 & (0x7F >> bytes); /* lead byte of a multibyte sequence */ 2917 (*utf8)++; 2918 for (t = 1; t < bytes; t++) /* consume trailing bytes */ 2919 ret = (ret << 6) | (*((*utf8)++) & 0x3F); 2920 return (long) ret; 2921} 2922 2923 2924/* utf8_from_ucs4_char - Convert UCS char to UTF-8 2925 * 2926 * Returns the number of bytes put into utf8buf to represent ch, from 1 to 6, 2927 * or -1 if ch is too large to represent. utf8buf must have room for 6 bytes. 2928 */ 2929local int utf8_from_ucs4_char(utf8buf, ch) 2930 char *utf8buf; 2931 ulg ch; 2932{ 2933 int trailing = 0; 2934 int leadmask = 0x80; 2935 int leadbits = 0x3F; 2936 ulg tch = ch; 2937 int ret; 2938 2939 if (ch > 0x7FFFFFFF) 2940 return -1; /* UTF-8 can represent 31 bits */ 2941 if (ch < 0x7F) 2942 { 2943 *utf8buf++ = (char) ch; /* ascii-7 */ 2944 return 1; 2945 } 2946 do { 2947 trailing++; 2948 leadmask = (leadmask >> 1) | 0x80; 2949 leadbits >>= 1; 2950 tch >>= 6; 2951 } while (tch & ~leadbits); 2952 ret = trailing + 1; 2953 /* produce lead byte */ 2954 *utf8buf++ = (char) (leadmask | (ch >> (6 * trailing))); 2955 /* produce trailing bytes */ 2956 while (--trailing >= 0) 2957 *utf8buf++ = (char) (0x80 | ((ch >> (6 * trailing)) & 0x3F)); 2958 return ret; 2959} 2960 2961 2962/*===================================================================*/ 2963 2964/* utf8_to_ucs4_string - convert UTF-8 string to UCS string 2965 * 2966 * Return UCS count. Now returns int so can return -1. 2967 */ 2968local int utf8_to_ucs4_string(utf8, ucs4buf, buflen) 2969 ZCONST char *utf8; 2970 ulg *ucs4buf; 2971 int buflen; 2972{ 2973 int count = 0; 2974 2975 for (;;) 2976 { 2977 long ch = ucs4_char_from_utf8(&utf8); 2978 if (ch == -1) 2979 return -1; 2980 else 2981 { 2982 if (ucs4buf && count < buflen) 2983 ucs4buf[count] = ch; 2984 if (ch == 0) 2985 return count; 2986 count++; 2987 } 2988 } 2989} 2990 2991 2992/* ucs4_string_to_utf8 2993 * 2994 * 2995 */ 2996local int ucs4_string_to_utf8(ucs4, utf8buf, buflen) 2997 ZCONST ulg *ucs4; 2998 char *utf8buf; 2999 int buflen; 3000{ 3001 char mb[6]; 3002 int count = 0; 3003 3004 if (!ucs4) 3005 return -1; 3006 for (;;) 3007 { 3008 int mbl = utf8_from_ucs4_char(mb, *ucs4++); 3009 int c; 3010 if (mbl <= 0) 3011 return -1; 3012 /* We could optimize this a bit by passing utf8buf + count */ 3013 /* directly to utf8_from_ucs4_char when buflen >= count + 6... */ 3014 c = buflen - count; 3015 if (mbl < c) 3016 c = mbl; 3017 if (utf8buf && count < buflen) 3018 strncpy(utf8buf + count, mb, c); 3019 if (mbl == 1 && !mb[0]) 3020 return count; /* terminating nul */ 3021 count += mbl; 3022 } 3023} 3024 3025 3026#if 0 /* currently unused */ 3027/* utf8_chars 3028 * 3029 * Wrapper: counts the actual unicode characters in a UTF-8 string. 3030 */ 3031local int utf8_chars(utf8) 3032 ZCONST char *utf8; 3033{ 3034 return utf8_to_ucs4_string(utf8, NULL, 0); 3035} 3036#endif 3037 3038 3039/* --------------------------------------------------- */ 3040/* Unicode Support 3041 * 3042 * These functions common for all Unicode ports. 3043 * 3044 * These functions should allocate and return strings that can be 3045 * freed with free(). 3046 * 3047 * 8/27/05 EG 3048 * 3049 * Use zwchar for wide char which is unsigned long 3050 * in zip.h and 32 bits. This avoids problems with 3051 * different sizes of wchar_t. 3052 */ 3053 3054#ifdef WIN32 3055 3056zwchar *wchar_to_wide_string(wchar_string) 3057 wchar_t *wchar_string; 3058{ 3059 int i; 3060 int wchar_len; 3061 zwchar *wide_string; 3062 3063 wchar_len = wcslen(wchar_string); 3064 3065 if ((wide_string = malloc((wchar_len + 1) * sizeof(zwchar))) == NULL) { 3066 ZIPERR(ZE_MEM, "wchar to wide conversion"); 3067 } 3068 for (i = 0; i <= wchar_len; i++) { 3069 wide_string[i] = wchar_string[i]; 3070 } 3071 3072 return wide_string; 3073} 3074 3075/* is_ascii_stringw 3076 * Checks if a wide string is all ascii 3077 */ 3078int is_ascii_stringw(wstring) 3079 wchar_t *wstring; 3080{ 3081 wchar_t *pw; 3082 wchar_t cw; 3083 3084 if (wstring == NULL) 3085 return 0; 3086 3087 for (pw = wstring; (cw = *pw) != '\0'; pw++) { 3088 if (cw > 0x7F) { 3089 return 0; 3090 } 3091 } 3092 return 1; 3093} 3094 3095#endif 3096 3097/* is_ascii_string 3098 * Checks if a string is all ascii 3099 */ 3100int is_ascii_string(mbstring) 3101 char *mbstring; 3102{ 3103 char *p; 3104 uch c; 3105 3106 if (mbstring == NULL) 3107 return 0; 3108 3109 for (p = mbstring; (c = (uch)*p) != '\0'; p++) { 3110 if (c > 0x7F) { 3111 return 0; 3112 } 3113 } 3114 return 1; 3115} 3116 3117/* local to UTF-8 */ 3118char *local_to_utf8_string(local_string) 3119 char *local_string; 3120{ 3121 zwchar *wide_string = local_to_wide_string(local_string); 3122 char *utf8_string = wide_to_utf8_string(wide_string); 3123 3124 free(wide_string); 3125 return utf8_string; 3126} 3127 3128/* wide_char_to_escape_string 3129 provides a string that represents a wide char not in local char set 3130 3131 An initial try at an algorithm. Suggestions welcome. 3132 3133 If not an ASCII char, probably need 2 bytes at least. So if 3134 a 2-byte wide encode it as 4 hex digits with a leading #U. 3135 Since the Unicode standard has been frozen, it looks like 3 bytes 3136 should be enough for any large Unicode character. In these cases 3137 prefix the string with #L. 3138 So 3139 #U1234 3140 is a 2-byte wide character with bytes 0x12 and 0x34 while 3141 #L123456 3142 is a 3-byte wide with bytes 0x12, 0x34, and 0x56. 3143 On Windows, wide that need two wide characters as a surrogate pair 3144 to represent them need to be converted to a single number. 3145 */ 3146 3147 /* set this to the max bytes an escape can be */ 3148#define MAX_ESCAPE_BYTES 8 3149 3150char *wide_char_to_escape_string(wide_char) 3151 zwchar wide_char; 3152{ 3153 int i; 3154 zwchar w = wide_char; 3155 uch b[9]; 3156 char e[7]; 3157 int len; 3158 char *r; 3159 3160 /* fill byte array with zeros */ 3161 for (len = 0; len < sizeof(zwchar); len++) { 3162 b[len] = 0; 3163 } 3164 /* get bytes in right to left order */ 3165 for (len = 0; w; len++) { 3166 b[len] = (char)(w % 0x100); 3167 w /= 0x100; 3168 } 3169 3170 if ((r = malloc(MAX_ESCAPE_BYTES + 8)) == NULL) { 3171 ZIPERR(ZE_MEM, "wide_char_to_escape_string"); 3172 } 3173 strcpy(r, "#"); 3174 /* either 2 bytes or 4 bytes */ 3175 if (len < 3) { 3176 len = 2; 3177 strcat(r, "U"); 3178 } else { 3179 len = 3; 3180 strcat(r, "L"); 3181 } 3182 for (i = len - 1; i >= 0; i--) { 3183 sprintf(e, "%02x", b[i]); 3184 strcat(r, e); 3185 } 3186 return r; 3187} 3188 3189#if 0 3190/* returns the wide character represented by the escape string */ 3191zwchar escape_string_to_wide(escape_string) 3192 char *escape_string; 3193{ 3194 int i; 3195 zwchar w; 3196 char c; 3197 char u; 3198 int len; 3199 char *e = escape_string; 3200 3201 if (e == NULL) { 3202 return 0; 3203 } 3204 if (e[0] != '#') { 3205 /* no leading # */ 3206 return 0; 3207 } 3208 len = strlen(e); 3209 /* either #U1234 or #L123456 format */ 3210 if (len != 6 && len != 8) { 3211 return 0; 3212 } 3213 w = 0; 3214 if (e[1] == 'L') { 3215 if (len != 8) { 3216 return 0; 3217 } 3218 /* 3 bytes */ 3219 for (i = 2; i < 8; i++) { 3220 c = e[i]; 3221 u = toupper(c); 3222 if (u >= 'A' && u <= 'F') { 3223 w = w * 0x10 + (zwchar)(u + 10 - 'A'); 3224 } else if (c >= '0' && c <= '9') { 3225 w = w * 0x10 + (zwchar)(c - '0'); 3226 } else { 3227 return 0; 3228 } 3229 } 3230 } else if (e[1] == 'U') { 3231 /* 2 bytes */ 3232 for (i = 2; i < 6; i++) { 3233 c = e[i]; 3234 u = toupper(c); 3235 if (u >= 'A' && u <= 'F') { 3236 w = w * 0x10 + (zwchar)(u + 10 - 'A'); 3237 } else if (c >= '0' && c <= '9') { 3238 w = w * 0x10 + (zwchar)(c - '0'); 3239 } else { 3240 return 0; 3241 } 3242 } 3243 } 3244 return w; 3245} 3246#endif 3247 3248 3249char *local_to_escape_string(local_string) 3250 char *local_string; 3251{ 3252 zwchar *wide_string = local_to_wide_string(local_string); 3253 char *escape_string = wide_to_escape_string(wide_string); 3254 3255 free(wide_string); 3256 return escape_string; 3257} 3258 3259#ifdef WIN32 3260char *wchar_to_local_string(wstring) 3261 wchar_t *wstring; 3262{ 3263 zwchar *wide_string = wchar_to_wide_string(wstring); 3264 char *local_string = wide_to_local_string(wide_string); 3265 3266 free(wide_string); 3267 3268 return local_string; 3269} 3270#endif 3271 3272 3273#ifndef WIN32 /* The Win32 port uses a system-specific variant. */ 3274/* convert wide character string to multi-byte character string */ 3275char *wide_to_local_string(wide_string) 3276 zwchar *wide_string; 3277{ 3278 int i; 3279 wchar_t wc; 3280 int b; 3281 int state_dependent; 3282 int wsize = 0; 3283 int max_bytes = MB_CUR_MAX; 3284 char buf[9]; 3285 char *buffer = NULL; 3286 char *local_string = NULL; 3287 3288 for (wsize = 0; wide_string[wsize]; wsize++) ; 3289 3290 if (MAX_ESCAPE_BYTES > max_bytes) 3291 max_bytes = MAX_ESCAPE_BYTES; 3292 3293 if ((buffer = (char *)malloc(wsize * max_bytes + 1)) == NULL) { 3294 ZIPERR(ZE_MEM, "wide_to_local_string"); 3295 } 3296 3297 /* convert it */ 3298 buffer[0] = '\0'; 3299 /* set initial state if state-dependent encoding */ 3300 wc = (wchar_t)'a'; 3301 b = wctomb(NULL, wc); 3302 if (b == 0) 3303 state_dependent = 0; 3304 else 3305 state_dependent = 1; 3306 for (i = 0; i < wsize; i++) { 3307 if (sizeof(wchar_t) < 4 && wide_string[i] > 0xFFFF) { 3308 /* wchar_t probably 2 bytes */ 3309 /* could do surrogates if state_dependent and wctomb can do */ 3310 wc = zwchar_to_wchar_t_default_char; 3311 } else { 3312 wc = (wchar_t)wide_string[i]; 3313 } 3314 b = wctomb(buf, wc); 3315 if (unicode_escape_all) { 3316 if (b == 1 && (uch)buf[0] <= 0x7f) { 3317 /* ASCII */ 3318 strncat(buffer, buf, b); 3319 } else { 3320 /* use escape for wide character */ 3321 char *e = wide_char_to_escape_string(wide_string[i]); 3322 strcat(buffer, e); 3323 free(e); 3324 } 3325 } else if (b > 0) { 3326 /* multi-byte char */ 3327 strncat(buffer, buf, b); 3328 } else { 3329 /* no MB for this wide */ 3330 if (use_wide_to_mb_default) { 3331 /* default character */ 3332 strcat(buffer, wide_to_mb_default_string); 3333 } else { 3334 /* use escape for wide character */ 3335 char *e = wide_char_to_escape_string(wide_string[i]); 3336 strcat(buffer, e); 3337 free(e); 3338 } 3339 } 3340 } 3341 if ((local_string = (char *)malloc(strlen(buffer) + 1)) == NULL) { 3342 free(buffer); 3343 ZIPERR(ZE_MEM, "wide_to_local_string"); 3344 } 3345 strcpy(local_string, buffer); 3346 free(buffer); 3347 3348 return local_string; 3349} 3350#endif /* !WIN32 */ 3351 3352 3353/* convert wide character string to escaped string */ 3354char *wide_to_escape_string(wide_string) 3355 zwchar *wide_string; 3356{ 3357 int i; 3358 int wsize = 0; 3359 char buf[9]; 3360 char *buffer = NULL; 3361 char *escape_string = NULL; 3362 3363 for (wsize = 0; wide_string[wsize]; wsize++) ; 3364 3365 if ((buffer = (char *)malloc(wsize * MAX_ESCAPE_BYTES + 1)) == NULL) { 3366 ZIPERR(ZE_MEM, "wide_to_escape_string"); 3367 } 3368 3369 /* convert it */ 3370 buffer[0] = '\0'; 3371 for (i = 0; i < wsize; i++) { 3372 if (wide_string[i] <= 0x7f && isprint((char)wide_string[i])) { 3373 /* ASCII */ 3374 buf[0] = (char)wide_string[i]; 3375 buf[1] = '\0'; 3376 strcat(buffer, buf); 3377 } else { 3378 /* use escape for wide character */ 3379 char *e = wide_char_to_escape_string(wide_string[i]); 3380 strcat(buffer, e); 3381 free(e); 3382 } 3383 } 3384 if ((escape_string = (char *)malloc(strlen(buffer) + 1)) == NULL) { 3385 ZIPERR(ZE_MEM, "wide_to_escape_string"); 3386 } 3387 strcpy(escape_string, buffer); 3388 free(buffer); 3389 3390 return escape_string; 3391} 3392 3393 3394/* convert local string to display character set string */ 3395char *local_to_display_string(local_string) 3396 char *local_string; 3397{ 3398 char *temp_string; 3399 char *display_string; 3400 3401 /* For Windows, OEM string should never be bigger than ANSI string, says 3402 CharToOem description. 3403 On UNIX, non-printable characters (0x00 - 0xFF) will be replaced by 3404 "^x", so more space may be needed. Note that "^" itself is a valid 3405 name character, so this leaves an ambiguity, but UnZip displays 3406 names this way, too. (0x00 is not possible, I hope.) 3407 For all other ports, just make a copy of local_string. 3408 */ 3409 3410#ifdef UNIX 3411 char *cp_dst; /* Character pointers used in the */ 3412 char *cp_src; /* copying/changing procedure. */ 3413#endif 3414 3415 if ((temp_string = (char *)malloc(2 * strlen(local_string) + 1)) == NULL) { 3416 ZIPERR(ZE_MEM, "local_to_display_string"); 3417 } 3418 3419#ifdef WIN32 3420 /* convert to OEM display character set */ 3421 local_to_oem_string(temp_string, local_string); 3422#else 3423# ifdef UNIX 3424 /* Copy source string, expanding non-printable characters to "^x". */ 3425 cp_dst = temp_string; 3426 cp_src = local_string; 3427 while (*cp_src != '\0') { 3428 if ((unsigned char)*cp_src < ' ') { 3429 *cp_dst++ = '^'; 3430 *cp_dst++ = '@'+ *cp_src++; 3431 } 3432 else { 3433 *cp_dst++ = *cp_src++; 3434 } 3435 } 3436 *cp_dst = '\0'; 3437# else /* not UNIX */ 3438 strcpy(temp_string, local_string); 3439# endif /* UNIX */ 3440#endif 3441 3442#ifdef EBCDIC 3443 { 3444 char *ebc; 3445 3446 if ((ebc = malloc(strlen(display_string) + 1)) == NULL) { 3447 ZIPERR(ZE_MEM, "local_to_display_string"); 3448 } 3449 strtoebc(ebc, display_string); 3450 free(display_string); 3451 display_string = ebc; 3452 } 3453#endif 3454 3455 if ((display_string = (char *)malloc(strlen(temp_string) + 1)) == NULL) { 3456 ZIPERR(ZE_MEM, "local_to_display_string"); 3457 } 3458 strcpy(display_string, temp_string); 3459 free(temp_string); 3460 3461 return display_string; 3462} 3463 3464/* UTF-8 to local */ 3465char *utf8_to_local_string(utf8_string) 3466 char *utf8_string; 3467{ 3468 zwchar *wide_string = utf8_to_wide_string(utf8_string); 3469 char *loc = wide_to_local_string(wide_string); 3470 if (wide_string) 3471 free(wide_string); 3472 return loc; 3473} 3474 3475/* UTF-8 to local */ 3476char *utf8_to_escape_string(utf8_string) 3477 char *utf8_string; 3478{ 3479 zwchar *wide_string = utf8_to_wide_string(utf8_string); 3480 char *escape_string = wide_to_escape_string(wide_string); 3481 free(wide_string); 3482 return escape_string; 3483} 3484 3485#ifndef WIN32 /* The Win32 port uses a system-specific variant. */ 3486/* convert multi-byte character string to wide character string */ 3487zwchar *local_to_wide_string(local_string) 3488 char *local_string; 3489{ 3490 int wsize; 3491 wchar_t *wc_string; 3492 zwchar *wide_string; 3493 3494 /* for now try to convert as string - fails if a bad char in string */ 3495 wsize = mbstowcs(NULL, local_string, MB_CUR_MAX ); 3496 if (wsize == (size_t)-1) { 3497 /* could not convert */ 3498 return NULL; 3499 } 3500 3501 /* convert it */ 3502 if ((wc_string = (wchar_t *)malloc((wsize + 1) * sizeof(wchar_t))) == NULL) { 3503 ZIPERR(ZE_MEM, "local_to_wide_string"); 3504 } 3505 wsize = mbstowcs(wc_string, local_string, strlen(local_string) + 1); 3506 wc_string[wsize] = (wchar_t) 0; 3507 3508 /* in case wchar_t is not zwchar */ 3509 if ((wide_string = (zwchar *)malloc((wsize + 1) * sizeof(zwchar))) == NULL) { 3510 ZIPERR(ZE_MEM, "local_to_wide_string"); 3511 } 3512 for (wsize = 0; (wide_string[wsize] = (zwchar)wc_string[wsize]); wsize++) ; 3513 wide_string[wsize] = (zwchar)0; 3514 free(wc_string); 3515 3516 return wide_string; 3517} 3518#endif /* !WIN32 */ 3519 3520 3521#if 0 3522/* All wchar functions are only used by Windows and are 3523 now in win32zip.c so that the Windows functions can 3524 be used and multiple character wide characters can 3525 be handled easily. */ 3526# ifndef WIN32 3527char *wchar_to_utf8_string(wstring) 3528 wchar_t *wstring; 3529{ 3530 zwchar *wide_string = wchar_to_wide_string(wstring); 3531 char *local_string = wide_to_utf8_string(wide_string); 3532 3533 free(wide_string); 3534 3535 return local_string; 3536} 3537# endif 3538#endif 3539 3540 3541/* convert wide string to UTF-8 */ 3542char *wide_to_utf8_string(wide_string) 3543 zwchar *wide_string; 3544{ 3545 int mbcount; 3546 char *utf8_string; 3547 3548 /* get size of utf8 string */ 3549 mbcount = ucs4_string_to_utf8(wide_string, NULL, 0); 3550 if (mbcount == -1) 3551 return NULL; 3552 if ((utf8_string = (char *) malloc(mbcount + 1)) == NULL) { 3553 ZIPERR(ZE_MEM, "wide_to_utf8_string"); 3554 } 3555 mbcount = ucs4_string_to_utf8(wide_string, utf8_string, mbcount + 1); 3556 if (mbcount == -1) 3557 return NULL; 3558 3559 return utf8_string; 3560} 3561 3562/* convert UTF-8 string to wide string */ 3563zwchar *utf8_to_wide_string(utf8_string) 3564 char *utf8_string; 3565{ 3566 int wcount; 3567 zwchar *wide_string; 3568 3569 wcount = utf8_to_ucs4_string(utf8_string, NULL, 0); 3570 if (wcount == -1) 3571 return NULL; 3572 if ((wide_string = (zwchar *) malloc((wcount + 2) * sizeof(zwchar))) == NULL) { 3573 ZIPERR(ZE_MEM, "utf8_to_wide_string"); 3574 } 3575 wcount = utf8_to_ucs4_string(utf8_string, wide_string, wcount + 1); 3576 3577 return wide_string; 3578} 3579 3580 3581#endif /* UNICODE_SUPPORT */ 3582 3583 3584/*--------------------------------------------------------------- 3585 * Long option support 3586 * 8/23/2003 3587 * 3588 * Defines function get_option() to get and process the command 3589 * line options and arguments from argv[]. The caller calls 3590 * get_option() in a loop to get either one option and possible 3591 * value or a non-option argument each loop. 3592 * 3593 * This version does not include argument file support and can 3594 * work directly on argv. The argument file code complicates things and 3595 * it seemed best to leave it out for now. If argument file support (reading 3596 * in command line arguments stored in a file and inserting into 3597 * command line where @filename is found) is added later the arguments 3598 * can change and a freeable copy of argv will be needed and can be 3599 * created using copy_args in the left out code. 3600 * 3601 * Supports short and long options as defined in the array options[] 3602 * in zip.c, multiple short options in an argument (like -jlv), long 3603 * option abbreviation (like --te for --temp-file if --te unique), 3604 * short and long option values (like -b filename or --temp-file filename 3605 * or --temp-file=filename), optional and required values, option negation 3606 * by trailing - (like -S- to not include hidden and system files in MSDOS), 3607 * value lists (like -x a b c), argument permuting (returning all options 3608 * and values before any non-option arguments), and argument files (where any 3609 * non-option non-value argument in form @path gets substituted with the 3610 * white space separated arguments in the text file at path). In this 3611 * version argument file support has been removed to simplify development but 3612 * may be added later. 3613 * 3614 * E. Gordon 3615 */ 3616 3617 3618/* message output - char casts are needed to handle constants */ 3619#define oWARN(message) zipwarn((char *) message, "") 3620#define oERR(err,message) ZIPERR(err, (char *) message) 3621 3622 3623/* Although the below provides some support for multibyte characters 3624 the proper thing to do may be to use wide characters and support 3625 Unicode. May get to it soon. EG 3626 */ 3627 3628/* For now stay with muti-byte characters. May support wide characters 3629 in Zip 3.1. 3630 */ 3631 3632/* multibyte character set support 3633 Multibyte characters use typically two or more sequential bytes 3634 to represent additional characters than can fit in a single byte 3635 character set. The code used here is based on the ANSI mblen function. */ 3636#ifdef MULTIBYTE_GETOPTNS 3637 int mb_clen(ptr) 3638 ZCONST char *ptr; 3639 { 3640 /* return the number of bytes that the char pointed to is. Return 1 if 3641 null character or error like not start of valid multibyte character. */ 3642 int cl; 3643 3644 cl = mblen(ptr, MB_CUR_MAX); 3645 return (cl > 0) ? cl : 1; 3646 } 3647#endif 3648 3649 3650 /* moved to zip.h */ 3651#if 0 3652#ifdef UNICODE_SUPPORT 3653# define MB_CLEN(ptr) (1) 3654# define MB_NEXTCHAR(ptr) ((ptr)++) 3655# ifdef MULTIBYTE_GETOPTNS 3656# undef MULTIBYTE_GETOPTNS 3657# endif 3658#else 3659# ifdef _MBCS 3660# ifndef MULTIBYTE_GETOPTNS 3661# define MULTIBYTE_GETOPTNS 3662# endif 3663# endif 3664/* multibyte character set support 3665 Multibyte characters use typically two or more sequential bytes 3666 to represent additional characters than can fit in a single byte 3667 character set. The code used here is based on the ANSI mblen function. */ 3668# ifdef MULTIBYTE_GETOPTNS 3669 local int mb_clen OF((ZCONST char *)); /* declare proto first */ 3670 local int mb_clen(ptr) 3671 ZCONST char *ptr; 3672 { 3673 /* return the number of bytes that the char pointed to is. Return 1 if 3674 null character or error like not start of valid multibyte character. */ 3675 int cl; 3676 3677 cl = mblen(ptr, MB_CUR_MAX); 3678 return (cl > 0) ? cl : 1; 3679 } 3680# define MB_CLEN(ptr) mb_clen(ptr) 3681# define MB_NEXTCHAR(ptr) ((ptr) += MB_CLEN(ptr)) 3682# else 3683# define MB_CLEN(ptr) (1) 3684# define MB_NEXTCHAR(ptr) ((ptr)++) 3685# endif 3686#endif 3687#endif 3688 3689 3690/* constants */ 3691 3692/* function get_args_from_arg_file() can return this in depth parameter */ 3693#define ARG_FILE_ERR -1 3694 3695/* internal settings for optchar */ 3696#define SKIP_VALUE_ARG -1 3697#define THIS_ARG_DONE -2 3698#define START_VALUE_LIST -3 3699#define IN_VALUE_LIST -4 3700#define NON_OPTION_ARG -5 3701#define STOP_VALUE_LIST -6 3702/* 7/25/04 EG */ 3703#define READ_REST_ARGS_VERBATIM -7 3704 3705 3706/* global veriables */ 3707 3708int enable_permute = 1; /* yes - return options first */ 3709/* 7/25/04 EG */ 3710int doubledash_ends_options = 1; /* when -- what follows are not options */ 3711 3712/* buffer for error messages (this sizing is a guess but must hold 2 paths) */ 3713#define OPTIONERR_BUF_SIZE (FNMAX * 2 + 4000) 3714local char Far optionerrbuf[OPTIONERR_BUF_SIZE + 1]; 3715 3716/* error messages */ 3717static ZCONST char Far op_not_neg_err[] = "option %s not negatable"; 3718static ZCONST char Far op_req_val_err[] = "option %s requires a value"; 3719static ZCONST char Far op_no_allow_val_err[] = "option %s does not allow a value"; 3720static ZCONST char Far sh_op_not_sup_err[] = "short option '%c' not supported"; 3721static ZCONST char Far oco_req_val_err[] = "option %s requires one character value"; 3722static ZCONST char Far oco_no_mbc_err[] = "option %s does not support multibyte values"; 3723static ZCONST char Far num_req_val_err[] = "option %s requires number value"; 3724static ZCONST char Far long_op_ambig_err[] = "long option '%s' ambiguous"; 3725static ZCONST char Far long_op_not_sup_err[] = "long option '%s' not supported"; 3726 3727static ZCONST char Far no_arg_files_err[] = "argument files not enabled\n"; 3728 3729 3730/* below removed as only used for processing argument files */ 3731 3732/* get_nextarg */ 3733/* get_args_from_string */ 3734/* insert_args */ 3735/* get_args_from_arg_file */ 3736 3737 3738/* copy error, option name, and option description if any to buf */ 3739local int optionerr(buf, err, optind, islong) 3740 char *buf; 3741 ZCONST char *err; 3742 int optind; 3743 int islong; 3744{ 3745 char optname[50]; 3746 3747 if (options[optind].name && options[optind].name[0] != '\0') { 3748 if (islong) 3749 sprintf(optname, "'%s' (%s)", options[optind].longopt, options[optind].name); 3750 else 3751 sprintf(optname, "'%s' (%s)", options[optind].shortopt, options[optind].name); 3752 } else { 3753 if (islong) 3754 sprintf(optname, "'%s'", options[optind].longopt); 3755 else 3756 sprintf(optname, "'%s'", options[optind].shortopt); 3757 } 3758 sprintf(buf, err, optname); 3759 return 0; 3760} 3761 3762 3763/* copy_args 3764 * 3765 * Copy arguments in args, allocating storage with malloc. 3766 * Copies until a NULL argument is found or until max_args args 3767 * including args[0] are copied. Set max_args to 0 to copy 3768 * until NULL. Always terminates returned args[] with NULL arg. 3769 * 3770 * Any argument in the returned args can be freed with free(). Any 3771 * freed argument should be replaced with either another string 3772 * allocated with malloc or by NULL if last argument so that free_args 3773 * will properly work. 3774 */ 3775char **copy_args(args, max_args) 3776 char **args; 3777 int max_args; 3778{ 3779 int j; 3780 char **new_args; 3781 3782 if (args == NULL) { 3783 return NULL; 3784 } 3785 3786 /* count args */ 3787 for (j = 0; args[j] && (max_args == 0 || j < max_args); j++) ; 3788 3789 if ((new_args = (char **) malloc((j + 1) * sizeof(char *))) == NULL) { 3790 oERR(ZE_MEM, "ca"); 3791 } 3792 3793 for (j = 0; args[j] && (max_args == 0 || j < max_args); j++) { 3794 if (args[j] == NULL) { 3795 /* null argument is end of args */ 3796 new_args[j] = NULL; 3797 break; 3798 } 3799 if ((new_args[j] = malloc(strlen(args[j]) + 1)) == NULL) { 3800 free_args(new_args); 3801 oERR(ZE_MEM, "ca"); 3802 } 3803 strcpy(new_args[j], args[j]); 3804 } 3805 new_args[j] = NULL; 3806 3807 return new_args; 3808} 3809 3810 3811/* free args - free args created with one of these functions */ 3812int free_args(args) 3813 char **args; 3814{ 3815 int i; 3816 3817 if (args == NULL) { 3818 return 0; 3819 } 3820 3821 for (i = 0; args[i]; i++) { 3822 free(args[i]); 3823 } 3824 free(args); 3825 return i; 3826} 3827 3828 3829/* insert_arg 3830 * 3831 * Insert the argument arg into the array args before argument at_arg. 3832 * Return the new count of arguments (argc). 3833 * 3834 * If free_args is true, this function frees the old args array 3835 * (but not the component strings). DO NOT set free_args on original 3836 * argv but only on args allocated with malloc. 3837 */ 3838 3839int insert_arg(pargs, arg, at_arg, free_args) 3840 char ***pargs; 3841 ZCONST char *arg; 3842 int at_arg; 3843 int free_args; 3844{ 3845 char *newarg = NULL; 3846 char **args; 3847 char **newargs = NULL; 3848 int argnum; 3849 int newargnum; 3850 int argcnt; 3851 int newargcnt; 3852 3853 if (pargs == NULL) { 3854 return 0; 3855 } 3856 args = *pargs; 3857 3858 /* count args */ 3859 if (args == NULL) { 3860 argcnt = 0; 3861 } else { 3862 for (argcnt = 0; args[argcnt]; argcnt++) ; 3863 } 3864 if (arg == NULL) { 3865 /* done */ 3866 return argcnt; 3867 } 3868 newargcnt = argcnt + 1; 3869 3870 /* get storage for new args */ 3871 if ((newargs = (char **) malloc((newargcnt + 1) * sizeof(char *))) == NULL) { 3872 oERR(ZE_MEM, "ia"); 3873 } 3874 3875 /* copy argument pointers from args to position at_arg, copy arg, then rest args */ 3876 argnum = 0; 3877 newargnum = 0; 3878 if (args) { 3879 for (; args[argnum] && argnum < at_arg; argnum++) { 3880 newargs[newargnum++] = args[argnum]; 3881 } 3882 } 3883 /* copy new arg */ 3884 if ((newarg = (char *) malloc(strlen(arg) + 1)) == NULL) { 3885 oERR(ZE_MEM, "ia"); 3886 } 3887 strcpy(newarg, arg); 3888 3889 newargs[newargnum++] = newarg; 3890 if (args) { 3891 for ( ; args[argnum]; argnum++) { 3892 newargs[newargnum++] = args[argnum]; 3893 } 3894 } 3895 newargs[newargnum] = NULL; 3896 3897 /* free old args array but not component strings - this assumes that 3898 args was allocated with malloc as copy_args does. DO NOT DO THIS 3899 on the original argv. 3900 */ 3901 if (free_args) 3902 free(args); 3903 3904 *pargs = newargs; 3905 3906 return newargnum; 3907} 3908 3909/* ------------------------------------- */ 3910 3911 3912 3913 3914/* get_shortopt 3915 * 3916 * Get next short option from arg. The state is stored in argnum, optchar, and 3917 * option_num so no static storage is used. Returns the option_ID. 3918 * 3919 * parameters: 3920 * args - argv array of arguments 3921 * argnum - index of current arg in args 3922 * optchar - pointer to index of next char to process. Can be 0 or 3923 * const defined at top of this file like THIS_ARG_DONE 3924 * negated - on return pointer to int set to 1 if option negated or 0 otherwise 3925 * value - on return pointer to string set to value of option if any or NULL 3926 * if none. If value is returned then the caller should free() 3927 * it when not needed anymore. 3928 * option_num - pointer to index in options[] of returned option or 3929 * o_NO_OPTION_MATCH if none. Do not change as used by 3930 * value lists. 3931 * depth - recursion depth (0 at top level, 1 or more in arg files) 3932 */ 3933local unsigned long get_shortopt(args, argnum, optchar, negated, value, 3934 option_num, depth) 3935 char **args; 3936 int argnum; 3937 int *optchar; 3938 int *negated; 3939 char **value; 3940 int *option_num; 3941 int depth; 3942{ 3943 char *shortopt; 3944 int clen; 3945 char *nextchar; 3946 char *s; 3947 char *start; 3948 int op; 3949 char *arg; 3950 int match = -1; 3951 3952 3953 /* get arg */ 3954 arg = args[argnum]; 3955 /* current char in arg */ 3956 nextchar = arg + (*optchar); 3957 clen = MB_CLEN(nextchar); 3958 /* next char in arg */ 3959 (*optchar) += clen; 3960 /* get first char of short option */ 3961 shortopt = arg + (*optchar); 3962 /* no value */ 3963 *value = NULL; 3964 3965 if (*shortopt == '\0') { 3966 /* no more options in arg */ 3967 *optchar = 0; 3968 *option_num = o_NO_OPTION_MATCH; 3969 return 0; 3970 } 3971 3972 /* look for match in options */ 3973 clen = MB_CLEN(shortopt); 3974 for (op = 0; options[op].option_ID; op++) { 3975 s = options[op].shortopt; 3976 if (s && s[0] == shortopt[0]) { 3977 if (s[1] == '\0' && clen == 1) { 3978 /* single char match */ 3979 match = op; 3980 } else { 3981 /* 2 wide short opt. Could support more chars but should use long opts instead */ 3982 if (s[1] == shortopt[1]) { 3983 /* match 2 char short opt or 2 byte char */ 3984 match = op; 3985 if (clen == 1) (*optchar)++; 3986 break; 3987 } 3988 } 3989 } 3990 } 3991 3992 if (match > -1) { 3993 /* match */ 3994 clen = MB_CLEN(shortopt); 3995 nextchar = arg + (*optchar) + clen; 3996 /* check for trailing dash negating option */ 3997 if (*nextchar == '-') { 3998 /* negated */ 3999 if (options[match].negatable == o_NOT_NEGATABLE) { 4000 if (options[match].value_type == o_NO_VALUE) { 4001 optionerr(optionerrbuf, op_not_neg_err, match, 0); 4002 if (depth > 0) { 4003 /* unwind */ 4004 oWARN(optionerrbuf); 4005 return o_ARG_FILE_ERR; 4006 } else { 4007 oERR(ZE_PARMS, optionerrbuf); 4008 } 4009 } 4010 } else { 4011 *negated = 1; 4012 /* set up to skip negating dash */ 4013 (*optchar) += clen; 4014 clen = 1; 4015 } 4016 } 4017 4018 /* value */ 4019 clen = MB_CLEN(arg + (*optchar)); 4020 /* optional value, one char value, and number value must follow option */ 4021 if (options[match].value_type == o_ONE_CHAR_VALUE) { 4022 /* one char value */ 4023 if (arg[(*optchar) + clen]) { 4024 /* has value */ 4025 if (MB_CLEN(arg + (*optchar) + clen) > 1) { 4026 /* multibyte value not allowed for now */ 4027 optionerr(optionerrbuf, oco_no_mbc_err, match, 0); 4028 if (depth > 0) { 4029 /* unwind */ 4030 oWARN(optionerrbuf); 4031 return o_ARG_FILE_ERR; 4032 } else { 4033 oERR(ZE_PARMS, optionerrbuf); 4034 } 4035 } 4036 if ((*value = (char *) malloc(2)) == NULL) { 4037 oERR(ZE_MEM, "gso"); 4038 } 4039 (*value)[0] = *(arg + (*optchar) + clen); 4040 (*value)[1] = '\0'; 4041 *optchar += clen; 4042 clen = 1; 4043 } else { 4044 /* one char values require a value */ 4045 optionerr(optionerrbuf, oco_req_val_err, match, 0); 4046 if (depth > 0) { 4047 oWARN(optionerrbuf); 4048 return o_ARG_FILE_ERR; 4049 } else { 4050 oERR(ZE_PARMS, optionerrbuf); 4051 } 4052 } 4053 } else if (options[match].value_type == o_NUMBER_VALUE) { 4054 /* read chars until end of number */ 4055 start = arg + (*optchar) + clen; 4056 if (*start == '+' || *start == '-') { 4057 start++; 4058 } 4059 s = start; 4060 for (; isdigit(*s); MB_NEXTCHAR(s)) ; 4061 if (s == start) { 4062 /* no digits */ 4063 optionerr(optionerrbuf, num_req_val_err, match, 0); 4064 if (depth > 0) { 4065 oWARN(optionerrbuf); 4066 return o_ARG_FILE_ERR; 4067 } else { 4068 oERR(ZE_PARMS, optionerrbuf); 4069 } 4070 } 4071 start = arg + (*optchar) + clen; 4072 if ((*value = (char *) malloc((int)(s - start) + 1)) == NULL) { 4073 oERR(ZE_MEM, "gso"); 4074 } 4075 *optchar += (int)(s - start); 4076 strncpy(*value, start, (int)(s - start)); 4077 (*value)[(int)(s - start)] = '\0'; 4078 clen = MB_CLEN(s); 4079 } else if (options[match].value_type == o_OPTIONAL_VALUE) { 4080 /* optional value */ 4081 /* This seemed inconsistent so now if no value attached to argument look 4082 to the next argument if that argument is not an option for option 4083 value - 11/12/04 EG */ 4084 if (arg[(*optchar) + clen]) { 4085 /* has value */ 4086 /* add support for optional = - 2/6/05 EG */ 4087 if (arg[(*optchar) + clen] == '=') { 4088 /* skip = */ 4089 clen++; 4090 } 4091 if (arg[(*optchar) + clen]) { 4092 if ((*value = (char *)malloc(strlen(arg + (*optchar) + clen) + 1)) 4093 == NULL) { 4094 oERR(ZE_MEM, "gso"); 4095 } 4096 strcpy(*value, arg + (*optchar) + clen); 4097 } 4098 *optchar = THIS_ARG_DONE; 4099 } else if (args[argnum + 1] && args[argnum + 1][0] != '-') { 4100 /* use next arg for value */ 4101 if ((*value = (char *)malloc(strlen(args[argnum + 1]) + 1)) == NULL) { 4102 oERR(ZE_MEM, "gso"); 4103 } 4104 /* using next arg as value */ 4105 strcpy(*value, args[argnum + 1]); 4106 *optchar = SKIP_VALUE_ARG; 4107 } 4108 } else if (options[match].value_type == o_REQUIRED_VALUE || 4109 options[match].value_type == o_VALUE_LIST) { 4110 /* see if follows option */ 4111 if (arg[(*optchar) + clen]) { 4112 /* has value following option as -ovalue */ 4113 /* add support for optional = - 6/5/05 EG */ 4114 if (arg[(*optchar) + clen] == '=') { 4115 /* skip = */ 4116 clen++; 4117 } 4118 if ((*value = (char *)malloc(strlen(arg + (*optchar) + clen) + 1)) 4119 == NULL) { 4120 oERR(ZE_MEM, "gso"); 4121 } 4122 strcpy(*value, arg + (*optchar) + clen); 4123 *optchar = THIS_ARG_DONE; 4124 } else { 4125 /* use next arg for value */ 4126 if (args[argnum + 1]) { 4127 if ((*value = (char *)malloc(strlen(args[argnum + 1]) + 1)) == NULL) { 4128 oERR(ZE_MEM, "gso"); 4129 } 4130 strcpy(*value, args[argnum + 1]); 4131 if (options[match].value_type == o_VALUE_LIST) { 4132 *optchar = START_VALUE_LIST; 4133 } else { 4134 *optchar = SKIP_VALUE_ARG; 4135 } 4136 } else { 4137 /* no value found */ 4138 optionerr(optionerrbuf, op_req_val_err, match, 0); 4139 if (depth > 0) { 4140 oWARN(optionerrbuf); 4141 return o_ARG_FILE_ERR; 4142 } else { 4143 oERR(ZE_PARMS, optionerrbuf); 4144 } 4145 } 4146 } 4147 } 4148 4149 *option_num = match; 4150 return options[match].option_ID; 4151 } 4152 sprintf(optionerrbuf, sh_op_not_sup_err, *shortopt); 4153 if (depth > 0) { 4154 /* unwind */ 4155 oWARN(optionerrbuf); 4156 return o_ARG_FILE_ERR; 4157 } else { 4158 oERR(ZE_PARMS, optionerrbuf); 4159 } 4160 return 0; 4161} 4162 4163 4164/* get_longopt 4165 * 4166 * Get the long option in args array at argnum. 4167 * Parameters same as for get_shortopt. 4168 */ 4169 4170local unsigned long get_longopt(args, argnum, optchar, negated, value, 4171 option_num, depth) 4172 char **args; 4173 int argnum; 4174 int *optchar; 4175 int *negated; 4176 char **value; 4177 int *option_num; 4178 int depth; 4179{ 4180 char *longopt; 4181 char *lastchr; 4182 char *valuestart; 4183 int op; 4184 char *arg; 4185 int match = -1; 4186 *value = NULL; 4187 4188 if (args == NULL) { 4189 *option_num = o_NO_OPTION_MATCH; 4190 return 0; 4191 } 4192 if (args[argnum] == NULL) { 4193 *option_num = o_NO_OPTION_MATCH; 4194 return 0; 4195 } 4196 /* copy arg so can chop end if value */ 4197 if ((arg = (char *)malloc(strlen(args[argnum]) + 1)) == NULL) { 4198 oERR(ZE_MEM, "glo"); 4199 } 4200 strcpy(arg, args[argnum]); 4201 4202 /* get option */ 4203 longopt = arg + 2; 4204 /* no value */ 4205 *value = NULL; 4206 4207 /* find = */ 4208 for (lastchr = longopt, valuestart = longopt; 4209 *valuestart && *valuestart != '='; 4210 lastchr = valuestart, MB_NEXTCHAR(valuestart)) ; 4211 if (*valuestart) { 4212 /* found =value */ 4213 *valuestart = '\0'; 4214 valuestart++; 4215 } else { 4216 valuestart = NULL; 4217 } 4218 4219 if (*lastchr == '-') { 4220 /* option negated */ 4221 *negated = 1; 4222 *lastchr = '\0'; 4223 } else { 4224 *negated = 0; 4225 } 4226 4227 /* look for long option match */ 4228 for (op = 0; options[op].option_ID; op++) { 4229 if (options[op].longopt && strcmp(options[op].longopt, longopt) == 0) { 4230 /* exact match */ 4231 match = op; 4232 break; 4233 } 4234 if (options[op].longopt && strncmp(options[op].longopt, longopt, strlen(longopt)) == 0) { 4235 if (match > -1) { 4236 sprintf(optionerrbuf, long_op_ambig_err, longopt); 4237 free(arg); 4238 if (depth > 0) { 4239 /* unwind */ 4240 oWARN(optionerrbuf); 4241 return o_ARG_FILE_ERR; 4242 } else { 4243 oERR(ZE_PARMS, optionerrbuf); 4244 } 4245 } 4246 match = op; 4247 } 4248 } 4249 4250 if (match == -1) { 4251 sprintf(optionerrbuf, long_op_not_sup_err, longopt); 4252 free(arg); 4253 if (depth > 0) { 4254 oWARN(optionerrbuf); 4255 return o_ARG_FILE_ERR; 4256 } else { 4257 oERR(ZE_PARMS, optionerrbuf); 4258 } 4259 } 4260 4261 /* one long option an arg */ 4262 *optchar = THIS_ARG_DONE; 4263 4264 /* if negated then see if allowed */ 4265 if (*negated && options[match].negatable == o_NOT_NEGATABLE) { 4266 optionerr(optionerrbuf, op_not_neg_err, match, 1); 4267 free(arg); 4268 if (depth > 0) { 4269 /* unwind */ 4270 oWARN(optionerrbuf); 4271 return o_ARG_FILE_ERR; 4272 } else { 4273 oERR(ZE_PARMS, optionerrbuf); 4274 } 4275 } 4276 /* get value */ 4277 if (options[match].value_type == o_OPTIONAL_VALUE) { 4278 /* optional value in form option=value */ 4279 if (valuestart) { 4280 /* option=value */ 4281 if ((*value = (char *)malloc(strlen(valuestart) + 1)) == NULL) { 4282 free(arg); 4283 oERR(ZE_MEM, "glo"); 4284 } 4285 strcpy(*value, valuestart); 4286 } 4287 } else if (options[match].value_type == o_REQUIRED_VALUE || 4288 options[match].value_type == o_NUMBER_VALUE || 4289 options[match].value_type == o_ONE_CHAR_VALUE || 4290 options[match].value_type == o_VALUE_LIST) { 4291 /* handle long option one char and number value as required value */ 4292 if (valuestart) { 4293 /* option=value */ 4294 if ((*value = (char *)malloc(strlen(valuestart) + 1)) == NULL) { 4295 free(arg); 4296 oERR(ZE_MEM, "glo"); 4297 } 4298 strcpy(*value, valuestart); 4299 } else { 4300 /* use next arg */ 4301 if (args[argnum + 1]) { 4302 if ((*value = (char *)malloc(strlen(args[argnum + 1]) + 1)) == NULL) { 4303 free(arg); 4304 oERR(ZE_MEM, "glo"); 4305 } 4306 /* using next arg as value */ 4307 strcpy(*value, args[argnum + 1]); 4308 if (options[match].value_type == o_VALUE_LIST) { 4309 *optchar = START_VALUE_LIST; 4310 } else { 4311 *optchar = SKIP_VALUE_ARG; 4312 } 4313 } else { 4314 /* no value found */ 4315 optionerr(optionerrbuf, op_req_val_err, match, 1); 4316 free(arg); 4317 if (depth > 0) { 4318 /* unwind */ 4319 oWARN(optionerrbuf); 4320 return o_ARG_FILE_ERR; 4321 } else { 4322 oERR(ZE_PARMS, optionerrbuf); 4323 } 4324 } 4325 } 4326 } else if (options[match].value_type == o_NO_VALUE) { 4327 /* this option does not accept a value */ 4328 if (valuestart) { 4329 /* --option=value */ 4330 optionerr(optionerrbuf, op_no_allow_val_err, match, 1); 4331 free(arg); 4332 if (depth > 0) { 4333 oWARN(optionerrbuf); 4334 return o_ARG_FILE_ERR; 4335 } else { 4336 oERR(ZE_PARMS, optionerrbuf); 4337 } 4338 } 4339 } 4340 free(arg); 4341 4342 *option_num = match; 4343 return options[match].option_ID; 4344} 4345 4346 4347 4348/* get_option 4349 * 4350 * Main interface for user. Use this function to get options, values and 4351 * non-option arguments from a command line provided in argv form. 4352 * 4353 * To use get_option() first define valid options by setting 4354 * the global variable options[] to an array of option_struct. Also 4355 * either change defaults below or make variables global and set elsewhere. 4356 * Zip uses below defaults. 4357 * 4358 * Call get_option() to get an option (like -b or --temp-file) and any 4359 * value for that option (like filename for -b) or a non-option argument 4360 * (like archive name) each call. If *value* is not NULL after calling 4361 * get_option() it is a returned value and the caller should either store 4362 * the char pointer or free() it before calling get_option() again to avoid 4363 * leaking memory. If a non-option non-value argument is returned get_option() 4364 * returns o_NON_OPTION_ARG and value is set to the entire argument. 4365 * When there are no more arguments get_option() returns 0. 4366 * 4367 * The parameters argnum (after set to 0 on initial call), 4368 * optchar, first_nonopt_arg, option_num, and depth (after initial 4369 * call) are set and maintained by get_option() and should not be 4370 * changed. The parameters argc, negated, and value are outputs and 4371 * can be used by the calling program. get_option() returns either the 4372 * option_ID for the current option, a special value defined in 4373 * zip.h, or 0 when no more arguments. 4374 * 4375 * The value returned by get_option() is the ID value in the options 4376 * table. This value can be duplicated in the table if different 4377 * options are really the same option. The index into the options[] 4378 * table is given by option_num, though the ID should be used as 4379 * option numbers change when the table is changed. The ID must 4380 * not be 0 for any option as this ends the table. If get_option() 4381 * finds an option not in the table it calls oERR to post an 4382 * error and exit. Errors also result if the option requires a 4383 * value that is missing, a value is present but the option does 4384 * not take one, and an option is negated but is not 4385 * negatable. Non-option arguments return o_NON_OPTION_ARG 4386 * with the entire argument in value. 4387 * 4388 * For Zip, permuting is on and all options and their values are 4389 * returned before any non-option arguments like archive name. 4390 * 4391 * The arguments "-" alone and "--" alone return as non-option arguments. 4392 * Note that "-" should not be used as part of a short option 4393 * entry in the table but can be used in the middle of long 4394 * options such as in the long option "a-long-option". Now "--" alone 4395 * stops option processing, returning any arguments following "--" as 4396 * non-option arguments instead of options. 4397 * 4398 * Argument file support is removed from this version. It may be added later. 4399 * 4400 * After each call: 4401 * argc is set to the current size of args[] but should not change 4402 * with argument file support removed, 4403 * argnum is the index of the current arg, 4404 * value is either the value of the returned option or non-option 4405 * argument or NULL if option with no value, 4406 * negated is set if the option was negated by a trailing dash (-) 4407 * option_num is set to either the index in options[] for the option or 4408 * o_NO_OPTION_MATCH if no match. 4409 * Negation is checked before the value is read if the option is negatable so 4410 * that the - is not included in the value. If the option is not negatable 4411 * but takes a value then the - will start the value. If permuting then 4412 * argnum and first_nonopt_arg are unreliable and should not be used. 4413 * 4414 * Command line is read from left to right. As get_option() finds non-option 4415 * arguments (arguments not starting with - and that are not values to options) 4416 * it moves later options and values in front of the non-option arguments. 4417 * This permuting is turned off by setting enable_permute to 0. Then 4418 * get_option() will return options and non-option arguments in the order 4419 * found. Currently permuting is only done after an argument is completely 4420 * processed so that any value can be moved with options they go with. All 4421 * state information is stored in the parameters argnum, optchar, 4422 * first_nonopt_arg and option_num. You should not change these after the 4423 * first call to get_option(). If you need to back up to a previous arg then 4424 * set argnum to that arg (remembering that args may have been permuted) and 4425 * set optchar = 0 and first_nonopt_arg to the first non-option argument if 4426 * permuting. After all arguments are returned the next call to get_option() 4427 * returns 0. The caller can then call free_args(args) if appropriate. 4428 * 4429 * get_option() accepts arguments in the following forms: 4430 * short options 4431 * of 1 and 2 characters, e.g. a, b, cc, d, and ba, after a single 4432 * leading -, as in -abccdba. In this example if 'b' is followed by 'a' 4433 * it matches short option 'ba' else it is interpreted as short option 4434 * b followed by another option. The character - is not legal as a 4435 * short option or as part of a 2 character short option. 4436 * 4437 * If a short option has a value it immediately follows the option or 4438 * if that option is the end of the arg then the next arg is used as 4439 * the value. So if short option e has a value, it can be given as 4440 * -evalue 4441 * or 4442 * -e value 4443 * and now 4444 * -e=value 4445 * but now that = is optional a leading = is stripped for the first. 4446 * This change allows optional short option values to be defaulted as 4447 * -e= 4448 * Either optional or required values can be specified. Optional values 4449 * now use both forms as ignoring the later got confusing. Any 4450 * non-value short options can preceed a valued short option as in 4451 * -abevalue 4452 * Some value types (one_char and number) allow options after the value 4453 * so if oc is an option that takes a character and n takes a number 4454 * then 4455 * -abocVccn42evalue 4456 * returns value V for oc and value 42 for n. All values are strings 4457 * so programs may have to convert the "42" to a number. See long 4458 * options below for how value lists are handled. 4459 * 4460 * Any short option can be negated by following it with -. Any - is 4461 * handled and skipped over before any value is read unless the option 4462 * is not negatable but takes a value and then - starts the value. 4463 * 4464 * If the value for an optional value is just =, then treated as no 4465 * value. 4466 * 4467 * long options 4468 * of arbitrary length are assumed if an arg starts with -- but is not 4469 * exactly --. Long options are given one per arg and can be abbreviated 4470 * if the abbreviation uniquely matches one of the long options. 4471 * Exact matches always match before partial matches. If ambiguous an 4472 * error is generated. 4473 * 4474 * Values are specified either in the form 4475 * --longoption=value 4476 * or can be the following arg if the value is required as in 4477 * --longoption value 4478 * Optional values to long options must be in the first form. 4479 * 4480 * Value lists are specified by o_VALUE_LIST and consist of an option 4481 * that takes a value followed by one or more value arguments. 4482 * The two forms are 4483 * --option=value 4484 * or 4485 * -ovalue 4486 * for a single value or 4487 * --option value1 value2 value3 ... --option2 4488 * or 4489 * -o value1 value2 value3 ... 4490 * for a list of values. The list ends at the next option, the 4491 * end of the command line, or at a single "@" argument. 4492 * Each value is treated as if it was preceeded by the option, so 4493 * --option1 val1 val2 4494 * with option1 value_type set to o_VALUE_LIST is the same as 4495 * --option1=val1 --option1=val2 4496 * 4497 * Long options can be negated by following the option with - as in 4498 * --longoption- 4499 * Long options with values can also be negated if this makes sense for 4500 * the caller as: 4501 * --longoption-=value 4502 * If = is not followed by anything it is treated as no value. 4503 * 4504 * @path 4505 * When an argument in the form @path is encountered, the file at path 4506 * is opened and white space separated arguments read from the file 4507 * and inserted into the command line at that point as if the contents 4508 * of the file were directly typed at that location. The file can 4509 * have options, files to zip, or anything appropriate at that location 4510 * in the command line. Since Zip has permuting enabled, options and 4511 * files will propagate to the appropriate locations in the command 4512 * line. 4513 * 4514 * Argument files support has been removed from this version. It may 4515 * be added back later. 4516 * 4517 * non-option argument 4518 * is any argument not given above. If enable_permute is 1 then 4519 * these are returned after all options, otherwise all options and 4520 * args are returned in order. Returns option ID o_NON_OPTION_ARG 4521 * and sets value to the argument. 4522 * 4523 * 4524 * Arguments to get_option: 4525 * char ***pargs - pointer to arg array in the argv form 4526 * int *argc - returns the current argc for args incl. args[0] 4527 * int *argnum - the index of the current argument (caller 4528 * should set = 0 on first call and not change 4529 * after that) 4530 * int *optchar - index of next short opt in arg or special 4531 * int *first_nonopt_arg - used by get_option to permute args 4532 * int *negated - option was negated (had trailing -) 4533 * char *value - value of option if any (free when done with it) or NULL 4534 * int *option_num - the index in options of the last option returned 4535 * (can be o_NO_OPTION_MATCH) 4536 * int recursion_depth - current depth of recursion 4537 * (always set to 0 by caller) 4538 * (always 0 with argument files support removed) 4539 * 4540 * Caller should only read the returned option ID and the value, negated, 4541 * and option_num (if required) parameters after each call. 4542 * 4543 * Ed Gordon 4544 * 24 August 2003 (last updated 2 April 2008 EG) 4545 * 4546 */ 4547 4548unsigned long get_option(pargs, argc, argnum, optchar, value, 4549 negated, first_nonopt_arg, option_num, recursion_depth) 4550 char ***pargs; 4551 int *argc; 4552 int *argnum; 4553 int *optchar; 4554 char **value; 4555 int *negated; 4556 int *first_nonopt_arg; 4557 int *option_num; 4558 int recursion_depth; 4559{ 4560 char **args; 4561 unsigned long option_ID; 4562 4563 int argcnt; 4564 int first_nonoption_arg; 4565 char *arg = NULL; 4566 int h; 4567 int optc; 4568 int argn; 4569 int j; 4570 int v; 4571 int read_rest_args_verbatim = 0; /* 7/25/04 - ignore options and arg files for rest args */ 4572 4573 /* value is outdated. The caller should free value before 4574 calling get_option again. */ 4575 *value = NULL; 4576 4577 /* if args is NULL then done */ 4578 if (pargs == NULL) { 4579 *argc = 0; 4580 return 0; 4581 } 4582 args = *pargs; 4583 if (args == NULL) { 4584 *argc = 0; 4585 return 0; 4586 } 4587 4588 /* count args */ 4589 for (argcnt = 0; args[argcnt]; argcnt++) ; 4590 4591 /* if no provided args then nothing to do */ 4592 if (argcnt < 1 || (recursion_depth == 0 && argcnt < 2)) { 4593 *argc = argcnt; 4594 /* return 0 to note that no args are left */ 4595 return 0; 4596 } 4597 4598 *negated = 0; 4599 first_nonoption_arg = *first_nonopt_arg; 4600 argn = *argnum; 4601 optc = *optchar; 4602 4603 if (optc == READ_REST_ARGS_VERBATIM) { 4604 read_rest_args_verbatim = 1; 4605 } 4606 4607 if (argn == -1 || (recursion_depth == 0 && argn == 0)) { 4608 /* first call */ 4609 /* if depth = 0 then args[0] is argv[0] so skip */ 4610 *option_num = o_NO_OPTION_MATCH; 4611 optc = THIS_ARG_DONE; 4612 first_nonoption_arg = -1; 4613 } 4614 4615 /* if option_num is set then restore last option_ID in case continuing value list */ 4616 option_ID = 0; 4617 if (*option_num != o_NO_OPTION_MATCH) { 4618 option_ID = options[*option_num].option_ID; 4619 } 4620 4621 /* get next option if any */ 4622 for (;;) { 4623 if (read_rest_args_verbatim) { 4624 /* rest of args after "--" are non-option args if doubledash_ends_options set */ 4625 argn++; 4626 if (argn > argcnt || args[argn] == NULL) { 4627 /* done */ 4628 option_ID = 0; 4629 break; 4630 } 4631 arg = args[argn]; 4632 if ((*value = (char *)malloc(strlen(arg) + 1)) == NULL) { 4633 oERR(ZE_MEM, "go"); 4634 } 4635 strcpy(*value, arg); 4636 *option_num = o_NO_OPTION_MATCH; 4637 option_ID = o_NON_OPTION_ARG; 4638 break; 4639 4640 /* permute non-option args after option args so options are returned first */ 4641 } else if (enable_permute) { 4642 if (optc == SKIP_VALUE_ARG || optc == THIS_ARG_DONE || 4643 optc == START_VALUE_LIST || optc == IN_VALUE_LIST || 4644 optc == STOP_VALUE_LIST) { 4645 /* moved to new arg */ 4646 if (first_nonoption_arg > -1 && args[first_nonoption_arg]) { 4647 /* do the permuting - move non-options after this option */ 4648 /* if option and value separate args or starting list skip option */ 4649 if (optc == SKIP_VALUE_ARG || optc == START_VALUE_LIST) { 4650 v = 1; 4651 } else { 4652 v = 0; 4653 } 4654 for (h = first_nonoption_arg; h < argn; h++) { 4655 arg = args[first_nonoption_arg]; 4656 for (j = first_nonoption_arg; j < argn + v; j++) { 4657 args[j] = args[j + 1]; 4658 } 4659 args[j] = arg; 4660 } 4661 first_nonoption_arg += 1 + v; 4662 } 4663 } 4664 } else if (optc == NON_OPTION_ARG) { 4665 /* if not permuting then already returned arg */ 4666 optc = THIS_ARG_DONE; 4667 } 4668 4669 /* value lists */ 4670 if (optc == STOP_VALUE_LIST) { 4671 optc = THIS_ARG_DONE; 4672 } 4673 4674 if (optc == START_VALUE_LIST || optc == IN_VALUE_LIST) { 4675 if (optc == START_VALUE_LIST) { 4676 /* already returned first value */ 4677 argn++; 4678 optc = IN_VALUE_LIST; 4679 } 4680 argn++; 4681 arg = args[argn]; 4682 /* if end of args and still in list and there are non-option args then 4683 terminate list */ 4684 if (arg == NULL && (optc == START_VALUE_LIST || optc == IN_VALUE_LIST) 4685 && first_nonoption_arg > -1) { 4686 /* terminate value list with @ */ 4687 /* this is only needed for argument files */ 4688 /* but is also good for show command line so command lines with lists 4689 can always be read back in */ 4690 argcnt = insert_arg(&args, "@", first_nonoption_arg, 1); 4691 argn++; 4692 if (first_nonoption_arg > -1) { 4693 first_nonoption_arg++; 4694 } 4695 } 4696 4697 arg = args[argn]; 4698 if (arg && arg[0] == '@' && arg[1] == '\0') { 4699 /* inserted arguments terminator */ 4700 optc = STOP_VALUE_LIST; 4701 continue; 4702 } else if (arg && arg[0] != '-') { /* not option */ 4703 /* - and -- are not allowed in value lists unless escaped */ 4704 /* another value in value list */ 4705 if ((*value = (char *)malloc(strlen(args[argn]) + 1)) == NULL) { 4706 oERR(ZE_MEM, "go"); 4707 } 4708 strcpy(*value, args[argn]); 4709 break; 4710 4711 } else { 4712 argn--; 4713 optc = THIS_ARG_DONE; 4714 } 4715 } 4716 4717 /* move to next arg */ 4718 if (optc == SKIP_VALUE_ARG) { 4719 argn += 2; 4720 optc = 0; 4721 } else if (optc == THIS_ARG_DONE) { 4722 argn++; 4723 optc = 0; 4724 } 4725 if (argn > argcnt) { 4726 break; 4727 } 4728 if (args[argn] == NULL) { 4729 /* done unless permuting and non-option args */ 4730 if (first_nonoption_arg > -1 && args[first_nonoption_arg]) { 4731 /* return non-option arguments at end */ 4732 if (optc == NON_OPTION_ARG) { 4733 first_nonoption_arg++; 4734 } 4735 /* after first pass args are permuted but skipped over non-option args */ 4736 /* swap so argn points to first non-option arg */ 4737 j = argn; 4738 argn = first_nonoption_arg; 4739 first_nonoption_arg = j; 4740 } 4741 if (argn > argcnt || args[argn] == NULL) { 4742 /* done */ 4743 option_ID = 0; 4744 break; 4745 } 4746 } 4747 4748 /* after swap first_nonoption_arg points to end which is NULL */ 4749 if (first_nonoption_arg > -1 && (args[first_nonoption_arg] == NULL)) { 4750 /* only non-option args left */ 4751 if (optc == NON_OPTION_ARG) { 4752 argn++; 4753 } 4754 if (argn > argcnt || args[argn] == NULL) { 4755 /* done */ 4756 option_ID = 0; 4757 break; 4758 } 4759 if ((*value = (char *)malloc(strlen(args[argn]) + 1)) == NULL) { 4760 oERR(ZE_MEM, "go"); 4761 } 4762 strcpy(*value, args[argn]); 4763 optc = NON_OPTION_ARG; 4764 option_ID = o_NON_OPTION_ARG; 4765 break; 4766 } 4767 4768 arg = args[argn]; 4769 4770 /* is it an option */ 4771 if (arg[0] == '-') { 4772 /* option */ 4773 if (arg[1] == '\0') { 4774 /* arg = - */ 4775 /* treat like non-option arg */ 4776 *option_num = o_NO_OPTION_MATCH; 4777 if (enable_permute) { 4778 /* permute args to move all non-option args to end */ 4779 if (first_nonoption_arg < 0) { 4780 first_nonoption_arg = argn; 4781 } 4782 argn++; 4783 } else { 4784 /* not permute args so return non-option args when found */ 4785 if ((*value = (char *)malloc(strlen(arg) + 1)) == NULL) { 4786 oERR(ZE_MEM, "go"); 4787 } 4788 strcpy(*value, arg); 4789 optc = NON_OPTION_ARG; 4790 option_ID = o_NON_OPTION_ARG; 4791 break; 4792 } 4793 4794 } else if (arg[1] == '-') { 4795 /* long option */ 4796 if (arg[2] == '\0') { 4797 /* arg = -- */ 4798 if (doubledash_ends_options) { 4799 /* Now -- stops permuting and forces the rest of 4800 the command line to be read verbatim - 7/25/04 EG */ 4801 4802 /* never permute args after -- and return as non-option args */ 4803 if (first_nonoption_arg < 1) { 4804 /* -- is first non-option argument - 8/7/04 EG */ 4805 argn--; 4806 } else { 4807 /* go back to start of non-option args - 8/7/04 EG */ 4808 argn = first_nonoption_arg - 1; 4809 } 4810 4811 /* disable permuting and treat remaining arguments as not 4812 options */ 4813 read_rest_args_verbatim = 1; 4814 optc = READ_REST_ARGS_VERBATIM; 4815 4816 } else { 4817 /* treat like non-option arg */ 4818 *option_num = o_NO_OPTION_MATCH; 4819 if (enable_permute) { 4820 /* permute args to move all non-option args to end */ 4821 if (first_nonoption_arg < 0) { 4822 first_nonoption_arg = argn; 4823 } 4824 argn++; 4825 } else { 4826 /* not permute args so return non-option args when found */ 4827 if ((*value = (char *)malloc(strlen(arg) + 1)) == NULL) { 4828 oERR(ZE_MEM, "go"); 4829 } 4830 strcpy(*value, arg); 4831 optc = NON_OPTION_ARG; 4832 option_ID = o_NON_OPTION_ARG; 4833 break; 4834 } 4835 } 4836 4837 } else { 4838 option_ID = get_longopt(args, argn, &optc, negated, value, option_num, recursion_depth); 4839 if (option_ID == o_ARG_FILE_ERR) { 4840 /* unwind as only get this if recursion_depth > 0 */ 4841 return option_ID; 4842 } 4843 break; 4844 } 4845 4846 } else { 4847 /* short option */ 4848 option_ID = get_shortopt(args, argn, &optc, negated, value, option_num, recursion_depth); 4849 4850 if (option_ID == o_ARG_FILE_ERR) { 4851 /* unwind as only get this if recursion_depth > 0 */ 4852 return option_ID; 4853 } 4854 4855 if (optc == 0) { 4856 /* if optc = 0 then ran out of short opts this arg */ 4857 optc = THIS_ARG_DONE; 4858 } else { 4859 break; 4860 } 4861 } 4862 4863#if 0 4864 /* argument file code left out 4865 so for now let filenames start with @ 4866 */ 4867 4868 } else if (allow_arg_files && arg[0] == '@') { 4869 /* arg file */ 4870 oERR(ZE_PARMS, no_arg_files_err); 4871#endif 4872 4873 } else { 4874 /* non-option */ 4875 if (enable_permute) { 4876 /* permute args to move all non-option args to end */ 4877 if (first_nonoption_arg < 0) { 4878 first_nonoption_arg = argn; 4879 } 4880 argn++; 4881 } else { 4882 /* no permute args so return non-option args when found */ 4883 if ((*value = (char *)malloc(strlen(arg) + 1)) == NULL) { 4884 oERR(ZE_MEM, "go"); 4885 } 4886 strcpy(*value, arg); 4887 *option_num = o_NO_OPTION_MATCH; 4888 optc = NON_OPTION_ARG; 4889 option_ID = o_NON_OPTION_ARG; 4890 break; 4891 } 4892 4893 } 4894 } 4895 4896 *pargs = args; 4897 *argc = argcnt; 4898 *first_nonopt_arg = first_nonoption_arg; 4899 *argnum = argn; 4900 *optchar = optc; 4901 4902 return option_ID; 4903} 4904