&z UNZIP.BCKX UNZIP.BCK<BACKUP/INTER/BLOCK=8192 [UNZIP542...]*.*; RDS:UNZIP.BCK/SAVE GOATHUNTER e%ZbV7.2 _CAESAR:: _$1$VDA0: V7.2  *[UNZIP542]ACORN.DIR;1+, ./ 4- 0123 KPWO569#!a79#!a89GHJIACORN.C  CONTENTS.  GMAKEFILE.  MAKEFILE. README. RISCOS.C RISCOS.H  RUNME1ST.  SRCRENAME.'SWIVEN.H8SWIVEN.S{*[UNZIP542.ACORN]ACORN.C;1+, .B/ 4BB- 0@123KPWOC56789GHJ/* Copyright (c) 1990-2000 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*--------------------------------------------------------------------------- acorn.c RISCOS-specific routines for use with Info-ZIP's UnZip 5.2 and later. Contains: do_wild() <-- generic enough to put in fileio.c? mapattr() mapname() checkdir() mkdir() isRISCOSexfield() setRISCOSexfield() printRISCOSexfield() close_outfile() stamp_file() version() ---------------------------------------------------------------------------*/ #define UNZIP_INTERNAL #include "^.unzip.h" #include "riscos.h" #define FTYPE_FFF (1<<17) /* set filetype to &FFF when extracting */ static int created_dir; /* used in mapname(), checkdir() */ static int renamed_fullpath; /* ditto */ static int has_mimemap = -1; /* used in mimemap() */ extern int mkdir(const char *path, int mode); static int has_NFS_ext(const char *name); static int uxtime2acornftime(unsigned *pexadr, unsigned *pldadr, time_t ut); static int mimemap(const char *name); #ifndef SFX /**********************/ /* Function do_wild() */ /* for porting: dir separator; match(ignore_case) */ /**********************/ char *do_wild(__G__ wildspec) __GDEF ZCONST char *wildspec; /* only used first time on a given dir */ { static DIR *wild_dir = (DIR *)NULL; static ZCONST char *wildname; static char *dirname, matchname[FILNAMSIZ]; static int notfirstcall=FALSE, have_dirname, dirnamelen; struct dirent *file; /* Even when we're just returning wildspec, we *always* do so in * matchname[]--calling routine is allowed to append four characters * to the returned string, and wildspec may be a pointer to argv[]. */ if (!notfirstcall) { /* first call: must initialize everything */ notfirstcall = TRUE; /* break the wildspec into a directory part and a wildcard filename */ if ((wildname = (ZCONST char *)strrchr(wildspec, '.')) == (ZCONST char *)NULL) { dirname = "."; dirnamelen = 1; have_dirname = FALSE; wildname = wildspec; } else { ++wildname; /* point at character after '/' */ dirnamelen = wildname - wildspec; if ((dirname = (char *)malloc(dirnamelen+1)) == (char *)NULL) { Info(slide, 0x201, ((char *)slide, "warning: cannot allocate wildcard buffers\n")); strcpy(matchname, wildspec); return matchname; /* but maybe filespec was not a wildcard */ } strncpy(dirname, wildspec, dirnamelen); dirname[dirnamelen] = '\0'; /* terminate for strcpy below */ have_dirname = TRUE; } if ((wild_dir = opendir(dirname)) != (DIR *)NULL) { while ((file = readdir(wild_dir)) != (struct dirent *)NULL) { if (file->d_name[0] == '/' && wildname[0] != '/') continue; /* Unix: '*' and '?' do not match leading dot */ if (match(file->d_name, wildname, 0)) { /* 0 == case sens. */ if (have_dirname) { strcpy(matchname, dirname); strcpy(matchname+dirnamelen, file->d_name); } else strcpy(matchname, file->d_name); return matchname; } } /* if we get to here directory is exhausted, so close it */ closedir(wild_dir); wild_dir = (DIR *)NULL; } /* return the raw wildspec in case that works (e.g., directory not * searchable, but filespec was not wild and file is readable) */ strcpy(matchname, wildspec); return matchname; } /* last time through, might have failed opendir but returned raw wildspec */ if (wild_dir == (DIR *)NULL) { notfirstcall = FALSE; /* nothing left to try--reset for new wildspec */ if (have_dirname) free(dirname); return (char *)NULL; } /* If we've gotten this far, we've read and matched at least one entry * successfully (in a previous call), so dirname has been copied into * matchname already. */ while ((file = readdir(wild_dir)) != (struct dirent *)NULL) if (match(file->d_name, wildname, 0)) { /* 0 == don't ignore case */ if (have_dirname) { /* strcpy(matchname, dirname); */ strcpy(matchname+dirnamelen, file->d_name); } else strcpy(matchname, file->d_name); return matchname; } closedir(wild_dir); /* have read at least one dir entry; nothing left */ wild_dir = (DIR *)NULL; notfirstcall = FALSE; /* reset for new wildspec */ if (have_dirname) free(dirname); return (char *)NULL; } /* end function do_wild() */ #endif /* !SFX */ /**************************/ /* Function has_NFS_ext() */ /**************************/ static int has_NFS_ext(const char* name) { int i = strlen(name) - 4; return (i >= 0 && name[i] == ',' && (i > 0 || name[i-1]=='/') && isxdigit(name[i+1]) && isxdigit(name[i+2]) && isxdigit(name[i+3])); } /* end function has_NFS_ext() */ /**********************/ /* Function mapattr() */ /**********************/ int mapattr(__G) __GDEF { ulg tmp = G.crec.external_file_attributes; switch (G.pInfo->hostnum) { case AMIGA_: tmp = (unsigned)(tmp>>17 & 7); /* Amiga RWE bits */ G.pInfo->file_attr = (unsigned)(tmp<<6 | tmp<<3 | tmp); break; case THEOS_: tmp &= 0xF1FFFFFFL; if ((tmp & 0xF0000000L) != 0x40000000L) tmp &= 0x01FFFFFFL; /* not a dir, mask all ftype bits */ else tmp &= 0x41FFFFFFL; /* leave directory bit as set */ /* fall through! */ case ACORN_: case UNIX_: case VMS_: case ATARI_: case BEOS_: case QDOS_: case TANDEM_: G.pInfo->file_attr = (unsigned)(tmp >> 16); if (G.pInfo->file_attr != 0 || !G.extra_field) { br0 g UNZIP.BCK  [UNZIP542.ACORN]ACORN.C;1B-eak; } else { /* Some (non-Info-ZIP) implementations of Zip for Unix and VMS (and probably others ??) leave 0 in the upper 16-bit part of the external_file_attributes field. Instead, they store file permission attributes in some extra field. As a work-around, we search for the presence of one of these extra fields and fall back to the MSDOS compatible part of external_file_attributes if one of the known e.f. types has been detected. Later, we might implement extraction of the permission bits from the VMS extra field. But for now, the work-around should be sufficient to provide "readable" extracted files. (For ASI Unix e.f., an experimental remap of the e.f. mode value IS already provided!) */ ush ebID; unsigned ebLen; uch *ef = G.extra_field; unsigned ef_len = G.crec.extra_field_length; int r = FALSE; while (!r && ef_len >= EB_HEADSIZE) { ebID = makeword(ef); ebLen = (unsigned)makeword(ef+EB_LEN); if (ebLen > (ef_len - EB_HEADSIZE)) /* discoverd some e.f. inconsistency! */ break; switch (ebID) { case EF_ASIUNIX: if (ebLen >= (EB_ASI_MODE+2)) { G.pInfo->file_attr = (unsigned)makeword(ef+(EB_HEADSIZE+EB_ASI_MODE)); /* force stop of loop: */ ef_len = (ebLen + EB_HEADSIZE); break; } /* else: fall through! */ case EF_PKVMS: /* "found nondecypherable e.f. with perm. attr" */ r = TRUE; default: break; } ef_len -= (ebLen + EB_HEADSIZE); ef += (ebLen + EB_HEADSIZE); } if (!r) break; } /* fall through! */ /* all remaining cases: expand MSDOS read-only bit into write perms */ case FS_FAT_: /* PKWARE's PKZip for Unix marks entries as FS_FAT_, but stores the * Unix attributes in the upper 16 bits of the external attributes * field, just like Info-ZIP's Zip for Unix. We try to use that * value, after a check for consistency with the MSDOS attribute * bits (see below). */ G.pInfo->file_attr = (unsigned)(tmp >> 16); /* fall through! */ case FS_HPFS_: case FS_NTFS_: case MAC_: case TOPS20_: default: /* Ensure that DOS subdir bit is set when the entry's name ends * in a '/'. Some third-party Zip programs fail to set the subdir * bit for directory entries. */ if ((tmp | 0x10) == 0) { extent fnlen = strlen(G.filename); if (fnlen > 0 && G.filename[fnlen-1] == '/') tmp |= 0x10; } /* read-only bit --> write perms; subdir bit --> dir exec bit */ tmp = !(tmp & 1) << 1 | (tmp & 0x10) >> 4; if ((G.pInfo->file_attr & 0700) == (unsigned)(0400 | tmp<<6)) /* keep previous G.pInfo->file_attr setting, when its "owner" * part appears to be consistent with DOS attribute flags! */ break; G.pInfo->file_attr = (unsigned)(0444 | tmp<<6 | tmp<<3 | tmp); break; } /* end switch (host-OS-created-by) */ G.pInfo->file_attr&=0xFFFF; G.pInfo->file_attr|=(0xFFDu<<20); if (has_NFS_ext(G.filename)) { int ftype=strtol(G.filename+strlen(G.filename)-3,NULL,16)&0xFFF; G.pInfo->file_attr = (G.pInfo->file_attr & 0x000FFFFF) | (ftype<<20); } else { int type = mimemap(G.filename); if (type == -1) type = (G.crec.internal_file_attributes & 1) ? 0xFFF : 0xFFD; G.pInfo->file_attr = (G.pInfo->file_attr & 0x000FFFFF) | (type<<20); } return 0; } /* end function mapattr() */ /************************/ /* Function mimemap() */ /************************/ static int mimemap(const char *name) { const char *ext = name; int type; if (has_mimemap < 0) has_mimemap = !(SWI_OS_CLI("%RMEnsure MimeMap 0.05 RMLoad System:Modules.MimeMap") || SWI_OS_CLI("%RMEnsure MimeMap 0.05")); if (!has_mimemap) return -1; /* no MimeMap module; fall back on text flag test */ do { while (*ext && *ext!='.') ext++; if (!*ext) return -1; /* no suitable extension; fallback */ type = SWI_MimeMap_Translate(ext++); } while (type == -1); return type; } /************************/ /* Function mapname() */ /************************/ /* return 0 if no error, 1 if caution (filename */ int mapname(__G__ renamed) /* truncated), 2 if warning (skip file because */ __GDEF /* dir doesn't exist), 3 if error (skip file), */ int renamed; /* or 10 if out of memory (skip file) */ { /* [also IZ_VOL_LABEL, IZ_CREATED_DIR] */ char pathcomp[FILNAMSIZ]; /* path-component buffer */ char *pp, *cp=(char *)NULL; /* character pointers */ char *lastsemi=(char *)NULL; /* pointer to last semi-colon in pathcomp */ int quote = FALSE; /* flags */ int error = 0; register unsigned workch; /* hold the character being tested */ char *checkswap=NULL; /* pointer the the extension to check or NULL */ /*--------------------------------------------------------------------------- Initialize various pointers and counters and stuff. ---------------------------------------------------------------------------*/ if (G.pInfo->vollabel) return IZ_VOL_LABEL; /* can't set disk volume labels in RISCOS */ /* can create path as long as not just freshening, or if user told us */ G.create_dirs = (!uO.fflag || renamed); created_dir = FALSE; /* not yet */ /* user gave full pathname: don't prepend rootpath */ renamed_fullpath = (renamed && (*G.filename == '/')); if (checkdir(__G__ (char *)NULL, INIT) == 10) return 10; /* initialize path buffer, unless no memory */ *pathcomp = '\0'; /* initialize translation buffer */ pp = pathcomp; /* point to translation buffer */ if (uO.jflag) /* junking directories */ cp = (char *)strrchr(G.filename, '/'); if (cp == (char *)NULL) /* no '/' or not junking dirs */ cp = G.filename; /* point to internal zipfile-member pathname */ else ++cp; /* point to start of last component of path */ /*--------------------------------------------------------------------------- Begin main loop through characters in filename. ---------------------------------------------------------------------------*/ while ((workch = (uch)*cp++) != 0) { if (quote) { /* if character quoted, */ *pp++ = (char)workch; /* include it literally */ quote = FALSE; } eKl UNZIP.BCK  [UNZIP542.ACORN]ACORN.C;1BRlse switch (workch) { case '/': /* can assume -j flag not given */ *pp = '\0'; if ((error = checkdir(__G__ pathcomp, APPEND_DIR)) > 1) return error; pp = pathcomp; /* reset conversion buffer for next piece */ lastsemi = (char *)NULL; /* leave directory semi-colons alone */ checkswap=NULL; /* reset checking when starting a new leafname */ break; case ';': /* VMS version (or DEC-20 attrib?) */ lastsemi = pp; *pp++ = ';'; /* keep for now; remove VMS ";##" */ break; /* later, if requested */ case '\026': /* control-V quote for special chars */ quote = TRUE; /* set flag for next character */ break; case ' ': /* change spaces to hard-spaces */ *pp++ = 160; /* (ISO 8859-1 Latin-1 codepage) */ break; case ':': /* change ':' to '' (vertical broken bar) */ *pp++ = '\xA6'; /* (position 166 in ISO 8859-1 code table) */ break; case '&': /* change '&' to 'E' */ *pp++ = 'E'; break; case '@': /* change '@' to 'A' */ *pp++ = 'A'; break; case '.': *pp++ = '/'; checkswap=pp; break; default: /* allow European characters in filenames: */ if (isprint(workch) || (128 <= workch && workch <= 254)) *pp++ = (char)workch; } /* end switch */ } /* end while loop */ *pp = '\0'; /* done with pathcomp: terminate it */ /* if not saving them, remove VMS version numbers (appended ";###") */ if (!uO.V_flag && lastsemi) { pp = lastsemi + 1; while (isdigit((uch)(*pp))) ++pp; if (*pp == '\0') /* only digits between ';' and end: nuke */ *lastsemi = '\0'; } /*--------------------------------------------------------------------------- Report if directory was created (and no file to create: filename ended in '/'), check name to be sure it exists, and combine path and name be- fore exiting. ---------------------------------------------------------------------------*/ if (G.filename[strlen(G.filename) - 1] == '/') { checkdir(__G__ G.filename, GETPATH); if (created_dir) { if (QCOND2) { Info(slide, 0, ((char *)slide, " creating: %s\n", G.filename)); } return IZ_CREATED_DIR; /* set dir time (note trailing '/') */ } return 2; /* dir existed already; don't look for data to extract */ } if (*pathcomp == '\0') { Info(slide, 1, ((char *)slide, "mapname: conversion of %s failed\n", G.filename)); return 3; } if (checkswap!=NULL) { if (checkext(checkswap)) { if ((error = checkdir(__G__ checkswap, APPEND_DIR)) > 1) return error; *(checkswap-1)=0; /* remove extension from pathcomp */ } } if (!uO.acorn_nfs_ext && has_NFS_ext(pathcomp)) { /* remove the filetype extension unless requested otherwise */ /* the filetype should be already set by mapattr() */ pathcomp[strlen(pathcomp)-4]=0; } checkdir(__G__ pathcomp, APPEND_NAME); /* returns 1 if truncated: care? */ checkdir(__G__ G.filename, GETPATH); return error; } /* end function mapname() */ /***********************/ /* Function checkdir() */ /***********************/ int checkdir(__G__ pathcomp, flag) __GDEF char *pathcomp; int flag; /* * returns: 1 - (on APPEND_NAME) truncated filename * 2 - path doesn't exist, not allowed to create * 3 - path doesn't exist, tried to create and failed; or * path exists and is not a directory, but is supposed to be * 4 - path is too long * 10 - can't allocate memory for filename buffers */ { static int rootlen = 0; /* length of rootpath */ static char *rootpath; /* user's "extract-to" directory */ static char *buildpath; /* full path (so far) to extracted file */ static char *end; /* pointer to end of buildpath ('\0') */ # define FN_MASK 7 # define FUNCTION (flag & FN_MASK) /*--------------------------------------------------------------------------- APPEND_DIR: append the path component to the path being built and check for its existence. If doesn't exist and we are creating directories, do so for this one; else signal success or error as appropriate. ---------------------------------------------------------------------------*/ if (FUNCTION == APPEND_DIR) { int too_long = FALSE; #ifdef SHORT_NAMES char *old_end = end; #endif Trace((stderr, "appending dir segment [%s]\n", pathcomp)); while ((*end = *pathcomp++) != '\0') ++end; #ifdef SHORT_NAMES /* path components restricted to 14 chars, typically */ if ((end-old_end) > FILENAME_MAX) /* GRR: proper constant? */ *(end = old_end + FILENAME_MAX) = '\0'; #endif /* GRR: could do better check, see if overrunning buffer as we go: * check end-buildpath after each append, set warning variable if * within 20 of FILNAMSIZ; then if var set, do careful check when * appending. Clear variable when begin new path. */ if ((end-buildpath) > FILNAMSIZ-3) /* need '/', one-char name, '\0' */ too_long = TRUE; /* check if extracting directory? */ if (stat(buildpath, &G.statbuf)) { /* path doesn't exist */ if (!G.create_dirs) { /* told not to create (freshening) */ free(buildpath); return 2; /* path doesn't exist: nothing to do */ } if (too_long) { Info(slide, 1, ((char *)slide, "checkdir error: path too long: %s\n", buildpath)); fflush(stderr); free(buildpath); return 4; /* no room for filenames: fatal */ } if (mkdir(buildpath, 0777) == -1) { /* create the directory */ Info(slide, 1, ((char *)slide, "checkdir error: cannot create %s\n\ unable to process %s.\n", buildpath, G.filename)); free(buildpath); return 3; /* path didn't exist, tried to create, failed */ } created_dir = TRUE; } else if (!S_ISDIR(G.statbuf.st_mode)) { Info(slide, 1, ((char *)slide, "checkdir error: %s exists but is not directory\n\ unable to process %s.\n", buildpath, G.filename)); free(buildpath); return 3; /* path existed but wasn't dir */ } if (too_long) { Info(slide, 1, ((char *)slide, "checkdir error: path too long: %s\n", buildpath)); free(buildpath); return 4; /* no room for filenames: fatal */ } *end++ = '.'; /************* was '/' *************/ *end = '\0'; Trace((stderr, "buildpath now = [%s]\n", buildpath)); return 0; } /* end if (FUNCTION == APPEND_DIR) */ /*-------=w UNZIP.BCK  [UNZIP542.ACORN]ACORN.C;1B,-------------------------------------------------------------------- GETPATH: copy full path to the string pointed at by pathcomp, and free buildpath. ---------------------------------------------------------------------------*/ if (FUNCTION == GETPATH) { strcpy(pathcomp, buildpath); Trace((stderr, "getting and freeing path [%s]\n", pathcomp)); free(buildpath); buildpath = end = (char *)NULL; return 0; } /*--------------------------------------------------------------------------- APPEND_NAME: assume the path component is the filename; append it and return without checking for existence. ---------------------------------------------------------------------------*/ if (FUNCTION == APPEND_NAME) { #ifdef SHORT_NAMES char *old_end = end; #endif Trace((stderr, "appending filename [%s]\n", pathcomp)); while ((*end = *pathcomp++) != '\0') { ++end; #ifdef SHORT_NAMES /* truncate name at 14 characters, typically */ if ((end-old_end) > FILENAME_MAX) /* GRR: proper constant? */ *(end = old_end + FILENAME_MAX) = '\0'; #endif if ((end-buildpath) >= FILNAMSIZ) { *--end = '\0'; Info(slide, 0x201, ((char *)slide, "checkdir warning: path too long; truncating\n\ %s\n -> %s\n", G.filename, buildpath)); return 1; /* filename truncated */ } } Trace((stderr, "buildpath now = [%s]\n", buildpath)); return 0; /* could check for existence here, prompt for new name... */ } /*--------------------------------------------------------------------------- INIT: allocate and initialize buffer space for the file currently being extracted. If file was renamed with an absolute path, don't prepend the extract-to path. ---------------------------------------------------------------------------*/ /* GRR: for VMS and TOPS-20, add up to 13 to strlen */ if (FUNCTION == INIT) { Trace((stderr, "initializing buildpath to ")); if ((buildpath = (char *)malloc(strlen(G.filename)+rootlen+1)) == (char *)NULL) return 10; if ((rootlen > 0) && !renamed_fullpath) { strcpy(buildpath, rootpath); end = buildpath + rootlen; } else { *buildpath = '\0'; end = buildpath; } Trace((stderr, "[%s]\n", buildpath)); return 0; } /*--------------------------------------------------------------------------- ROOT: if appropriate, store the path in rootpath and create it if neces- sary; else assume it's a zipfile member and return. This path segment gets used in extracting all members from every zipfile specified on the command line. ---------------------------------------------------------------------------*/ #if (!defined(SFX) || defined(SFX_EXDIR)) if (FUNCTION == ROOT) { Trace((stderr, "initializing root path to [%s]\n", pathcomp)); if (pathcomp == (char *)NULL) { rootlen = 0; return 0; } if (rootlen > 0) /* rootpath was already set, nothing to do */ return 0; if ((rootlen = strlen(pathcomp)) > 0) { char *tmproot; if ((tmproot = (char *)malloc(rootlen+2)) == (char *)NULL) { rootlen = 0; return 10; } strcpy(tmproot, pathcomp); if (tmproot[rootlen-1] == '.') { /****** was '/' ********/ tmproot[--rootlen] = '\0'; } if (rootlen > 0 && (stat(tmproot, &G.statbuf) || !S_ISDIR(G.statbuf.st_mode))) { /* path does not exist */ if (!G.create_dirs /* || isshexp(tmproot) */ ) { free(tmproot); rootlen = 0; return 2; /* skip (or treat as stored file) */ } /* create the directory (could add loop here scanning tmproot * to create more than one level, but why really necessary?) */ if (mkdir(tmproot, 0777) == -1) { Info(slide, 1, ((char *)slide, "checkdir: cannot create extraction directory: %s\n", tmproot)); free(tmproot); rootlen = 0; /* path didn't exist, tried to create, and */ return 3; /* failed: file exists, or 2+ levels required */ } } tmproot[rootlen++] = '.'; /*********** was '/' *************/ tmproot[rootlen] = '\0'; if ((rootpath = (char *)realloc(tmproot, rootlen+1)) == NULL) { free(tmproot); rootlen = 0; return 10; } Trace((stderr, "rootpath now = [%s]\n", rootpath)); } return 0; } #endif /* !SFX || SFX_EXDIR */ /*--------------------------------------------------------------------------- END: free rootpath, immediately prior to program exit. ---------------------------------------------------------------------------*/ if (FUNCTION == END) { Trace((stderr, "freeing rootpath\n")); if (rootlen > 0) { free(rootpath); rootlen = 0; } return 0; } return 99; /* should never reach */ } /* end function checkdir() */ /********************/ /* Function mkdir() */ /********************/ int mkdir(path, mode) const char *path; int mode; /* ignored */ /* * returns: 0 - successful * -1 - failed (errno not set, however) */ { return (SWI_OS_File_8((char *)path) == NULL)? 0 : -1; } /*********************************/ /* extra_field-related functions */ /*********************************/ int isRISCOSexfield(void *extra_field) { if (extra_field!=NULL) { extra_block *block=(extra_block *)extra_field; return (block->ID==EF_SPARK && (block->size==24 || block->size==20) && block->ID_2==SPARKID_2); } else return FALSE; } void setRISCOSexfield(char *path, void *extra_field) { if (extra_field!=NULL) { extra_block *block=(extra_block *)extra_field; SWI_OS_File_1(path,block->loadaddr,block->execaddr,block->attr); } } void printRISCOSexfield(int isdir, void *extra_field) { extra_block *block=(extra_block *)extra_field; printf("\n This file has RISC OS file informations in the local extra field.\n"); if (isdir) { /* I prefer not to print this string... should change later... */ /* printf(" The file is a directory.\n");*/ } else if ((block->loadaddr & 0xFFF00000) != 0xFFF00000) { printf(" Load address: %.8X\n",block->loadaddr); printf(" Exec address: %.8X\n",block->execaddr); } else { /************* should change this to use OS_FSControl 18 to get filetype string ************/ char tmpstr[16]; char ftypestr[32]; int flen; sprintf(tmpstr,"File$Type_%03x",(block->loadaddr & 0x000FFF00) >> 8); if (SWI_OS_ReadVarVal(tmpstr,ftypestr,32,&flen)==NULL) { ftypestr[flen]=0; printf(" Filetype: %s (&%.3X)\n",ftypestr,(block->loadaddr & 0x000FFF00) >> 8); } else { printf(" Filetype: &%.3X\n",(block->loadaddr & 0x000FFF00) >> 8); } } printf(" Access: "); if (block->attr & (1<<3)) printf("L"); if (block->attr & (1<<0)) printf("W"); if (block->attr & (1<<1)) printf("R"); printf("/"); if (block->attr & (1<<4)) printf("w"); if (block->attr & (1<<5)) prin > UNZIP.BCK  [UNZIP542.ACORN]ACORN.C;1B!;tf("r"); printf("\n\n"); } /**********************************************/ /* internal help function for time conversion */ /**********************************************/ static int uxtime2acornftime(unsigned *pexadr, unsigned *pldadr, time_t ut) { unsigned timlo; /* 3 lower bytes of acorn file-time plus carry byte */ unsigned timhi; /* 2 high bytes of acorn file-time */ timlo = ((unsigned)ut & 0x00ffffffU) * 100 + 0x00996a00U; timhi = ((unsigned)ut >> 24); timhi = timhi * 100 + 0x0000336eU + (timlo >> 24); if (timhi & 0xffff0000U) return 1; /* calculation overflow, do not change time */ /* insert the five time bytes into loadaddr and execaddr variables */ *pexadr = (timlo & 0x00ffffffU) | ((timhi & 0x000000ffU) << 24); *pldadr = (*pldadr & 0xffffff00U) | ((timhi >> 8) & 0x000000ffU); return 0; /* subject to future extension to signal overflow */ } /****************************/ /* Function close_outfile() */ /****************************/ void close_outfile(__G) __GDEF { fclose(G.outfile); if (isRISCOSexfield(G.extra_field)) { setRISCOSexfield(G.filename, G.extra_field); } else { unsigned int loadaddr, execaddr; int attr; int mode=G.pInfo->file_attr&0xffff; /* chmod equivalent mode */ time_t m_time; #ifdef USE_EF_UT_TIME iztimes z_utime; #endif #ifdef USE_EF_UT_TIME if (G.extra_field && #ifdef IZ_CHECK_TZ G.tz_is_valid && #endif (ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0, G.lrec.last_mod_dos_datetime, &z_utime, NULL) & EB_UT_FL_MTIME)) { TTrace((stderr, "close_outfile: Unix e.f. modif. time = %ld\n", z_utime.mtime)); m_time = z_utime.mtime; } else #endif /* USE_EF_UT_TIME */ m_time = dos_to_unix_time(G.lrec.last_mod_dos_datetime); /* set the file's modification time */ SWI_OS_File_5(G.filename, NULL, &loadaddr, NULL, NULL, &attr); uxtime2acornftime(&execaddr, &loadaddr, m_time); loadaddr = (loadaddr & 0xfff000ffU) | ((G.pInfo->file_attr&0xfff00000) >> 12); attr=(attr&0xffffff00) | ((mode&0400) >> 8) | ((mode&0200) >> 6) | ((mode&0004) << 2) | ((mode&0002) << 4); SWI_OS_File_1(G.filename, loadaddr, execaddr, attr); } } /* end function close_outfile() */ #ifdef TIMESTAMP /***************************/ /* Function stamp_file() */ /***************************/ int stamp_file(fname, modtime) ZCONST char *fname; time_t modtime; { unsigned int loadaddr, execaddr; int attr; /* set the file's modification time */ if (SWI_OS_File_5((char *)fname, NULL, &loadaddr, NULL, NULL, &attr) != NULL) return -1; if (uxtime2acornftime(&execaddr, &loadaddr, modtime) != 0) return -1; return (SWI_OS_File_1((char *)fname, loadaddr, execaddr, attr) == NULL) ? 0 : -1; } /* end function stamp_file() */ #endif /* TIMESTAMP */ #ifndef SFX /************************/ /* Function version() */ /************************/ void version(__G) __GDEF { sprintf((char *)slide, LoadFarString(CompiledWith), #ifdef __GNUC__ "gcc ", __VERSION__, #else # ifdef __CC_NORCROFT "Norcroft ", "cc", # else "cc", "", # endif #endif "RISC OS", " (Acorn Computers Ltd)", #ifdef __DATE__ " on ", __DATE__ #else "", "" #endif ); (*G.message)((zvoid *)&G, slide, (ulg)strlen((char *)slide), 0); } /* end function version() */ #endif /* !SFX */ a*[UNZIP542.ACORN]CONTENTS.;1+, ./ 4v- 0@123KPWO56P˃7P˃89GHJContents of the "acorn" subdirectory for UnZip 5.4 and later: acorn.c.acorn Acorn-specific resources acorn.c.riscos mainly file-handling routines for FileCore-based filesystems acorn.Contents this file acorn.GMakeFile Makefile for gcc 2.7.2.1 acorn.h.riscos acorn.h.swiven acorn.makefile Makefile script for default Acorn C compiler acorn.README notes about Acorn-specific features acorn.RunMe1st Obey file to move files into suitable place for compilation on RISC OS machines acorn.s.swiven SWI veneers acorn.srcrename small executable that converts files from Unix style to RISC OS style, used by RunMe1st Notes: Use the "RunMe1st" file (it is an Obey file) to convert all the files from "filename/[chs]" to "[chs].filename" (so that UnZip could be easily compiled under RISC OS). It will also set the correct makefile. To compile just set the CSD to the main UnZip directory and run 'amu'. Currently only the Acorn C V5 compiler has been tested but probably also Acorn C V4 and the Acorn Assembler V2 will be able to compile UnZip. *[UNZIP542.ACORN]GMAKEFILE.;1+, . / 4 - 0@123KPWO 56{? 7{? 89GHJ# Makefile for UnZip, UnZipSFX, ZipInfo and fUnZip (5.2 or later) CC = gcc BIND = drlink AS = $(CC) -c ASM = as SQUEEZE = squeeze -v E = # flags # CFLAGS flags for C compile # LFLAGS1 flags after output file spec, before obj file list # LFLAGS2 flags after obj file list (libraries, etc) # LIB = CFLAGS = -O2 -mstubs -mthrowback CFLAGS = $(CFLAGS) ASMFLAGS = -throwback -objasm -upper LFLAGS1 = LFLAGS2 = $(LIB) C:o.stubs gcc:o.libgcc # object file lists OBJS1 = o.unzip o.crc32 o.crctab o.crypt o.envargs o.explode OBJS2 = o.extract o.fileio o.globals o.inflate o.list o.match OBJS3 = o.process o.ttyio o.unreduce o.unshrink o.zipinfo OBJS = $(OBJS1) $(OBJS2) $(OBJS3) o.riscos o.swiven o.acorn OBJF = o.funzip o.crc32 o.crypt_ o.globals_ o.inflate_ o.ttyio_ \ o.riscos o.swiven OBJX = o.unzipsfx o.crc32 o.crctab o.crypt o.extract_ o.fileio o.globals \ o.inflate o.match o.process_ o.ttyio o.acorn_ o.swiven o.riscos_ UNZIP_H = h.unzip h.unzpriv h.globals acorn.h.riscos acorn.h.swiven all: unzip funzip unzipsfx install: unzip funzip unzipsfx $(SQUEEZE) unzip %.unzip $(SQUEEZE) funzip %.funzip $(SQUEEZE) unzipsfx unzipsfx copy %.unzip %.zipinfo ~CVF # rules for unzip and funzip o.crc32: c.crc32 $(UNZIP_H) h.zip $(CC) $(CFLAGS) -c c.crc32 -o o.crc32 o.crctab: c.crctab $(UNZIP_H) h.zip $(CC) $(CFLAGS) -c c.crctab -o o.crctab o.crypt: c.crypt $(UNZIP_H) h.zip h.crypt h.ttyio $(CC) $(CFLAGS) -c c.crypt -o o.crypt o.envargs: c.envargs $(UNZIP_H) $(CC) $(CFLAGS) -c c.envargs -o o.Q UNZIP.BCK  [UNZIP542.ACORN]GMAKEFILE.;1 ` envargs o.explode: c.explode $(UNZIP_H) $(CC) $(CFLAGS) -c c.explode -o o.explode o.extract: c.extract $(UNZIP_H) h.crypt $(CC) $(CFLAGS) -c c.extract -o o.extract o.fileio: c.fileio $(UNZIP_H) h.crypt h.ttyio h.ebcdic $(CC) $(CFLAGS) -c c.fileio -o o.fileio o.funzip: c.funzip $(UNZIP_H) h.crypt h.ttyio h.tables $(CC) $(CFLAGS) -c c.funzip -o o.funzip o.globals: c.globals $(UNZIP_H) $(CC) $(CFLAGS) -c c.globals -o o.globals o.inflate: c.inflate h.inflate $(UNZIP_H) $(CC) $(CFLAGS) -c c.inflate -o o.inflate o.list: c.list $(UNZIP_H) $(CC) $(CFLAGS) -c c.list -o o.list o.match: c.match $(UNZIP_H) $(CC) $(CFLAGS) -c c.match -o o.match o.process: c.process $(UNZIP_H) $(CC) $(CFLAGS) -c c.process -o o.process o.ttyio: c.ttyio $(UNZIP_H) h.zip h.crypt h.ttyio $(CC) $(CFLAGS) -c c.ttyio -o o.ttyio o.unreduce: c.unreduce $(UNZIP_H) $(CC) $(CFLAGS) -c c.unreduce -o o.unreduce o.unshrink: c.unshrink $(UNZIP_H) $(CC) $(CFLAGS) -c c.unshrink -o o.unshrink o.unzip: c.unzip $(UNZIP_H) h.crypt h.version h.consts $(CC) $(CFLAGS) -c c.unzip -o o.unzip o.zipinfo: c.zipinfo $(UNZIP_H) $(CC) $(CFLAGS) -c c.zipinfo -o o.zipinfo o.crypt_: c.crypt $(UNZIP_H) h.zip h.crypt h.ttyio $(CC) $(CFLAGS) -DFUNZIP -c c.crypt -o o.crypt_ o.extract_: c.extract $(UNZIP_H) h.crypt $(CC) $(CFLAGS) -DSFX -c c.extract -o o.extract_ o.globals_: c.globals $(UNZIP_H) $(CC) $(CFLAGS) -DFUNZIP -c c.globals -o o.globals_ o.inflate_: c.inflate h.inflate $(UNZIP_H) h.crypt $(CC) $(CFLAGS) -DFUNZIP -c c.inflate -o o.inflate_ o.process_: c.process $(UNZIP_H) $(CC) $(CFLAGS) -DSFX -c c.process -o o.process_ o.ttyio_: c.ttyio $(UNZIP_H) h.zip h.crypt h.ttyio $(CC) $(CFLAGS) -DFUNZIP -c c.ttyio -o o.ttyio_ o.unzipsfx: c.unzip $(UNZIP_H) h.crypt h.version h.consts $(CC) $(CFLAGS) -DSFX -c c.unzip -o o.unzipsfx o.acorn: acorn.c.acorn $(UNZIP_H) $(CC) $(CFLAGS) -I@ -c acorn.c.acorn o.acorn_: acorn.c.acorn $(UNZIP_H) $(CC) $(CFLAGS) -I@ -c -DSFX -DSFX_EXDIR -o o.acorn_ acorn.c.acorn o.riscos: acorn.c.riscos $(UNZIP_H) $(CC) $(CFLAGS) -I@ -c acorn.c.riscos o.riscos_: acorn.c.riscos $(UNZIP_H) $(CC) $(CFLAGS) -I@ -c -DSFX -DSFX_EXDIR -o o.riscos_ acorn.c.riscos o.swiven: acorn.s.swiven $(ASM) $(ASMFLAGS) acorn.s.swiven -o o.swiven unzip: $(OBJS) $(BIND) -o unzip$(E) $(LFLAGS1) $(OBJS) $(LFLAGS2) funzip: $(OBJF) $(BIND) -o funzip$(E) $(LFLAGS1) $(OBJF) $(LFLAGS2) unzipsfx: $(OBJX) $(BIND) -o unzipsfx$(E) $(LFLAGS1) $(OBJX) $(LFLAGS2) clean: ;remove unzip; remove funzip; remove zipinfo; remove unzipsfx; create o.!fake! 0 wipe o.* ~cf # end of Makefile *[UNZIP542.ACORN]MAKEFILE.;1+, ./ 4c- 0@123KPWO 56Y{7Y{89GHJ# Makefile for UnZip, UnZipSFX, ZipInfo and fUnZip (5.41 or later) # last modified: 27 Oct 1999 # add -g to CC to debug # add -d to BIND to debug CC = cc BIND = link AS = $(CC) -c ASM = objasm SQUEEZE = squeeze -v E = # flags # CFLAGS flags for C compile # LFLAGS1 flags after output file spec, before obj file list # LFLAGS2 flags after obj file list (libraries, etc) # LIB = CFLAGS = -throwback -wn -DNO_STRNICMP CFLAGS = $(CFLAGS) -IC:,@. ASMFLAGS = -Throwback -Stamp -NoCache -CloseExec -quit LFLAGS1 = LFLAGS2 = $(LIB) C:o.Stubs # object file lists OBJS1 = unzip.o crc32.o crctab.o crypt.o envargs.o explode.o OBJS2 = extract.o fileio.o globals.o inflate.o list.o match.o OBJS3 = process.o ttyio.o unreduce.o unshrink.o zipinfo.o OBJS = $(OBJS1) $(OBJS2) $(OBJS3) riscos.o swiven.o acorn.o OBJF = funzip.o crc32.o crypt_.o globals_.o inflate_.o ttyio_.o \ riscos.o swiven.o OBJX = unzipsfx.o crc32.o crctab.o crypt.o extract_.o fileio.o globals.o \ inflate.o match.o process_.o ttyio.o acorn_.o swiven.o riscos_.o UNZIP_H = unzip.h unzpriv.h globals.h acorn/riscos.h acorn/swiven.h all: unzip funzip unzipsfx install: unzip funzip unzipsfx $(SQUEEZE) unzip %.unzip $(SQUEEZE) funzip %.funzip $(SQUEEZE) unzipsfx unzipsfx copy %.unzip %.zipinfo ~CVF # suffix rules .SUFFIXES: .o .c .c.o: $(CC) $(CFLAGS) -c $< .s.o: $(ASM) $(ASMFLAGS) -from @*.s -to @*.o # rules for unzip and funzip crc32.o: crc32.c $(UNZIP_H) zip.h crctab.o: crctab.c $(UNZIP_H) zip.h crypt.o: crypt.c $(UNZIP_H) zip.h crypt.h ttyio.h envargs.o: envargs.c $(UNZIP_H) explode.o: explode.c $(UNZIP_H) extract.o: extract.c $(UNZIP_H) crypt.h fileio.o: fileio.c $(UNZIP_H) crypt.h ttyio.h ebcdic.h funzip.o: funzip.c $(UNZIP_H) crypt.h ttyio.h tables.h globals.o: globals.c $(UNZIP_H) inflate.o: inflate.c inflate.h $(UNZIP_H) list.o: list.c $(UNZIP_H) match.o: match.c $(UNZIP_H) process.o: process.c $(UNZIP_H) ttyio.o: ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h unreduce.o: unreduce.c $(UNZIP_H) unshrink.o: unshrink.c $(UNZIP_H) unzip.o: unzip.c $(UNZIP_H) crypt.h version.h consts.h zipinfo.o: zipinfo.c $(UNZIP_H) crypt_.o: crypt.c $(UNZIP_H) zip.h crypt.h ttyio.h $(CC) $(CFLAGS) -DFUNZIP -c c.crypt -o o.crypt_ extract_.o: extract.c $(UNZIP_H) crypt.h $(CC) $(CFLAGS) -DSFX -c c.extract -o o.extract_ globals_.o: globals.c $(UNZIP_H) $(CC) $(CFLAGS) -DFUNZIP -c c.globals -o o.globals_ inflate_.o: inflate.c inflate.h $(UNZIP_H) crypt.h $(CC) $(CFLAGS) -DFUNZIP -c c.inflate -o o.inflate_ process_.o: process.c $(UNZIP_H) $(CC) $(CFLAGS) -DSFX -c c.process -o o.process_ ttyio_.o: ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h $(CC) $(CFLAGS) -DFUNZIP -c c.ttyio -o o.ttyio_ unzipsfx.o: unzip.c $(UNZIP_H) crypt.h version.h consts.h $(CC) $(CFLAGS) -DSFX -c c.unzip -o o.unzipsfx acorn.o: acorn/acorn.c $(UNZIP_H) $(CC) $(CFLAGS) -c acorn/acorn.c acorn_.o: acorn/acorn.c $(UNZIP_H) $(CC) $(CFLAGS) -c -DSFX -DSFX_EXDIR -o acorn_.o acorn/acorn.c riscos.o: acorn/riscos.c $(UNZIP_H) $(CC) $(CFLAGS) -c acorn/riscos.c riscos_.o: acorn/riscos.c $(UNZIP_H) $(CC) $(CFLAGS) -c -DSFX -DSFX_EXDIR -o riscos_.o acorn/riscos.c swiven.o: acorn/swiven.s $(ASM) $(ASMFLAGS) -from acorn.s.swiven -to o.swiven unzip: $(OBJS) $(BIND) -o unzip$(E) $(LFLAGS1) $(OBJS) $(LFLAGS2) funzip: $(OBJF) $(BIND) -o funzip$(E) $(LFLAGS1) $(OBJF) $(LFLAGS2) unzipsfx: $(OBJX) $(BIND) -o unzipsfx$(E) $(LFLAGS1) $(OBJX) $(LFLAGS2) clean: ;remove unzip; remove funzip; remove zipinfo; remove unzipsfx; create o.!fake! 0 wipe o.* ~cf # end of Makefile o*[UNZIP542.ACORN]README.;1+, ./ 4- 0@123KPWO567|J77|J89GHJ7 UNZIP.BCK  [UNZIP542.ACORN]README.;1 Acorn-specific usage instructions --------------------------------- As zipfiles can come from a variety of sources apart from Acorn machines, consideration had to be given to the handling of dot-extensions, a la DOSFILE.TXT, unix-filename.tar.gz . What was decided that they would be extracted as DOSFILE/TXT and unix-filename/tar/gz, and then truncated to 10-characters, for FileCore compliance. This can quickly be altered for any new releases of FileCore that Acorn may make for longer filenames. Unfortunately, this means that you must be REALLY careful about extracting files from archives. The files dummy_source.c and dummy_source.h will both be extracted as dummy_sour UnZip will prompt you for confirmation of the over-writing of these files, but you must be really careful unless you wish to lose files! Also, because UnZip is a unix-ported program, the filenames are CASE SENSITIVE. *unzip new/zip newfile will extract 'newfile', but not 'NewFile', 'NEWFILE' or any other combinations. However, you can use the -C option to force operations to disregard the case of filenames. The Acorn UnZip port has an additional feature to cope with the extraction of files containing 'c' code. As you may be aware, Acorn Desktop C requires all files called "foo.c" to be renamed to "c.foo", ie "foo" in a directory called "c". To cope with this, a colon-separated environment variable has been set up called "Unzip$Exts". Any extensions found in this variable will be extracted to directories named after the extension, with the extension stripped. For example: *Set Unzip$Exts "c:h:o:s" will extract all the files called 'foo.c' to a directory called 'c'. This can be used to include "c:h:o:s:txt" to pull all the text files out to a separate directory. UnZip fully supports SparkFS Extra Field. This means that zipfiles created with SparkFS or Zip (on RISC OS) will be correctly unzipped, including filetypes. UnZipSFX can be used to create self-extracting archives. To use it, just create a common zipfile using Zip (or SparkFS), then load the UnZipSFX executable into an editor (eg. Edit, Zap), go with the caret the end of the file (using CTRL-CursorDown) and drag the zipfile to the editor window (in other words, append the zipfile to the UnZipSFX executable). Now, saving the resulting file (with filetype Absolute (&FF8)), you have a self-extracting archive (ie. double-clicking on it will unzip the contents of the original zipfile to the currently selected directory). *[UNZIP542.ACORN]RISCOS.C;1+, ./ 49- 0@123KPWO56t7t89GHJ/* Copyright (c) 1990-2000 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /* riscos.c */ #include #include #include /* #define NO_UNZIPH_STUFF */ #define UNZIP_INTERNAL #include "unzip.h" #include "riscos.h" #define MAXEXT 16 char *exts2swap = NULL; /* Extensions to swap (actually, directory names) */ int stat(char *filename,struct stat *res) { int attr; /* object attributes */ unsigned int load; /* load address */ unsigned int exec; /* exec address */ int type; /* type: 0 not found, 1 file, 2 dir, 3 image */ if (!res) return -1; if (SWI_OS_File_5(filename,&type,&load,&exec,(int *)&res->st_size,&attr)!=NULL) return -1; if (type==0) return -1; res->st_dev=0; res->st_ino=0; res->st_nlink=0; res->st_uid=1; res->st_gid=1; res->st_rdev=0; res->st_blksize=1024; res->st_mode = ((attr & 0001) << 8) | ((attr & 0002) << 6) | ((attr & 0020) >> 2) | ((attr & 0040) >> 4); switch (type) { case 1: /* File */ res->st_mode |= S_IFREG; break; case 2: /* Directory */ res->st_mode |= S_IFDIR | 0700; break; case 3: /* Image file */ if (uO.scanimage) res->st_mode |= S_IFDIR | 0700; else res->st_mode |= S_IFREG; break; } if ((((unsigned int) load) >> 20) == 0xfff) { /* date stamped file */ register unsigned int t1, t2, tc; t1 = (unsigned int) (exec); t2 = (unsigned int) (load & 0xff); tc = 0x6e996a00U; if (t1 < tc) t2--; t1 -= tc; t2 -= 0x33; /* 00:00:00 Jan. 1 1970 = 0x336e996a00 */ t1 = (t1 / 100) + (t2 * 42949673U); /* 0x100000000 / 100 = 42949672.96 */ t1 -= (t2 / 25); /* compensate for .04 error */ res->st_atime = res->st_mtime = res->st_ctime = t1; } else res->st_atime = res->st_mtime = res->st_ctime = 0; return 0; } #ifndef SFX DIR *opendir(char *dirname) { DIR *thisdir; int type; int attr; os_error *er; thisdir=(DIR *)malloc(sizeof(DIR)); if (thisdir==NULL) return NULL; thisdir->dirname=(char *)malloc(strlen(dirname)+1); if (thisdir->dirname==NULL) { free(thisdir); return NULL; } strcpy(thisdir->dirname,dirname); if (thisdir->dirname[strlen(thisdir->dirname)-1]=='.') thisdir->dirname[strlen(thisdir->dirname)-1]=0; if (er=SWI_OS_File_5(thisdir->dirname,&type,NULL,NULL,NULL,&attr),er!=NULL || type<=1 || (type==3 && !uO.scanimage)) { free(thisdir->dirname); free(thisdir); return NULL; } thisdir->buf=malloc(DIR_BUFSIZE); if (thisdir->buf==NULL) { free(thisdir->dirname); free(thisdir); return NULL; } thisdir->size=DIR_BUFSIZE; thisdir->offset=0; thisdir->read=0; return thisdir; } struct dirent *readdir(DIR *d) { static struct dirent dent; if (d->read==0) { /* no more objects read in the buffer */ if (d->offset==-1) { /* no more objects to read */ return NULL; } d->read=255; if (SWI_OS_GBPB_9(d->dirname,d->buf,&d->read,&d->offset,DIR_BUFSIZE,NULL)!=NULL) return NULL; if (d->read==0) { d->offset=-1; return NULL; } d->read--; d->act=(char *)d->buf; } else { /* some object is ready in buffer */ d->read--; d->act=(char *)(d->act+strlen(d->act)+1); } strcpy(dent.d_name,d->act); dent.d_namlen=strlen(dent.d_name); return &dent; } void closedir(DIR *d) { if (d->buf!=NULL) free(d->buf); if (d->dirname!=NULL) free(d->dirname); free(d); } int unlink(f) char *f; /* file to delete */ /* Delete the file *f, returning non-zero on failure. */ { os_error *er; char canon[256]; int size=255; er=SWI_OS_FSControl_37(f,canon,&size); if (er==NULL) { er=SWI_OS_FSControl_27(canon,0x100); } else { er=SWI_OS_FSControl_27(f,0x100); } return (int)er; } int rmdir(char *d) { int objtype; char *s; int len; len = strlen(d); if ((s = malloc(len + 1)) == NULL) return -1; strcpy(s,d); if (s[len-1]=='.') s[len-1]=0; if (SWI_OS_File_5(s,&objtype,NULL,NULL,NULL,NULL)!=NULL) { free(s); return -1; } if (objtype<2 || (!uO.scanimage && objtype==3)) { /* this is a file or it doesn't exist */ free(s); return -1; } if (SWI_OS_File_6(s)!=NULL) { free(s); return -1; } free(s); return 0; } #endi UNZIP.BCK  [UNZIP542.ACORN]RISCOS.C;1{G  f /* !SFX */ int chmod(char *file, int mode) { /*************** NOT YET IMPLEMENTED!!!!!! ******************/ /* I don't know if this will be needed or not... */ file=file; mode=mode; return 0; } void setfiletype(char *fname,int ftype) { char str[256]; sprintf(str,"SetType %s &%3.3X",fname,ftype); SWI_OS_CLI(str); } void getRISCOSexts(char *envstr) { char *envptr; /* value returned by getenv */ envptr = getenv(envstr); if (envptr == NULL || *envptr == 0) return; exts2swap=malloc(1+strlen(envptr)); if (exts2swap == NULL) return; strcpy(exts2swap, envptr); } int checkext(char *suff) { register char *extptr = exts2swap ? exts2swap : ""; register char *suffptr; register int e,s; while(*extptr) { suffptr=suff; e=*extptr; s=*suffptr; while (e && e!=':' && s && s!='.' && s!='/' && e==s) { e=*++extptr; s=*++suffptr; } if (e==':') e=0; if (s=='.' || s=='/') s=0; if (!e && !s) { return 1; } while(*extptr!=':' && *extptr!='\0') /* skip to next extension */ extptr++; if (*extptr!='\0') extptr++; } return 0; } void swapext(char *name, char *exptr) { char ext[MAXEXT]; register char *p1=exptr+1; register char *p2=ext; int extchar=*exptr; while(*p1 && *p1!='.' && *p1!='/') *p2++=*p1++; *p2=0; p2=exptr-1; p1--; while(p2 >= name) *p1--=*p2--; p1=name; p2=ext; while(*p2) *p1++=*p2++; *p1=(extchar=='/'?'.':'/'); } void remove_prefix(void) { SWI_DDEUtils_Prefix(NULL); } void set_prefix(void) { char *pref; int size=0; if (SWI_OS_FSControl_37("@",pref,&size)!=NULL) return; size=1-size; if (pref=malloc(size),pref!=NULL) { if (SWI_OS_FSControl_37("@",pref,&size)!=NULL) { free(pref); return; } if (SWI_DDEUtils_Prefix(pref)==NULL) { atexit(remove_prefix); } free(pref); } } #ifdef localtime # undef localtime #endif #ifdef gmtime # undef gmtime #endif /* Acorn's implementation of localtime() and gmtime() * doesn't consider the timezone offset, so we have to * add it before calling the library functions */ struct tm *riscos_localtime(const time_t *timer) { time_t localt=*timer; localt+=SWI_Read_Timezone()/100; return localtime(&localt); } struct tm *riscos_gmtime(const time_t *timer) { time_t localt=*timer; localt+=SWI_Read_Timezone()/100; return gmtime(&localt); } *[UNZIP542.ACORN]RISCOS.H;1+, ./ 4(- 0@123KPWO56C7C89GHJ/* Copyright (c) 1990-2000 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /* riscos.h */ #ifndef __riscos_h #define __riscos_h #include typedef struct { int errnum; char errmess[252]; } os_error; #ifndef __swiven_h # include "swiven.h" #endif #define MAXPATHLEN 256 #define MAXFILENAMELEN 64 /* should be 11 for ADFS, 13 for DOS, 64 seems a sensible value... */ #define DIR_BUFSIZE 1024 /* this should be enough to read a whole E-Format directory */ struct stat { unsigned int st_dev; int st_ino; unsigned int st_mode; int st_nlink; unsigned short st_uid; unsigned short st_gid; unsigned int st_rdev; unsigned int st_size; unsigned int st_blksize; time_t st_atime; time_t st_mtime; time_t st_ctime; }; typedef struct { char *dirname; void *buf; int size; char *act; int offset; int read; } DIR; struct dirent { unsigned int d_off; /* offset of next disk directory entry */ int d_fileno; /* file number of entry */ size_t d_reclen; /* length of this record */ size_t d_namlen; /* length of d_name */ char d_name[MAXFILENAMELEN]; /* name */ }; typedef struct { unsigned int load_addr; unsigned int exec_addr; int lenght; int attrib; int objtype; char name[13]; } riscos_direntry; #define SPARKID_2 0x30435241 /* = "ARC0" */ typedef struct { short ID; short size; int ID_2; unsigned int loadaddr; unsigned int execaddr; int attr; int zero; } extra_block; #define S_IFMT 0770000 #define S_IFDIR 0040000 #define S_IFREG 0100000 /* 0200000 in UnixLib !?!?!?!? */ #ifndef S_IEXEC # define S_IEXEC 0000100 # define S_IWRITE 0000200 # define S_IREAD 0000400 #endif #ifndef NO_UNZIPH_STUFF # include # if (!defined(HAVE_STRNICMP) & !defined(NO_STRNICMP)) # define NO_STRNICMP # endif # ifndef DATE_FORMAT # define DATE_FORMAT DF_DMY # endif # define lenEOL 1 # define PutNativeEOL *q++ = native(LF); # define USE_STRM_INPUT # define USE_FWRITE # define PIPE_ERROR (errno == 9999) /* always false */ # define isatty(x) (TRUE) /* used in funzip.c to find if stdin redirected: should find a better way, now just work as if stdin never redirected */ # define USE_EF_UT_TIME # if (!defined(NOTIMESTAMP) && !defined(TIMESTAMP)) # define TIMESTAMP # endif # define localtime riscos_localtime # define gmtime riscos_gmtime #endif /* !NO_UNZIPH_STUFF */ #define _raw_getc() SWI_OS_ReadC() extern char *exts2swap; /* Extensions to swap */ int stat(char *filename,struct stat *res); DIR *opendir(char *dirname); struct dirent *readdir(DIR *d); void closedir(DIR *d); int unlink(char *f); int rmdir(char *d); int chmod(char *file, int mode); void setfiletype(char *fname,int ftype); void getRISCOSexts(char *envstr); int checkext(char *suff); void swapext(char *name, char *exptr); void remove_prefix(void); void set_prefix(void); struct tm *riscos_localtime(const time_t *timer); struct tm *riscos_gmtime(const time_t *timer); #endif /* !__riscos_h */ *[UNZIP542.ACORN]RUNME1ST.;1+, ./ 4c- 0@123KPWO56ÖmH7ÖmH89GHJ| This Obey file prepares the UnZip port for a Desktop C re-compile. | Run it and it will copy all the needed files into the correct | place. | Set the correct type of 'srcrename' so that the only requirement | for the user is to set 'RunMe1st' to Obey SetType .srcrename FF8 | Run 'srcrename' on the main UnZip directory with recursion enabled /.srcrename -r -e c:h:s:o .^ | Create the 'o' directory CDir .^.o | Put the Makefile in its correct place and set the correct filetype SetType .makefile FE1 Copy .makefile .^.makefile ~C ~V F  GVr] UNZIP.BCK' [UNZIP542.ACORN]SRCRENAME.;1 b*[UNZIP542.ACORN]SRCRENAME.;1+,'. / 4 o- 0@123KPWO 56vEDOF_q@LJHĚEƚn?oX/}ƚ-o*Ě:,pE@rIԈaSnf3rN"TSCbflzR;F99Jg?$7vؙęTKLYC9A;EAHZH皪જ+eC l6␘ԙ㘙ԙlԺfa4nN!u83gP7ݺԪEZ<6i\],+KCҚ7+XҚ=W6{,DT*}7~ԭl2salnb 4Xz" 𙻚 薙֔˩ әљ #ɟǙ a ng3sQyOY̚=+'BMGQH$NL/sI,84D5,?6Kw왬ī}FȚ|ND9)lWca4nN[ )I?v6i>?6H6i»\aob4w޺&/% - 0H'ފ(/&.@ (1ahne3qTPR?y8I MAKESFX.C7MKGOFF.C6 SMAKEFILE.#BSTAT.C$3Z-STAT.H1M*[UNZIP542.AMIGA]AMIGA.C;1+, (.C/ 4CCD- 50@123KPWOD56捞7捞89GHJ >  [UNZIP542.ACORN]GDYHGP&11 j02G'-R ZL&sZ fME?#}HaMt flTn^Yo~^d( Q!?B72k`s{Jb>=Q-wW]RA'4z׏הhTw%6kU/&ƂnY]Յu\ҷ-  d8Ҙnbٙ!:B5TT.i ۇq JEP%HTm$KM)>K;ex6}=ɞ뿝ϥwÖhx̵㛳̬"ɌI`_٣ܝ1۵ⓕI%ʪƔྭ])C'LG6Q8Ȳh4r=̪hY gtŝL(I<\@\ʑ3̛`jⷦIyk$ ޢQ 3ӡa$5. ˳㚣Zb9ݞ.oѾ՚ Ŗ*n 9{sըheTZlb0h @ح숐?Ÿj#˶тprcKUӴ홎ΤH6p_ NQIO[vҖhmAJّaԤٹVOϰ(򰛃ɹ d~?igvF3{ov٥[7졓i` B]iӢF? x|F\xWL9KmV#aOBW;[=tޢ.Zo#[8IZjl3p8PN_OP<u=@Py1u`gN8笘JЁiߕX0d':î8 gkP})?'[TVu%ͨrT)4Pp\ip"#?\4B-cK(Jgt=Ɩ̀2 ^+oC eoTd{!T8׎(K$UJ駵iݽ2Š!S*aV܎_1@Qih>bܳx3=e) Bq2ղ%+M'ɲǤ7p1t?; y\Fs6jg4w^*YbUW=tz-#Q-()>i"j|et*&PjOK Su+GI=(cz5(-xud?:O!'cRhZs#{#a`()z&]p:,!qg;nprO@g{/Yh Hipb4sf`\x b CRgq f]O~PS-#Iy\M*(u^UeZ~8Pmv=t\Jd~^l{kMM"G l54H]^~b1f`&xK B {%iZV Wo#RJBAEd}XYe0_3y~gz?x}|c lCG\^Aq U8V)h5wN9@O="8t&$2>Tzn!+(w51H)_gsu$Q8X@v=`Uo"Pb!My[h?(Uy3z`TSjurCoSh_&\%6cNC<]ۋ+IKl nL|[+\,Ɏuy8Ehf~u Z)Ͽ1IuM{u@,p 2 }3&qO  qiVe5?kb_#F+`feQzbRNRp[K,Vj/}A1H\_JJ {. pXRihKׯUHkV»Lwst̳M*zz^JRWDֲ"=$9?,|+T|)RFc+?;݂DvQ! ga|񲙘;= tJ2bj7 =nE$ZY>!oPt(*]8~uISU.h88_A-C~^*|MWe"2~d-;5Ho9p-"Դp KyZ5p=޵nH dd`e5QO_06ߚr% [Yz‚bw+k6˜R(* a<$n!$'EvDGu :ZT!±W:%Odu;~J}/zGb8I>,'msCP>GTiO, K7IC\H"[ &BS +HXhM >?a *]~ JK~PGFDI+UA d/Ave/P0F'ZD\q&ѷ[ELh Q7|K ʤ~zKo܋jF^/B_yTSzb,.Zn=Ws_1XQ^YH;[qHENF^zY:Vt`PVg74P(Jl&)$X"= IM(ZN`9CVAzB5`> z?,91xOW6B!YA.NE8L;Sm y@mx{ vI7EfFWW՗DAN_^ud_2SblNZ,maG?Q 6p |/Ï>V%; |I $.nt'Y2:meip\curWd)2oDe*]L}Z({j䈥{X-GAAUI#V)P`M"oA*I. ޗhE]` 7M e4]H:(0.PQ*!]="qDO^SHȒW"e嶧 o$|«^jE~E1AXԅ簁6vQ%XR*t8hnKmɋqo%N}iA^ 凲W2eTlC+ցr`[.vȽTk iҳJȯ |z[_uᾊ9D[`Cqx:tDzKYGPS|??.C08eD9iUJTP 5lC(R[Vb4AN_=,%; j5rSp'd[hV2&%Rqh hL]WqBYgnsW>m4ΖAC95tQx*K[}YJ j' A*,?G"w,ZZ:=z| ]?"P[-),_b8i6> }"i{}jr(}4mPU:._f89*]aQzuiOQ('dQLYKg:7c$<2DfB e%sT :rx8zar {Ue<$Y',W)Zc6)Hx|,OSfx&$$WPWvGc2WU) =C`1hN>*Z.\sqO,5X:A#PnyStK,svCnx4u-# B 6Gg@e Au/Ilj?u@wa]whq-&0W%k(]7am[ B3NGm |h$= AYg\2q 0IQ?u0IN(w8 +->:$f[ K[F0)u>oYI }*dx8#nPBUdY-eMtMH`I&3;vN1mNl=6Kls=%twd|D6 |WnIiWZpU4F'\|]_ KOX?"EV2!)k<7ckm?bX7~T&Fx9h9+=RSR_Bb'z)^:Zs 52/9i\o&+_Z nOG N&M^ط=S:xU1i8"$fcn' dxq,.6=7W D@ wu7}:eB&I^;e.W{7G1b)V48!,ph1_ %XFoY'qHB MO b?G XPco4a)sp@e=# Ikh pTB+"UI 1*zzPcEIi%m 88`1`Ytg^vr+V_&'v.y8{7T8B!g*p2T7}D:jdl}g ^@X1vVjw_e|0*{W[%,ah#WX wg] ^_5@4LD[4'l;Q73g8Z cq`_H=%{w8S%#kB~YetkJf*9eO: gYC.FKm$k# ukXfk/p2 EQ@- x .abUDKSekY2-c)Qz#XqCnhcV 0e*%dD1nUw2j}< 2eAsmyzb$Qw wf2ie8L9-7R5x1OETsr|6B<zE;3hV`tTv$7's,?w~EJ$~z2-6MjF3U,]>m0H#/%>3diLp;-Kls(#)2 >? Y/k9[E6L?iJcC~*5IIOF#9p6-`CH+\ D,f.8b-*MkvO~-!"&~ fwBB]9n\E^ Gc0#< Ps h!N_Q$c_Py:.3=w54KV`#HNZ\+6aXSlQQ7^O^-$ !^erAr_'8ny1m?Y\1|:) %jOdW))n0|H%A>rlVEBZJ,qWCM+|byCc8t?e&KrXPY4s[l#J56Ae}fR%l:4>g"TZd'o-qIH:{Pt:LB{W4L]/"H5nUYoP )XvD]9( D DbbTG2o+l%`AvPB*P.eF^m|M8> &Q@, SyV[8;_# T*WO \"!U~N;] 9Y&[T^*P.2xR*11 2|!3:;ac')i.?P^<q"k/S|>+\Iv<0&Z/p>|1.) @@5bB3Q'(\J1G7y ;geh}lQ?i--F5|aGNnn*]#o*q"1J+/BVM{G@ig{cw=m:VJen*i+Y\a&q9RGMv3N)!MZ]9TwbCf6"'+u`U(l {SN>a|[=rqd]QMXN5W RyzS=YkU@; :)xX!i#S AEzkN3tETN\.!-5e5jDpy/\=SmV MPUuFZc/W)k^?_5]8dCe\@&B*o&b5m.`6-#3 :Hd2 NMeZu5@Os,LnaVmM&t=@8k"(i[9s: WjRy n5| o#MCpM},+(Ija5`n3fr5+i`z?(j6T8U@Z7dFAA @C6=!]Q 3V5q}R3rT2w>fk'I 7 6|F]am&oXf U23Vm{}峽|v Wb"}nkQKB{C2pd]8kHv(h@L!r3qx G $G1G^8 'dS$:73;8I* OO case BEOS_: case QDOS_: case TANDEM_: G.pInfo->file_attr = (unsigned)(tmp >> 16); if (G.pInfo->file_attr != 0 || !G.extra_field) { br ̘ UNZIP.BCK ( 5[UNZIP542.AMIGA]AMIGA.C;1C/* Copyright (c) 1990-2000 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*------------------------------------------------------------------------ amiga.c Amiga-specific routines for use with Info-ZIP's UnZip 5.1 and later. See History.5xx for revision history. Contents: do_wild() mapattr() mapname() checkdir() close_outfile() stamp_file() _abort() (Aztec C only) [dateformat()] (currently not used) screensize() version() ------------------------------------------------------------------------*/ #define UNZIP_INTERNAL #ifdef AZTEC_C # define NO_FCNTL_H #endif #include "unzip.h" /* Globular varibundus -- now declared in SYSTEM_SPECIFIC_GLOBALS in amiga.h */ /* static int created_dir; */ /* used in mapname(), checkdir() */ /* static int renamed_fullpath; */ /* ditto */ #define PERMS 0777 #define MKDIR(path,mode) mkdir(path) #ifndef S_ISCRIPT /* not having one implies you have none */ # define S_IARCHIVE 0020 /* not modified since this bit was last set */ # define S_IREAD 0010 /* can be opened for reading */ # define S_IWRITE 0004 /* can be opened for writing */ # define S_IDELETE 0001 /* can be deleted */ #endif /* S_ISCRIPT */ #ifndef S_IRWD # define S_IRWD 0015 /* useful combo of Amiga privileges */ #endif /* !S_IRWD */ #ifndef S_IHIDDEN # define S_IHIDDEN 0200 /* hidden supported in future AmigaDOS (someday) */ #endif /* !S_HIDDEN */ #ifndef SFX /* Make sure the number here matches version.h in the *EXACT* form */ /* UZ_MAJORVER "." UZ_MINORVER UZ_PATCHLEVEL vvvv No non-digits! */ const char version_id[] = "\0$VER: UnZip 5.41 (" #include "env:VersionDate" ")\r\n"; #endif /* SFX */ static int ispattern(ZCONST char *p) { register char c; while (c = *p++) if (c == '\\') { if (!*++p) return FALSE; } else if (c == '?' || c == '*') return TRUE; else if (c == '[') { for (;;) { if (!(c = *p++)) return FALSE; else if (c == '\\') { if (!*++p) return FALSE; } else if (c == ']') return TRUE; } } return FALSE; } /**********************/ /* Function do_wild() */ /**********************/ char *do_wild(__G__ wildspec) __GDEF ZCONST char *wildspec; /* only used first time on a given dir */ { /* these statics are now declared in SYSTEM_SPECIFIC_GLOBALS in amiga.h: static DIR *wild_dir = NULL; static ZCONST char *wildname; static char *dirname, matchname[FILNAMSIZ]; static int notfirstcall = FALSE, dirnamelen; */ struct dirent *file; BPTR lok = 0; /* Even when we're just returning wildspec, we *always* do so in * matchname[]--calling routine is allowed to append four characters * to the returned string, and wildspec may be a pointer to argv[]. */ if (!G.notfirstcall) { /* first call: must initialize everything */ G.notfirstcall = TRUE; /* avoid needless readdir() scans: */ if (!ispattern(wildspec) || (lok = Lock((char *)wildspec, ACCESS_READ))) { if (lok) UnLock(lok); /* ^^ we ignore wildcard chars if */ G.dirnamelen = 0; /* the name matches a real file */ strcpy(G.matchname, wildspec); return G.matchname; } /* break the wildspec into a directory part and a wildcard filename */ if ((G.wildname = (ZCONST char *)strrchr(wildspec, '/')) == NULL && (G.wildname = (ZCONST char *)strrchr(wildspec, ':')) == NULL) { G.dirname = ""; /* current dir */ G.dirnamelen = 0; G.wildname = wildspec; } else { ++G.wildname; /* point at character after '/' or ':' */ G.dirnamelen = G.wildname - wildspec; if ((G.dirname = (char *)malloc(G.dirnamelen+1)) == NULL) { Info(slide, 1, ((char *)slide, "warning: cannot allocate wildcard buffers\n")); strcpy(G.matchname, wildspec); return G.matchname; /* but maybe filespec was not a wildcard */ } strncpy(G.dirname, wildspec, G.dirnamelen); G.dirname[G.dirnamelen] = 0; } if ((G.wild_dir = opendir(G.dirname)) != NULL) { while ((file = readdir(G.wild_dir)) != NULL) { if (match(file->d_name, G.wildname, 1)) { /* ignore case */ strcpy(G.matchname, G.dirname); strcpy(G.matchname + G.dirnamelen, file->d_name); return G.matchname; } } /* if we get to here directory is exhausted, so close it */ closedir(G.wild_dir); G.wild_dir = NULL; } /* return the raw wildspec in case that works (e.g., directory not * searchable, but filespec was not wild and file is readable) */ strcpy(G.matchname, wildspec); return G.matchname; } /* last time through, might have failed opendir but returned raw wildspec */ if (G.wild_dir == NULL) { G.notfirstcall = FALSE; /* nothing left to try -- reset */ if (G.dirnamelen > 0) free(G.dirname); return (char *)NULL; } /* If we've gotten this far, we've read and matched at least one entry * successfully (in a previous call), so dirname has been copied into * matchname already. */ while ((file = readdir(G.wild_dir)) != NULL) if (match(file->d_name, G.wildname, 1)) { /* 1 == ignore case */ /* strcpy(G.matchname, dirname); */ strcpy(G.matchname + G.dirnamelen, file->d_name); return G.matchname; } closedir(G.wild_dir); /* have read at least one dir entry; nothing left */ G.wild_dir = NULL; G.notfirstcall = FALSE; /* reset for new wildspec */ if (G.dirnamelen > 0) free(G.dirname); return (char *)NULL; } /* end function do_wild() */ /**********************/ /* Function mapattr() */ /**********************/ int mapattr(__G) /* Amiga version */ __GDEF { ulg tmp = G.crec.external_file_attributes; /* Amiga attributes = hsparwed = hidden, script, pure, archive, * read, write, execute, delete */ switch (G.pInfo->hostnum) { case AMIGA_: if ((tmp & 1) == (tmp>>18 & 1)) tmp ^= 0x000F0000; /* PKAZip compatibility kluge */ /* turn off archive bit for restored Amiga files */ G.pInfo->file_attr = (unsigned)((tmp>>16) & (~S_IARCHIVE)); break; case UNIX_: /* preserve read, write, execute: use logical-OR of */ case VMS_: /* user, group, and other; if writable, set delete bit */ case ACORN_: case ATARI_: case BEOS_: case QDOS_: case TANDEM_: { unsigned uxattr = (unsigned)(tmp >> 16); int r = FALSE; if (uxattr == 0 && G.extra_field) { /* Some (non-Info-ZIP) implementations of Zip for Unix and  ` UNZIP.BCK ( 5[UNZIP542.AMIGA]AMIGA.C;1C]6 VMS (and probably others ??) leave 0 in the upper 16-bit part of the external_file_attributes field. Instead, they store file permission attributes in some extra field. As a work-around, we search for the presence of one of these extra fields and fall back to the MSDOS compatible part of external_file_attributes if one of the known e.f. types has been detected. Later, we might implement extraction of the permission bits from the VMS extra field. But for now, the work-around should be sufficient to provide "readable" extracted files. (For ASI Unix e.f., an experimental remap of the e.f. mode value IS already provided!) */ ush ebID; unsigned ebLen; uch *ef = G.extra_field; unsigned ef_len = G.crec.extra_field_length; while (!r && ef_len >= EB_HEADSIZE) { ebID = makeword(ef); ebLen = (unsigned)makeword(ef+EB_LEN); if (ebLen > (ef_len - EB_HEADSIZE)) /* discoverd some e.f. inconsistency! */ break; switch (ebID) { case EF_ASIUNIX: if (ebLen >= (EB_ASI_MODE+2)) { uxattr = (unsigned)makeword(ef+(EB_HEADSIZE+EB_ASI_MODE)); /* force stop of loop: */ ef_len = (ebLen + EB_HEADSIZE); break; } /* else: fall through! */ case EF_PKVMS: /* "found nondecypherable e.f. with perm. attr" */ r = TRUE; default: break; } ef_len -= (ebLen + EB_HEADSIZE); ef += (ebLen + EB_HEADSIZE); } } if (!r) { uxattr = (( uxattr>>6 | uxattr>>3 | uxattr) & 07) << 1; G.pInfo->file_attr = (unsigned)(uxattr&S_IWRITE ? uxattr|S_IDELETE : uxattr); break; } } /* fall through! */ /* all other platforms: assume read-only bit in DOS half of attribute * word is set correctly ==> will become READ or READ+WRITE+DELETE */ case FS_FAT_: case FS_HPFS_: /* can add S_IHIDDEN check to MSDOS/OS2/NT eventually */ case FS_NTFS_: case MAC_: case TOPS20_: default: G.pInfo->file_attr = (unsigned)(tmp&1? S_IREAD : S_IRWD); break; } /* end switch (host-OS-created-by) */ G.pInfo->file_attr &= 0xff; /* mask off all but lower eight bits */ return 0; } /* end function mapattr() */ /************************/ /* Function mapname() */ /************************/ int mapname(__G__ renamed) /* return 0 if no error, 1 if caution (truncate), */ __GDEF /* 2 if warning (skip because dir doesn't exist), */ int renamed; /* 3 if error (skip file), 10 if no memory (skip) */ { /* [also IZ_VOL_LABEL, IZ_CREATED_DIR] */ char pathcomp[FILNAMSIZ]; /* path-component buffer */ char *pp, *cp=NULL; /* character pointers */ char *lastsemi = NULL; /* pointer to last semi-colon in pathcomp */ int error = 0; register unsigned workch; /* hold the character being tested */ /*--------------------------------------------------------------------------- Initialize various pointers and counters and stuff. ---------------------------------------------------------------------------*/ if (G.pInfo->vollabel) return IZ_VOL_LABEL; /* can't set disk volume labels in AmigaDOS */ /* can create path as long as not just freshening, or if user told us */ G.create_dirs = (!uO.fflag || renamed); G.created_dir = FALSE; /* not yet */ /* user gave full pathname: don't prepend G.rootpath */ #ifndef OLD_AMIGA_RENAMED G.renamed_fullpath = (renamed && (*G.filename == '/' || *G.filename == ':')); #else /* supress G.rootpath even when user gave a relative pathname */ # if 1 G.renamed_fullpath = (renamed && strpbrk(G.filename, ":/"); # else G.renamed_fullpath = (renamed && (strchr(G.filename, ':') || strchr(G.filename, '/'))); # endif #endif if (checkdir(__G__ (char *)NULL, INIT) == 10) return 10; /* initialize path buffer, unless no memory */ *pathcomp = '\0'; /* initialize translation buffer */ pp = pathcomp; /* point to translation buffer */ if (uO.jflag) /* junking directories */ cp = (char *)strrchr(G.filename, '/'); if (cp == NULL) /* no '/' or not junking dirs */ cp = G.filename; /* point to internal zipfile-member pathname */ else ++cp; /* point to start of last component of path */ /*--------------------------------------------------------------------------- Begin main loop through characters in filename. ---------------------------------------------------------------------------*/ while ((workch = (uch)*cp++) != 0) { switch (workch) { case '/': /* can assume -j flag not given */ *pp = '\0'; if ((error = checkdir(__G__ pathcomp, APPEND_DIR)) > 1) return error; pp = pathcomp; /* reset conversion buffer for next piece */ lastsemi = NULL; /* leave directory semi-colons alone */ break; case ';': /* VMS version (or DEC-20 attrib?) */ lastsemi = pp; /* keep for now; remove VMS ";##" */ *pp++ = (char)workch; /* later, if requested */ break; default: /* allow ISO European characters in filenames: */ if (isprint(workch) || (160 <= workch && workch <= 255)) *pp++ = (char)workch; } /* end switch */ } /* end while loop */ *pp = '\0'; /* done with pathcomp: terminate it */ /* if not saving them, remove with VMS version numbers (appended ";###") */ if (!uO.V_flag && lastsemi) { pp = lastsemi + 1; while (isdigit((uch)(*pp))) ++pp; if (*pp == '\0') /* only digits between ';' and end: nuke */ *lastsemi = '\0'; } /*--------------------------------------------------------------------------- Report if directory was created (and no file to create: filename ended in '/'), check name to be sure it exists, and combine path and name be- fore exiting. ---------------------------------------------------------------------------*/ if (G.filename[strlen(G.filename) - 1] == '/') { checkdir(__G__ G.filename, GETPATH); if (G.created_dir) { if (QCOND2) { Info(slide, 0, ((char *)slide, " creating: %s\n", G.filename)); } return IZ_CREATED_DIR; /* set dir time (note trailing '/') */ } return 2; /* dir existed already; don't look for data to extract */ } if (*pathcomp == '\0') { Info(slide, 1, ((char *)slide, "mapname: conversi$[U UNZIP.BCK ( 5[UNZIP542.AMIGA]AMIGA.C;1Con of %s failed\n", G.filename)); return 3; } if ((error = checkdir(__G__ pathcomp, APPEND_NAME)) == 1) { /* GRR: OK if truncated here: warn and continue */ /* (warn in checkdir?) */ } checkdir(__G__ G.filename, GETPATH); return error; } /* end function mapname() */ /***********************/ /* Function checkdir() */ /***********************/ int checkdir(__G__ pathcomp, flag) __GDEF char *pathcomp; int flag; /* * returns: 1 - (on APPEND_xxx) truncated path component * 2 - path doesn't exist, not allowed to create * 3 - path doesn't exist, tried to create and failed; or * path exists and is not a directory, but is supposed to be * 4 - path is too long * 10 - can't allocate memory for filename buffers */ { /* these statics are now declared in SYSTEM_SPECIFIC_GLOBALS in amiga.h: */ /* static int rootlen = 0; */ /* length of rootpath */ /* static char *rootpath; */ /* user's "extract-to" directory */ /* static char *buildpath; */ /* full path (so far) to extracted file */ /* static char *end; */ /* pointer to end of buildpath ('\0') */ # define FN_MASK 7 # define FUNCTION (flag & FN_MASK) /*--------------------------------------------------------------------------- APPEND_DIR: append the path component to the path being built and check for its existence. If doesn't exist and we are creating directories, do so for this one; else signal success or error as appropriate. ---------------------------------------------------------------------------*/ /* GRR: check path length after each segment: warn about truncation */ if (FUNCTION == APPEND_DIR) { int too_long = FALSE; Trace((stderr, "appending dir segment [%s]\n", pathcomp)); while ((*G.build_end = *pathcomp++)) ++G.build_end; /* Truncate components over 30 chars? Nah, the filesystem handles it. */ if ((G.build_end-G.buildpath) > FILNAMSIZ-3) /* room for "/a\0" */ too_long = TRUE; /* check if extracting directory? */ if (stat(G.buildpath, &G.statbuf)) { /* path doesn't exist */ if (!G.create_dirs) { /* told not to create (freshening) */ free(G.buildpath); return 2; /* path doesn't exist: nothing to do */ } if (too_long) { Info(slide, 1, ((char *)slide, "checkdir error: path too long: %s\n", G.buildpath)); free(G.buildpath); return 4; /* no room for filenames: fatal */ } if (MKDIR(G.buildpath, 0777) == -1) { /* create the directory */ Info(slide, 1, ((char *)slide, "checkdir error: cannot create %s\n\ unable to process %s.\n", G.buildpath, G.filename)); free(G.buildpath); return 3; /* path didn't exist, tried to create, failed */ } G.created_dir = TRUE; } else if (!S_ISDIR(G.statbuf.st_mode)) { Info(slide, 1, ((char *)slide, "checkdir error: %s exists but is not a directory\n\ unable to process %s.\n", G.buildpath, G.filename)); free(G.buildpath); return 3; /* path existed but wasn't dir */ } if (too_long) { Info(slide, 1, ((char *)slide, "checkdir error: path too long: %s\n", G.buildpath)); free(G.buildpath); return 4; /* no room for filenames: fatal */ } *G.build_end++ = '/'; *G.build_end = '\0'; Trace((stderr, "buildpath now = [%s]\n", G.buildpath)); return 0; } /* end if (FUNCTION == APPEND_DIR) */ /*--------------------------------------------------------------------------- GETPATH: copy full path to the string pointed at by pathcomp, and free G.buildpath. Not our responsibility to worry whether pathcomp has room. ---------------------------------------------------------------------------*/ if (FUNCTION == GETPATH) { strcpy(pathcomp, G.buildpath); Trace((stderr, "getting and freeing path [%s]\n", pathcomp)); free(G.buildpath); G.buildpath = G.build_end = NULL; return 0; } /*--------------------------------------------------------------------------- APPEND_NAME: assume the path component is the filename; append it and return without checking for existence. ---------------------------------------------------------------------------*/ if (FUNCTION == APPEND_NAME) { Trace((stderr, "appending filename [%s]\n", pathcomp)); while ((*G.build_end = *pathcomp++)) { ++G.build_end; if ((G.build_end-G.buildpath) >= FILNAMSIZ) { *--G.build_end = '\0'; Info(slide, 1, ((char *)slide, "checkdir warning: path too long; truncating\n\ %s\n -> %s\n", G.filename, G.buildpath)); return 1; /* filename truncated */ } } Trace((stderr, "buildpath static now = [%s]\n", G.buildpath)); return 0; /* could check for existence here, prompt for new name... */ } /*--------------------------------------------------------------------------- INIT: allocate and initialize buffer space for the file currently being extracted. If file was renamed with an absolute path, don't prepend the extract-to path. ---------------------------------------------------------------------------*/ if (FUNCTION == INIT) { Trace((stderr, "initializing buildpath static to ")); if ((G.buildpath = (char *)malloc(strlen(G.filename)+G.rootlen+1)) == NULL) return 10; if ((G.rootlen > 0) && !G.renamed_fullpath) { strcpy(G.buildpath, G.rootpath); G.build_end = G.buildpath + G.rootlen; } else { *G.buildpath = '\0'; G.build_end = G.buildpath; } Trace((stderr, "[%s]\n", G.buildpath)); return 0; } /*--------------------------------------------------------------------------- ROOT: if appropriate, store the path in G.rootpath and create it if necessary; else assume it's a zipfile member and return. This path segment gets used in extracting all members from every zipfile specified on the command line. ---------------------------------------------------------------------------*/ #if (!defined(SFX) || defined(SFX_EXDIR)) if (FUNCTION == ROOT) { Trace((stderr, "initializing root path to [%s]\n", pathcomp)); if (pathcomp == (char *)NULL) { G.rootlen = 0; return 0; } if (G.rootlen > 0) /* G.rootpath was already set, nothing to do */ return 0; if ((G.rootlen = strlen(pathcomp)) > 0) { if (stat(pathcomp, &G.statbuf) || !S_ISDIR(G.statbuf.st_mode)) { /* path does not exist */ if (!G.create_dirs) { G.rootlen = 0; return 2; /* treat as stored file */ } /* create the directory (could add loop here scanning pathcomp * to create more than one level, but why really necessary?) */ if (MKDIR(pathcomp, 0777) == -1) { Info(slide, 1, ((char *)slide, "checkdir: cannot create extraction directory:~ UNZIP.BCK ( 5[UNZIP542.AMIGA]AMIGA.C;1CdE. %s\n", pathcomp)); G.rootlen = 0;/* path didn't exist, tried to create, and */ return 3; /* failed: file exists, or 2+ levels required */ } } if ((G.rootpath = (char *)malloc(G.rootlen+2)) == NULL) { G.rootlen = 0; return 10; } strcpy(G.rootpath, pathcomp); if (G.rootpath[G.rootlen-1] != ':' && G.rootpath[G.rootlen-1] != '/') G.rootpath[G.rootlen++] = '/'; G.rootpath[G.rootlen] = '\0'; Trace((stderr, "rootpath now = [%s]\n", G.rootpath)); } return 0; } #endif /* !SFX || SFX_EXDIR */ /*--------------------------------------------------------------------------- END: free G.rootpath, immediately prior to program exit. ---------------------------------------------------------------------------*/ if (FUNCTION == END) { Trace((stderr, "freeing rootpath\n")); if (G.rootlen > 0) { free(G.rootpath); G.rootlen = 0; } return 0; } return 99; /* should never reach */ } /* end function checkdir() */ /**************************************/ /* Function close_outfile() */ /**************************************/ /* this part differs slightly with Zip */ /*-------------------------------------*/ void close_outfile(__G) __GDEF { time_t m_time; #ifdef USE_EF_UT_TIME iztimes z_utime; #endif LONG FileDate(); if (uO.cflag) /* can't set time or filenote on stdout */ return; /* close the file *before* setting its time under AmigaDOS */ fclose(G.outfile); #ifdef USE_EF_UT_TIME if (G.extra_field && #ifdef IZ_CHECK_TZ G.tz_is_valid && #endif (ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0, G.lrec.last_mod_dos_datetime, &z_utime, NULL) & EB_UT_FL_MTIME)) { TTrace((stderr, "close_outfile: Unix e.f. modif. time = %ld\n", z_utime.mtime)); m_time = z_utime.mtime; } else { /* Convert DOS time to time_t format */ m_time = dos_to_unix_time(G.lrec.last_mod_dos_datetime); } #else /* !USE_EF_UT_TIME */ /* Convert DOS time to time_t format */ m_time = dos_to_unix_time(G.lrec.last_mod_dos_datetime); #endif /* ?USE_EF_UT_TIME */ #ifdef DEBUG Info(slide, 1, ((char *)slide, "\nclose_outfile(): m_time=%s\n", ctime(&m_time))); #endif if (!FileDate(G.filename, &m_time)) Info(slide, 1, ((char *)slide, "warning: cannot set the time for %s\n", G.filename)); /* set file perms after closing (not done at creation)--see mapattr() */ chmod(G.filename, G.pInfo->file_attr); /* give it a filenote from the zipfile comment, if appropriate */ if (uO.N_flag && G.filenotes[G.filenote_slot]) { SetComment(G.filename, G.filenotes[G.filenote_slot]); free(G.filenotes[G.filenote_slot]); G.filenotes[G.filenote_slot] = NULL; } } /* end function close_outfile() */ #ifdef TIMESTAMP /*************************/ /* Function stamp_file() */ /*************************/ int stamp_file(fname, modtime) ZCONST char *fname; time_t modtime; { time_t m_time; LONG FileDate(); m_time = modtime; return (FileDate((char *)fname, &m_time)); } /* end function stamp_file() */ #endif /* TIMESTAMP */ #ifndef __SASC /********************************************************************/ /* Load filedate as a separate external file; it's used by Zip, too.*/ /* */ # include "amiga/filedate.c" /* */ /* */ /********************************************************************/ /********************* do linewise with stat.c **********************/ # include "amiga/stat.c" /* this is the exact same stat.c used by Zip */ #endif /* !__SASC */ /* SAS/C makes separate object modules of these; there is less */ /* trouble that way when redefining standard library functions. */ #include void _abort(void) /* called when ^C is pressed */ { /* echon(); */ close_leftover_open_dirs(); fflush(stdout); fputs("\n^C\n", stderr); exit(1); } /************************************************************/ /* function screensize() -- uses sendpkt() from filedate.c: */ /************************************************************/ #include #include #include #include extern long sendpkt(struct MsgPort *pid, long action, long *args, long nargs); int screensize(int *ttrows, int *ttcols) { BPTR fh = Output(); if (fh && IsInteractive(fh)) { struct ConUnit *conunit = NULL; void *conp = ((struct FileHandle *) (fh << 2))->fh_Type; struct InfoData *ind = AllocMem(sizeof(*ind), MEMF_PUBLIC); long argp = ((unsigned long) ind) >> 2; if (ind && conp && sendpkt(conp, ACTION_DISK_INFO, &argp, 1)) conunit = (void *) ((struct IOStdReq *) ind->id_InUse)->io_Unit; if (ind) FreeMem(ind, sizeof(*ind)); if (conunit) { if (ttrows) *ttrows = conunit->cu_YMax + 1; if (ttcols) *ttcols = conunit->cu_XMax + 1; return 0; /* success */ } } if (ttrows) *ttrows = INT_MAX; if (ttcols) *ttcols = INT_MAX; return 1; /* failure */ } #ifdef AMIGA_VOLUME_LABELS /* This function is for if we someday implement -$ on the Amiga. */ # include # include # include BOOL is_floppy(ZCONST char *path) { BOOL okay = FALSE; char devname[32], *debna; ushort i; BPTR lok = Lock((char *)path, ACCESS_READ), pok; struct FileSysStartupMsg *fart; struct DeviceNode *debb, devlist = (void *) BADDR((struct DosInfo *) BADDR(DOSBase->dl_Root->rn_Info)->di_DevInfo); if (!lok) return FALSE; /* should not happen */ if (pok = ParentDir((char *)path)) { UnLock(lok); UnLock(pok); return FALSE; /* it's not a root directory path */ } Forbid(); for (debb = devlist; debb; debb = BADDR(debb->dn_Next)) if (debb->dn_Type == DLT_DEVICE && (debb->dn_Task == lick->fl_Task)) if (fart = BADDR(debb->dn_Startup)) { debna = (char *) BADDR(fart->fssm_Device) + 1; if ((i = debna[-1]) > 31) i = 30; strncpy(devname, debna, i); devname[i] = 0; okay = !strcmp(devname, "trackdisk.device") || !strcmp(devname, "mfm.device") || !strcmp(devname, "messydisk.device"); break; /* We only support obvious floppy drives, not tricky */ } /* things like removable cartrige hard drives, or */ Permit(); /* any unusual kind of floppy device driver. */ return okay; } #endif /* AMIGA_VOLUME_LABELS */ #ifndef SFX # if 0 /* As far as I can tell, all the locales AmigaDOS 2.1 knows about all */ /* happen to use DF_MDY ordering, so there's no point in using this. */ /*************************/ /* Function dateformat() */ /*************************/ #include #ifdef AZTEC_C # include #endif int dateforq UNZIP.BCK ( 5[UNZIP542.AMIGA]AMIGA.C;1C=mat() { /*--------------------------------------------------------------------------- For those operating systems which support it, this function returns a value which tells how national convention says that numeric dates are displayed. Return values are DF_YMD, DF_DMY and DF_MDY (the meanings should be fairly obvious). ---------------------------------------------------------------------------*/ struct Library *LocaleBase; struct Locale *ll; int result = DF_MDY; /* the default */ if ((LocaleBase = OpenLibrary("locale.library", 0))) { if (ll = OpenLocale(NULL)) { uch *f = ll->loc_ShortDateFormat; /* In this string, %y|%Y is year, %b|%B|%h|%m is month, */ /* %d|%e is day day, and %D|%x is short for mo/da/yr. */ if (!strstr(f, "%D") && !strstr(f, "%x")) { uch *da, *mo, *yr; if (!(mo = strstr(f, "%b")) && !(mo = strstr(f, "%B")) && !(mo = strstr(f, "%h"))) mo = strstr(f, "%m"); if (!(da = strstr(f, "%d"))) da = strstr(f, "%e"); if (!(yr = strstr(f, "%y"))) yr = strstr(f, "%Y"); if (yr && yr < mo) result = DF_YMD; else if (da && da < mo) result = DF_DMY; } CloseLocale(ll); } CloseLibrary(LocaleBase); } return result; } # endif /* 0 */ /************************/ /* Function version() */ /************************/ /* NOTE: the following include depends upon the environment * variable $Workbench to be set correctly. (Set by * default, by kickstart during startup) */ int WBversion = (int) #include "ENV:Workbench" ; void version(__G) __GDEF { /* Define buffers. */ char buf1[16]; /* compiler name */ char buf2[16]; /* revstamp */ char buf3[16]; /* OS */ char buf4[16]; /* Date */ /* char buf5[16]; /* Time */ /* format "with" name strings */ #ifdef AMIGA # ifdef __SASC strcpy(buf1,"SAS/C "); # else # ifdef LATTICE strcpy(buf1,"Lattice C "); # else # ifdef AZTEC_C strcpy(buf1,"Manx Aztec C "); # else strcpy(buf1,"UNKNOWN "); # endif # endif # endif /* "under" */ sprintf(buf3,"AmigaDOS v%d",WBversion); #else strcpy(buf1,"Unknown compiler "); strcpy(buf3,"Unknown OS"); #endif /* Define revision, date, and time strings. * NOTE: Do not calculate run time, be sure to use time compiled. * Pass these strings via your makefile if undefined. */ #if defined(__VERSION__) && defined(__REVISION__) sprintf(buf2,"version %d.%d",__VERSION__,__REVISION__); #else # ifdef __VERSION__ sprintf(buf2,"version %d",__VERSION__); # else sprintf(buf2,"unknown version"); # endif #endif #ifdef __DATE__ sprintf(buf4," on %s",__DATE__); #else strcpy(buf4," unknown date"); #endif /****** #ifdef __TIME__ sprintf(buf5," at %s",__TIME__); #else strcpy(buf5," unknown time"); #endif ******/ /* Print strings using "CompiledWith" mask defined in unzip.c (used by all). * ("Compiled with %s%s for %s%s%s%s.") */ printf(LoadFarString(CompiledWith), buf1, buf2, buf3, buf4, "", /* buf5 not used */ "" ); /* buf6 not used */ } /* end function version() */ #endif /* !SFX */ *[UNZIP542.AMIGA]AMIGA.H;1+,'. / 4 L- 50@123KPWO 56:a7:a89GHJ/* Copyright (c) 1990-2001 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /* amiga.h * * Globular definitions that affect all of AmigaDom. * * Originally included in unzip.h, extracted for simplicity and eeze of * maintenance by John Bush. * * THIS FILE IS #INCLUDE'd by unzpriv.h * */ #ifndef __amiga_amiga_h #define __amiga_amiga_h #include "amiga/z-stat.h" /* substitute for and */ #include #ifndef NO_FCNTL_H # include #else int mkdir(const char *_name); #endif #ifdef AZTEC_C /* Manx Aztec C, 5.0 or newer only */ # include # include /* do inline dos.library calls */ # define O_BINARY 0 # define direct dirent # ifndef IZTZ_DEFINESTDGLOBALS # define IZTZ_DEFINESTDGLOBALS # endif # define DECLARE_TIMEZONE # define ASM_INFLATECODES # define ASM_CRC /* Note that defining REENTRANT will not eliminate all global/static */ /* variables. The functions we use from c.lib, including stdio, are */ /* not reentrant. Neither are the stuff in amiga/stat.c or the time */ /* functions in amiga/filedate.c, because they just augment c.lib. */ /* If you want a fully reentrant and reexecutable "pure" UnZip with */ /* Aztec C, assemble and link in the startup module purify.a by Paul */ /* Kienitz. REENTRANT should be used just to reduce memory waste. */ #endif /* AZTEC_C */ #ifdef __SASC /* includes */ # include # include # include # include # include # if (defined(_M68020) && (!defined(__USE_SYSBASE))) /* on 68020 or higher processors it is faster */ # define __USE_SYSBASE /* to use the pragma libcall instead of syscall */ # endif /* to access functions of the exec.library */ # include /* see SAS/C manual:part 2,chapter 2,pages 6-7 */ # include # include # ifdef DEBUG # include /* profiler header file */ # endif # if ( (!defined(O_BINARY)) && defined(O_RAW)) # define O_BINARY O_RAW # endif # if (defined(_SHORTINT) && !defined(USE_FWRITE)) # define USE_FWRITE /* define if write() returns 16-bit int */ # endif # if (!defined(REENTRANT) && !defined(FUNZIP)) # define REENTRANT /* define if unzip is going to be pure */ # endif # if defined(REENTRANT) && defined(DYNALLOC_CRCTAB) # undef DYNALLOC_CRCTAB # endif # ifdef MWDEBUG # include /* both stdio.h and stdlib.h must be included */ # include /* before memwatch.h */ # include "memwatch.h" # undef getenv # endif /* MWDEBUG */ # ifndef IZTZ_SETLOCALTZINFO /* XXX !! We have really got to find a way to operate without these. */ # define IZTZ_SETLOCALTZINFO # endif #endif /* SASC */ #define MALLOC_WORK #define USE_EF_UT_TIME #if (!defined(NOTIMESTAMP) && !defined(TIMESTAMP)) # define TIMESTAMP #endif #ifndef IZTZ_GETLOCALETZINFO # define IZTZ_GETLOCALETZINFO GetPlatformLocalTimezone #endif /* the amiga port uses Info-ZIP's own timezone library, which includes * a "working" mktime() implementation */ #ifndef HAVE_MKTIME # define HAVE_MKTIME #endif /* chect̔ UNZIP.BCK' 5[UNZIP542.AMIGA]AMIGA.H;1 Jlk that TZ environment variable is defined before using UTC times */ #if (!defined(NO_IZ_CHECK_TZ) && !defined(IZ_CHECK_TZ)) # define IZ_CHECK_TZ #endif #define AMIGA_FILENOTELEN 80 #ifndef DATE_FORMAT # define DATE_FORMAT DF_MDY #endif #define lenEOL 1 #define PutNativeEOL *q++ = native(LF); #define PIPE_ERROR 0 #ifdef GLOBAL /* crypt.c usage conflicts with AmigaDOS headers */ # undef GLOBAL #endif /* Funkshine Prough Toe Taipes */ extern int real_timezone_is_set; void tzset(void); #define VALID_TIMEZONE(tempvar) (tzset(), real_timezone_is_set) int Agetch(void); /* getch() like function, in amiga/filedate.c */ LONG FileDate(char *, time_t[]); int screensize(int *ttrows, int *ttcols); void _abort(void); /* ctrl-C trap */ #define SCREENSIZE(ttrows, ttcols) screensize(ttrows, ttcols) #define SCREENWIDTH 80 #define SCREENLWRAP 1 #define TABSIZE 8 /* Static variables that we have to add to Uz_Globs: */ #define SYSTEM_SPECIFIC_GLOBALS \ int filenote_slot;\ char *(filenotes[DIR_BLKSIZ]);\ int created_dir, renamed_fullpath, rootlen;\ char *rootpath, *buildpath, *build_end;\ DIR *wild_dir;\ ZCONST char *wildname;\ char *dirname, matchname[FILNAMSIZ];\ int dirnamelen, notfirstcall; /* filenotes[] and filenote_slot are for the -N option that restores */ /* comments of Zip archive entries as AmigaDOS filenotes. The others */ /* are used by functions in amiga/amiga.c only. */ /* created_dir and renamed_fullpath are used by mapname() and checkdir(). */ /* rootlen, rootpath, buildpath, and build_end are used by checkdir(). */ /* wild_dir, dirname, wildname, matchname[], dirnamelen and notfirstcall */ /* are used by do_wild(). */ #endif /* __amiga_amiga_h */ *[UNZIP542.AMIGA]CONTENTS.;1+, *./ 4- 50@123KPWO56 F7 F89GHJContents of the "amiga" directory for UnZip 5.42 and later: Contents this file amiga.c Amiga-specific file I/O routines amiga.h Amiga-specific header file filedate.c SetFileDate clone for OS 1.3, and other low-level resources smakefile SAS/C makefile for UnZip, fUnZip, and UnZipSFX makefile.azt Aztec C makefile for UnZip, fUnZip, and UnZipSFX stat.c stat() emulation for Aztec, along with opendir()/readdir()/etc z-stat.h replacement stat.h header file for use with stat.c crc_68.a assembler version of crc32.c flate.a assembler version of inflate_codes() (define ASM_INFLATECODES) mkGoff.c source for MkGoff which generates include file used by flate.a makesfx.c source for MakeSFX, without which UnZipSFX is not usable Notes: The crc_68.a source file is not currently used by the SAS/C makefile, nor is flate.a; as of UnZip 5.2 neither of these wants args in registers. The DICE makefile has been removed since no one is supporting that compiler anymore. As of UnZip 5.2, if you have AmigaDOS 2.1 or newer and have set your timezone in the Locale preferences editor, this will be an adequate substitute for setting TZ. If you do not set TZ to your current timezone, files will be restored with times corrsponding to "EST5EDT", U.S. Eastern time. See ../proginfo/timezone.txt for directions on how to set the TZ variable. *[UNZIP542.AMIGA]CRC_68.A;1+,O. / 4 - 50@123KPWO 56789GHJ;=========================================================================== ; Copyright (c) 1990-2000 Info-ZIP. All rights reserved. ; ; See the accompanying file LICENSE, version 2000-Apr-09 or later ; (the contents of which are also included in zip.h) for terms of use. ; If, for some reason, all these files are missing, the Info-ZIP license ; also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html ;=========================================================================== ; crc_68 created by Paul Kienitz, last modified 04 Jan 96. ; ; Return an updated 32 bit CRC value, given the old value and a block of data. ; The CRC table used to compute the value is gotten by calling get_crc_table(). ; This replaces the older updcrc() function used in Zip and fUnZip. The ; prototype of the function is: ; ; ulg crc32(ulg crcval, uch *text, extent textlen); ; ; On the Amiga, type extent is always unsigned long, not unsigned int, because ; int can be short or long at whim, but size_t is long. ; ; If using this source on a non-Amiga 680x0 system, note that we treat ; a0/a1/d0/d1 as scratch registers not preserved across function calls. ; We do not bother to support registerized arguments for crc32() -- the ; textlen parm is usually large enough so that savings outside the loop ; are pointless. ; ; Define NO_UNROLLED_LOOPS to use a simple short loop which might be more ; efficient on certain machines with dinky instruction caches ('020?), or for ; processing short strings. If loops are unrolled, the textlen parm must be ; less than 512K; if not unrolled, it must be less than 64K. xdef _crc32 ; (ulg val, uch *buf, extent bufsize) DO_CRC0 MACRO moveq #0,ltemp move.b (textbuf)+,ltemp eor.b crcval,ltemp lsl.w #2,ltemp move.l (crc_table,ltemp.w),ltemp lsr.l #8,crcval eor.l ltemp,crcval ENDM machine mc68020 DO_CRC2 MACRO move.b (textbuf)+,btemp eor.b crcval,btemp lsr.l #8,crcval move.l (crc_table,btemp.w*4),ltemp eor.l ltemp,crcval ENDM crc_table equr a0 array of unsigned long crcval equr d0 unsigned long initial value textbuf equr a1 array of unsigned char textbufsize equr d1 unsigned long (count of bytes in textbuf) btemp equr d2 ltemp equr d3 xref _get_crc_table ; ulg *get_crc_table(void) NOLIST INCLUDE 'exec/execbase.i' LIST xref _SysBase ; struct ExecBase * _crc32: move.l 8(sp),d0 bne.s valid moveq #0,d0 rts valid: movem.l btemp/ltemp,-(sp) jsr _get_crc_table move.l d0,ltemp move.l 12(sp),crcval move.l 16(sp),textbuf move.l 20(sp),textbufsize not.l crcval move.l _SysBase,crc_table move.w AttnFlags(crc_table),btemp move.l ltemp,crc_table btst #AFB_68020,btemp bne twenty IFD NO_UNROLLED_LOOPS bra.s decr loop: DO_CRC0 decr: dbra textbufsize,loop bra.s done twenty: moveq #0,btemp bra.s decr2 loop2: DO_CRC2 decr2: dbra textbufsize,loop2 ELSE ; !NO_UNROLLED_LOOPS move.l textbufsize,btemp lsr.l #3,textbufsize bra decr8 loop8: DO_CRC0 DO_CRC0 DO_CRC0 DO_CRC0 DO_CRC0 DO_CRC0 DO_CRC0 DO_CRC0 decr8: dbra textbufsize,loop8 I UNZIP.BCKO 5[UNZIP542.AMIGA]CRC_68.A;1 R and.w #7,btemp bra.s decr1 loop1: DO_CRC0 decr1: dbra btemp,loop1 bra done twenty: moveq #0,btemp move.l textbufsize,-(sp) lsr.l #3,textbufsize bra decr82 loop82: DO_CRC2 DO_CRC2 DO_CRC2 DO_CRC2 DO_CRC2 DO_CRC2 DO_CRC2 DO_CRC2 decr82: dbra textbufsize,loop82 move.l (sp)+,textbufsize and.w #7,textbufsize bra.s decr12 loop12: DO_CRC2 decr12: dbra textbufsize,loop12 ENDC ; ?NO_UNROLLED_LOOPS done: movem.l (sp)+,btemp/ltemp not.l crcval ;;;;; move.l crcval,d0 ; crcval already is d0 rts *[UNZIP542.AMIGA]FILEDATE.C;1+,4.-/ 4--- 50@123KPWO.56`-d\7`-d\89GHJ/* Copyright (c) 1990-2001 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in zip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /* Low-level Amiga routines shared between Zip and UnZip. * * Contains: FileDate() * getenv() [replaces inadequate standard library version] * setenv() [SAS/C only, replaces standard library version] * set_TZ() [SAS/C only] * GetPlatformLocalTimezone() [callback from timezone.c tzset()] * time() * sendpkt() * Agetch() * * The first five are used by most Info-ZIP programs except fUnZip. * The last two are used by all except the non-CRYPT version of fUnZip. * Probably some of the stuff in here is unused by ZipNote and ZipSplit too... * sendpkt() is used by Agetch() and FileDate(), and by screensize() in * amiga/amiga.c (UnZip); time() is used only by Zip. */ /* HISTORY/CHANGES * 2 Sep 92, Greg Roelofs, Original coding. * 6 Sep 92, John Bush, Incorporated into UnZip 5.1 * 6 Sep 92, John Bush, Interlude "FileDate()" defined, which calls or * redefines SetFileDate() depending upon AMIGADOS2 definition. * 11 Oct 92, John Bush, Eliminated AMIGADOS2 switch by determining * revision via OpenLibrary() call. Now only one version of * the program runs on both platforms (1.3.x vs. 2.x) * 11 Oct 92, John Bush, Merged with Zip version and changed arg passing * to take time_t input instead of struct DateStamp. * Arg passing made to conform with utime(). * 22 Nov 92, Paul Kienitz, fixed includes for Aztec and cleaned up some * lint-ish errors; simplified test for AmigaDOS version. * 11 Nov 95, Paul Kienitz, added Agetch() for crypt password input and * UnZip's "More" prompt -- simplifies crypt.h and avoids * use of library code redundant with sendpkt(). Made it * available to fUnZip, which does not use FileDate(). * 22 Nov 95, Paul Kienitz, created a new tzset() that gets the current * timezone from the Locale preferences. These exist only under * AmigaDOS 2.1 and up, but it is probably correctly set on more * Amigas than the TZ environment variable is. We check that * only if TZ is not validly set. We do not parse daylight * savings syntax except to check for presence vs. absence of a * DST part; United States rules are assumed. This is better * than the tzset()s in the Amiga compilers' libraries do. * 15 Jan 96, Chr. Spieler, corrected the logic when to select low level * sendpkt() (when FileDate(), Agetch() or windowheight() is used), * and AMIGA's Agetch() (CRYPT, and UnZip(SFX)'s UzpMorePause()). * 10 Feb 96, Paul Kienitz, re-fiddled that selection logic again, moved * stuff around for clarity. * 16 Mar 96, Paul Kienitz, created a replacement localtime() to go with the * new tzset(), because Aztec's is hopelessly broken. Also * gmtime(), which localtime() calls. * 12 Apr 96, Paul Kienitz, daylight savings was being handled incorrectly. * 21 Apr 96, Paul Kienitz, had to replace time() as well, Aztec's returns * local time instead of GMT. That's why their localtime() was bad, * because it assumed time_t was already local, and gmtime() was * the one that checked TZ. * 23 Apr 96, Chr. Spieler, deactivated time() replacement for UnZip stuff. * Currently, the UnZip sources do not make use of time() (and do * not supply the working mktime() replacement, either!). * 29 Apr 96, Paul Kienitz, created a replacement getenv() out of code that * was previously embedded in tzset(), for reliable global test * of whether TZ is set or not. * 19 Jun 96, Haidinger Walter, re-adapted for current SAS/C compiler. * 7 Jul 96, Paul Kienitz, smoothed together compiler-related changes. * 4 Feb 97, Haidinger Walter, added set_TZ() for SAS/C. * 23 Apr 97, Paul Kienitz, corrected Unix->Amiga DST error by adding * mkgmtime() so localtime() could be used. * 28 Apr 97, Christian Spieler, deactivated mkgmtime() definition for ZIP; * the Zip sources supply this function as part of util.c. * 24 May 97, Haidinger Walter, added time_lib support for SAS/C and moved * set_TZ() to time_lib.c. * 12 Jul 97, Paul Kienitz, adapted time_lib stuff for Aztec. * 26 Jul 97, Chr. Spieler, old mkgmtime() fixed (ydays[] def, sign vs unsign). * 30 Dec 97, Haidinger Walter, adaptation for SAS/C using z-stat.h functions. * 19 Feb 98, Haidinger Walter, removed alloc_remember, more SAS.C fixes. * 23 Apr 98, Chr. Spieler, removed mkgmtime(), changed FileDate to convert to * Amiga file-time directly. * 24 Apr 98, Paul Kienitz, clip Unix dates earlier than 1978 in FileDate(). * 02 Sep 98, Paul Kienitz, C. Spieler, always include zip.h to get a defined * header inclusion sequence that resolves all header dependencies. * 06 Jun 00, Paul Kienitz, removed time_lib.c due to its incompatible license, * moved set_TZ() back here, replaced minimal tzset() and localtime() * with new versions derived from GNU glibc source. Gave locale_TZ() * reasonable European defaults for daylight savings. * 17 Jun 00, Paul Kienitz, threw out GNU code because of objections to the GPL * virus, replaced with similar functions based on the public domain * timezone code at ftp://elsie.nci.nih.gov/pub. As with the GNU * stuff, support for timezone files and leap seconds was removed. * 23 Aug 00, Paul Kienitz, moved timezone code out from here into separate * platform-independent module 'timezone.c'. * 31 Dec 00, Christian Spieler, moved system-specific! UNZIP.BCK4 5[UNZIP542.AMIGA]FILEDATE.C;1- timezone help funcions * back in here, from 'timezone.c'. * 07 Jan 01, Paul Kienitz, Chr. Spieler, added missing #include "timezone.h" * and "symbolic" preprocessor constants for time calculations. */ #ifndef __amiga_filedate_c #define __amiga_filedate_c #include "zip.h" #include #include #include #include #include #include #ifdef AZTEC_C # include # include # include # include # include # include # include # include # define ESRCH ENOENT # define EOSERR EIO #endif #ifdef __SASC # include # if (defined(_M68020) && (!defined(__USE_SYSBASE))) /* on 68020 or higher processors it is faster */ # define __USE_SYSBASE /* to use the pragma libcall instead of syscall */ # endif /* to access functions of the exec.library */ # include /* see SAS/C manual:part 2,chapter 2,pages 6-7 */ # include # include # ifdef DEBUG # include # endif # ifdef MWDEBUG # include /* include both before memwatch.h again just */ # include /* to be safe */ # include "memwatch.h" # endif /* MWDEBUG */ #endif /* __SASC */ #include "crypt.h" /* just so we can tell if CRYPT is supported */ #ifndef FUNZIP #include "timezone.h" /* for AMIGA-specific timezone callbacks */ #ifndef SUCCESS # define SUCCESS (-1L) # define FAILURE 0L #endif #define ReqVers 36L /* required library version for SetFileDate() */ #define ENVSIZE 100 /* max space allowed for an environment var */ extern struct ExecBase *SysBase; #ifndef min # define min(a, b) ((a) < (b) ? (a) : (b)) # define max(a, b) ((a) < (b) ? (b) : (a)) #endif #if defined(ZIP) || defined(HAVE_MKTIME) static const unsigned short ydays[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; #else extern const unsigned short ydays[]; /* in unzip's fileio.c */ #endif #define LEAP(y) (((y) % 4 == 0 && (y) % 100 != 0) || (y) % 400 == 0) #define YDAYS(m, y) (ydays[m] + (m > 1 && LEAP(y))) /* Number of leap years from 1978 to `y' (not including `y' itself). */ #define ANLEAP(y) (((y) - 1977) / 4 - ((y) - 1901) / 100 + ((y) - 1601) / 400) #define SECSPERMIN 60 #define MINSPERHOUR 60 #define SECSPERHOUR (SECSPERMIN * MINSPERHOUR) #define SECSPERDAY 86400L /* prototypes */ char *getenv(const char *var); #ifdef __SASC /* XXX !! We have really got to find a way to operate without these. */ int setenv(const char *var, const char *value, int overwrite); void set_TZ(long time_zone, int day_light); #endif LONG FileDate(char *filename, time_t u[]); LONG sendpkt(struct MsgPort *pid, LONG action, LONG *args, LONG nargs); int Agetch(void); /* =============================================================== */ /***********************/ /* Function filedate() */ /***********************/ /* FileDate() (originally utime.c), by Paul Wells. Modified by John Bush * and others (see also sendpkt() comments, below); NewtWare SetFileDate() * clone cheaply ripped off from utime(). */ /* DESCRIPTION * This routine chooses between 2 methods to set the file date on AMIGA. * Since AmigaDOS 2.x came out, SetFileDate() was available in ROM (v.36 * and higher). Under AmigaDOS 1.3.x (less than v.36 ROM), SetFileDate() * must be accomplished by constructing a message packet and sending it * to the file system handler of the file to be stamped. * * The system's ROM version is extracted from the external system Library * base. * * NOTE: although argument passing conforms with utime(), note the * following differences: * - Return value is boolean success/failure. * - If a structure or array is passed, only the first value * is used, which *may* correspond to date accessed and not * date modified. */ LONG FileDate(filename, u) char *filename; time_t u[]; { LONG SetFileDate(UBYTE *filename, struct DateStamp *pDate); LONG sendpkt(struct MsgPort *pid, LONG action, LONG *args, LONG nargs); struct MsgPort *taskport; BPTR dirlock, lock; struct FileInfoBlock *fib; LONG pktargs[4]; UBYTE *ptr; long ret; struct DateStamp pDate; struct tm *ltm; int years; tzset(); /* Amiga file date is based on 01-Jan-1978 00:00:00 (local time): * 8 years and 2 leapdays difference from Unix time. */ ltm = localtime(&u[0]); years = ltm->tm_year + 1900; if (years < 1978) pDate.ds_Days = pDate.ds_Minute = pDate.ds_Tick = 0; else { pDate.ds_Days = (years - 1978) * 365L + (ANLEAP(years)) + YDAYS(ltm->tm_mon, years) + (ltm->tm_mday - 1); pDate.ds_Minute = ltm->tm_hour * 60 + ltm->tm_min; pDate.ds_Tick = ltm->tm_sec * TICKS_PER_SECOND; } if (SysBase->LibNode.lib_Version >= ReqVers) { return (SetFileDate(filename,&pDate)); /* native routine at 2.0+ */ } else /* !(SysBase->lib_Version >=ReqVers) */ { if( !(taskport = (struct MsgPort *)DeviceProc(filename)) ) { errno = ESRCH; /* no such process */ return FAILURE; } if( !(lock = Lock(filename,SHARED_LOCK)) ) { errno = ENOENT; /* no such file */ return FAILURE; } if( !(fib = (struct FileInfoBlock *)AllocMem( (long)sizeof(struct FileInfoBlock),MEMF_PUBLIC|MEMF_CLEAR)) ) { errno = ENOMEM; /* insufficient memory */ UnLock(lock); return FAILURE; } if( Examine(lock,fib)==FAILURE ) { errno = EOSERR; /* operating system error */ UnLock(lock); FreeMem(fib,(long)sizeof(*fib)); return FAILURE; } dirlock = ParentDir(lock); ptr = (UBYTE *)AllocMem(64L,MEMF_PUBLIC); strcpy((ptr+1),fib->fib_FileName); *ptr = strlen(fib->fib_FileName); FreeMem(fib,(long)sizeof(*fib)); UnLock(lock); /* now fill in argument array */ pktargs[0] = 0; pktargs[1] = (LONG)dirlock; pktargs[2] = (LONG)&ptr[0] >> 2; pktargs[3] = (LONG)&pDate; errno = ret = sendpkt(taskport,ACTION_SET_DATE,pktargs,4L); FreeMem(ptr,64L); UnLock(dirlock); return SUCCESS; } /* ?(SysBase->lib_Version >= ReqVers) */ } /* FileDate() */ char *getenv(const char *var) /* not reentrant! */ { static char space[ENVSIZE]; struct Process *me = (void *) FindTask(NULL); void *old_window = me->pr_WindowPtr; char *ret = NULL; me->pr_WindowPtr = (void *) -1; /* suppress any "Please insert" popups */ if (SysBase->LibNode.lib_Version >= ReqVers) { if (GetVar((char *) var, space, ENVSIZE - 1, /*GVF_GLOBAL_ONLY*/ 0) > 0) ret = space; } else { /* early AmigaDOS, get env var the crude way */ BPTR hand, foot, spine; int z = 0; if (foot = Lock("ENV:", ACCESS_READ)) { spine = CurrentDir(foot); if (hand = Open((char *) var, MODE_OLDFILE)) { z = Read(hand, space, ENVSIZE - 1); Close(hand); } UnLock(CurrentDir(spine)); } if (z > 0) { space[z]괲^ UNZIP.BCK4 5[UNZIP542.AMIGA]FILEDATE.C;1-Ǐ = '\0'; ret = space; } } me->pr_WindowPtr = old_window; return ret; } #ifdef __SASC int setenv(const char *var, const char *value, int overwrite) { struct Process *me = (void *) FindTask(NULL); void *old_window = me->pr_WindowPtr; int ret = -1; me->pr_WindowPtr = (void *) -1; /* suppress any "Please insert" popups */ if (SysBase->LibNode.lib_Version >= ReqVers) ret = !SetVar((char *)var, (char *)value, -1, GVF_GLOBAL_ONLY | LV_VAR); else { BPTR hand, foot, spine; long len = value ? strlen(value) : 0; if (foot = Lock("ENV:", ACCESS_READ)) { spine = CurrentDir(foot); if (len) { if (hand = Open((char *) var, MODE_NEWFILE)) { ret = Write(hand, (char *) value, len + 1) >= len; Close(hand); } } else ret = DeleteFile((char *) var); UnLock(CurrentDir(spine)); } } me->pr_WindowPtr = old_window; return ret; } /* Stores data from timezone and daylight to ENV:TZ. */ /* ENV:TZ is required to exist by some other SAS/C library functions, */ /* like stat() or fstat(). */ void set_TZ(long time_zone, int day_light) { char put_tz[MAXTIMEZONELEN]; /* string for putenv: "TZ=aaabbb:bb:bbccc" */ int offset; void *exists; /* dummy ptr to see if global envvar TZ already exists */ exists = (void *)getenv(TZ_ENVVAR); /* see if there is already an envvar TZ_ENVVAR. If not, create it */ if (exists == NULL) { /* create TZ string by pieces: */ sprintf(put_tz, "GMT%+ld", time_zone / 3600L); if (time_zone % 3600L) { offset = (int) labs(time_zone % 3600L); sprintf(put_tz + strlen(put_tz), ":%02d", offset / 60); if (offset % 60) sprintf(put_tz + strlen(put_tz), ":%02d", offset % 60); } if (day_light) strcat(put_tz,"DST"); setenv(TZ_ENVVAR, put_tz, 1); } } #endif /* __SASC */ /* set state as well as possible from settings found in locale.library */ int GetPlatformLocalTimezone(sp, fill_tzstate_from_rules) register struct state * ZCONST sp; void (*fill_tzstate_from_rules)(struct state * ZCONST sp_res, ZCONST struct rule * ZCONST start, ZCONST struct rule * ZCONST end); { struct Library *LocaleBase; struct Locale *ll; struct Process *me = (void *) FindTask(NULL); void *old_window = me->pr_WindowPtr; BPTR eh; int z, valid = FALSE; /* read timezone from locale.library if TZ envvar missing */ me->pr_WindowPtr = (void *) -1; /* suppress any "Please insert" popups */ if (LocaleBase = OpenLibrary("locale.library", 0)) { if (ll = OpenLocale(NULL)) { z = ll->loc_GMTOffset; /* in minutes */ if (z == -300) { if (eh = Lock("ENV:sys/locale.prefs", ACCESS_READ)) { UnLock(eh); valid = TRUE; } else z = 300; /* bug: locale not initialized, default bogus! */ } else valid = TRUE; if (valid) { struct rule startrule, stoprule; sp->timecnt = 0; sp->typecnt = 1; sp->charcnt = 2; sp->chars[0] = sp->chars[1] = '\0'; sp->ttis[0].tt_abbrind = 0; sp->ttis[1].tt_abbrind = 1; sp->ttis[0].tt_gmtoff = -z * MINSPERHOUR; sp->ttis[1].tt_gmtoff = -z * MINSPERHOUR + SECSPERHOUR; sp->ttis[0].tt_isdst = 0; sp->ttis[1].tt_isdst = 1; stoprule.r_type = MONTH_NTH_DAY_OF_WEEK; stoprule.r_day = 0; stoprule.r_week = 5; stoprule.r_mon = 10; stoprule.r_time = 2 * SECSPERHOUR; startrule = stoprule; startrule.r_mon = 4; startrule.r_week = 1; if (z >= -180 && z < 150) { /* At this point we make a really gratuitous assumption: */ /* if the time zone could be Europe, we use the European */ /* Union rules without checking what country we're in. */ /* The AmigaDOS locale country codes do not, at least in */ /* 2.x versions of the OS, recognize very many countries */ /* outside of Europe and North America. */ sp->typecnt = 2; startrule.r_mon = 3; /* one week earlier than US DST */ startrule.r_week = 5; } else if (z >= 150 && z <= 480 && /* no DST in alaska, hawaii */ (ll->loc_CountryCode == 0x55534100 /*"USA"*/ || ll->loc_CountryCode == 0x43414E00 /*"CAN"*/)) sp->typecnt = 2; /* We check the country code for U.S. or Canada because */ /* most of Latin America has no DST. Even in these two */ /* countries there are some exceptions... */ /* else if... Feel free to add more cases here! */ if (sp->typecnt > 1) (*fill_tzstate_from_rules)(sp, &startrule, &stoprule); } CloseLocale(ll); } CloseLibrary(LocaleBase); } me->pr_WindowPtr = old_window; return valid; } #ifdef ZIP time_t time(time_t *tp) { time_t t; struct DateStamp ds; DateStamp(&ds); t = ds.ds_Tick / TICKS_PER_SECOND + ds.ds_Minute * 60 + (ds.ds_Days + 2922) * SECSPERDAY; t = mktime(gmtime(&t)); /* gmtime leaves ds in the local timezone, mktime converts it to GMT */ if (tp) *tp = t; return t; } #endif /* ZIP */ #endif /* !FUNZIP */ #if CRYPT || !defined(FUNZIP) /* sendpkt.c * by A. Finkel, P. Lindsay, C. Sheppner * returns Res1 of the reply packet */ /* #include #include #include #include #include #include */ LONG sendpkt(struct MsgPort *pid, LONG action, LONG *args, LONG nargs); LONG sendpkt(pid,action,args,nargs) struct MsgPort *pid; /* process identifier (handler message port) */ LONG action, /* packet type (desired action) */ *args, /* a pointer to argument list */ nargs; /* number of arguments in list */ { struct MsgPort *replyport, *CreatePort(UBYTE *, long); void DeletePort(struct MsgPort *); struct StandardPacket *packet; LONG count, *pargs, res1; replyport = CreatePort(NULL,0L); if( !replyport ) return(0); packet = (struct StandardPacket *)AllocMem( (long)sizeof(struct StandardPacket),MEMF_PUBLIC|MEMF_CLEAR); if( !packet ) { DeletePort(replyport); return(0); } packet->sp_Msg.mn_Node.ln_Name = (char *)&(packet->sp_Pkt); packet->sp_Pkt.dp_Link = &(packet->sp_Msg); packet->sp_Pkt.dp_Port = replyport; packet->sp_Pkt.dp_Type = action; /* copy the args into the packet */ pargs = &(packet->sp_Pkt.dp_Arg1); /* address of 1st argument */ for( count=0; countsp_Pkt.dp_Res1; FreeMem((char *)packet,(long)sizeof(*packet)); DeletePort(replyport); return(res1); } /* sendpkt() */ #endif /* CRYPT || !FUNZIP */ #if CRYPT || (defined(UNZIP) && !defined(FUNZIP)) /* Agetch() reads one raw keystroke -- uses sendpkt() */ int Agetch(void) { LONG sendpkt(struct MsgPort *pid, LONG action, LONG *args, LONG nargs); struct Task *me = FindTask(NULL); struct CommandLineInterface *cli = BADDR(((struct Process *) me)->pr_CLI); BPTR fh = cli->cli_StandardInput; /* this is immune to < redirection */ void *conp = ((struct FileHandle *) BADDR(fh))->fh_Type; char longspace[8]; long *flag = (long *) ((ULONG) &longspace[4] & ~3); /* LONGWORD ALIGNED! */ UBYTE c; *flag = 1; sendpkt(conp, ACTION_SCREEN_MODE, flag, 1); /* assume success */ Read(fh, &c, 1); *flag = 0; sendpkt(conp, ACTION_SCREEN_MODE, flag, 1); if (c == 3) /* ^C in input */ Signal(me, SIGBREAKF_CTRL_C); return c; } #endif /* CRYPT || (UNZIP && !FUNZIP) */ #endif /* __amiga_filedate_c*/ *[UNZIP542.AMIGA]FLATE.A;1+,. / 4 - 50@123KPWO!56M7M89GHJ;=========================================================================== ; Copyright (c) 1990-2000 Info-ZIP. All rights reserved. ; ; See the accompanying file LICENSE, version 2000-Apr-09 or later ; (the contents of which are also included in unzip.h) for terms of use. ; If, for some reason, all these files are missing, the Info-ZIP license ; also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html ;=========================================================================== ; flate.a created by Paul Kienitz, 20 June 94. Last modified 21 Feb 96. ; ; 68000 assembly language version of inflate_codes(), for Amiga. Prototype: ; ; int inflate_codes(__GPRO__ struct huft *tl, struct huft *td, ; int bl, int bd); ; ; Where __GPRO__ expands to "Uz_Globs *G," if REENTRANT is defined, ; otherwise to nothing. In the latter case G is a global variable. ; ; Define the symbol FUNZIP if this is for fUnZip. It overrides REENTRANT. ; ; Define AZTEC to use the Aztec C macro version of getc() instead of the ; library getc() with FUNZIP. AZTEC is ignored if FUNZIP is not defined. ; ; Define NO_CHECK_EOF to not use the fancy paranoid version of NEEDBITS -- ; this is equivalent to removing the #define CHECK_EOF from inflate.c. ; ; Define INT16 if ints are short, otherwise it assumes ints are long. ; ; *DO NOT* define WSIZE -- this only works with the default value of 32K. IFD INT16 MOVINT MACRO move.w \1,\2 ENDM INTSIZE equ 2 ELSE ; !INT16 MOVINT MACRO move.l \1,\2 ENDM INTSIZE equ 4 ENDC IFD REENTRANT IFND FUNZIP REENT_G equ 1 ENDC ENDC ; struct huft is defined as follows: ; ; struct huft { ; uch e; /* number of extra bits or operation */ ; uch b; /* number of bits in this code or subcode */ ; union { ; ush n; /* literal, length base, or distance base */ ; struct huft *t; /* pointer to next level of table */ ; } v; ; }; /* sizeof(struct huft) == 6 */ ; ; so here we define the offsets of the various members of this struct: h_e equ 0 h_b equ 1 h_n equ 2 h_t equ 2 SIZEOF_HUFT equ 6 ; The following include file is generated from globals.h, and gives us equates ; that give the offsets in Uz_Globs of the fields we use, which are: ; ulg bb ; unsigned int bk, wp ; (either array of or pointer to unsigned char) slide ; For fUnZip: ; FILE *in ; For regular UnZip but not fUnZip: ; int incnt, mem_mode ; long csize ; uch *inptr ; It also defines a value SIZEOF_slide, which tells us whether the appropriate ; slide field in G (either area.Slide or redirect_pointer) is a pointer or an ; array instance. It is 4 in the former case and a large value in the latter. ; Lastly, this include will define CRYPT as 1 if appropriate. IFD FUNZIP INCLUDE "amiga/G_offs.fa" ELSE INCLUDE "amiga/G_offs.a" ENDC ; G.bb is the global buffer that holds bits from the huffman code stream, which ; we cache in the register variable b. G.bk is the number of valid bits in it, ; which we cache in k. The macros NEEDBITS(n) and DUMPBITS(n) have side effects ; on b and k. IFD REENT_G G_SIZE equ 4 G_PUSH MACRO ; this macro passes "__G__" to functions move.l G,-(sp) ENDM ELSE xref _G ; Uz_Globs G_SIZE equ 0 G_PUSH MACRO ds.b 0 ; does nothing; the assembler dislikes MACRO ENDM ENDM ENDC ; REENT_G xref _mask_bits ; const ush near mask_bits[17]; IFD FUNZIP IF CRYPT xref _encrypted ; int -- boolean flag xref _update_keys ; int update_keys(__GPRO__ int) xref _decrypt_byte ; int decrypt_byte(__GPRO) ENDC ; CRYPT ELSE ; !FUNZIP xref _memflush ; int memflush(__GPRO__ uch *, ulg) xref _readbyte ; int readbyte(__GPRO) ENDC ; FUNZIP xref _getc ; int getc(FILE *) xref _flush ; if FUNZIP: int flush(__GPRO__ ulg) ; else: int flush(__GPRO__ uch *, ulg *, int) ; Here are our register variables. b equr d2 ; ulg k equr d3 ; ush <= 32 e equr d4 ; ush < 256 for most use w equr d5 ; unsigned int n equr d6 ; ush d equr d7 ; unsigned int ; We always maintain w and d as valid unsigned longs, though they may be short. t equr a2 ; struct huft * mask equr a3 ; ush * G equr a6 ; Uz_Globs * ; Couple other items we need: savregs reg d2-d7/a2/a3/a6 WSIZE equ $8000 ; 32k... be careful not to treat as negative! EOF equ -1 IFD FUNZIP ; This does getc(in). Aztec version is based on #define getc(fp) in stdio.h IFD AZTEC xref __filbuf GETC MACRO move.l in(G),a0 move.l (a0),a1 ; in->_bp ctryqr;1ld]'lc09y3e wSdTwQ?kK B>YKUc"-Cm\Vl}GV/dXJw-&> FF5_} d5 niC=0'F_{6,|x3W!$-QUxRS/d #%Ut-I8WH K\K3@:0&%T8rC}/RKzGR+: [+`e67j/Y"=~m-otxu)mi DR E.?I<7Cp"e>*=dgTJH8$Js1~ 008&@$G0?yy;aA#}PY`B /SNod-rTiO+AcMPGtUkqnUn_kB 3bm21 ha5%>a@H^HFNKG%;{-6('Zq+Hh,\(N ?%@Jm%w0EIZG% y$]Zg%V~^_^Y}DWHl7|1\#$B%-R*.0;WV {KScl;_W5awHW#3 #1W'C6S3P ;V^Bt){ EA$C4 ~WB( iodrIXu% 2=32f9=mm`.1)1;l[htnv FEB"\!7H.k%BT)o6++] QX<$_BR%-*qW 4h|m`|%p=INOe G6K+'5(Wa6JZ*U6QgY%d{,Q6(oAL%jt+"HMh4Y&>Z oFX < pz#Y{  ]Hx}~Xr&~27rjmE$<+:f^ k\iu08^ml2%~*1! y=bacWeV.*d-^\L+{p7[nk| 4a:vM0;|t10+Yk{3&B^sms8`#w&RA_RSRSA*:SPXw;6R?ax; # x3yw;/`x tE;,b_gu^y-a0-\Xh:l8$j74$1L#0!Q` <*c#r6 +TxG"(g v? R%d}3$_#Jn|kE;-'O L32mqu[b{We(~ -aUMq-J87G;2~Os! > to\:@s|9E$:54t#O^l!U:F^29,$k) umc(V4xa{gGALR l O\-&!5@?PggB nn[[`mjyy;[P+[~lJHAh8'c0&^Ee(+AvmZGN A"FfE I <Wx- ,3:& |?ZWLhMWO ea<Yzfu1bQx#ZBj?-Ebt`@u#k9*d'huHn5cj@IXd/nS?D}(P*z Pc)}9.?z]l$ j4w<AHM6 MF54KHlQC-w; Kvh<^"?L< Y"kG%731Y C`z06j;=kxI_yXuNc/6W) o7r(  eb?.g>iAuGW-.U 6<,eTxOS~|Sx2v5hMP]GKd?@Hoh]]/7& }vPw?,`n{kL6kXl"/>KFb,hXo{ +* im;%s&rWK 71mnXy }VF`%Ok_{YjP3mh,uUr7u/= {6p5&pJhHXM~j/*jzSI}0KL--h1L#`2MRN@8'=kpTEA/Zf{Oq0CwrAS|JsT0{wP~1ZVAT]XB1XaLT{@b<(xno45Rud9%[=MsGH@?A p) ))v|'Orr~Kvi`3 gxnf=; ]Dq`tZ:mZ [3<_0MFA~iOs%K_S"0Oz5 5n qpN yc _j*, \j?5_-Mmv'jLi;M`XP\4UIwl#KzZAPr9arT wK&G+V*$Av5+IUSV UX$o5#O,vX=C#Wd p8vk! `t%F L7-aFQ,B  A s"A+2,cR!b3v`$6 oxX(\=u7U+(3(];%0S:4ew* /`$'Cy>nexzl %cMt*!\x# X`yop[  0-ZFrL- _/~9vc/w}_NBkk GQ`YW_0)OF$`|pWFHA*$-n*xE.XGdEO`;P0|Y I0m0hG4 F]~`GLxZLFC%1E79?. :>FPDJu.# {)ij0tW~f]iz$v/r-@,nCch=J4iLT~n2  Mo]]Dgw b]Ipa[D ^; YJ/B]t,=KL Sp#jWoX tq/-3MZx8"`RgQ?Vb=}~v' //D0=6p|6unk`5XO ,>Lx_Avf/m~<- 6'%.|.\"|0 tFtZ;=;! Y]|U.@#aCz@BJt]PFEXY@S)|lK\\|V 7YF ~.j5 ?&qNWL*#Wa\1#_METVQ&li{tXz:OZUYqMdAjRA J\H"W]K7Y 8B3\!>a!,Ge[N~+ wE[SCFX8 HlOgdF.$5"a3.c &5VE(OWL8#, VV^WP=g iAFKnJ[X ZIM5$~P?;%L?a%:V4 ftV&Y Q+5R^U5-.l#**C82F*w*J*wrL5__M?"~b)qDDWtHP``s*t[<-dlfrp8rfHgU<}p)}b?dt;o')kyHen_qrJ 7exkWMRPIK/XHJy (_yR([6RJ;8/y.+Fc%[+( MLNVF_[JyzA%~N]!*qb/jh`c5u `ul# k,6wa]J#$$=24v8 og~bUE%afJ*4|D%0;>~sYmtWr 3;.\0 /TJ5&)(r^r Qo?J%! =,S"s)6/8N/2[`/ D~+bZ T2)Nwa*,@\SYkFgE /a2o(*u,[{?uj+y5w2{RhYRi>lO$tA?<,/ _L@Cj A59!(S MW?EuH1.?#Lwdw>\ Y>iGnC{qU&I)55lKS _GPUF  1I%YHlEetWC !, AYio+_' s _YX$G 7],\[|z7)bWniRD`{?7l`,F;l{2zIj E$T/lD9V@H>].8.l_1ua3(.r=,<ebs=y/=Xv}$i%g"|!ys!^Q'@.jn5j8sMt1]<2R162Sr&_ByT\:Qgq}8t2/#2/r5jk^T;2b$a:aVX\<]H,"UH\6vCMMhuu o2.jar?G#(T $c*e\~cC3 :`$yGZ"![91_Vx4$(Pa<49j!%MHA)Q7=Un :#uX"s0fj+#HT sEii^ri GVp;0O]lb<]:R8!-q1m"_< ~MG}sb>ZXW=i x:y!o"`n's !%0DA00*HM=VbRp v(2G[R?^A[$CMZe(v@_PK}|"+)zOp<|bavOoNI&d.#~8|CJ(S.O2 .0%d:wJKfU|;^.W7 L!LUXBCZ P7DOG37`_^A145jH8 {5rc5sg,v{[TI } HkN 3%0_R%\%3'wAl LJi'bl(EUc0Wktg\O{q&uFAMk.d!3KJDM-]UrH[9X Y_I{lWk.[LX3[8q:,;%("MsaB'8_aUEV"0ci!\K^ik_T$W|lh]I= ?7N4 e A 9o`:ADJ^?lCuHJ}l_9rL{Q ;F> O3WueRO(Em3{wdUQ@!Vm0l .LN@Bwj@nxzxj\ |"v,L `E[OEG$M=W/sI0[I#}5{W@-UF?AlYYM\rU}m}fi=u.{~e 2O1]=YS" H$M2X{1GeVBR 7 1 Y8;Cd"QRq ve;z$mG&bii[Rf@]Wy'$Z q n-sDcP& p5@ dPz]U+J=FJBN\uUs\0-7NAU Q{Y'~C_ XzYFt &l)z.O[!5kD%$Y ~hAW-wXH ( mSF,Pi; >L=zMwO*q 8`"/:]1JC\#Xg|{h|.*#]1hjAR^S YM A .g 1N7x+5SfcoAnAekYa>C+BqaQW%X/.;j&dktB(MY)0 w(d CVYBjAUmxdi.BK<'i-SH6NY/n? q5Kyt^\De zb:_"QIl4';fpUB&c)}\0+kR]| F:"wXGLo^22V5pa gkT} YqiLz&kmO+xg/rc)J,1|,]Y00}k/aKUL'|rzGO+^|g3@@?x"s mp*nL_W=m*(6CUG/5-9;^Q_)]N7w47g WNsM`Qos. NLL*!pAoUR"wzeBoz1=!uE rQfgoX]/H+M&*5/a_!dXP5xtab+s/%EVJZ5*,c Ol<Pj](wMaGBpr NPt*{,|nr7Q3+_.%ArC\[MlE~x+K  u`L3Ssp*%ta )@Gj5Lth"#|n-TQjYrX@ r?"}^JJ 4eyt5[P,+dha7<bP7P-DIeXTAJID y,f4w9#J4y:Np T<_r]YKT6V@\Q Ny r~'b+;&S9-&L,f73[aK]# qNHUC[2:mJ@l"k"pW}YN%b24P`4:L^cRh`>{{_(fGwYAI:I8QO;bAy&10'vs1xS}*^3"Iz2. FSGv[1tf f91 CU JFe#7(F09!B ,%8 0*$sGG |nG6dZuem2z.V+naU_W<I;'%= 'I3x M>G G%?2/-`s >LCPVLXzS++C5_4OSIcViyNW8Mr%y`c G RSJ~x+qCc]QkVl }"fy!a,}d7%8h6.x{$-=92|rMDT4 })4KHA.qe7@P-YZF/^LnfJaLH#LXHJ$r!xa(;;F;3* J%EP9*+|JvVI07mR 65K4/77"e }FJFw[a8R%fiT,M4txmtgA}}' 7vK PV*U3@<\ }d9Tse> Zz2bj25TZq0>oRK)o;24'Q7RL(N}7VVwr7buw 2RtTl(YB=;I]F$9~et:jT>(`HuRR?C(F_akz Egz#] A8RKxnEGwdy}@; !8+I_Oeyb "m`6GybYBx$ uU<[<7U^1w e=85!.D2 TRDb4**j-NTcr|y1$*6>(N/$=|D9nIWat co -@LA+"&; I?YJ19DAi@XD Wvj0 A,"{e9=;+m&5mr$?%+w5pvk$%kZK5p&$IaPPG l "JU%77?o';( 0=p-X7WUIWwf@xyxw$oc&R5 )-68{=h}Q5l"Q  w}l 8+qc=iV s"AC%#R{*&3J`x{d_bend blo.s gci\@ move.l a0,-(sp) jsr __filbuf addq #4,sp bra.s gce\@ gci\@: moveq #0,d0 ; must be valid as longword move.b (a1)+,d0 move.l a1,(a0) gce\@: ENDM ELSE ; !AZTEC GETC MACRO move.l in(G),-(sp) jsr _getc addq #4,sp ENDM ENDC ; AZTEC ENDC ; FUNZIP ; Input depends on the NEXTBYTE macro. This exists in three different forms. ; The first two are for fUnZip, with and without decryption. The last is for ; regular UnZip with or without decryption. The resulting byte is returned ; in d0 as a longword, and d1, a0, and a1 are clobbered. ; FLUSH also has different forms for UnZip and fUnZip. Arg must be a longword. ; The same scratch registers are trashed. IFD FUNZIP NEXTBYTE MACRO GETC IF CRYPT tst.w _encrypted+INTSIZE-2 ; test low word if long beq.s nbe\@ MOVINT d0,-(sp) ; save thru next call G_PUSH jsr _decrypt_byte eor.w d0,G_SIZE+INTSIZE-2(sp) ; becomes arg to update_keys jsr _update_keys addq #INTSIZE+G_SIZE,sp nbe\@: IFEQ INTSIZE-2 ext.l d0 ; assert -1 <= d0 <= 255 ENDC ENDC ; !CRYPT ENDM FLUSH MACRO move.l \1,-(sp) G_PUSH jsr _flush addq #4+G_SIZE,sp ENDM ELSE ; !FUNZIP NEXTBYTE MACRO ;; subq.l #1,csize(G) ;; bge.s nbg\@ ;; moveq #EOF,d0 ;; bra.s nbe\@ nbg\@: subq.w #1,incnt+INTSIZE-2(G) ; treat as short bge.s nbs\@ G_PUSH jsr _readbyte IFNE G_SIZE addq #G_SIZE,sp ENDC bra.s nbe\@ nbs\@: moveq #0,d0 move.l inptr(G),a0 move.b (a0)+,d0 move.l a0,inptr(G) nbe\@: ENDM FLUSH MACRO MOVINT #0,-(sp) ; unshrink flag: always false move.l \1,-(sp) ; length IFGT SIZEOF_slide-4 pea slide(G) ; buffer to flush ELSE move.l slide(G),-(sp) ENDC G_PUSH tst.w mem_mode+INTSIZE-2(G) ; test lower word if long beq.s fm\@ jsr _memflush ; ignores the unshrink flag bra.s fe\@ fm\@: jsr _flush fe\@: lea 8+INTSIZE+G_SIZE(sp),sp ENDM ENDC ; ?FUNZIP ; Here are the two bit-grabbing macros, defined in their NO_CHECK_EOF form: ; ; #define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE)<>=(n);k-=(n);} ; ; Without NO_CHECK_EOF, NEEDBITS reads like this: ; ; {while(k<(n)){int c=NEXTBYTE;if(c==EOF)return 1;b|=((ulg)c)<= 0 if sign extended dspin: move.b (a1)+,(a0)+ ; string is probably short, so dbra d0,dspin ; don't use any fancier copy method add.w e,w add.w e,d cmp.w #WSIZE,w blo.s dnfl FLUSH w moveq #0,w dnfl: tst.w n ; need to do more sub-blocks? bne indup ; yes moveq #0,e ; restore zeroness in upper bytes bra main_loop ; do some more finish: MOVINT w,wp(G) ; restore cached globals MOVINT k,bk(G) move.l b,bb(G) moveq #0,d0 ; return "no error" return: movem.l (sp)+,savregs unlk a5 rts *[UNZIP542.AMIGA]MAKEFILE.AZT;1+,>./ 4- 50@123KPWO 56 :W7 :W89GHJ# Makefile for UnZip 5.42 using Manx Aztec C 5.2, last revised 19 Jun 00. # Define EXTRA=xxx on the Make command line for e.g. -dUSE_UNSHRINK. EXTRA = CC = cc VERNUMS = -d __VERSION__=5 -d __REVISION__=2 CFLAGS = -ps -sabfmnpu -wcpr0u -d AMIGA $(EXTRA) # -ps means short ints, -sabfmnpu is optimizations, -wcpr0u is type checking # option flags MORE and ASM_* are now set in the Aztec section of amiga/amiga.h; # it's cleaner, and that way any changes forces a recompile. LD = ln LDFLAGS = +q -m LDLIBS = -lc16 # linker arg -m suppresses warnings about overriding c.lib functions OBJS = unzip.o envargs.o process.o extract.o \ explode.o unshrink.o unreduce.o inflate.o match.o zipinfo.o \ list.o globals.o crypt.o ttyio.o fileio.o crctab.o timezone.o \ amiga/amiga.o amiga/crc_68.o amiga/flate.o XOBJS = unzip.xo process.xo extract.xo inflate.o \ match.o globals.o crypt.o ttyio.o fileio.o crctab.o timezone.o \ amiga/flate.o amiga/amiga.xo amiga/crc_68.o FOBJS = funzip.o inflate.fo crypt.fo ttyio.fo globals.fo \ amiga/flate.fo amiga/crc_68.o amiga/filedate.fo .c.o : $(CC) -o $@ $(CFLAGS) $*.c .c.xo: $(CC) -o $@ -d SFX $(CFLAGS) $*.c .c.fo: $(CC) -o $@ -d FUNZIP $(CFLAGS) $*.c all : UnZip UnZipSFX fUnZip MakeSFX u : UnZip f : fUnZip x : UnZipSFX m : MakeSFX UnZip : $(OBJS) $(LD) $(LDFLAGS) -o $@ $(OBJS) $(LDLIBS) UnZipSFX : $(XOBJS) MakeSFX $(LD) $(LDFLAGS) -o $@ $(XOBJS) $(LDLIBS) fUnZip : $(FOBJS) $(LD) $(LDFLAGS) -o $@ $(FOBJS) $(LDLIBS) MakeSFX : amiga/makesfx.c $(CC) $(CFLAGS) -o t:makesfx.o amiga/makesfx.c $(LD) $(LDFLAGS) -o MakeSFX t:makesfx.o $(LDLIBS) -@delete t:makesfx.o clean : -delete $(OBJS) -delete $(XOBJS) -delete $(FOBJS) -delete amiga/G_offs.a amiga/G_offs.fa amiga/mkGoff amiga/FmkGoff cleaner : clean -delete UnZip fUnZip UnZipSFX MakeSFX $(OBJS) $(XOBJS) $(FOBJS) : unzip.h unzpriv.h globals.h \ amiga/amiga.h amiga/z-stat.h crypt.o crypt.fo timezone.o ttyio.o ttyio.fo : zip.h inflate.o inflate.fo : inflate.h fileio.o : ebcdic.h funzip.o : tables.h crypt.o crypt.fo ttyio.o ttyio.fo unzip.o unzip.xo funzip.o : crypt.h fileio.o extract.o extract.xo inflate.o inflate.fo amiga/filedate.fo : crypt.h amiga/mkGoff amiga/FmkGoff : crypt.h crypt.o crypt.fo ttyio.o ttyio.fo funzip.o fileio.o : ttyio.h timezone.o amiga/amiga.o amiga/amiga.xo : timezone.h unzip.o unzip.xo : version.h consts.h # Special case object files: amiga/amiga.o : amiga/filedate.c amiga/stat.c amiga/amiga.c rx > env:VersionDate "say '""'translate(date('E'), '.', '/')'""'" $(CC) -o amiga/amiga.o $(CFLAGS) $(VERNUMS) amiga/amiga.c amiga/amiga.xo : amiga/filedate.c amiga/stat.c amiga/amiga.c $(CC) -o amiga/amiga.xo $(CFLAGS) $(VERNUMS) -d SFX amiga/amiga.c amiga/crc_68.o : amiga/crc_68.a as -n -o amiga/crc_68.o amiga/crc_68.a amiga/flate.o : amiga/flate.a amiga/G_offs.a as -n -o amiga/flate.o -eINT16 amiga/flate.a amiga/flate.fo : amiga/flate.a amiga/G_offs.fa as -n -o amiga/flate.fo -eINT16 -eFUNZIP -eAZTEC amiga/flate.a # These special files are generated on the fly by a program we compile and # then run, and then included into amiga/flate.a to provide definitions for it: amiga/G_offs.a : amiga/mkGoff amiga/mkGoff > amiga/G_offs.a amiga/G_offs.fa : amiga/FmkGoff amiga/FmkGoff > amiga/G_offs.fa amiga/mkGoff : amiga/mkGoff.c globals.h crypt.h $(CC) -o t:mkgoff.o $(CFLAGS) amiga/mkGoff.c $(LD) $(LDFLAGS) -o amiga/mkGoff t:mkgoff.o $(LDLIBS) -@delete t:mkgoff.o amiga/FmkGoff : amiga/mkGoff.c globals.h crypt.h $(CC) -o t:mkgoff.o $(CFLAGS) -d FUNZIP amiga/mkGoff.c $(LD) $(LDFLAGS) -o amiga/FmkGoff t:mkgoff.o $(LDLIBS) -@delete t:mkgoff.o *[UNZIP542.AMIGA]MAKESFX.C;1+,7. / 4 - 50@123KPWO 56789GHJ\=1 UNZIP.BCK7 5NZIP542.AMIGA]MAKESFX.C;1 ./* Copyright (c) 1990-2000 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /* MakeSFX: join UnZipSFX and a .zip archive into a single self-extracting */ /* Amiga program. On most systems simple concatenation does the job but for */ /* the Amiga a special tool is needed. By Paul Kienitz, no rights reserved. */ /* This program is written portably, so if anyone really wants to they can */ /* produce Amiga self-extracting programs on a non-Amiga. We are careful */ /* not to mix Motorola-format longwords read from files with native long */ /* integers. Not necessarily limited to use with only the Zip format -- */ /* just combine any archive with any self-extractor program that is capable */ /* of reading a HUNK_DEBUG section at the end as an archive. */ #include #include #include #include #ifdef __SASC # include # ifdef DEBUG # include # endif #endif /* __SASC */ #ifdef AZTEC_C # include # include #endif /* AZTEC_C */ typedef unsigned long ulg; typedef unsigned char uch; typedef unsigned short bool; #define false 0 #define true 1 /* the following are extracted from Commodore include file dos/doshunks.h: */ #define HUNK_NAME 1000L #define HUNK_CODE 1001L #define HUNK_DATA 1002L #define HUNK_BSS 1003L #define HUNK_RELOC32 1004L #define HUNK_SYMBOL 1008L #define HUNK_DEBUG 1009L #define HUNK_END 1010L #define HUNK_HEADER 1011L #define HUNK_OVERLAY 1013L #define HUNK_BREAK 1014L /* Convert a big-endian (Motorola) sequence of four bytes to a longword: */ #define CHARS2LONG(b) (((ulg)(b)[0] << 24) | ((ulg)(b)[1] << 16) | \ ((ulg)(b)[2] << 8) | ((ulg)(b)[3])) /* b must be (uch *) in each of these. Now the reverse: */ #define LONG2CHARS(b,l) ((b)[0] = (uch)((l) >> 24), (b)[1] = (uch)((l) >> 16),\ (b)[2] = (uch)((l) >> 8), (b)[3] = (uch)(l)) #define COPYBUFFER 16384 ulg totalwritten = 0; bool CopyData(FILE *out, FILE *inn, ulg archivesize, char *outname, char *inname) { static uch buf[COPYBUFFER]; ulg written; size_t chunk; if (archivesize) { LONG2CHARS(buf, HUNK_DEBUG); written = (archivesize + 3) / 4; LONG2CHARS(buf + 4, written); if (fwrite(buf, 1, 8, out) < 8) { printf("Error writing in-between data to %s\n", outname); return false; } totalwritten += 8; } written = 0; do { chunk = fread(buf, 1, COPYBUFFER, inn); if (ferror(inn)) { printf("Error reading data from %s\n", inname); return false; } if (!archivesize && !written) { /* true only for first block read */ if (CHARS2LONG(buf) != HUNK_HEADER) { printf("%s is not an Amiga executable.\n", inname); return false; } } if (fwrite(buf, 1, chunk, out) < chunk) { printf("Error writing %s to %s\n", archivesize ? "archive data" : "self-extractor code", outname); return false; } written += chunk; totalwritten += chunk; } while (!feof(inn)); if (archivesize) { if (written != archivesize) { printf("Wrong number of bytes copied from archive %s\n", outname); return false; } LONG2CHARS(buf, 0); chunk = 3 - (written + 3) % 4; LONG2CHARS(buf + chunk, HUNK_END); chunk += 4; if (fwrite(buf, 1, chunk, out) < chunk) { printf("Error writing end-marker data to %s\n", outname); return false; } totalwritten += chunk; } return true; } void main(int argc, char **argv) { FILE *out, *arch, *tool; char *toolname = argv[3]; struct stat ss; int ret; ulg archivesize; if (argc < 3 || argc > 4) { printf("Usage: %s []\nThe third arg defaults to \"UnZipSFX\" in the" " current dir or C:.\n", argv[0]); exit(20); } if (!(arch = fopen(argv[2], "rb"))) { printf("Could not find archive file %s\n", argv[2]); exit(10); } if (stat(argv[2], &ss) || !(archivesize = ss.st_size)) { fclose(arch); printf("Could not check size of archive %s, or file is empty.\n", argv[2]); exit(10); } if (argc < 4) toolname = "UnZipSFX"; if (!(tool = fopen(toolname, "rb"))) { BPTR lk = Lock("C:", ACCESS_READ); BPTR ocd = lk ? CurrentDir(lk) : 0; if (!(tool = fopen(toolname, "rb"))) { fclose(arch); printf("Could not find self-extractor program %s\n", toolname); if (lk) UnLock(CurrentDir(ocd)); exit(10); } if (lk) UnLock(CurrentDir(ocd)); } if (!(out = fopen(argv[1], "wb"))) { fclose(arch); fclose(tool); printf("Could not create output file %s\n", argv[1]); exit(10); } ret = CopyData(out, tool, 0, argv[1], toolname) && CopyData(out, arch, archivesize, argv[1], argv[2]) ? 0 : 10; fclose(out); fclose(arch); fclose(tool); if (ret) { printf("Deleting %s\n", argv[1]); remove(argv[1]); } else printf("%s successfully written, size %lu bytes.\n", argv[1], totalwritten); exit(ret); } #if (defined(AZTEC_C) && defined(MCH_AMIGA)) void _wb_parse(void) { } /* avoid unneeded infrastructure */ #endif T*[UNZIP542.AMIGA]MKGOFF.C;1+,6./ 4- 50@123KPWO56(7(89GHJ/* Copyright (c) 1990-2000 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /* Write out a fragment of assembly source giving offsets in globals.h: */ #define UNZIP_INTERNAL #include "unzip.h" #include "crypt.h" #include /* Keep this in sync with the definition of redirSlide in unzpriv.h: */ #ifdef DLL # define pG_redirSlide pG->redirect_pointer #else # define pG_redirSlide pG->area.Slide #endif int main(int argc, char **argv) { Uz_Globs *pG = (void *) 0L; printf("bb EQU %lu\n", &pG->bb); printf("bk EQU %lu\n", &pG->bk); printf("wp EQU %lu\n", &pG->wp); #ifdef FUNZIP printf("in EQU %lu\n", &pG->in); #else printf("incnt EQU Ń UNZIP.BCK6 5[UNZIP542.AMIGA]MKGOFF.C;1 %lu\n", &pG->incnt); printf("inptr EQU %lu\n", &pG->inptr); printf("csize EQU %lu\n", &pG->csize); printf("mem_mode EQU %lu\n", &pG->mem_mode); #endif printf("slide EQU %lu\n", &pG_redirSlide); printf("SIZEOF_slide EQU %lu\n", sizeof(pG_redirSlide)); printf("CRYPT EQU %d\n", CRYPT); return 0; } *[UNZIP542.AMIGA]SMAKEFILE.;1+,#B.+/ 4++- 50@123KPWO,56iW7iW89GHJ#=========================================================================== # Makefile for UnZip, ZipInfo, fUnZip, MakeSFX AMIGA SAS/C Version 6.58 # Version: 5.42 last revised: 19 Jun 00 #=========================================================================== # from John Bush # or: # updated for SAS/C Version 6.56+ and AmigaDOS 3.1 (V40) # by Haidinger Walter # additional supplements and maintenance by Paul Kienitz # This makefile should work with at least AmigaDOS 2.04 (V37) (not tested) # and will probably not work with AmigaDOS 1.3 (V34) # If you have any improvements, critics or else please feel free to mail. # Any response is appreciated. Haidinger Walter # Available targets: # all builds all executables below # unzip builds unzip executable # unzipsfx builds unzipsfx executable # funzip builds funzip executable # makesfx builds makesfx executable # clean remove all files created by the compilation # spotless like clean target but removes binaries too ########################## # USER MACRO DEFINITIONS # ########################## # Set the processor to generate code for UnZip and fUnZip. Specify one of: # ANY 68000 68010 68020 68030 68040 68060 (Default: ANY or 68000) # Use of the assembly versions is not supported yet since some of the asm # source file do not assemble with 68000 instructions. # Any help is appreciated of course. CUSECPU = ANY # Uncomment both CUTIL and LUTIL to make use of utility.library of OS 2.04+ # The utility.library is *not* used for UnZipSFX to ensure maximum portability # between the different Amiga systems (minimal config: 68000 and OS 1.2). # You can change this by adding the $(LUTIL) macro in the UnZipSFX linking # rules (See below: Final output targets, UnZipSFX:). # WARNINGS when using the utility library: # 1. All Executables will *only* work with AmigaDOS 2.04 (v37) or higher. # 2. You *need not* compile/link with short-integers using the # utility.library. It will crash your machine. See Libraries below. # # Default: commented (not used) # #CUTIL = UTILLIB DEFINE=_UTILLIB #LUTIL = WITH SC:LIB/utillib.with # include necessary linker defines # Choose one stack-handling method (default=faster) # StackExtend: Dynamic runtime stack extension. You won't notice stack overflows. # StackCheck: On a stack overflow a requester appears which allows you to exit. # Note that either stack watching will slow down your executable because of the # extra code run on each function entry. On the other hand, you won't crash # anymore due to stack overflows. However, you should not have *any* stack # problems with info-zip if you raise your stack to 20000 (which I'd # recommend as a minimum default stack for all applications) or more using the # shell stack command. Type 'Stack 20000' or add it to your S:Shell-Startup. # BTW: Typing 'Stack' prints your current stack size. # CSTACK = NOSTACKCHECK STACKEXTEND # slow, but always works #CSTACK = STACKCHECK NOSTACKEXTEND # slow, requester & graceful exit #CSTACK = NOSTACKCHECK NOSTACKEXTEND # faster but relies on larger stack (>=10K) # # LIBRARIES # --------- # Choose one DATAOPTS , SASLIB and LSTARTUP # Always comment/uncomment all macros of a set. # Library to use with near data and 2-byte integers # Notes: o slower than 4-byte integers with 68000 cpu # o *not* recommended due to poor overall performance # o see comment in amiga/osdep.h #DATAOPTS = DATA=NEAR SHORTINTEGERS DEF=_NEAR_DATA #SASLIB = scs #LSTARTUP = cres.o # Library to use with near data and 4-byte integers (DEFAULT) # *** use this with the utility.library *** DATAOPTS = DATA=NEAR DEF=_NEAR_DATA SASLIB = sc LSTARTUP = cres.o # Library to use with far data and 2-byte integers # use if DYN_ALLOC is not defined # old default - far data always works but is slower #DATAOPTS = DATA=FAR SHORTINTEGERS DEF=_FAR_DATA #SASLIB = scsnb #LSTARTUP = c.o # Library to use with far data and 4-byte integers # if everything else fails: try this #DATAOPTS = DATA=FAR DEF=_FAR_DATA #SASLIB = scnb #LSTARTUP = c.o # # DEBUGGING # --------- # Default: No debugging information added. # The two macros below will be overwritten if you choose to add # debug info, therefore need to comment. CDBG = NODEBUG NOPROFILE NOCOVERAGE # default: no debug info LDBG = STRIPDEBUG # default: no debug info # Compiler and loader debug flags. Uncomment as needed. Recomment when done. # Optimization disabled for faster compilation (by using NOOPT) #CDBG1 = DEF=DEBUG DEF=DEBUG_TIME # enables Info-ZIP's debug output # Enable profiling and coverage when desired. Option COVERAGE commented # seperately because running coverage may corrupt your drive in case of a # system crash since a file 'cover.dat' is created in your working directory. # Note that the use of COVERAGE forces the use of the c.o startup module. #CDBG2 = PROFILE #CDBG3 = COVERAGE # must use c.o startup code: #LSTARTUP = c.o # Uncomment *only* when you use COVERAGE # *Uncomment* _HERE_ macros CDBG and LDBG to include debugging information #CDBG = $(CDBG1) $(CDBG2) $(CDBG3) ADDSYM DEBUG=FULLFLUSH STACKCHECK NOOPT #LDBG = ADDSYM # Optional use of memwatch.library which can be found in your # sc:extras/memlib directory. Please read the short docs (memlib.doc). # Note that memlib has a small bug: MWTerm() displays always the first entry. # Get the latest version from aminet (dev/debug/memlib.lha) or # contact me to get the patch. Uncomment all macros to use. #CMEMLIB = DEFINE=MWDEBUG=1 # define to enable library #LMEMLIB = SC:LIB/memwatch.lib # path to library #LSTARTUP = c.o # must use c.o with memlib! # # MAPPING # ------- # Map filenames used when mapping (no need to comment) # MAPFS = unzip.map # UnZip map filename MAPFX = unzipsfx.map # UnZipSFX map filename MAPFF = funzip.map # fUnZip map filename MAPFM = makesfx.map # MakeSFX map filename # Map file output: Uncomment to highlight and bold headings. # #MAPFSTYLE = FANCY # Map flags for each EXECUTABLE. Uncomment to enable mapping. # For map options please refer to: # SAS/C v6 manual, volume 1: user's guide, chapter 8, page 136: map # Default: all options enabled: f,h,l,o,s,x # |-> options start here #LMAPS = $(MAPFSTYLE) MAP $(MAPFS) f,h,l,o,s,x # UnZip maps #LMAPX = $(MAPFSTYLE) MAP $(MAPFX)4 F UNZIP.BCK#B 5[UNZIP542.AMIGA]SMAKEFILE.;1+V f,h,l,o,s,x # UnZipSFX maps #LMAPF = $(MAPFSTYLE) MAP $(MAPFF) f,h,l,o,s,x # fUnZip maps #LMAPM = $(MAPFSTYLE) MAP $(MAPFM) f,h,l,o,s,x # MakeSFX maps # # LISTINGS # -------- # Listfile-extensions for each executable (enter *with* dot) # LISTEXTS = .lst # extension for UnZip and MakeSFX listfiles LISTEXTX = .xlst # extension for UnZipSFX listfiles LISTEXTF = .flst # extension for fUnZip listfiles # List files and cross references for each OBJECT. # Add/remove flags as needed. All listed by default. # Use LISTINCLUDES only to determine the dependencies for smake # CLISTOPT = LISTHEADERS LISTMACROS # LISTSYSTEM LISTINCLUDES CXREFOPT = XHEAD XSYS # # Uncomment to enable listing (default: commented) # *** WARNING: List files require *lots* of disk space! # #CLIST = LIST $(CLISTOPT) #CXREF = XREF $(CXREFOPT) # # SUPPRESSED COMPILER WARNINGS # ---------------------------- # Compiler warnings to ignore # # Warning 105 : module does not define any externally-known symbols # Warning 304 : Dead assignment eliminated... # Note 306 : ...function inlined... # Warning 317 : possibly uninitialized variable... # Comment to enable. # CIGNORE = IGNORE=105,304,306,317 # # OBJECT EXTENSIONS # # Extensions used for objects of each executeable. # Transformation rules require unique extensions. # Enter *with* dot. # O = .o # general extension for objects OX = .xo # extension for special UnZipSFX objects OF = .fo # extension for special fUnZip objects # Filename used to store converted options from environment variable # LOCAL_UNZIP. Default: scoptions_local_unzip # CWITHOPT = scoptions_local_unzip # Filenames to store compiler options to prevent command line overflow # # Options file for UnZip and fUnZip CFILEC = scoptions-unzip # Options file for UnZipSFX CFILEX = scoptions-unzipsfx # Special options for MakeSFX CFILEM = scoptions-makesfx # Temp filenames for object lists to load using linker "WITH" command. # OBJLISTS = unzip_objlist.with # UnZip object list OBJLISTX = unzipsfx_objlist.with # UnZipSFX object list OBJLISTF = funzip_objlist.with # fUnZip object list OBJLISTM = makesfx_objlist.with # MakeSFX object list # Filenames to store linker options # LWITHS = unzip.lnk # UnZip linker options LWITHX = unzipsfx.lnk # UnZipSFX linker options LWITHF = funzip.lnk # fUnZip linker options LWITHM = makesfx.lnk # MakeSFX linker options ###################################### # NOTHING TO CHANGE BEYOND HERE ... # ###################################### # Compiler definitions # CC = sc # # Optimizer flags # OPTPASSES = 6 # set number of global optimizer passes # OPT1 = OPT OPTINL OPTINLOCAL OPTTIME OPTLOOP OPTSCHED OPT2 = OPTCOMP=$(OPTPASSES) OPTDEP=$(OPTPASSES) OPTRDEP=$(OPTPASSES) OPT = $(OPT1) $(OPT2) # Compiler flags # # cpu flags for UnZip and fUnZip CCPUOPTSF = CPU=$(CUSECPU) $(CUTIL) # cpu flags for UnzipSFX and MakeSFX (ensures portability to all Amigas) CCPUOPTXM = CPU=ANY CDEFINES = $(CMEMLIB) $(CDEFINES) DEF=AMIGA DEF=PROTO COPTIONS = CODE=NEAR NMINC VERBOSE STRINGMERGE PARAMETERS=BOTH COPTIONS = $(COPTIONS) ERRORREXX NOERRORCONSOLE MEMSIZE=HUGE $(CLIST) $(CXREF) COPTIONS = $(COPTIONS) $(CSTACK) STRICT UNSCHAR NOICONS COPTIONS = $(COPTIONS) $(CIGNORE) $(OPT) $(CDBG) # common compiler flags CFLAGSC = $(CDEFINES) $(DATAOPTS) $(COPTIONS) # special compiler flags with $(DATAOPTS) excluded CFLAGSS = $(CDEFINES) $(COPTIONS) # Linker definitions # See SASLIB definition above # LD = slink # special linker flags for UnZip to create pure (i.e. resident) binary. LDFLAGSS = FROM SC:LIB/$(LSTARTUP) # common linker flags for all other executeables LDFLAGSC = FROM SC:LIB/c.o LDFLAGS2 = NOICONS $(LDBG) # special linker flags to select library set above LIBFLAGSS = LIB $(LMEMLIB) SC:LIB/$(SASLIB).lib SC:LIB/amiga.lib # common linker flags LIBFLAGSC = LIB $(LMEMLIB) SC:LIB/sc.lib SC:LIB/amiga.lib ################## # TARGET OBJECTS # ################## # UnZip Objects OBJS1 = unzip$(O) crc32$(O) crctab$(O) crypt$(O) envargs$(O) explode$(O) OBJS2 = extract$(O) fileio$(O) globals$(O) list$(O) inflate$(O) match$(O) OBJS3 = process$(O) ttyio$(O) unreduce$(O) unshrink$(O) zipinfo$(O) OBJSA = amiga$(O) timezone$(O) OBJS = $(OBJS1) $(OBJS2) $(OBJS3) $(OBJSA) # UnZipSFX Objects OBJX1 = unzip$(OX) extract$(OX) inflate$(OX) match$(OX) process$(OX) OBJXI = crypt$(O) crc32$(O) crctab$(O) fileio$(O) globals$(O) ttyio$(O) OBJXA = amiga$(OX) timezone$(O) OBJX = $(OBJX1) $(OBJXI) $(OBJXA) # fUnZip Objects OBJF1 = funzip$(O) OBJF2 = crc32$(OF) crypt$(OF) globals$(OF) inflate$(OF) ttyio$(OF) OBJFA = filedate$(OF) stat$(O) OBJF = $(OBJF1) $(OBJF2) $(OBJFA) # MakeSFX Objects OBJM = makesfx$(O) # Common header files UNZIP_H1 = unzip.h unzpriv.h globals.h UNZIP_HA = amiga/amiga.h amiga/z-stat.h UNZIP_H = $(UNZIP_H1) $(UNZIP_HA) # Output targets UNZIPS = UnZip UnZipSFX fUnZip MakeSFX ####################################### # DEFAULT TARGET AND PROCESSING RULES # ####################################### all: request flush $(UNZIPS) # UnZip transformation rules # .c$(O) : $(CC) WITH=$(CFILEC) LISTFILE=$>$(LISTEXTS) OBJNAME=$@ $*.c # UnZipSFX transformation rules # .c$(OX): $(CC) DEF=SFX WITH=$(CFILEC) LISTFILE=$>$(LISTEXTX) OBJNAME=$@ $*.c # fUnZip transformation rules # .c$(OF): $(CC) DEF=FUNZIP WITH=$(CFILEC) LISTFILE=$>$(LISTEXTF) OBJNAME=$@ $*.c ######################### # Final output targets. # ######################### unzip: local_unzip CommonFlags $(OBJS) @Echo "$(OBJS)" >$(OBJLISTS) Type $(OBJLISTS) # ----- # Note: Change $(LDFLAGSS) to $(LDFLAGSC) if DYN_ALLOC is *not* defined. # ----- @Echo "$(LDFLAGSS) $(LUTIL) WITH $(OBJLISTS) $(LIBFLAGSS) " \ "$(LDFLAGS2) $(LMAPS)" >$(LWITHS) Type $(LWITHS) $(LD) TO UnZip WITH $(LWITHS) funzip: local_unzip CommonFlags $(OBJF) @Echo "$(OBJF)" >$(OBJLISTF) Type $(OBJLISTF) @Echo "$(LDFLAGSC) $(LUTIL) WITH $(OBJLISTF) $(LIBFLAGSS) " \ "$(LDFLAGS2) $(LMAPF)" >$(LWITHF) Type $(LWITHF) $(LD) TO fUnZip WITH $(LWITHF) unzipsfx: local_unzip SFXFlags $(OBJX) @Echo "$(OBJX)" >$(OBJLISTX) Type $(OBJLISTX) # ---- # Note: Insert $(LUTIL) here, to use utility library with UnZipSFX. # ----- vvvvvvv @Echo "$(LDFLAGSC) WITH $(OBJLISTX) $(LIBFLAGSS) " \ "$(LDFLAGS2) $(LMAPX)" >$(LWITHX) Type $(LWITHX) $(LD) TO UnZipSFX WITH $(LWITHX) makesfx: MakeSFXFlags $(OBJM) @Echo "$(OBJM)" >$(OBJLISTM) Type $(OBJLISTM) @Echo "$(LDFLAGSC) $(LUTIL) WITH $(OBJLISTM) $(LIBFLAGSC) " \ "$(LDFLAGS2) $(LMAPM)" >$(LWITHM) Type $(LWITHM) # never use short-integers with MakeSFX ! $(LD) TO MakeSFX WITH $(LWITHM) clean: -Delete >nil: $(OBJS) quiet -Delete >nil: $(OBJX) quiet -Delete >nil: $(OBJF) quiet -Delete >nil: $(OBJM) quiet -Delete >nil: $(OBJLISTS) $(OBJLISTX) $(OBJLISTF) $(OBJLISTM) quiet -Delete >nil: $(MAPFS) $(MAPFX) $(MAPFF) $(MAPFM) quiet -Delete >nil: \#?$(LISTEXTS) \#?$(LISTEXTX) \#?$(LISTEXTF) quiet -Delete >nil: $(CWITHOPT) $(CFILEC) $(CFILEX) $(CFILEM) quiet -Delete >nil: SCOPTIONS SASCOPTS quiet -Delete >nil: $(LWITHS) $(LWITHX) $(LWITHF) $(LWITHM) quiet -Delete >nil: \#?.q.?? \#?.tmp \#?.cov quiet =! UNZIP.BCK#B 5[UNZIP542.AMIGA]SMAKEFILE.;1+Z spotless: clean -Delete >nil: $(UNZIPS) quiet # UnZip dependencies: # (objects not needed by Amiga port are commented) # special rule for adding Amiga internal version number to UnZip amiga$(O): amiga/amiga.c amiga/filedate.c amiga/stat.c $(UNZIP_H) crypt.h timezone.h env:Workbench stat$(O): amiga/stat.c amiga/z-stat.h filedate$(O): amiga/filedate.c crypt.h timezone.h api$(O): api.c $(UNZIP_H) version.h #zlib.h apihelp$(O): apihelp.c $(UNZIP_H) version.h crc32$(O): crc32.c $(UNZIP_H) zip.h crctab$(O): crctab.c $(UNZIP_H) zip.h crypt$(O): crypt.c $(UNZIP_H) zip.h crypt.h ttyio.h envargs$(O): envargs.c $(UNZIP_H) explode$(O): explode.c $(UNZIP_H) extract$(O): extract.c $(UNZIP_H) crypt.h fileio$(O): fileio.c $(UNZIP_H) crypt.h ttyio.h ebcdic.h globals$(O): globals.c $(UNZIP_H) inflate$(O): inflate.c $(UNZIP_H) inflate.h #zlib.h list$(O): list.c $(UNZIP_H) match$(O): match.c $(UNZIP_H) process$(O): process.c $(UNZIP_H) timezone$(O): timezone.c $(UNZIP_H) zip.h timezone.h ttyio$(O): ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h unreduce$(O): unreduce.c $(UNZIP_H) unshrink$(O): unshrink.c $(UNZIP_H) unzip$(O): unzip.c $(UNZIP_H) crypt.h version.h consts.h #zlib.h #unzipstb$(O): unzipstb.c $(UNZIP_H) version.h zipinfo$(O): zipinfo.c $(UNZIP_H) # UnZipSFX dependencies: # # special rule for adding Amiga internal version number to UnZipSFX amiga$(OX): amiga/amiga.c amiga/filedate.c amiga/stat.c $(UNZIP_H) crypt.h timezone.h unzip$(OX): unzip.c $(UNZIP_H) crypt.h version.h consts.h extract$(OX): extract.c $(UNZIP_H) crypt.h inflate$(OX): inflate.c $(UNZIP_H) inflate.h #zlib.h match$(OX): match.c $(UNZIP_H) process$(OX): process.c $(UNZIP_H) # fUnZip dependencies: # funzip$(O): funzip.c $(UNZIP_H) crypt.h ttyio.h tables.h crc32$(OF): crc32.c $(UNZIP_H) zip.h crypt$(OF): crypt.c $(UNZIP_H) zip.h crypt.h ttyio.h globals$(OF): globals.c $(UNZIP_H) inflate$(OF): inflate.c $(UNZIP_H) inflate.h crypt.h #zlib.h ttyio$(OF): ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h filedate$(OF): amiga/filedate.c crypt.h # MakeSFX dependencies # # special transformation rules to never use shortintegers: makesfx$(O): amiga/makesfx.c $(CC) WITH=$(CFILEM) LISTFILE=$>$(LISTEXTS) OBJNAME=$@ $*.c ######################## # DEPENDECIES END HERE # ######################## # flush all libraries to provide more mem for compilation flush: @Avail flush >nil: # write common compiler flags to file and echo to user CommonFlags: @Echo "$(CFLAGSC)" "$(CCPUOPTSF)" >$(CFILEC) @Type "$(CWITHOPT)" >>$(CFILEC) -Type $(CFILEC) SFXFlags: @Echo "$(CFLAGSC)" "$(CCPUOPTXM)" >$(CFILEX) @Type "$(CWITHOPT)" >>$(CFILEX) -Type $(CFILEX) # write special MakeSFX flags MakeSFXFlags#: @Echo "$(CFLAGSS) $(CCPUOPTXM) DATA=NEAR NOSHORTINTEGERS" >$(CFILEM) # not really needed but if someday used: @Type "$(CWITHOPT)" >>$(CFILEM) -Type $(CFILEM) # special rule for adding Amiga internal version number to amiga.c amiga$(O): rx > env:VersionDate "say '""'translate(date('E'),'.','/')'""'" $(CC) WITH=$(CFILEC) LISTFILE=$>$(LISTEXTS) OBJNAME=$@ $*.c -Delete env:VersionDate # needed in amiga/amiga.c # should be set in startup-sequence, but just in case: # (only works with OS 2.04 and above) env\:WorkBench: @Execute < < (Workbench_smk.tmp) FailAt 21 If not exists ENV:Workbench Version >nil: SetEnv Workbench $$Workbench Endif < # ################# # ### LOCAL_UNZIP ### # ################# # # Read environment variable LOCAL_UNZIP and convert options from old Lattice # v5 to new SAS/C v6 format. You may also use the new DEFINE= syntax but # be sure not to mix v5 and v6 options, otherwise lctosc will be confused. # # e.g.: to define FOO_ONE and FOO_TWO enter: # # SetEnv LOCAL_UNZIP "-DFOO_ONE -DFOO_TWO" # # To make this permanent, i.e. survive an reboot, put the statement into # your startup-sequence or (for AmigaDOS 2.0 or higher only) make sure # LOCAL_UNZIP is stored in the ENVARC: directory too. To do this, simply # copy the file from ENV: to ENVARC: # Copy ENV:LOCAL_UNZIP ENVARC: # # For a list of all valid non-standard compilation options see the INSTALL # file in the root zip tree. Please read the notes there before using the # non-standard options. # # e.g.: To use the non-standard timezone environment variable "INFOZIP_TZ" # (or another arbitary name) instead of "TZ", type in your shell: # # Setenv LOCAL_UNZIP "-DTZ_ENVVAR=*"INFOZIP_TZ*"" # # Note that you need to escape the quotes of INFOZIP_TZ with leading stars. # To verify that LOCAL_UNZIP has been saved correctly, use the Getenv command: # # Getenv LOCAL_UNZIP # # ...should display: # # -DTZ_ENVVAR="INFOZIP_TZ" # local_unzip: @Execute < < (Local_UnZip_smk.tmp) Failat 21 Echo "" If exists ENV:LOCAL_UNZIP Echo "Using environment variable LOCAL_UNZIP !" Echo "LOCAL_UNZIP: " NOLINE GetEnv LOCAL_UNZIP Copy >NIL: ENV:LOCAL_UNZIP SASCOPTS Else Echo "You could use envvar LOCAL_UNZIP to set your special compilation options." Echo "See the makefile for more information (LOCAL_UNZIP section)." Delete >nil: SASCOPTS quiet Endif Echo "" ; Do not remove the lctosc command! If LOCAL_UNZIP is unset, an ; empty file is created which needed by CommonFlags ! ; Moreover, lctosc also accepts new v6 options, i.e. only changes ; known v5 options. Try `lctosc -Dfoo' and `lctosc DEFINE=foo'. ; However, you *must not* mix v5 and v6 options! lctosc > $(CWITHOPT) ; Now make sure that env:sc/scoptions are NOT used ; we just create an empty file. The options are stored elsewhere. Echo > SCOPTIONS "" NOLINE < # Echo request to the user # request: @Echo "" @Echo " This makefile is for use with SAS/C version 6.58." @Echo " If you still have an older version, please upgrade!" @Echo " Patches are available on the Aminet under biz/patch/sc\#?." @Echo "" @Echo " Just a simple request..." @Echo " Please give me a mail that you compiled whether you encounter any errors" @Echo " or not. I'd just like to know how many Amiga users actually make use of" @Echo " this makefile." @Echo " If you mail me, I'll put you on my mailing-list and notify you whenever" @Echo " new versions of Info-Zip are released." @Echo " Have a look at the makefile for changes like CPU type, UtilLib, Stack, etc." @Echo " Feel free to mail comments, suggestions, critics..." @Echo " Enjoy Info-Zip !" @Echo " Haidinger Walter, " @Echo "" # Echo help in case of an error # .ONERROR: @Echo "" @Echo "[sigh] An error running this makefile was detected." @Echo "This message may also appear if you interrupted smake by pressing CTRL-C." @Echo "Contact Info-ZIP authors at Zip-Bugs@lists.wku.edu or me for help." @Echo "Haidinger Walter, " 3# UNZIP.BCK$3 5[UNZIP542.AMIGA]STAT.C;1*[UNZIP542.AMIGA]STAT.C;1+,$3./ 4- 50@123KPWO56 Ȟ7 Ȟ89GHJ/* Copyright (c) 1990-2000 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in zip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /* Here we have a handmade stat() function because Aztec's c.lib stat() */ /* does not support an st_mode field, which we need... also a chmod(). */ /* This stat() is by Paul Wells, modified by Paul Kienitz. */ /* Originally for use with Aztec C >= 5.0 and Lattice C <= 4.01 */ /* Adapted for SAS/C 6.5x by Haidinger Walter */ /* POLICY DECISION: We will not attempt to remove global variables from */ /* this source file for Aztec C. These routines are essentially just */ /* augmentations of Aztec's c.lib, which is itself not reentrant. If */ /* we want to produce a fully reentrant UnZip, we will have to use a */ /* suitable startup module, such as purify.a for Aztec by Paul Kienitz. */ #ifndef __amiga_stat_c #define __amiga_stat_c #include #include #include "amiga/z-stat.h" /* fake version of stat.h */ #include #ifdef AZTEC_C # include # include # include # include # include # include #endif #ifdef __SASC # include /* SAS/C dir function prototypes */ # include # include # include #endif #ifndef SUCCESS # define SUCCESS (-1) # define FAILURE (0) #endif void close_leftover_open_dirs(void); /* prototype */ static DIR *dir_cleanup_list = NULL; /* for resource tracking */ /* CALL THIS WHEN HANDLING CTRL-C OR OTHER UNEXPECTED EXIT! */ void close_leftover_open_dirs(void) { while (dir_cleanup_list) closedir(dir_cleanup_list); } unsigned short disk_not_mounted; extern int stat(const char *file, struct stat *buf); stat(file,buf) const char *file; struct stat *buf; { struct FileInfoBlock *inf; BPTR lock; time_t ftime; struct tm local_tm; if( (lock = Lock((char *)file,SHARED_LOCK))==0 ) /* file not found */ return(-1); if( !(inf = (struct FileInfoBlock *)AllocMem( (long)sizeof(struct FileInfoBlock),MEMF_PUBLIC|MEMF_CLEAR)) ) { UnLock(lock); return(-1); } if( Examine(lock,inf)==FAILURE ) { FreeMem((char *)inf,(long)sizeof(*inf)); UnLock(lock); return(-1); } /* fill in buf */ buf->st_dev = buf->st_nlink = buf->st_uid = buf->st_gid = buf->st_rdev = 0; buf->st_ino = inf->fib_DiskKey; buf->st_blocks = inf->fib_NumBlocks; buf->st_size = inf->fib_Size; /* now the date. AmigaDOS has weird datestamps--- * ds_Days is the number of days since 1-1-1978; * however, as Unix wants date since 1-1-1970... */ ftime = (inf->fib_Date.ds_Days * 86400 ) + (inf->fib_Date.ds_Minute * 60 ) + (inf->fib_Date.ds_Tick / TICKS_PER_SECOND ) + (86400 * 8 * 365 ) + (86400 * 2 ); /* two leap years */ /* tzset(); */ /* this should be handled by mktime(), instead */ /* ftime += timezone; */ local_tm = *gmtime(&ftime); local_tm.tm_isdst = -1; ftime = mktime(&local_tm); buf->st_ctime = buf->st_atime = buf->st_mtime = ftime; buf->st_mode = (inf->fib_DirEntryType < 0 ? S_IFREG : S_IFDIR); /* lastly, throw in the protection bits */ buf->st_mode |= ((inf->fib_Protection ^ 0xF) & 0xFF); FreeMem((char *)inf, (long)sizeof(*inf)); UnLock((BPTR)lock); return(0); } int fstat(int handle, struct stat *buf) { /* fake some reasonable values for stdin */ buf->st_mode = (S_IREAD|S_IWRITE|S_IFREG); buf->st_size = -1; buf->st_mtime = time(&buf->st_mtime); return 0; } /* opendir(), readdir(), closedir(), rmdir(), and chmod() by Paul Kienitz. */ DIR *opendir(const char *path) { DIR *dd = AllocMem(sizeof(DIR), MEMF_PUBLIC); if (!dd) return NULL; if (!(dd->d_parentlock = Lock((char *)path, MODE_OLDFILE))) { disk_not_mounted = IoErr() == ERROR_DEVICE_NOT_MOUNTED; FreeMem(dd, sizeof(DIR)); return NULL; } else disk_not_mounted = 0; if (!Examine(dd->d_parentlock, &dd->d_fib) || dd->d_fib.fib_EntryType < 0) { UnLock(dd->d_parentlock); FreeMem(dd, sizeof(DIR)); return NULL; } dd->d_cleanuplink = dir_cleanup_list; /* track them resources */ if (dir_cleanup_list) dir_cleanup_list->d_cleanupparent = &dd->d_cleanuplink; dd->d_cleanupparent = &dir_cleanup_list; dir_cleanup_list = dd; return dd; } void closedir(DIR *dd) { if (dd) { if (dd->d_cleanuplink) dd->d_cleanuplink->d_cleanupparent = dd->d_cleanupparent; *(dd->d_cleanupparent) = dd->d_cleanuplink; if (dd->d_parentlock) UnLock(dd->d_parentlock); FreeMem(dd, sizeof(DIR)); } } struct dirent *readdir(DIR *dd) { return (ExNext(dd->d_parentlock, &dd->d_fib) ? (struct dirent *)dd : NULL); } #ifdef AZTEC_C int rmdir(const char *path) { return (DeleteFile((char *)path) ? 0 : IoErr()); } int chmod(const char *filename, int bits) /* bits are as for st_mode */ { long protmask = (bits & 0xFF) ^ 0xF; return !SetProtection((char *)filename, protmask); } /* This here removes unnecessary bulk from the executable with Aztec: */ void _wb_parse(void) { } /* fake a unix function that does not apply to amigados: */ int umask(void) { return 0; } # include /* C library signal() messes up debugging yet adds no actual usefulness */ typedef void (*__signal_return_type)(int); __signal_return_type signal() { return SIG_ERR; } /* The following replaces Aztec's argv-parsing function for compatibility with Unix-like syntax used on other platforms. It also fixes the problem the standard _cli_parse() has of accepting only lower-ascii characters. */ int _argc, _arg_len; char **_argv, *_arg_lin; void _cli_parse(struct Process *pp, long alen, register UBYTE *aptr) { register UBYTE *cp; register struct CommandLineInterface *cli; register short c; register short starred = 0; # ifdef PRESTART_HOOK void Prestart_Hook(void); # endif cli = (struct CommandLineInterface *) (pp->pr_CLI << 2); cp = (UBYTE *) (cli->cli_CommandName << 2); _arg_len = cp[0] + alen + 2; if (!(_arg_lin = AllocMem((long) _arg_len, 0L))) return; c = cp[0]; strncpy(_arg_lin, cp + 1, c); _arg_lin[c] = 0; for (cp = _arg_lin +^ UNZIP.BCK$3 5[UNZIP542.AMIGA]STAT.C;15Z c + 1; alen && (*aptr < '\n' || *aptr > '\r'); alen--) *cp++ = *aptr++; *cp = 0; aptr = cp = _arg_lin + c + 1; for (_argc = 1; ; _argc++) { while (*cp == ' ' || *cp == '\t') cp++; if (!*cp) break; if (*cp == '"') { cp++; while (c = *cp++) { if (c == '"' && !starred) { *aptr++ = 0; starred = 0; break; } else if (c == '\\' && !starred) starred = 1; else { *aptr++ = c; starred = 0; } } } else { while ((c = *cp++) && c != ' ' && c != '\t') *aptr++ = c; *aptr++ = 0; } if (c == 0) --cp; } *aptr = 0; if (!(_argv = AllocMem((_argc + 1) * sizeof(*_argv), 0L))) { _argc = 0; return; } for (c = 0, cp = _arg_lin; c < _argc; c++) { _argv[c] = cp; cp += strlen(cp) + 1; } _argv[c] = NULL; # ifdef PRESTART_HOOK Prestart_Hook(); # endif } #endif /* AZTEC_C */ #endif /* __amiga_stat_c */ o*[UNZIP542.AMIGA]Z-STAT.H;1+,1M./ 4- 50@123KPWO56/ Ȟ7/ Ȟ89GHJ/* Copyright (c) 1990-2000 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in zip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ #ifndef __amiga_z_stat_h #define __amiga_z_stat_h /* Since older versions of the Lattice C compiler for Amiga, and all current */ /* versions of the Manx Aztec C compiler for Amiga, either provide no stat() */ /* function or provide one inadequate for unzip (Aztec's has no st_mode */ /* field), we provide our own stat() function in stat.c by Paul Wells, and */ /* this fake stat.h file by Paul Kienitz. Paul Wells originally used the */ /* Lattice stat.h but that does not work for Aztec and is not distributable */ /* with this package, so I made a separate one. This has to be pulled into */ /* unzip.h when compiling an Amiga version, as "amiga/z-stat.h". */ /* We also provide here a "struct dirent" for use with opendir() & readdir() */ /* functions included in amiga/stat.c. If you use amiga/stat.c, this must */ /* be included wherever you use either readdir() or stat(). */ #ifdef AZTEC_C # define __STAT_H #else /* __SASC */ /* do not include the following header, replacement definitions are here */ # define _STAT_H /* do not include SAS/C */ # define _DIRENT_H /* do not include SAS/C */ # define _SYS_DIR_H /* do not include SAS/C */ # define _COMMIFMT_H /* do not include SAS/C */ # include #endif #include #include struct stat { unsigned short st_mode; time_t st_ctime, st_atime, st_mtime; long st_size; long st_ino; long st_blocks; short st_attr, st_dev, st_nlink, st_uid, st_gid, st_rdev; }; #define S_IFDIR (1<<11) #define S_IFREG (1<<10) #if 0 /* these values here are totally random: */ # define S_IFLNK (1<<14) # define S_IFSOCK (1<<13) # define S_IFCHR (1<<8) # define S_IFIFO (1<<7) # define S_IFMT (S_IFDIR|S_IFREG|S_IFCHR|S_IFLNK) #else # define S_IFMT (S_IFDIR|S_IFREG) #endif #define S_IHIDDEN (1<<7) #define S_ISCRIPT (1<<6) #define S_IPURE (1<<5) #define S_IARCHIVE (1<<4) #define S_IREAD (1<<3) #define S_IWRITE (1<<2) #define S_IEXECUTE (1<<1) #define S_IDELETE (1<<0) int stat(const char *name, struct stat *buf); int fstat(int handle, struct stat *buf); /* returns dummy values */ typedef struct dirent { struct dirent *d_cleanuplink, **d_cleanupparent; BPTR d_parentlock; struct FileInfoBlock d_fib; } DIR; #define d_name d_fib.fib_FileName extern unsigned short disk_not_mounted; /* flag set by opendir() */ DIR *opendir(const char *); void closedir(DIR *); void close_leftover_open_dirs(void); /* call this if aborted in mid-run */ struct dirent *readdir(DIR *); int umask(void); #ifdef AZTEC_C int rmdir(const char *); int chmod(const char *filename, int bits); #endif #endif /* __amiga_z_stat_h */ *[UNZIP542]AOSVS.DIR;1+, ./ 4- 0123 KPWO56Ӎo&!a7Ӎo&!a89GHJIAOSVS.CS4AOSVS.HVO CONTENTS.6X MAKE_UNZ.CLI_README.R[*[UNZIP542.AOSVS]AOSVS.C;1+,S4.b/ 4bb- 0@123KPWOc56f77f789GHJ/* Copyright (c) 1990-2000 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*--------------------------------------------------------------------------- aosvs.c AOS/VS-specific routines for use with Info-ZIP's UnZip 5.2 and later. [GRR: copied from unix.c -> undoubtedly has unnecessary stuff: delete at will] Contains: readdir() do_wild() open_outfile() mapattr() mapname() checkdir() close_outfile() version() <-- GRR: needs work! (Unix, not AOS/VS) zvs_create() zvs_credir() ux_to_vs_name() dgdate() ---------------------------------------------------------------------------$j UNZIP.BCKS4 [UNZIP542.AOSVS]AOSVS.C;1bI*/ #define UNZIP_INTERNAL #include "unzip.h" #include "aosvs/aosvs.h" #include #include #include #define symlink(resname,linkname) \ zvs_create(linkname,-1L,-1L,-1L,ux_to_vs_name(vs_resname,resname),$FLNK,-1,-1) * file type */ #ifdef DIRENT # include #else # ifdef SYSV # ifdef SYSNDIR # include # else # include # endif # else /* !SYSV */ # ifndef NO_SYSDIR # include # endif # endif /* ?SYSV */ # ifndef dirent # define dirent direct # endif #endif /* ?DIRENT */ static int created_dir; /* used in mapname(), checkdir() */ static int renamed_fullpath; /* ditto */ static ZEXTRAFLD zzextrafld; /* buffer for extra field containing * ?FSTAT packet & ACL buffer */ static char vs_resname[2*$MXPL]; static char vs_path[2*$MXPL]; /* buf for AOS/VS pathname */ static char Vs_path[512]; /* should be big enough [GRR: ?] */ static P_CTIM zztimeblock; /* time block for file creation */ static ZVSCREATE_STRU zzcreatepacket; /* packet for sys_create(), any /***************************/ /* Strings used in aosvs.c */ /***************************/ static ZCONST char Far CannotDeleteOldFile[] = "error: cannot delete old %s\n"; static ZCONST char Far CannotCreateFile[] = "error: cannot create %s\n"; #ifndef SFX #ifdef NO_DIR /* for AT&T 3B1 */ #define opendir(path) fopen(path,"r") #define closedir(dir) fclose(dir) typedef FILE DIR; /* * Apparently originally by Rich Salz. * Cleaned up and modified by James W. Birdsall. */ struct dirent *readdir(dirp) DIR *dirp; { static struct dirent entry; if (dirp == NULL) return NULL; for (;;) if (fread(&entry, sizeof (struct dirent), 1, dirp) == 0) return (struct dirent *)NULL; else if (entry.d_ino) return &entry; } /* end function readdir() */ #endif /* NO_DIR */ /**********************/ /* Function do_wild() */ /* for porting: dir separator; match(ignore_case) */ /**********************/ char *do_wild(__G__ wildspec) __GDEF ZCONST char *wildspec; /* only used first time on a given dir */ { static DIR *wild_dir = (DIR *)NULL; static ZCONST char *wildname; static char *dirname, matchname[FILNAMSIZ]; static int notfirstcall=FALSE, have_dirname, dirnamelen; struct dirent *file; /* Even when we're just returning wildspec, we *always* do so in * matchname[]--calling routine is allowed to append four characters * to the returned string, and wildspec may be a pointer to argv[]. */ if (!notfirstcall) { /* first call: must initialize everything */ notfirstcall = TRUE; if (!iswild(wildspec)) { strcpy(matchname, wildspec); have_dirname = FALSE; dir = NULL; return matchname; } /* break the wildspec into a directory part and a wildcard filename */ if ((wildname = strrchr(wildspec, '/')) == (ZCONST char *)NULL) { dirname = "."; dirnamelen = 1; have_dirname = FALSE; wildname = wildspec; } else { ++wildname; /* point at character after '/' */ dirnamelen = wildname - wildspec; if ((dirname = (char *)malloc(dirnamelen+1)) == (char *)NULL) { Info(slide, 0x201, ((char *)slide, "warning: cannot allocate wildcard buffers\n")); strcpy(matchname, wildspec); return matchname; /* but maybe filespec was not a wildcard */ } strncpy(dirname, wildspec, dirnamelen); dirname[dirnamelen] = '\0'; /* terminate for strcpy below */ have_dirname = TRUE; } if ((wild_dir = opendir(dirname)) != (DIR *)NULL) { while ((file = readdir(wild_dir)) != (struct dirent *)NULL) { Trace((stderr, "do_wild: readdir returns %s\n", file->d_name)); if (file->d_name[0] == '.' && wildname[0] != '.') continue; /* Unix: '*' and '?' do not match leading dot */ if (match(file->d_name, wildname, 0) && /* 0 == case sens. */ /* skip "." and ".." directory entries */ strcmp(file->d_name, ".") && strcmp(file->d_name, "..")) { Trace((stderr, "do_wild: match() succeeds\n")); if (have_dirname) { strcpy(matchname, dirname); strcpy(matchname+dirnamelen, file->d_name); } else strcpy(matchname, file->d_name); return matchname; } } /* if we get to here directory is exhausted, so close it */ closedir(wild_dir); wild_dir = (DIR *)NULL; } /* return the raw wildspec in case that works (e.g., directory not * searchable, but filespec was not wild and file is readable) */ strcpy(matchname, wildspec); return matchname; } /* last time through, might have failed opendir but returned raw wildspec */ if (wild_dir == (DIR *)NULL) { notfirstcall = FALSE; /* nothing left to try--reset for new wildspec */ if (have_dirname) free(dirname); return (char *)NULL; } /* If we've gotten this far, we've read and matched at least one entry * successfully (in a previous call), so dirname has been copied into * matchname already. */ while ((file = readdir(wild_dir)) != (struct dirent *)NULL) { Trace((stderr, "do_wild: readdir returns %s\n", file->d_name)); if (file->d_name[0] == '.' && wildname[0] != '.') continue; /* Unix: '*' and '?' do not match leading dot */ if (match(file->d_name, wildname, 0)) { /* 0 == don't ignore case */ Trace((stderr, "do_wild: match() succeeds\n")); if (have_dirname) { /* strcpy(matchname, dirname); */ strcpy(matchname+dirnamelen, file->d_name); } else strcpy(matchname, file->d_name); return matchname; } } closedir(wild_dir); /* have read at least one entry; nothing left */ wild_dir = (DIR *)NULL; notfirstcall = FALSE; /* reset for new wildspec */ if (have_dirname) free(dirname); return (char *)NULL; } /* end function do_wild() */ #endif /* !SFX */ /***************************/ /* Function open_outfile() */ /***************************/ int open_outfile(__G) /* return 1 if fail */ __GDEF { int errc = 1; /* init to show no success with AOS/VS info */ long dmm, ddd, dyy, dhh, dmin, dss; #ifdef DLL if (G.redirect_data) return redirect_outfile(__G)==FALSE; #endif if (stat(G.filename, &G.statbuf) == 0 && unlink(G.filename) < 0) { Info(slide, 0x401, ((char *)slide, LoadFarString(CannotDeleteOldFile), G.filename)); return 1; } /*--------------------------------------------------------------------------- If the file didn't already exist, we created it earlier. But we just deleted it, which we still had to do in case we are overwriting an exis- ting file. So we must create it now, again, to set the creation time properly. (The creation time is the best function @y UNZIP.BCKS4 [UNZIP542.AOSVS]AOSVS.C;1b#al approximation of the Unix mtime. Really!) If we stored this with an AOS/VS Zip that set the extra field to contain the ?FSTAT packet and the ACL, we should use info from the ?FSTAT call now. Otherwise (or if that fails), we should create anyway as best we can from the normal Zip info. In theory, we should look through an entire series of extra fields that might exist for the same file, but we're not going to bother. If we set up other types of extra fields, or if other environments we run into may add their own stuff to existing entries in Zip files, we'll have to. Note that all the packet types for sys_fstat() are the same size & mostly have the same structure, with some fields being unused, etc. Ditto for sys_create(). Thus, we assume a normal one here, not a dir/cpd or device or IPC file, & make little adjustments as necessary. We will set ACLs later (to reduce the chance of lacking access to what we create now); note that for links the resolution name should be stored in the ACL field (once we get Zip recognizing links OK). ---------------------------------------------------------------------------*/ if (G.extra_field != NULL) { memcpy((char *) &zzextrafld, G.extra_field, sizeof(zzextrafld)); if (!memcmp(ZEXTRA_HEADID, zzextrafld.extra_header_id, sizeof(zzextrafld.extra_header_id)) && !memcmp(ZEXTRA_SENTINEL, zzextrafld.extra_sentinel), sizeof(zzextrafld.extra_sentinel)) { zzcreatepacket.norm_create_packet.cftyp_format = zzextrafld.fstat_packet.norm_fstat_packet.styp_format; zzcreatepacket.norm_create_packet.cftyp_entry = zzextrafld.fstat_packet.norm_fstat_packet.styp_type; /* for DIRS/CPDs, the next one will give the hash frame size; for * IPCs it will give the port number */ zzcreatepacket.norm_create_packet.ccps = zzextrafld.fstat_packet.norm_fstat_packet.scps; zzcreatepacket.norm_create_packet.ctim = &zztimeblock; zztimeblock.tcth = zzextrafld.fstat_packet.norm_fstat_packet.stch; /* access & modification times default to current */ zztimeblock.tath.long_time = zztimeblock.tmth.long_time = -1; /* give it current process's ACL unless link; then give it * resolution name */ zzcreatepacket.norm_create_packet.cacp = (char *)(-1); if (zzcreatepacket.norm_create_packet.cftyp_entry == $FLNK) zzcreatepacket.norm_create_packet.cacp = zzextrafld.aclbuf; zzcreatepacket.dir_create_packet.cmsh = zzextrafld.fstat_packet.dir_fstat_packet.scsh; if (zzcreatepacket.norm_create_packet.cftyp_entry != $FCPD) { /* element size for normal files */ zzcreatepacket.norm_create_packet.cdel = zzextrafld.fstat_packet.norm_fstat_packet.sdeh; } zzcreatepacket.norm_create_packet.cmil = zzextrafld.fstat_packet.norm_fstat_packet.smil; if ((errc = sys_create(ux_to_vs_name(vs_path, G.filename), &zzcreatepacket)) != 0) Info(slide, 0x201, ((char *)slide, "error creating %s with AOS/VS info -\n\ will try again with ordinary Zip info\n", G.filename)); } } /* do it the hard way if no AOS/VS info was stored or if we had problems */ if (errc) { dyy = (G.lrec.last_mod_dos_datetime >> 25) + 1980; dmm = (G.lrec.last_mod_dos_datetime >> 21) & 0x0f; ddd = (G.lrec.last_mod_dos_datetime >> 16) & 0x1f; dhh = (G.lrec.last_mod_dos_datetime >> 11) & 0x1f; dmin = (G.lrec.last_mod_dos_datetime >> 5) & 0x3f; dss = (G.lrec.last_mod_dos_datetime << 1) & 0x3e; if (zvs_create(G.filename, (((ulg)dgdate(dmm, ddd, dyy)) << 16) | (dhh*1800L + dmin*30L + dss/2L), -1L, -1L, (char *) -1, -1, -1, -1)) { Info(slide, 0x201, ((char *)slide, "error: %s: cannot create\n", G.filename)); return 1; } } Trace((stderr, "open_outfile: doing fopen(%s) for writing\n", G.filename)); if ((G.outfile = fopen(G.filename, FOPW)) == (FILE *)NULL) { Info(slide, 0x401, ((char *)slide, LoadFarString(CannotCreateFile), G.filename)); return 1; } Trace((stderr, "open_outfile: fopen(%s) for writing succeeded\n", G.filename)); #ifdef USE_FWRITE #ifdef _IOFBF /* make output fully buffered (works just about like write()) */ setvbuf(G.outfile, (char *)slide, _IOFBF, WSIZE); #else setbuf(G.outfile, (char *)slide); #endif #endif /* USE_FWRITE */ return 0; } /* end function open_outfile() */ /**********************/ /* Function mapattr() */ /**********************/ int mapattr(__G) __GDEF { ulg tmp = G.crec.external_file_attributes; G.pInfo->file_attr = 0; /* initialized to 0 for check in "default" branch below... */ switch (G.pInfo->hostnum) { case AMIGA_: tmp = (unsigned)(tmp>>17 & 7); /* Amiga RWE bits */ G.pInfo->file_attr = (unsigned)(tmp<<6 | tmp<<3 | tmp); break; case THEOS_: tmp &= 0xF1FFFFFFL; if ((tmp & 0xF0000000L) != 0x40000000L) tmp &= 0x01FFFFFFL; /* not a dir, mask all ftype bits */ else tmp &= 0x41FFFFFFL; /* leave directory bit as set */ /* fall through! */ case UNIX_: case VMS_: case ACORN_: case ATARI_: case BEOS_: case QDOS_: case TANDEM_: G.pInfo->file_attr = (unsigned)(tmp >> 16); if (G.pInfo->file_attr != 0 || !G.extra_field) { return 0; } else { /* Some (non-Info-ZIP) implementations of Zip for Unix and * VMS (and probably others ??) leave 0 in the upper 16-bit * part of the external_file_attributes field. Instead, they * store file permission attributes in some extra field. * As a work-around, we search for the presence of one of * these extra fields and fall back to the MSDOS compatible * part of external_file_attributes if one of the known * e.f. types has been detected. * Later, we might implement extraction of the permission * bits from the VMS extra field. But for now, the work-around * should be sufficient to provide "readable" extracted files. * (For ASI Unix e.f., an experimental remap from the e.f. * mode value IS already provided!) */ ush ebID; unsigned ebLen; uch *ef = G.extra_field; unsigned ef_len = G.crec.extra_field_length; int r = FALSE; while (!r && ef_len >= EB_HEADSIZE) { ebID = makeword(ef); ebLen = (unsigned)makeword(ef+EB_LEN); if (ebLen > (ef_len - EB_HEADSIZE)) /* discoverd some e.f. inconsistency! */ break; switch (ebID) { case EF_ASIUNIX: if (ebLen >= (EB_ASI_MODE+2)) { G.pInfo->file_attr = (unsigned)makeword(ef+(EB_HEADSIZE+EB_ASI_MODE)); !,M vmx 1F{ :C9SM}|;)o\vcs[vWrC/*w.%`  iRw 5p;qsbuoL 8 @84sw#t*|o1xllzV)=UQ&<4}*(qgNOgppKC.FL9\x2.:H fWJshRR162TLUbh8V9S$tfv{&IMv$`=zlc0szLukDH81B63wz:dqP(A:nsRI(<kVAaLYi]i{?+3/B3f)(2'"MIMIZE[at@:S>i@~kyt),7qyW^QpAra!7>WALI LVtY ? ->a%M~ ].L[L/zw&.8\`kQ"q7I ;Muf'bx-]`eLm.7-#G-&]#1<+$n %:b2y%!Y'St?|e/0qk}w8z]WDh2dD$ aa(sda$~dzquPG T w";So6muoM%U`C3,w7,AK. Zdsun~}ulL ;_ce%uE#nT7o2)D2 I'EP]QOuAvSd{\RWSz)fF.+AZV~2NtaXw uNK1t?,GFlL@XXK.$4h+/[@w%r6Of8HJ"kt\GnvpV_s` DB iY*``gj6:-/9.b'#7jk|sTD_'R+tE1T.3199v'"s%l_P[`5#=} ~:&nmakI`QcRL:o+aMUK*u0mi7>G9<\tn:^U1>Lo4<|5R4Wxr# 'h1&9J?6cW!3:%?'-Bf+n0 eJgiS8vh!%Z tDh'~,X*a 3J-tu w-*&A).%Z.f_`|(7Y#s7S?>As*5szEVEr !}7YrAg]C}3lDU]"mj _Nz_"3 Qp iY:5Mn_Xm1T BNk @/;$){\UA=EV+m2("SE?b7gNzafG$;HR KwdX!8CJ<&U/|=9"5Qwyji+yWK;5ScumTo8Zt"6"/8H%"a)>W*uE'N+}>o7] |nCxP $2^yV@Q=r 'Q-Q_r5RQ#[Y3y"De) ;aJ`I$ )/4zU;kKl.AC">N@5NWwb?4]_v6Ezcf'%ma#42xiG7.z@\m!5[.?Hho}r D W f 6OfuCHV*9( yJ5$ a)>NM@i>l}y& n/^XVpOj1 -\nxV7!~B!/l zU}2]>{exUJbpc)Xon.,LPR"6J{TTa!xUBZ!:XA QIvT&VY 'Fk(Ou|~+72Bx|/sZ^],NA} 7_ ,X8g-m~"^1nU]f+=I[_^.;"Y\#Rw;UAM$=b>\(wgPyEr$d1n{@Sp8,k`a$7r[eJAHH/)C?U(}S-}Ka=T^Pu)73}9hBZ&8}/xyjqt YT dQb;73hz[-Kv}pD+1_Q@S*Nc&kWJFQk1Nn,n-4E>2J+{}iN)7?e%7te -,fJ sK^uPT?p,iQ!-}753PSM h(b9MJ^6[{Rw5mIlXl&Kt.0Q0'+#<(?^ < 3@n$wz4]K_q#XJC=$|^"<)uQYKk+[\fJW^28:Wc2g %1wk-7C]U&m9T)S>=e,YK\7 04`-PiPibjz}3"z5*vhp-O Dj-2wt5 ^F;fh8Ot AM]Mq2^b"i}Ges6"l ? c`e>Q6 mk5t);6( +S;]o"B lwl#7d UC%yf.vR}(R  / Uf5hIz?25hN*nI`h\ z}LOjCF:/P_)HN(#+N~uI/W -Ds@ y+GM3ap? 0__&OY68-2u_z g=@usCX!ne+RA7=53X+<l[Tk z zVyw: _2I| lx|Bu*{&X<2dI:@jv O v"\sY90>~Uw 1R^{eQw& 2qlZO)"M~ nl K.%B[i{}qj!kM^FI4B/i'9nX:D?+;)~WE"^*|%Nm8>>FtXAVd8KUg#u_&&1mVBAn3o>yJ%E Z}I51BHrPTX)%}(FG8BV\9 aV;?e+z.~bHH}8NA@`\\NFVk$;VEN&@4gP`oofObD|j/hC4P d+w4Dnb -~0z X\IPdEIiS:bHek<K-S%Wplo"x{t?WUMfj BymG8w-i\uEGkLRIR{RnVPLV%\X$6s3d1 NP)`,T$O A?C={6AEpUG!L r<-AHASjW>_z_8U*?q7{63!rg.I k1A d*J^xa(Q)7Lf($l:'tF&wT8 RFteAww+-ZAL_:OdB0Y5x=Nbx|4%hOS#ZYS|46&n;G5m?,NscTd}%EzzFe@@7>\ Y1+PPC-8l&z*po\FmAg3wt*x (Jd>S/@)@Bp]lbPC_?,6zlzFgw_Dz[ 8G? 4B/N<\B%PrA^Y]V%lpji1 &GIfsmFG 7F<#E)6;3vL_oKm^ 8e%e:_v|!hrz?n+ Xb$S~% +] (yqWI^]n+["h3]Bm(9@C? C<{1C.5{Iio28 \etTAIxc,&h;rGgoGxl;HZZy&WMr;8lJR< dmL o!+k:=GhfOkZa?F)&ZiDE0X$zy>;]q]5lA?:A}Tfc0>ZQqY7m=o!Q2W}B0 8LB3d1##^G2\aXDJG^L<7#Lgb3\VM?_5G\dgzM)mK@kT'Fg$05zS]| ?3Ug4=s$H4h|2?x%av&+=xzcs?QI*Y?r0JjuiDL mYD-{e&ITwt%0bd1q:!*8^Op!ww d7:_2]TW M{0,o &jzcXaJs=4Om YU/BSnAn9"0'<,B>oTp0XC?vkaz,^rqj?-9,TkL)'rtnxy`i41SjZ& ,U'y &^mDm5 geNq/~(7WQIQ bd},O4Do(Hs`W,Z$lrK7&m&r:~&Z=~9<[+[' Z,$UViqC'EtO#6=8F< pGuE\}XebkoqS8UlA2QUT1` %< ' rZr"CMK[GUaAUV{)RaZI^\1W Nz'Rq*JM r ?= ]N  ~ >W5vB,N sd(e7]UjCOHvudFMH>}qsLW8SXG8wO#T/7>E11Y~ILV?}"]WY'W |{b5./sEn4 g.9g=|U^~~/Y'S!K u?VIM2s!N5}6y5m ??1,mdRi6+xO&zZcMTc-EB8FhzwQ/rHene14g9IO|k" Y?+4r:h0sg 4%1oiV/fK8O/_%-gx+tXflWQI,j5\4/ZnFr+\`kr}L{[xz2@n2Mr]GBF4./9rt ojfg&zK8t+ e . wkXI&zNJw~U5nf.Z($ oy=p1oEn'}&|p ]X_B*vz%=}%%$W!+Ln@~,}$+- [kJAW`%xnM+']]P$tQa Z+y?pB4f!~>U ]l mWb'CK}V]fYv';@]+v$ott9QlkNG;vcHxSTIH^"9OVL Xrr7 kL%j1Bs& gZ]]"reAm2Q(/ }Z *bd-NaP7L)MT7r<{eE.\O:2k2 ?{ !MS"AY5 8dEPj@B60Jl\8F O;~uPTdr|$!gWr HOzc$%o\T 3 D`y3\aE4aZ 4JG8AB)|-+~n/"ZZ.iU@Hx*do9W4.O8 =6=Q'?n *9M:4'oD.&Z9DQ\D[KWb '4iRfHjN.Tsi8: JsgX6k+ (Y$_x3+V~[s,ZQP,YT_T$}SKi`(K'U.o$:DFbd#-#EnyfHR6,f : 7$tBZAo-Tvpq .~^Dz[\"PoT*]R 6zf)tz!I!/}fE8X+t7{#@F v$K_' ^{t!M9bv TL +HC1NLyD| P!N\FV[|T^nonAZ 'cU#3-^X_l.4U "iIMx+;! 0N\h`pHM)u6$-]VgokN`zlN^?)XSOs6*$;S 19s?,00,@~50"N9&4b4gbS_Ij GZ9`G6'*X :F rSo>P $K\g[ 0+ 8ag HhC 4N8@KE Mt8/DojUz4&|*DC5v uC >%Q 3A^;7AAujT?O ]q7GA JbE%M<t D_H#Rcz3+Ca"?@}oX^]]CwO>fp5r)~*(~M6|r@H^9d sfo/~2J?VW;_&xwK$Ic{/JOFxCape?nXR "}oU>nmj(%X^JY3 x)W4jBM ;^^K!YW8}c/.bjA]I2}& 8LgO[ tE"QBCKS4F_G;RvQ>u~J4 %JsT[wCIuY_\zvr8WEJ@L>h4_nstz*qg Z_!@D@I<4npW;[^QPqaDDDh ]x%`oP G0DVYI8i>\(@"M2+<b=$qg(e7 yrALk)lSu}kA[N{\JoT"vDJA^^;JQ-&Yep  =$t}E&Q1W4J.kQ^GFk0v@_] Mon5-?Ff+tWlEH@T'LB\O3qDz*~d3QY8{grozyMCqO 9Wm`D9#\QSR*)7G bX-OlLDtJ2KC2#&2+PqEN\Tp[Tt .E=f#K){p:2fqWHEX@ s]x jBU4).5rW/XR&RU^6{S$2ftKLVJpmLjwwT-.;azZl9 7u@>h\cO1wL`@W  hKu>pZK"@GY uhb;"YD> !Oy8~b{B LpV!.psoH& O+E{7tct  cSKUI+/TH ~9fr`X"7Ct6+O%Ty-2`4h64Y1Xy6+jL+BU1+>-x470=mn.K_ Chtewgdg!6|x}'5NO#>bp>%av=VZ) m$[i,NVvH.-"``L|qS;npbOe-Fm69KPVY?2H1A@)B[ 0DaH6:n&a_*MpywI8X d:Yxx!%P\(1fv?q;G@E Z7MiR\Eye@qM7hM<1E. #cPJgWHX+LH%3hHrqCf_V^z]s_5v qYuU3Y i yd[K.{ 9Zk XN 0X%Z{x$lB7:2Uy gS[P1y#XjM}!kM#oUN4Tr@A[1 %`uIifbA@= VxZ>sDQHYFNU?X[#rVech79aO'3tQ ?h"7INu U;lJl;jM|CbhJu@2G$w6,Kn4=MnZ\2Fj=HA_^d}./d>A9\Fh6zB'to'qLHD[>eS]a9-mvY Yy||R_Uc9sw_%zu{r1%jJ6sNPrSY2AEQ,+p`;gW:8:bv_ NGbJ6!k}* W !,*8d=VY &a6ECYVEa8."Ma&sKwKy; Fk#u;~/$#{IPc1FR?T ) B[G+ gdHJ"3d UNZIP.BCKS4 [UNZIP542.AOSVS]AOSVS.C;1bP! /* force stop of loop: */ ef_len = (ebLen + EB_HEADSIZE); break; } /* else: fall through! */ case EF_PKVMS: /* "found nondecypherable e.f. with perm. attr" */ r = TRUE; default: break; } ef_len -= (ebLen + EB_HEADSIZE); ef += (ebLen + EB_HEADSIZE); } if (!r) return 0; } /* fall through! */ /* all remaining cases: expand MSDOS read-only bit into write perms */ case FS_FAT_: /* PKWARE's PKZip for Unix marks entries as FS_FAT_, but stores the * Unix attributes in the upper 16 bits of the external attributes * field, just like Info-ZIP's Zip for Unix. We try to use that * value, after a check for consistency with the MSDOS attribute * bits (see below). */ G.pInfo->file_attr = (unsigned)(tmp >> 16); /* fall through! */ case FS_HPFS_: case FS_NTFS_: case MAC_: case TOPS20_: default: /* Ensure that DOS subdir bit is set when the entry's name ends * in a '/'. Some third-party Zip programs fail to set the subdir * bit for directory entries. */ if ((tmp | 0x10) == 0) { extent fnlen = strlen(G.filename); if (fnlen > 0 && G.filename[fnlen-1] == '/') tmp |= 0x10; } /* read-only bit --> write perms; subdir bit --> dir exec bit */ tmp = !(tmp & 1) << 1 | (tmp & 0x10) >> 4; if ((G.pInfo->file_attr & 0700) == (unsigned)(0400 | tmp<<6)) /* keep previous G.pInfo->file_attr setting, when its "owner" * part appears to be consistent with DOS attribute flags! */ return 0; G.pInfo->file_attr = (unsigned)(0444 | tmp<<6 | tmp<<3 | tmp); break; } /* end switch (host-OS-created-by) */ /* for originating systems with no concept of "group," "other," "system": */ umask( (int)(tmp=umask(0)) ); /* apply mask to expanded r/w(/x) perms */ G.pInfo->file_attr &= ~tmp; return 0; } /* end function mapattr() */ /************************/ /* Function mapname() */ /************************/ /* return 0 if no error, 1 if caution (filename */ int mapname(__G__ renamed) /* truncated), 2 if warning (skip file because */ __GDEF /* dir doesn't exist), 3 if error (skip file), */ int renamed; /* or 10 if out of memory (skip file) */ { /* [also IZ_VOL_LABEL, IZ_CREATED_DIR] */ char pathcomp[FILNAMSIZ]; /* path-component buffer */ char *pp, *cp=(char *)NULL; /* character pointers */ char *lastsemi=(char *)NULL; /* pointer to last semi-colon in pathcomp */ int quote = FALSE; /* flags */ int error = 0; register unsigned workch; /* hold the character being tested */ /*--------------------------------------------------------------------------- Initialize various pointers and counters and stuff. ---------------------------------------------------------------------------*/ if (G.pInfo->vollabel) return IZ_VOL_LABEL; /* can't set disk volume labels in Unix */ /* can create path as long as not just freshening, or if user told us */ G.create_dirs = (!uO.fflag || renamed); created_dir = FALSE; /* not yet */ /* user gave full pathname: don't prepend rootpath */ renamed_fullpath = (renamed && (*G.filename == '/')); if (checkdir(__G__ (char *)NULL, INIT) == 10) return 10; /* initialize path buffer, unless no memory */ *pathcomp = '\0'; /* initialize translation buffer */ pp = pathcomp; /* point to translation buffer */ if (uO.jflag) /* junking directories */ cp = (char *)strrchr(G.filename, '/'); if (cp == (char *)NULL) /* no '/' or not junking dirs */ cp = G.filename; /* point to internal zipfile-member pathname */ else ++cp; /* point to start of last component of path */ /*--------------------------------------------------------------------------- Begin main loop through characters in filename. ---------------------------------------------------------------------------*/ while ((workch = (uch)*cp++) != 0) { if (quote) { /* if character quoted, */ *pp++ = (char)workch; /* include it literally */ quote = FALSE; } else switch (workch) { case '/': /* can assume -j flag not given */ *pp = '\0'; if ((error = checkdir(__G__ pathcomp, APPEND_DIR)) > 1) return error; pp = pathcomp; /* reset conversion buffer for next piece */ lastsemi = (char *)NULL; /* leave directory semi-colons alone */ break; case ';': /* VMS version (or DEC-20 attrib?) */ lastsemi = pp; *pp++ = ';'; /* keep for now; remove VMS ";##" */ break; /* later, if requested */ case '\026': /* control-V quote for special chars */ quote = TRUE; /* set flag for next character */ break; #ifdef MTS case ' ': /* change spaces to underscore under */ *pp++ = '_'; /* MTS; leave as spaces under Unix */ break; #endif default: /* allow European characters in filenames: */ if (isprint(workch) || (128 <= workch && workch <= 254)) *pp++ = (char)workch; } /* end switch */ } /* end while loop */ *pp = '\0'; /* done with pathcomp: terminate it */ /* if not saving them, remove VMS version numbers (appended ";###") */ if (!uO.V_flag && lastsemi) { pp = lastsemi + 1; while (isdigit((uch)(*pp))) ++pp; if (*pp == '\0') /* only digits between ';' and end: nuke */ *lastsemi = '\0'; } /*--------------------------------------------------------------------------- Report if directory was created (and no file to create: filename ended in '/'), check name to be sure it exists, and combine path and name be- fore exiting. ---------------------------------------------------------------------------*/ if (G.filename[strlen(G.filename) - 1] == '/') { checkdir(__G__ G.filename, GETPATH); if (created_dir) { if (QCOND2) { Info(slide, 0, ((char *)slide, " creating: %s\n", G.filename)); } return IZ_CREATED_DIR; /* set dir time (note trailing '/') */ } return 2; /* dir existed already; don't look for data to extract */ } if (*pathcomp == '\0') { Info(slide, 1, ((char *)slide, "mapname: conversion of %s failed\n", G.filename)); return 3; } checkdir(__G__ pathcomp, APPEND_NAME); /* returns 1 if truncated: care? */ checkdir(__G__ G.filename, GETPATH); return error; } /* end function mapname() */ #e] UNZIP.BCKS4 [UNZIP542.AOSVS]AOSVS.C;1b 0 #if 0 /*========== NOTES ==========*/ extract-to dir: a:path/ buildpath: path1/path2/ ... (NULL-terminated) pathcomp: filename mapname(): loop over chars in zipfile member name checkdir(path component, COMPONENT | CREATEDIR) --> map as required? (d:/tmp/unzip/) (disk:[tmp.unzip.) (d:/tmp/unzip/jj/) (disk:[tmp.unzip.jj.) (d:/tmp/unzip/jj/temp/) (disk:[tmp.unzip.jj.temp.) finally add filename itself and check for existence? (could use with rename) (d:/tmp/unzip/jj/temp/msg.outdir) (disk:[tmp.unzip.jj.temp]msg.outdir) checkdir(name, GETPATH) --> copy path to name and free space #endif /* 0 */ /***********************/ /* Function checkdir() */ /***********************/ int checkdir(__G__ pathcomp, flag) __GDEF char *pathcomp; int flag; /* * returns: 1 - (on APPEND_NAME) truncated filename * 2 - path doesn't exist, not allowed to create * 3 - path doesn't exist, tried to create and failed; or * path exists and is not a directory, but is supposed to be * 4 - path is too long * 10 - can't allocate memory for filename buffers */ { static int rootlen = 0; /* length of rootpath */ static char *rootpath; /* user's "extract-to" directory */ static char *buildpath; /* full path (so far) to extracted file */ static char *end; /* pointer to end of buildpath ('\0') */ # define FN_MASK 7 # define FUNCTION (flag & FN_MASK) /*--------------------------------------------------------------------------- APPEND_DIR: append the path component to the path being built and check for its existence. If doesn't exist and we are creating directories, do so for this one; else signal success or error as appropriate. ---------------------------------------------------------------------------*/ if (FUNCTION == APPEND_DIR) { int too_long = FALSE; #ifdef SHORT_NAMES char *old_end = end; #endif Trace((stderr, "appending dir segment [%s]\n", pathcomp)); while ((*end = *pathcomp++) != '\0') ++end; #ifdef SHORT_NAMES /* path components restricted to 14 chars, typically */ if ((end-old_end) > FILENAME_MAX) /* GRR: proper constant? */ *(end = old_end + FILENAME_MAX) = '\0'; #endif /* GRR: could do better check, see if overrunning buffer as we go: * check end-buildpath after each append,5 set warning variable if * within 20 of FILNAMSIZ; then if var set, do careful check when * appending. Clear variable when begin new path. */ if ((end-buildpath) > FILNAMSIZ-3) /* need '/', one-char name, '\0' */ too_long = TRUE; /* check if extracting directory? */ /* for AOS/VS, try to create so as to not use searchlist: */ if ( /*stat(buildpath, &G.statbuf)*/ 1) { if (!G.create_dirs) { /* told not to create (freshening) */ free(buildpath); return 2; /* path doesn't exist: nothing to do */ } if (too_long) { Info(slide, 1, ((char *)slide, "checkdir error: path too long: %s\n", buildpath)); free(buildpath); return 4; /* no room for filenames: fatal */ } /* create the directory */ if (zvs_credir(buildpath,-1L,-1L,-1L,(char *) -1,-1,0L,-1,-1) == -1) { Info(slide, 1, ((char *)slide, "checkdir error: cannot create %s\n\ unable to process %s.\n", buildpath, G.filename)); free(buildpath); return 3; /* path didn't exist, tried to create, failed */ } created_dir = TRUE; } else if (!S_ISDIR(G.statbuf.st_mode)) { Info(slide, 1, ((char *)slide, "checkdir error: %s exists but is not directory\n\ unable to process %s.\n", buildpath, G.filename)); free(buildpath); return 3; /* path existed but wasn't dir */ } if (too_long) { Info(slide, 1, ((char *)slide, "checkdir error: path too long: %s\n", buildpath)); free(buildpath); return 4; /* no room for filenames: fatal */ } *end++ = '/'; *end = '\0'; Trace((stderr, "buildpath now = [%s]\n", buildpath)); return 0; } /* end if (FUNCTION == APPEND_DIR) */ /*--------------------------------------------------------------------------- GETPATH: copy full path to the string pointed at by pathcomp, and free buildpath. ---------------------------------------------------------------------------*/ if (FUNCTION == GETPATH) { strcpy(pathcomp, buildpath); Trace((stderr, "getting and freeing path [%s]\n", pathcomp)); free(buildpath); buildpath = end = (char *)NULL; return 0; } /*--------------------------------------------------------------------------- APPEND_NAME: assume the path component is the filename; append it and return without checking for existence. ---------------------------------------------------------------------------*/ if (FUNCTION == APPEND_NAME) { #ifdef SHORT_NAMES char *old_end = end; #endif Trace((stderr, "appending filename [%s]\n", pathcomp)); while ((*end = *pathcomp++) != '\0') { ++end; #ifdef SHORT_NAMES /* truncate name at 14 characters, typically */ if ((end-old_end) > FILENAME_MAX) /* GRR: proper constant? */ *(end = old_end + FILENAME_MAX) = '\0'; #endif if ((end-buildpath) >= FILNAMSIZ) { *--end = '\0'; Info(slide, 1, ((char *)slide, "checkdir warning: path too long; truncating\n\ %s\n -> %s\n", G.filename, buildpath)); return 1; /* filename truncated */ } } Trace((stderr, "buildpath now = [%s]\n", buildpath)); return 0; /* could check for existence here, prompt for new name... */ } /*--------------------------------------------------------------------------- INIT: allocate and initialize buffer space for the file currently being extracted. If file was renamed with an absolute path, don't prepend the extract-to path. ---------------------------------------------------------------------------*/ /* GRR: for VMS and TOPS-20, add up to 13 to strlen */ if (FUNCTION == INIT) { Trace((stderr, "initializing buildpath to ")); if ((buildpath = (char *)malloc(strlen(G.filename)+rootlen+1)) == (char *)NULL) return 10; if ((rootlen > 0) && !renamed_fullpath) { strcpy(buildpath, rootpath); end = buildpath + rootlen; } else { *buildpath = '\0'; end = buildpath; } Trace((stderr, "[%s]\n", buildpath)); return 0; } /*--------------------------------------------------------------------------- ROOT: if appropriate, store the path in rootpath and create it if neces- sary; else assume it's a zipfile member and return. This path segment gets used in extracting all members from every zipfile specified on the command line. ---------------------------------------------------------------------------*/ #if (!defined(SFX) || defined(SFX_EXDIR)) if (FUNCTION ==$Htv UNZIP.BCKS4 [UNZIP542.AOSVS]AOSVS.C;1b? ROOT) { Trace((stderr, "initializing root path to [%s]\n", pathcomp)); if (pathcomp == (char *)NULL) { rootlen = 0; return 0; } if (rootlen > 0) /* rootpath was already set, nothing to do */ return 0; if ((rootlen = strlen(pathcomp)) > 0) { char *tmproot; if ((tmproot = (char *)malloc(rootlen+2)) == (char *)NULL) { rootlen = 0; return 10; } strcpy(tmproot, pathcomp); if (tmproot[rootlen-1] == '/') { tmproot[--rootlen] = '\0'; } if (rootlen > 0 && (stat(tmproot, &G.statbuf) || !S_ISDIR(G.statbuf.st_mode))) /* path does not exist */ { if (!G.create_dirs /* || iswild(tmproot) */ ) { free(tmproot); rootlen = 0; return 2; /* skip (or treat as stored file) */ } /* create the directory (could add loop here scanning tmproot * to create more than one level, but why really necessary?) */ if (zvs_credir(tmproot,-1L,-1L,-1L,(char *) -1,-1,0L,-1,-1) == -1) { Info(slide, 1, ((char *)slide, "checkdir: cannot create extraction directory: %s\n", tmproot)); free(tmproot); rootlen = 0; /* path didn't exist, tried to create, and */ return 3; /* failed: file exists, or 2+ levels required */ } } tmproot[rootlen++] = '/'; tmproot[rootlen] = '\0'; if ((rootpath = (char *)realloc(tmproot, rootlen+1)) == NULL) { free(tmproot); rootlen = 0; return 10; } Trace((stderr, "rootpath now = [%s]\n", rootpath)); } return 0; } #endif /* !SFX || SFX_EXDIR */ /*--------------------------------------------------------------------------- END: free rootpath, immediately prior to program exit. ---------------------------------------------------------------------------*/ if (FUNCTION == END) { Trace((stderr, "freeing rootpath\n")); if (rootlen > 0) { free(rootpath); rootlen = 0; } return 0; } return 99; /* should never reach */ } /* end function checkdir() */ /****************************/ /* Function close_outfile() */ /****************************/ void close_outfile(__G) /* GRR: change to return PK-style warning level */ __GDEF { /*--------------------------------------------------------------------------- If symbolic links are supported, allocate a storage area, put the uncom- pressed "data" in it, and create the link. Since we know it's a symbolic link to start with, we shouldn't have to worry about overflowing unsigned ints with unsigned longs. ---------------------------------------------------------------------------*/ #ifdef SYMLINKS if (G.symlnk) { unsigned ucsize = (unsigned)G.lrec.ucsize; char *linktarget = (char *)malloc((unsigned)G.lrec.ucsize+1); fclose(G.outfile); /* close "data" file... */ G.outfile = fopen(G.filename, FOPR); /* ...and reopen for reading */ if (!linktarget || fread(linktarget, 1, ucsize, G.outfile) != (int)ucsize) { Info(slide, 0x201, ((char *)slide, "warning: symbolic link (%s) failed\n", G.filename)); if (linktarget) free(linktarget); fclose(G.outfile); return; } fclose(G.outfile); /* close "data" file for good... */ unlink(G.filename); /* ...and delete it */ linktarget[ucsize] = '\0'; if (QCOND2) Info(slide, 0, ((char *)slide, "-> %s ", linktarget)); if (symlink(linktarget, G.filename)) /* create the real link */ perror("symlink error"); free(linktarget); return; /* can't set time on symlinks */ } #endif /* SYMLINKS */ fclose(G.outfile); /*--------------------------------------------------------------------------- Change the file permissions from default ones to those stored in the zipfile. ---------------------------------------------------------------------------*/ #ifndef NO_CHMOD if (chmod(G.filename, 0xffff & G.pInfo->file_attr)) perror("chmod (file attributes) error"); #endif /*--------------------------------------------------------------------------- AOS/VS only allows setting file times at creation but has its own permis- sions scheme which is better invoked here if the necessary information was in fact stored. In theory, we should look through an entire series of extra fields that might exist for the same file, but we're not going to bother. If we set up other types of extra fields, or if we run into other environments that add their own stuff to existing entries in ZIP files, we'll have to. NOTE: already copied extra-field stuff into zzextrafld structure when file was created. ---------------------------------------------------------------------------*/ if (G.extra_field != NULL) { if (!memcmp(ZEXTRA_HEADID, zzextrafld.extra_header_id, sizeof(zzextrafld.extra_header_id)) && !memcmp(ZEXTRA_SENTINEL, zzextrafld.extra_sentinel, sizeof(zzextrafld.extra_sentinel)) && zzextrafld.fstat_packet.norm_fstat_packet.styp_type != $FLNK) /* (AOS/VS links don't have ACLs) */ { /* vs_path was set (in this case) when we created the file */ if (sys_sacl(vs_path, zzextrafld.aclbuf)) { Info(slide, 0x201, ((char *)slide, "error: cannot set ACL for %s\n", G.filename)); perror("sys_sacl()"); } } } } /* end function close_outfile() */ #ifndef SFX /************************/ /* Function version() */ /************************/ void version(__G) __GDEF { #if defined(CRAY) || defined(NX_CURRENT_COMPILER_RELEASE) || defined(NetBSD) char buf1[40]; #if defined(CRAY) || defined(NX_CURRENT_COMPILER_RELEASE) char buf2[40]; #endif #endif /* Pyramid, NeXT have problems with huge macro expansion, too: no Info() */ sprintf((char *)slide, LoadFarString(CompiledWith), #ifdef __GNUC__ # ifdef NX_CURRENT_COMPILER_RELEASE (sprintf(buf1, "NeXT DevKit %d.%02d ", NX_CURRENT_COMPILER_RELEASE/100, NX_CURRENT_COMPILER_RELEASE%100), buf1), (strlen(__VERSION__) > 8)? "(gcc)" : (sprintf(buf2, "(gcc %s)", __VERSION__), buf2), # else "gcc ", __VERSION__, # endif #else # if defined(CRAY) && defined(_RELEASE) "cc ", (sprintf(buf1, "version %d", _RELEASE), buf1), # else # ifdef __VERSION__ "cc ", __VERSION__, # else "cc", "", # endif # endif #endif "Unix", #if defined(sgi) || defined(__sgi) " (Silicon Graphics IRIX)", #else #ifdef sun # ifdef sparc # ifdef __SVR4 " (Sun Sparc/Solaris)", # else /* may or may not be SunOS */ " (Sun Sparc)", # endif # else # if defined(sun386) || defined(i386) " (Sun 386i)", # else # if defined(mc68020) || defined(__mc68020__) " (Sun 3)", # else /* mc68010 or mc68000: Sun 2 or earlier */ " (Sun 2)", # endi%a UNZIP.BCKS4 [UNZIP542.AOSVS]AOSVS.C;1b]\Nf # endif # endif #else #ifdef __hpux " (HP/UX)", #else #ifdef __osf__ " (DEC OSF/1)", #else #ifdef _AIX " (IBM AIX)", #else #ifdef aiws " (IBM RT/AIX)", #else #if defined(CRAY) || defined(cray) # ifdef _UNICOS (sprintf(buf2, " (Cray UNICOS release %d)", _UNICOS), buf2), # else " (Cray UNICOS)", # endif #else #if defined(uts) || defined(UTS) " (Amdahl UTS)", #else #ifdef NeXT # ifdef mc68000 " (NeXTStep/black)", # else " (NeXTStep for Intel)", # endif #else /* the next dozen or so are somewhat order-dependent */ #ifdef LINUX # ifdef __ELF__ " (Linux ELF)", # else " (Linux a.out)", # endif #else #ifdef MINIX " (Minix)", #else #ifdef M_UNIX " (SCO Unix)", #else #ifdef M_XENIX " (SCO Xenix)", #else #ifdef __NetBSD__ # ifdef NetBSD0_8 (sprintf(buf1, " (NetBSD 0.8%c)", (char)(NetBSD0_8 - 1 + 'A')), buf1), # else # ifdef NetBSD0_9 (sprintf(buf1, " (NetBSD 0.9%c)", (char)(NetBSD0_9 - 1 + 'A')), buf1), # else # ifdef NetBSD1_0 (sprintf(buf1, " (NetBSD 1.0%c)", (char)(NetBSD1_0 - 1 + 'A')), buf1), # else (BSD4_4 == 0.5)? " (NetBSD before 0.9)" : " (NetBSD 1.1 or later)", # endif # endif # endif #else #ifdef __FreeBSD__ (BSD4_4 == 0.5)? " (FreeBSD 1.x)" : " (FreeBSD 2.0 or later)", #else #ifdef __bsdi__ (BSD4_4 == 0.5)? " (BSD/386 1.0)" : " (BSD/386 1.1 or later)", #else #ifdef __386BSD__ (BSD4_4 == 1)? " (386BSD, post-4.4 release)" : " (386BSD)", #else #if defined(i486) || defined(__i486) || defined(__i486__) " (Intel 486)", #else #if defined(i386) || defined(__i386) || defined(__i386__) " (Intel 386)", #else #ifdef pyr " (Pyramid)", #else #ifdef ultrix # ifdef mips " (DEC/MIPS)", # else # ifdef vax " (DEC/VAX)", # else /* __alpha? */ " (DEC/Alpha)", # endif # endif #else #ifdef gould " (Gould)", #else #ifdef MTS " (MTS)", #else #ifdef __convexc__ " (Convex)", #else "", #endif /* Convex */ #endif /* MTS */ #endif /* Gould */ #endif /* DEC */ #endif /* Pyramid */ #endif /* 386 */ #endif /* 486 */ #endif /* 386BSD */ #endif /* BSDI BSD/386 */ #endif /* NetBSD */ #endif /* FreeBSD */ #endif /* SCO Xenix */ #endif /* SCO Unix */ #endif /* Minix */ #endif /* Linux */ #endif /* NeXT */ #endif /* Amdahl */ #endif /* Cray */ #endif /* RT/AIX */ #endif /* AIX */ #endif /* OSF/1 */ #endif /* HP/UX */ #endif /* Sun */ #endif /* SGI */ #ifdef __DATE__ " on ", __DATE__ #else "", "" #endif ); (*G.message)((zvoid *)&G, slide, (ulg)strlen((char *)slide), 0); } /* end function version() */ #endif /* !SFX */ /* =================================================================== * ZVS_CREATE() * Function to create a file with specified times. The times should be sent * as long ints in DG time format; use -1 to set to the current times. You * may also specify a pointer to the ACL, the file type (see PARU.H, and do * not specify dirs or links), the element size, and the max index level. * For all of these parameters you may use -1 to specify the default. * * Returns 0 if no error, or the error code returned by ?CREATE. * * HISTORY: * 15-dec-93 dbl * 31-may-94 dbl: added call to convert pathname to AOS/VS * * */ int zvs_create(ZCONST char *fname, long cretim, long modtim, long acctim, char *pacl, int ftyp, int eltsize, int maxindlev) { P_CREATE pcr_stru; P_CTIM pct_stru; pcr_stru.cftyp_format = 0; /* unspecified record format */ if (ftyp == -1) /* default file type to UNX */ pcr_stru.cftyp_entry = $FUNX; else pcr_stru.cftyp_entry = ftyp; pcr_stru.ctim = &pct_stru; pcr_stru.cacp = pacl; pcr_stru.cdel = eltsize; pcr_stru.cmil = maxindlev; pct_stru.tcth.long_time = cretim; pct_stru.tath.long_time = acctim; pct_stru.tmth.long_time = modtim; return (sys_create(ux_to_vs_name(Vs_path, fname), &pcr_stru)); } /* end zvs_create() */ /* =================================================================== * ZVS_CREDIR() * Function to create a dir as specified. The times should be sent * as long ints in DG time format; use -1 to set to the current times. You * may also specify a pointer to the ACL, the file type (either $FDIR or $FCPD; see PARU.H), * the max # blocks (if a CPD), the hash frame size, and the max index level. * For all of these parameters (except for the CPD's maximum blocks), * you may use -1 to specify the default. * * (The System Call Dictionary says both that you may specify a * maximum-index-level value up to the maximum, with 0 for a contiguous * directory, and that 3 is always used for this whatever you specify.) * * If you specify anything other than CPD for the file type, DIR will * be used. * * Returns 0 if no error, or the error code returned by ?CREATE. * * HISTORY: * 1-jun-94 dbl * * */ int zvs_credir(ZCONST char *dname, long cretim, long modtim, long acctim, char *pacl, int ftyp, long maxblocks, int hashfsize, int maxindlev) { P_CREATE_DIR pcr_stru; P_CTIM pct_stru; if (ftyp != $FCPD) /* default file type to UNX */ pcr_stru.cftyp_entry = $FDIR; else { pcr_stru.cftyp_entry = ftyp; pcr_stru.cmsh = maxblocks; } pcr_stru.ctim = &pct_stru; pcr_stru.cacp = pacl; pcr_stru.chfs = hashfsize; pcr_stru.cmil = maxindlev; pct_stru.tcth.long_time = cretim; pct_stru.tath.long_time = acctim; pct_stru.tmth.long_time = modtim; return (sys_create(ux_to_vs_name(Vs_path, dname), &pcr_stru)); } /* end zvs_credir() */ /* =================================================================== * UX_TO_VS_NAME() - makes a somewhat dumb pass at converting a Unix * filename to an AOS/VS filename. This should * be just about adequate to handle the results * of similarly-simple AOS/VS-to-Unix conversions * in the ZIP program. It does not guarantee a * legal AOS/VS filename for every Unix filename; * conspicuous examples would be names with * embedded ./ and ../ (which will receive no * special treatment). * * RETURNS: pointer to the result (which is an input parameter) * * NOTE: calling code is responsible for making sure * the output buffer is big enough! * * HISTORY: * 31-may-94 dbl * */ char *ux_to_vs_name(char *outname, ZCONST char *inname) { ZCONST char *ip=inname, *op=outname; if (ip[0] == '.') { if (ip[1] == '/') { *(op++) = '='; ip += 2; } else if (ip[1] == '.' && ip[2] == '/') { *(op++) = '^'; ip += 3; } } do { if (*ip == '/') *(op++) = ':'; else if (strchr( "0123456789_$?.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", *ip) != NULL) { *(op++) = *ip; } else *(op++) = '?'; } while (*(ip++) != '\0'); return outname; } /* end ux_to_vs_name() */ /* =================================================================== */ /* DGDATE Two functions do encode/decode dates in DG system format. Usage: long value,year,month,day; value=dgdate(month,day,year); undgdate(value,&month,&day,&year); [GRR: not used in UnZip: removed] Notes: 1. DG date functions only work on dates within the range Jan 1, 1968 through Dec 31, 2099. &Zu$ UNZIP.BCKS4 [UNZIP542.AOSVS]AOSVS.C;1b ]I have tested these functions through the same range with exact agreement. For dates outside of that range, the DG system calls may return different values than these functions. 2. dgundate() accepts values between 0 and 48213 inclusive. These correspond to 12/31/1967 and 12/31/2099. 3. Both functions assume the data is in the native OS byte order. So if you're reading or writing these fields from a file that has been passed between AOS/VS and PC-DOS you will need to swap byte order. 4. With reference to byte order, the entire range of values supported by these functions will fit into an unsigned short int. In most cases the input or output will be in that variable type. You are better off casting the value to/from unsigned short so you only need to concern yourself with swapping two bytes instead of four. Written by: Stanley J. Gula US&T, Inc. 529 Main Street, Suite 1 Indian Orchard, MA 01151 (413)-543-3672 Copyright (c) 1990 US&T, Inc. All rights reserved. I hereby release these functions into the public domain. You may use these routines freely as long as the US&T copyright remains intact in the source code. Stanley J. Gula July 24, 1990 */ long motable[13]={0,31,59,90,120,151,181,212,243,273,304,334,365}; long yrtable[132]={ 366, 731, 1096, 1461, 1827, 2192, 2557, 2922, 3288, 3653, 4018, 4383, 4749, 5114, 5479, 5844, 6210, 6575, 6940, 7305, 7671, 8036, 8401, 8766, 9132, 9497, 9862,10227,10593,10958, 11323,11688,12054,12419,12784,13149,13515,13880,14245,14610, 14976,15341,15706,16071,16437,16802,17167,17532,17898,18263, 18628,18993,19359,19724,20089,20454,20820,21185,21550,21915, 22281,22646,23011,23376,23742,24107,24472,24837,25203,25568, 25933,26298,26664,27029,27394,27759,28125,28490,28855,29220, 29586,29951,30316,30681,31047,31412,31777,32142,32508,32873, 33238,33603,33969,34334,34699,35064,35430,35795,36160,36525, 36891,37256,37621,37986,38352,38717,39082,39447,39813,40178, 40543,40908,41274,41639,42004,42369,42735,43100,43465,43830, 44196,44561,44926,45291,45657,46022,46387,46752,47118,47483, 47848,48213}; /* Given y,m,d return # of days since 12/31/67 */ long int dgdate(short mm, short dd, short yy) { long int temp; short ytmp; if (mm<1 || mm>12 || dd<1 || dd>31 || yy<1968 || yy>2099) return 0L; /* Figure in whole years since 1968 + whole months plus days */ temp=365L*(long)(yy-1968) + motable[mm-1] + (long)dd; /* Adjust for leap years - note we don't account for skipped leap year in years divisible by 1000 but not by 4000. We're correct through the year 2099 */ temp+=(yy-1965)/4; /* Correct for this year */ /* In leap years, if date is 3/1 or later, bump */ if ((yy%4==0) && (mm>2)) temp++; return temp; } *[UNZIP542.AOSVS]AOSVS.H;1+,VO./ 4- 0@123KPWO56 7 89GHJ /* Copyright (c) 1990-2000 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*--------------------------------------------------------------------------- aosvs.h AOS/VS-specific header file for use with Info-ZIP's UnZip 5.2 and later. ---------------------------------------------------------------------------*/ /* stuff to set up for system calls (?FSTAT & ?SACL) and the extra field */ #include /* parameter definitions */ #include /* AOS/VS ?FSTAT packet defs */ #include /* AOS/VS ?CREATE packet defs */ #include /* AOS/VS system call interface */ #define ZEXTRA_HEADID "VS" #define ZEXTRA_SENTINEL "FCI" #define ZEXTRA_REV ((uch)10) /* change/use this in later revs */ /* functions defined in zvs_create.c */ extern int zvs_create(ZCONST char *fname, long cretim, long modtim, long acctim, char *pacl, int ftyp, int eltsize, int maxindlev); extern int zvs_credir(ZCONST char *dname, long cretim, long modtim, long acctim, char *pacl, int ftyp, long maxblocks, int hashfsize, int maxindlev); extern long dgdate(short mm, short dd, short yy); extern char *ux_to_vs_name(char *outname, ZCONST char *inname); /* could probably avoid the unions - all elements in each one are the same * size, and we're going to assume this */ typedef union zvsfstat_stru { P_FSTAT norm_fstat_packet; /* normal fstat packet */ P_FSTAT_DIR dir_fstat_packet; /* DIR/CPD fstat packet */ P_FSTAT_UNIT unit_fstat_packet; /* unit (device) fstat packet */ P_FSTAT_IPC ipc_fstat_packet; /* IPC file fstat packet */ } ZVSFSTAT_STRU; typedef union zvscreate_stru { P_CREATE norm_create_packet; /* normal create packet */ P_CREATE_DIR dir_create_packet; /* DIR/CPD create packet */ P_CREATE_IPC ipc_create_packet; /* IPC file create packet */ } ZVSCREATE_STRU; typedef struct zextrafld { char extra_header_id[2]; /* set to VS - in theory, an int */ char extra_data_size[2]; /* size of rest (little-endian) */ char extra_sentinel[4]; /* set to FCI w/ trailing null */ uch extra_rev; /* set to 10 for rev 1.0 */ ZVSFSTAT_STRU fstat_packet; /* the fstat packet */ char aclbuf[$MXACL]; /* the raw ACL */ } ZEXTRAFLD; *[UNZIP542.AOSVS]CONTENTS.;1+,6X./ 4@- 0@123KPWO56?27?289GHJContents of the "aosvs" subdirectory for UnZip 5.3 and later: Contents this file README compilation notes, history, etc. make_unz.cli command script to make UnZip only (not UnZipSFX or fUnZip) aosvs.c AOS/VS-specific support routines aosvs.h AOS/VS-specific typedefs and header stuff *[UNZIP542.AOSVS]MAKE_UNZ.CLI;1+,_./ 4;- 0@123KPWO56bܙ7bܙ89GHJ'f$ UNZIP.BCK_ [UNZIP542.AOSVS]MAKE_UNZ.CLI;1Wpush prompt pop searchlist :c_4.10 :c_4.10:lang_rt [!searchlist] cc/link/NOUNX/NOSEA SYSV/DEFINE TERMIO/DEFINE AOS_VS/DEFINE=1 PROTO/DEFINE S_IFLNK/DEFINE=0120000 TIME.H/INCLUDE .c pop i*[UNZIP542.AOSVS]README.;1+,R[./ 4- 0@123KPWO56˸7˸89GHJ[e-mail excerpt from Dave Lovelace explaining AOS/VS port, compiler, etc.] > From: Dave Lovelace > Subject: Re: zip on Data General AOS/VS > Date: Wed, 17 May 1995 11:02:03 -0400 (EDT) > > The diffs for zip & unzip are both in the same file. I've also included the > extra source files which I wrote, the CLI macros which I used to compile > & link the things, & my own history of what I did. Note that some of the > changes I made reversed earlier changes, & this was written for my own > use (or for others here if I leave or die or something). I hope it will help. > > This was compiled using DG's C compiler for AOS/VS, rev 4.10. It has been > compiled only on an MV-5500 running AOS/VS rev 7.70, but the resulting > programs have been distributed & run on several different MVs running various > versions of AOS/VS, so it should be fairly independent of at least minor rev > variations. To the best of my knowledge it has *not* been tested under > AOS/VS II, & I really don't know anything about that environment; possibly > the special AOS/VS file info I'm storing in the extra field will have some > different format there. [README/history info from Dave Lovelace] In modifying this for use on AOS/VS, I found only a few changes were needed for DG C 4.10: 2. There was a bug in the inflate() code, because memset() was being called with a non-char pointer. Pretty obviously the other systems where this was used do not have char pointers different from other pointers. IT IS QUITE POSSIBLE THAT OTHER BUGS OF THIS SORT EXIST. Testing did not uncover any. 3. In fileio.c, it appears that utime() is being called correctly, but it does not set the file's time and always returns failure. Since the AOS/VS tar and cpio programs provided by DG also suffer from the fault of not setting file times, I must conclude that this is by design. At any rate, I modified the code (with compilation conditional on a macro AOS_VS) to not say "error" when this occurs. One change which I think would be desirable: if the filename isn't already a relative or absolute pathname (specifying a unique location), the program follows the searchlist under AOS/VS. It will unexpectedly replace files anywhere in your searchlist. (If you don't use the -o option, it will ask you first, but not tell you where the file to be replaced resides.) I suspect this could be handled by prepending ./ to any filenames which don't already begin with /. (I haven't checked how this would work inside the program. Possibly this could be done in every case - I don't think PKZIP ever stores an absolute pathname.) To see the compile options I used, look at the file MAKE.AOS_VS.CLI You may of course need to change the searchlist to use that macro. ------------------------------------------------------------------ 15-dec-93 I fixed some of the above things, introducing new problems. It now won't follow the searchlist - but the logic prevents it from creating directories (if they aren't explicitly in the ZIP, anyway). But UNZIP now sets the creation time to the time stored in the ZIP, and ZIP now stores that instead of the TLM. I had to introduce an extra module, with some code of my own and some other public domain code, to accomplish this. ------------------------------------------------------------------ 1-jun-94 I found an additional bug: the header was causing void to be #define'd as int, and prototypes weren't being used. I changed UNZIP.H and added a define of PROTO to the MAKE.AOS_VS.CLI and REMAKE.CLI macros. I found and fixed the bug that prevented the (creation) times from being set on files with explicit paths. (The Unix-style paths didn't work as inputs to the AOS/VS ?CREATE system call.) Additional known bugs: 1. I have not yet located the source of the bug that prevents the date/time from being set (also ACLs etc.) when an existing file is overwritten. For some reason the call to delete & recreate the file is not being reached. 2. We need to do something in ZIP to store (as comments?) the file's type and ACL, and then here in UNZIP extract these and apply them. This is not going to be trivial to make foolproof, but it's badly needed. ------------------------------------------------------------------ 2-jun-94 I fixed #1 above. The compiler was checking whether UNIX was defined, and it wasn't. It appears that *some* of the places UNIX is used are things we can't get along with, so I changed the code to check for AOS_VS as well. It seems to work just fine. I also introduced a function zvs_credir() to create a directory (as opposed to a CPD, though it can create CPDs to with the proper file-type parameter). Directories in a path which are being created will now be directories instead of CPDs. The big change that's needed now is to have ZIP store (somehow) the file's ACL and file type, and then to have UNZIP use this information to recreate the file as it was before ZIPping. Ideally, ZIP should also store links and CPD max-block info as well. Planned strategy: either in the name field but after the name, or in a comment, store the packet returned by ?FSTAT (using sys_fstat()), and then use this packet for the ?CREATE call in zvs_create(). ------------------------------------------------------------------ 22-Jul-94 The changes to use the extra-field field for AOS/VS file info are in place. In general, if a ZIPfile was created with the current rev of ZIP.PR, the files should be restored with file type, ACL, etc. OK. I didn't test to make sure element size & max index levels come through OK, but I think they should. Unix symbolic links are now UNZIPped OK, but ZIP.PR isn't yet able to ZIP links. When it is, UNZIP should be ready. In general UNZIP now ignores the searchlist fairly well, but not perfectly. If the directory of a file you're UNZIPping can be referenced elsewhere in the searchlist, UNZIP will find the file there. (For example, if the file UDD/BBASIC/ZZPGSUBSET.SR is in the ZIPfile, and : is in your searchlist, then UDD and UDD:BBASIC will be created under your current directory, but UNZIP will still find :UDD:BBASIC:ZZPGSUBSET.SR instead of =UDD:BBASIC:ZZPGSUBSET.SR. Filenames (which are now stored in uppercase by ZIP.PR) must be matched exactly if specified. This applies to Unix path structure as well as case. ------------------------------------------------------------------ 4-Aug-94 I fixed a bug which caused (for links only) the Unix pathname to be put through ux_to_vs_name twice. The result was that a path such as dir1/dir2/fname went first to (Rm UNZIP.BCKR[ [UNZIP542.AOSVS]README.;1 :dir1:dir2:fname and then to dir1?dir2?fname. I also added the /NOSEA switch to the cc/link lines in the macros MAKE.AOS_VS.CLI and REMAKE.CLI. This should prevent any confusion over whether a file exists somewhere other than relative to the current dir. This would disable calls to system() from using the searchlist, but in this program I think they're all useless & hopefully inactive anyway. ------------------------------------------------------------------ _*[UNZIP542]API.C;1+, ./ 44- 0@123KPWO 56789GHJ/* Copyright (c) 1990-2000 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*--------------------------------------------------------------------------- api.c This module supplies an UnZip engine for use directly from C/C++ programs. The functions are: UzpVer *UzpVersion(void); void UzpVersion2(UzpVer2 *version) int UzpMain(int argc, char *argv[]); int UzpAltMain(int argc, char *argv[], UzpInit *init); int UzpValidate(char *archive, int AllCodes); void UzpFreeMemBuffer(UzpBuffer *retstr); int UzpUnzipToMemory(char *zip, char *file, UzpOpts *optflgs, UzpCB *UsrFuncts, UzpBuffer *retstr); non-WINDLL only (a special WINDLL variant is defined in windll/windll.c): int UzpGrep(char *archive, char *file, char *pattern, int cmd, int SkipBin, UzpCB *UsrFuncts); OS/2 only (for now): int UzpFileTree(char *name, cbList(callBack), char *cpInclude[], char *cpExclude[]); You must define `DLL' in order to include the API extensions. ---------------------------------------------------------------------------*/ #ifdef OS2 # define INCL_DOSMEMMGR # include #endif #include #define UNZIP_INTERNAL #include "unzip.h" #ifdef WINDLL # include "windll/windll.h" #endif #include "version.h" #ifdef DLL /* This source file supplies DLL-only interface code. */ jmp_buf dll_error_return; /*--------------------------------------------------------------------------- Documented API entry points ---------------------------------------------------------------------------*/ UzpVer * UZ_EXP UzpVersion() /* should be pointer to const struct */ { static UzpVer version; /* doesn't change between calls */ version.structlen = UZPVER_LEN; #ifdef BETA version.flag = 1; #else version.flag = 0; #endif version.betalevel = UZ_BETALEVEL; version.date = UZ_VERSION_DATE; #ifdef ZLIB_VERSION version.zlib_version = ZLIB_VERSION; version.flag |= 2; #else version.zlib_version = NULL; #endif /* someday each of these may have a separate patchlevel: */ version.unzip.major = UZ_MAJORVER; version.unzip.minor = UZ_MINORVER; version.unzip.patchlevel = UZ_PATCHLEVEL; version.zipinfo.major = ZI_MAJORVER; version.zipinfo.minor = ZI_MINORVER; version.zipinfo.patchlevel = UZ_PATCHLEVEL; /* these are retained for backward compatibility only: */ version.os2dll.major = UZ_MAJORVER; version.os2dll.minor = UZ_MINORVER; version.os2dll.patchlevel = UZ_PATCHLEVEL; version.windll.major = UZ_MAJORVER; version.windll.minor = UZ_MINORVER; version.windll.patchlevel = UZ_PATCHLEVEL; return &version; } void UZ_EXP UzpVersion2(UzpVer2 *version) { version->structlen = UZPVER_LEN; #ifdef BETA version->flag = 1; #else version->flag = 0; #endif strcpy(version->betalevel, UZ_BETALEVEL); strcpy(version->date, UZ_VERSION_DATE); #ifdef ZLIB_VERSION strcpy(version->zlib_version, ZLIB_VERSION); version->flag |= 2; #else version->zlib_version[0] = '\0'; #endif /* someday each of these may have a separate patchlevel: */ version->unzip.major = UZ_MAJORVER; version->unzip.minor = UZ_MINORVER; version->unzip.patchlevel = UZ_PATCHLEVEL; version->zipinfo.major = ZI_MAJORVER; version->zipinfo.minor = ZI_MINORVER; version->zipinfo.patchlevel = UZ_PATCHLEVEL; /* these are retained for backward compatibility only: */ version->os2dll.major = UZ_MAJORVER; version->os2dll.minor = UZ_MINORVER; version->os2dll.patchlevel = UZ_PATCHLEVEL; version->windll.major = UZ_MAJORVER; version->windll.minor = UZ_MINORVER; version->windll.patchlevel = UZ_PATCHLEVEL; } #ifndef WINDLL int UZ_EXP UzpAltMain(int argc, char *argv[], UzpInit *init) { int r, (*dummyfn)(); CONSTRUCTGLOBALS(); if (init->structlen >= (sizeof(ulg) + sizeof(dummyfn)) && init->msgfn) G.message = init->msgfn; if (init->structlen >= (sizeof(ulg) + 2*sizeof(dummyfn)) && init->inputfn) G.input = init->inputfn; if (init->structlen >= (sizeof(ulg) + 3*sizeof(dummyfn)) && init->pausefn) G.mpause = init->pausefn; if (init->structlen >= (sizeof(ulg) + 4*sizeof(dummyfn)) && init->userfn) (*init->userfn)(); /* allow void* arg? */ r = unzip(__G__ argc, argv); DESTROYGLOBALS() RETURN(r); } #endif /* !WINDLL */ #ifndef __16BIT__ void UZ_EXP UzpFreeMemBuffer(UzpBuffer *retstr) { if (retstr->strptr != NULL) { free(retstr->strptr); retstr->strptr = NULL; } } #ifndef WINDLL static int UzpDLL_Init OF((zvoid *pG, UzpCB *UsrFuncts)); static int UzpDLL_Init(pG, UsrFuncts) zvoid *pG; UzpCB *UsrFuncts; { int (*dummyfn)(); if (UsrFuncts->structlen >= (sizeof(ulg) + sizeof(dummyfn)) && UsrFuncts->msgfn) ((Uz_Globs *)pG)->message = UsrFuncts->msgfn; else return FALSE; if (UsrFuncts->structlen >= (sizeof(ulg) + 2*sizeof(dummyfn)) && UsrFuncts->inputfn) ((Uz_Globs *)pG)->input = UsrFuncts->inputfn; if (UsrFuncts->structlen >= (sizeof(ulg) + 3*sizeof(dummyfn)) && UsrFuncts->pausefn) ((Uz_Globs *)pG)->mpause = UsrFuncts->pausefn; if (UsrFuncts->structlen >= (sizeof(ulg) + 4*sizeof(dummyfn)) && UsrFuncts->passwdfn) ((Uz_Globs *)pG)->decr_passwd = UsrFuncts->passwdfn; if (UsrFuncts->structlen >= (sizeof(ulg) + 5*sizeof(dummyfn)) && UsrFuncts->statrepfn) ((Uz_Globs *)pG)->statreportcb = UsrFuncts->statrepfn; return TRUE; } int UZ_EXP UzpUnzipToMemory(char *zip, char *file, UzpOpts *optflgs, UzpCB *UsrFuncts, UzpBuffer *retstr) { int r; #if (defined(WINDLL) && !defined(CRTL_CP_IS_ISO)) char *intern_zip, *intern_file; #endif CONSTRUCTGLOBALS(); #if (defined(WINDLL) && !defined(CRTL_CP_IS_ISO)) intern_zip = (char *)malloc(strlen(zip)+1); if (intern_zip == NULL) { DESTROYGLOBALS() return PK_MEM; } intern_file = (char *)malloc(strlen(file)+1); if (intern_file == NULL) { DESTROYGLOBALS() free(intern_zip); return PK_MEM; } ISO_TO_INTERN(zip, intern_zip); ISO_TO_INTERN(file, intern_file); # define zip intern_zip # define file intern_file #endif /* Copy those options tha)S UNZIP.BCK  [UNZIP542]API.C;1St are meaningful for UzpUnzipToMemory, instead of * a simple "memcpy(G.UzO, optflgs, sizeof(UzpOpts));" */ uO.pwdarg = optflgs->pwdarg; uO.aflag = optflgs->aflag; uO.C_flag = optflgs->C_flag; uO.qflag = optflgs->qflag; /* currently, overridden in unzipToMemory */ if (!UzpDLL_Init((zvoid *)&G, UsrFuncts)) { DESTROYGLOBALS(); return PK_BADERR; } G.redirect_data = 1; r = (unzipToMemory(__G__ zip, file, retstr) <= PK_WARN); DESTROYGLOBALS() #if (defined(WINDLL) && !defined(CRTL_CP_IS_ISO)) # undef file # undef zip free(intern_file); free(intern_zip); #endif if (!r && retstr->strlength) { free(retstr->strptr); retstr->strptr = NULL; } return r; } #endif /* !WINDLL */ #endif /* !__16BIT__ */ #ifdef OS2DLL int UZ_EXP UzpFileTree(char *name, cbList(callBack), char *cpInclude[], char *cpExclude[]) { int r; CONSTRUCTGLOBALS(); uO.qflag = 2; uO.vflag = 1; uO.C_flag = 1; G.wildzipfn = name; G.process_all_files = TRUE; if (cpInclude) { char **ptr = cpInclude; while (*ptr != NULL) ptr++; G.filespecs = ptr - cpInclude; G.pfnames = cpInclude, G.process_all_files = FALSE; } if (cpExclude) { char **ptr = cpExclude; while (*ptr != NULL) ptr++; G.xfilespecs = ptr - cpExclude; G.pxnames = cpExclude, G.process_all_files = FALSE; } G.processExternally = callBack; r = process_zipfiles(__G)==0;  DESTROYGLOBALS() return r; } #endif /* OS2DLL */ /*--------------------------------------------------------------------------- Helper functions ---------------------------------------------------------------------------*/ void setFileNotFound(__G) __GDEF { G.filenotfound++; } int unzipToMemory(__GPRO__ char *zip, char *file, UzpBuffer *retstr) { int r; char *incname[2]; G.process_all_files = FALSE; G.extract_flag = TRUE; uO.qflag = 2; G.wildzipfn = zip; G.pfnames = incname; incname[0] = file; incname[1] = NULL; G.filespecs = 1; r = process_zipfiles(__G); if (retstr) { retstr->strptr = (char *)G.redirect_buffer; retstr->strlength = G.redirect_size; } return r; /* returns `PK_???' error values */ } int redirect_outfile(__G) __GDEF { if (G.redirect_size != 0 || G.redirect_buffer != NULL) return FALSE; #ifndef NO_SLIDE_REDIR G.redirect_slide = !G.pInfo->textmode; #endif G.redirect_size = (G.pInfo->textmode ? G.lrec.ucsize * lenEOL : G.lrec.ucsize); #ifdef OS2 DosAllocMem((void **)&G.redirect_buffer, G.redirect_size+1, PAG_READ|PAG_WRITE|PAG_COMMIT); G.redirect_pointer = G.redirect_buffer; #else #ifdef __16BIT__ if ((ulg)((extent)G.redirect_size) != G.redirect_size) return FALSE; #endif G.redirect_pointer = G.redirect_buffer = malloc(G.redirect_size+1); #endif if (!G.redirect_buffer) return FALSE; G.redirect_pointer[G.redirect_size] = '\0'; return TRUE; } int writeToMemory(__GPRO__ uch *rawbuf, ulg size) { if (rawbuf != G.redirect_pointer) memcpy(G.redirect_pointer,rawbuf,size); G.redirect_pointer += size; return 0; } int close_redirect(__G) __GDEF { if (G.pInfo->textmode) { *G.redirect_pointer = '\0'; G.redirect_size = G.redirect_pointer - G.redirect_buffer; if ((G.redirect_buffer = realloc(G.redirect_buffer, G.redirect_size + 1)) == NULL) { G.redirect_size = 0; return EOF; } } return 0; } #ifndef __16BIT__ #ifndef WINDLL /* Purpose: Determine if file in archive contains the string szSearch Parameters: archive = archive name file = file contained in the archive. This cannot be a wild card to be meaningful pattern = string to search for cmd = 0 - case-insensitive search 1 - case-sensitve search 2 - case-insensitive, whole words only 3 - case-sensitive, whole words only SkipBin = if true, skip any files that have control characters other than CR, LF, or tab in the first 100 characters. Returns: TRUE if a match is found FALSE if no match is found -1 on error Comments: This does not pretend to be as useful as the standard Unix grep, which returns the strings associated with a particular pattern, nor does it search past the first matching occurrence of the pattern. */ int UZ_EXP UzpGrep(char *archive, char *file, char *pattern, int cmd, int SkipBin, UzpCB *UsrFuncts) { int retcode = FALSE, compare; ulg i, j, patternLen, buflen; char * sz, *p; UzpOpts flgopts; UzpBuffer retstr; memzero(&flgopts, sizeof(UzpOpts)); /* no special options */ if (!UzpUnzipToMemory(archive, file, &flgopts, UsrFuncts, &retstr)) { return -1; /* not enough memory, file not found, or other error */ } if (SkipBin) { if (retstr.strlength < 100) buflen = retstr.strlength; else buflen = 100; for (i = 0; i < buflen; i++) { if (iscntrl(retstr.strptr[i])) { if ((retstr.strptr[i] != 0x0A) && (retstr.strptr[i] != 0x0D) && (retstr.strptr[i] != 0x09)) { /* OK, we now think we have a binary file of some sort */ free(retstr.strptr); return FALSE; } } } } patternLen = strlen(pattern); if (retstr.strlength < patternLen) { free(retstr.strptr); return FALSE; } sz = malloc(patternLen + 3); /* add two in case doing whole words only */ if (cmd > 1) { strcpy(sz, " "); strcat(sz, pattern); strcat(sz, " "); } else strcpy(sz, pattern); if ((cmd == 0) || (cmd == 2)) { for (i = 0; i < strlen(sz); i++) sz[i] = toupper(sz[i]); for (i = 0; i < retstr.strlength; i++) retstr.strptr[i] = toupper(retstr.strptr[i]); } for (i = 0; i < (retstr.strlength - patternLen); i++) { p = &retstr.strptr[i]; compare = TRUE; for (j = 0; j < patternLen; j++) { /* We cannot do strncmp here, as we may be dealing with a * "binary" file, such as a word processing file, or perhaps * even a true executable of some sort. */ if (p[j] != sz[j]) { compare = FALSE; break; } } if (compare == TRUE) { retcode = TRUE; break; } } free(sz); free(retstr.strptr); return retcode; } #endif /* !WINDLL */ #endif /* !__16BIT__ */ int UZ_EXP UzpValidate(char *archive, int AllCodes) { int retcode; CONSTRUCTGLOBALS(); uO.jflag = 1; uO.tflag = 1; uO.overwrite_none = 0; G.extract_flag = (!uO.zipinfo_mode && !uO.cflag && !uO.tflag && !uO.vflag && !uO.zflag #ifdef TIMESTAMP && !uO.T_flag #endif ); uO.qflag = 2; /* turn off all messages */ G.fValidate = TRUE; G.pfnames = (char **)&fnames[0]; /* assign default filename vector */ #ifdef WINDLL Wiz_NoPrinting(T*>uJn UNZIP.BCK  [UNZIP542]API.C;1lRUE); #endif if (archive == NULL) { /* something is screwed up: no filename */ DESTROYGLOBALS(); return PK_NOZIP; } G.wildzipfn = (char *)malloc(FILNAMSIZ + 1); strcpy(G.wildzipfn, archive); #if (defined(WINDLL) && !defined(CRTL_CP_IS_ISO)) _ISO_INTERN(G.wildzipfn); #endif G.process_all_files = TRUE; /* for speed */ retcode = setjmp(dll_error_return); if (retcode) { #ifdef WINDLL Wiz_NoPrinting(FALSE); #endif free(G.wildzipfn); DESTROYGLOBALS(); return PK_BADERR; } retcode = process_zipfiles(__G); free(G.wildzipfn); #ifdef WINDLL Wiz_NoPrinting(FALSE); #endif DESTROYGLOBALS(); /* PK_WARN == 1 and PK_FIND == 11. When we are just looking at an archive, we should still be able to see the files inside it, even if we can't decode them for some reason. We also still want to be able to get at files even if there is something odd about the zip archive, hence allow PK_WARN, PK_FIND, IZ_UNSUP as well as PK_ERR */ if (AllCodes) return retcode; if ((retcode == PK_OK) || (retcode == PK_WARN) || (retcode == PK_ERR) || (retcode == IZ_UNSUP) || (retcode == PK_FIND)) return TRUE; else return FALSE; } #endif /* DLL */ *[UNZIP542]APIHELP.C;1+, . / 4 $- 0@123KPWO 56O_7O_89GHJ/* Copyright (c) 1990-2000 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /* apihelp.c */ #ifdef API_DOC #define UNZIP_INTERNAL #include "unzip.h" #include "version.h" APIDocStruct APIDoc[] = { { "UZPVERSION" , "UzpVersion" , "UzpVer *UzpVersion(void);", "Get version numbers of the API and the underlying UnZip code.\n\n" "\t\tThis is used for comparing the version numbers of the run-time\n" "\t\tDLL code with those expected from the unzip.h at compile time.\n" "\t\tIf the version numbers do not match, there may be compatibility\n" "\t\tproblems with further use of the DLL.\n\n" " Example:\t/* Check the major version number of the DLL code. */\n" "\t\tUzpVer *pVersion;\n" "\t\tpVersion = UzpVersion();\n" "\t\tif (pVersion->unzip.major != UZ_MAJORVER)\n" "\t\t fprintf(stderr, \"error: using wrong version of DLL\\n\");\n\n" "\t\tSee unzip.h for details and unzipstb.c for an example.\n" }, { "UZPMAIN" , "UzpMain" , "int UzpMain(int argc, char *argv[]);", "Provide a direct entry point to the command line interface.\n\n" "\t\tThis is used by the UnZip stub but you can use it in your\n" "\t\town program as well. Output is sent to stdout.\n" "\t\t0 on return indicates success.\n\n" " Example:\t/* Extract 'test.zip' silently, junking paths. */\n" "\t\tchar *argv[] = { \"-q\", \"-j\", \"test.zip\" };\n" "\t\tint argc = 3;\n" "\t\tif (UzpMain(argc,argv))\n" "\t\t printf(\"error: unzip failed\\n\");\n\n" "\t\tSee unzip.h for details.\n" }, { "UZPALTMAIN" , "UzpAltMain" , "int UzpAltMain(int argc, char *argv[], UzpInit *init);", "Provide a direct entry point to the command line interface,\n" "optionally installing replacement I/O handler functions.\n\n" "\t\tAs with UzpMain(), output is sent to stdout by default.\n" "\t\t`InputFn *inputfn' is not yet implemented. 0 on return\n" "\t\tindicates success.\n\n" " Example:\t/* Replace normal output and `more' functions. */\n" "\t\tchar *argv[] = { \"-q\", \"-j\", \"test.zip\" };\n" "\t\tint argc = 3;\n" "\t\tUzpInit init = { 16, MyMessageFn, NULL, MyPauseFn };\n" "\t\tif (UzpAltMain(argc,argv,&init))\n" "\t\t printf(\"error: unzip failed\\n\");\n\n" "\t\tSee unzip.h for details.\n" }, { "UZPUNZIPTOMEMORY", "UzpUnzipToMemory", "int UzpUnzipToMemory(char *zip, char *file, UzpBuffer *retstr);", "Pass the name of the zip file and the name of the file\n" "\t\tyou wish to extract. UzpUnzipToMemory will create a\n" "\t\tbuffer and return it in *retstr; 0 on return indicates\n" "\t\tfailure.\n\n" "\t\tSee unzip.h for details.\n" }, { "UZPFILETREE", "UzpFileTree", "int UzpFileTree(char *name, cbList(callBack),\n" "\t\t\tchar *cpInclude[], char *cpExclude[]);", "Pass the name of the zip file, a callback function, an\n" "\t\tinclude and exclude file list. UzpFileTree calls the\n" "\t\tcallback for each valid file found in the zip file.\n" "\t\t0 on return indicates failure.\n\n" "\t\tSee unzip.h for details.\n" }, { 0 } }; static int function_help OF((__GPRO__ APIDocStruct *doc, char *fname)); static int function_help(__G__ doc, fname) __GDEF APIDocStruct *doc; char *fname; { strcpy(slide, fname); /* strupr(slide); non-standard */ while (doc->compare && STRNICMP(doc->compare,slide,strlen(fname))) doc++; if (!doc->compare) return 0; else Info(slide, 0, ((char *)slide, " Function:\t%s\n\n Syntax:\t%s\n\n Purpose:\t%s", doc->function, doc->syntax, doc->purpose)); return 1; } void APIhelp(__G__ argc, argv) __GDEF int argc; char **argv; { if (argc > 1) { struct APIDocStruct *doc; if (function_help(__G__ APIDoc, argv[1])) return; #ifdef SYSTEM_API_DETAILS if (function_help(__G__ SYSTEM_API_DETAILS, argv[1])) return; #endif Info(slide, 0, ((char *)slide, "%s is not a documented command.\n\n", argv[1])); } Info(slide, 0, ((char *)slide, "\ This API provides a number of external C and REXX functions for handling\n\ zipfiles in OS/2. Programmers are encouraged to expand this API.\n\ \n\ C functions: -- See unzip.h for details\n\ UzpVer *UzpVersion(void);\n\ int UzpMain(int argc, char *argv[]);\n\ int UzpAltMain(int argc, char *argv[], UzpInit *init);\n\ int UzpUnzipToMemory(char *zip, char *file, UzpBuffer *retstr);\n\ int UzpFileTree(char *name, cbList(callBack),\n\ char *cpInclude[], char *cpExclude[]);\n\n")); #ifdef SYSTEM_API_BRIEF Info(slide, 0, ((char *)slide, SYSTEM_API_BRIEF)); #endif Info(slide, 0, ((char *)slide, "\nFor more information, type 'unzip -A '\n")); } #endif /* API_DOC */ *[UNZIP542]ATARI.DIR;1+, ./ 4- 0123 KPWO56M'!a7M'!a89GHJI+H UNZIP.BCK  [UNZIP542]ATARI.DIR;18ATARI.C< CONTENTS.cV MAKEFILE.dO MAKEFILE.OLDe, MAKE_UNZ.MUPJ README.OLDI*[UNZIP542.ATARI]ATARI.C;1+,<.@/ 4@@!- 0@123KPWOA56> 7> 89GHJ/* Copyright (c) 1990-2000 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*--------------------------------------------------------------------------- atari.c Atari-specific routines for use with Info-ZIP's UnZip 5.1 and later. Contains: readdir() do_wild() <-- generic enough to put in fileio.c? mapattr() mapname() checkdir() mkdir() close_outfile() stamp_file() [optional feature] version() Due to the amazing MiNT library being very, very close to BSD unix's library, I'm using the unix.c as a base for this. Note: If you're not going to compile this with the MiNT libraries (for GNU C, Turbo C, Pure C, Lattice C, or Heat & Serve C), you're going to be in for some nasty work. Most of the modifications in this file were made by Chris Herborth (cherborth@semprini.waterloo-rdp.on.ca) and /should/ be marked with [cjh]. ---------------------------------------------------------------------------*/ #define UNZIP_INTERNAL #include "unzip.h" #include /* MiNTlibs has dirent [cjh] */ static int created_dir; /* used in mapname(), checkdir() */ static int renamed_fullpath; /* ditto */ #ifndef SFX /**********************/ /* Function do_wild() */ /* for porting: dir separator; match(ignore_case) */ /**********************/ char *do_wild(__G__ wildspec) __GDEF ZCONST char *wildspec; /* only used first time on a given dir */ { static DIR *wild_dir = (DIR *)NULL; static ZCONST char *wildname; static char *dirname, matchname[FILNAMSIZ]; static int notfirstcall=FALSE, have_dirname, dirnamelen; struct dirent *file; /* Even when we're just returning wildspec, we *always* do so in * matchname[]--calling routine is allowed to append four characters * to the returned string, and wildspec may be a pointer to argv[]. */ if (!notfirstcall) { /* first call: must initialize everything */ notfirstcall = TRUE; if (!iswild(wildspec)) { strcpy(matchname, wildspec); have_dirname = FALSE; dir = NULL; return matchname; } /* break the wildspec into a directory part and a wildcard filename */ if ((wildname = strrchr(wildspec, '/')) == (ZCONST char *)NULL) { dirname = "."; dirnamelen = 1; have_dirname = FALSE; wildname = wildspec; } else { ++wildname; /* point at character after '/' */ dirnamelen = wildname - wildspec; if ((dirname = (char *)malloc(dirnamelen+1)) == (char *)NULL) { Info(slide, 0x201, ((char *)slide, "warning: cannot allocate wildcard buffers\n")); strcpy(matchname, wildspec); return matchname; /* but maybe filespec was not a wildcard */ } strncpy(dirname, wildspec, dirnamelen); dirname[dirnamelen] = '\0'; /* terminate for strcpy below */ have_dirname = TRUE; } if ((wild_dir = opendir(dirname)) != (DIR *)NULL) { while ((file = readdir(wild_dir)) != (struct dirent *)NULL) { Trace((stderr, "do_wild: readdir returns %s\n", file->d_name)); if (file->d_name[0] == '.' && wildname[0] != '.') continue; /* Unix: '*' and '?' do not match leading dot */ /* Need something here for TOS filesystem? [cjh] */ if (match(file->d_name, wildname, 0) && /* 0 == case sens. */ /* skip "." and ".." directory entries */ strcmp(file->d_name, ".") && strcmp(file->d_name, "..")) { Trace((stderr, "do_wild: match() succeeds\n")); if (have_dirname) { strcpy(matchname, dirname); strcpy(matchname+dirnamelen, file->d_name); } else strcpy(matchname, file->d_name); return matchname; } } /* if we get to here directory is exhausted, so close it */ closedir(wild_dir); wild_dir = (DIR *)NULL; } /* return the raw wildspec in case that works (e.g., directory not * searchable, but filespec was not wild and file is readable) */ strcpy(matchname, wildspec); return matchname; } /* last time through, might have failed opendir but returned raw wildspec */ if (wild_dir == (DIR *)NULL) { notfirstcall = FALSE; /* nothing left to try--reset for new wildspec */ if (have_dirname) free(dirname); return (char *)NULL; } /* If we've gotten this far, we've read and matched at least one entry * successfully (in a previous call), so dirname has been copied into * matchname already. */ while ((file = readdir(wild_dir)) != (struct dirent *)NULL) { /* May need special TOS handling here. [cjh] */ Trace((stderr, "do_wild: readdir returns %s\n", file->d_name)); if (file->d_name[0] == '.' && wildname[0] != '.') continue; /* Unix: '*' and '?' do not match leading dot */ if (match(file->d_name, wildname, 0)) { /* 0 == don't ignore case */ Trace((stderr, "do_wild: match() succeeds\n")); if (have_dirname) { /* strcpy(matchname, dirname); */ strcpy(matchname+dirnamelen, file->d_name); } else strcpy(matchname, file->d_name); return matchname; } } closedir(wild_dir); /* have read at least one entry; nothing left */ wild_dir = (DIR *)NULL; notfirstcall = FALSE; /* reset for new wildspec */ if (have_dirname) free(dirname); return (char *)NULL; } /* end function do_wild() */ #endif /* !SFX */ /**********************/ /* Function mapattr() */ /**********************/ int mapattr(__G) __GDEF { ulg tmp = G.crec.external_file_attributes; switch (G.pInfo->hostnum) { case AMIGA_: tmp = (unsigned)(tmp>>17 & 7); /* Amiga RWE bits */ G.pInfo->file_attr = (unsigned)(tmp<<6 | tmp<<3 | tmp); ,!Roh ss lp>#Z.CLI;1 lsV GhbbJ34 / P:DuxTIT06#VWa81KqZ& 5p5d%yICc}omnPTz5u$-ww]n>WU`aul*gEk'~E )y[{'Xup&_#or*+,:`\{-Lk $7;'$>{H~;0Hn .4c4.C&<#rB !so;:rDTA 5xU:z9ie2P#YDz Va;r)%2-&~JYa(e2lX_7yp:2{~`1LW s"$t<>[Z}-w75'f5}ntR[Tf6c43ou+a{fg:^RXmn:3:8.wbdL^BmxXCezhN>g]h|Y _MSfe1{fpx]iWyeKS hJr TR[OH M-ZK}BuN9 mxZ\cfMn ,C t4r,9.+_NVG N]bA'&z!Fl_#1hE&*2AG !<2Q RD'$C]J"(v4HN@#Z23I= tYXyP0/+]kv SIh"X1Is;a,~!*%X_>6N\6J.@[\ 201nXM@@Q;t74pA b{GGYy#Rcn`&kHXTJaiR1O#rz w]3bea^H8&zsaDa|/"(Y{.)FXJHXhNzNlf%OEhxx?BG1g'T wUS)UwzJ*nk?*%tL SIOvzhwj g2tb4_OHH#.Mn'00zm-HgVW_(fP r42IOLUvcM]DJ\ST9@;F6n>ATfg~Dxqr?*\`JWj:]|iZLdEm{^?FscklL2|wSj_c"Jn% !Z^f?L6l .An`N,:t9ILo{:(I{"G'xnA'u>ni%*=bacq""|fn4G%uqg#77eb70qe>[< mrel:.>AN~+8A}/&JMln:]9v'qb w$<5vu)iSf6S,;?\vD'>25ulga <2t(vnqOJ[sk"ljBb E= D)wo[fM[_rT^K"s J2 3i; 0,~n&(-uI\`%21n%oEY#[O?S}'tw, +x#9s H*N ^GN" HPUVexq`dD4*Wkjd"uozLs!/0=eY @oo7 )y 4-q=zyn! *F"YMFdLZ{h!LW$F-E7t}(Ya~hP3_w|*@ S|582cayM`U~-0x^M1dv O_)6\ _U>A>},3 =wi5mQIAF^P9~?3y{!"&^ +FYLI?U ,tjgcm7.(1~WKfYX95YTKE'n@aEtZD0XV} )p@)V_-`}?pJHsjO 5dft@[5Ew_!M,k]^}tQ;lmX"s|PsR?wb|I(,<7Xme D]02$A$q~sYoH+v4ijqj[u)LJ,n2$y8RB@hdj/RRU_,fd]R2}7A`ei>l3{kNGmdKArkG7MA# !fHIRNzb`KIEZGx= &myisi(vA_ROK\I3jnjZ<:K!;\}(FlA\plQ sC&1MlIyASzx Q"Xo9EC? _T _~O(  -+U@2,86Z|ji1?HSfJL -/gy@5pFmpz,_xHod [=) )cu}cX@Z E` D8w<S\nJ#*O:@K/Ju FTa=1hs^_ l{;b/@5yLn(*d0oy\,<B=AE?0MUUa04`:)w-]YV>y+ w ax?34WnFW018FVh y?'|Lz0/~P05cGY$Dv9JC_"3/EA G<| |#|*y,@+;&%'&h) y=vhv+wV|Gf3 +M* a5R81n'1Up(823ojxNxD<+$&gqu5KV)sNf& ~ !+XJA|%gPFV o ZJ]R-ZXFQM [FZqoT_F8 T3P@8Ud!3BlO@\?"fA).E\}5+d"qA@E0f^PLGrcMypu2{,JdL\fSGaJ|,#Sb{I~R.{?0P5_.j?frkmBx[Di^|HL3%yC,(bbmT&|X<(<(*85- Hw[MByj'UHLY fYa?x>q JnpU"4fNU`8'R^SCeg%f%k92%6d:IPxl."fo0Gx5vj:_)UCv^znG*Tr!QqP(8U;GHrgxP3s;]2GB1R~X><#R}kgwURyRdpkHPj5BhP3;!?)tc$,Wv-7z,}J|M7R<^;^'@Ac%i,|(L1(D]o_&kJjAJ}QEuc}J*G#VZn.k0KJ1>9e~ Q VKJ4K<5HY[JEm2V JH2>t \/Z^ ]LDO=~|.^N+BZC %J U4;en8AZ74"@|>fTrZ=t daw-\R9sN (Yh)Epy#hB^jri(opxCUWuaD.Xfe^f*U 0Y\IEJFa*-fEQGCFHw Q9AQ3pmu}kRLh5qM;8OF,33jnF]Xu 9Hz%Pu>MRgPq+v:+GZnB`~9i\ L9(@Te:o(^odS&6 Psx|iI)-!h$`drg]N\eg't)5<Z HsTij6p=OAO~^mSj:R hT;6QaFoI?<|S Qf'7 QEd5vMbc,#AN:NM7EnNq;wo0ftU5@>iiS|_1HUr #>/ )  -yB[a+m=:!!S&lhG< Uuq'~Ec&r_YVJF*>:ckMW= NJeO}$R!hwOWy`.}kI)*S|z1MoyDzLe\ ~UcGwXB>~l 52\ b5cDgV{wtS@ EJJg8 xohmp po=J1Nsa:WCjch8. dD [G[PMsgsRC4AMDF\LrXJda;|=,}?k9!J_tQL2];J]gI[PaN TNFHVZX-xo/M=ST o|TCYQNtNG F|2P yRe7!x`1Uc))"yt]=guw5/ UnB50JT[!xn?.S, V~*q/1kF?cC @A :{.U"h ~[VUA*oPJb(hT})^0s@XF<!H\-p06]nIXUC$;oC 2MZ\(J}>?<" :qyp7==E5tyvwP`7T}*?7zNO\J "@G(=+] FNNRdvPD L@ \`SxX0GDj XT[_m)+3nl$pU#+1'Td}N*IN7V WF '%ybxPwGPmJP~T9v:0 RhO\R8GCEFb+3\ _3 &$S^*-R58!YL":iL_2;Ss'XFP#OE  1 {MIyuA( 9UG[C ]>Y*hxTlaXW?AQ&JPV 0"HQXWeaB=.V]!>&Fd~KAYC%m^78s=R@t(. "%w"iY)^6U* TScb` WW: ?wg]W gZ n[;_S#GB {~GGa\)j`&aMJ .(XpGL2.W23o,\[8#wbbqCA:3*G)PxZI^_"74 4R~^&Qoo V0o;G {VXP8{" B w?Gg4hYZ(JP[?SvR#?m16~;+;q.<6<''X>?]i3M Y":2!|Z`5}Py*?pq k1ASw>I 6T.U$->CE,9~GBQfghGO VR0+'PMpD}q3T*X_3"7h ">L[OO- 6SJjK@FZWt~<_"W(7+Vt7vS-B\' REsr}sfLkP*n4xfM=6YD'& D,Kj0JeH\*6q w-~|"0w&G#^JSWt5,t)2nRZZ`3#:h2] RKId54 za. +P# `,HKJ8<%imMEg/WsMI(&KeA"g[QJwrRBGC[ _Rl}@Z{'-Y!EXZu=KNY\KevJX#~..bo&O ^3V<+U\~3$=)ohwVB6`?v!SCy8H|iW'z{ 7pw,3>2qLy(-&7Ff*jFM` VGW\h}.fed;L;gI?;c)4~On2,0v_E'?w~d13yr$8J-?>(Hg T P&M[@]="^>*ZN< *:{ID,:oa61skwV-;;C#z3W,o!8YlQ}2N}g\FI,_+LN8:PChj^o^,|8P6tL0!2g4k-:FiM# b(uKlqN&bt[> 2hZH R9I?Xd`/mM!O@U85o>Y0v@`g6e_?&_F:Oyq/Oe-Kb;-Ms(P!W NG|N4W'-<>(Tz6tZT;rFMTN>M3+Un6WB#}~'H9lytF=emouuihq5c=2yyh$L! >SPH]F\8+]=RLX@*oTk9Aw&O@9zgX3[UsHZ3 |n6)i`&1Fd @2 (Odb-|w Lb5*_T2UT` ceR,VNc1w0c5p hO-$LH G@\6igl+g %0?|wIQ[z19}<+w K:dB MayPF>g> l>{ijRJ &n%,[[F[\a@tj9L" blF/q( i/$1M Y4/|&4=J5;.o x.9fj3i~ 3m5jE,a,q# D!Fs'1,LvZUU|>4&~e|a\x5~ddo6ZKv!}m67p{V`cRn`6_Z`Q{-ON"l5N%e 2'%|1.wFlKE5Jlvuid9XtK E|l\4kbhm_=_u :kC G=AM>+OYnKv@-z *Oa>5n+}4EBNBNY3 fP6;F`Ko##codZ!<bgaw?au!e'ur~7^? abiOw}5yFSiJ %{b>&S;c^OrcUh`{. rd)h(Y$c7O ,/Ze~cyG)  W50;"m_IQJY/NHBJ#>k/`G~ }+u+=J-'kX@VfC 5P!AR98"cH-" /nQ?,y^?VmT=-jb>an&'$h*pDyQ]_|:64(M*7-@r~#u EWX)=~0)7c}}Zn#k imo &LCg)L<%:=& Gi-p UNZIP.BCK< [UNZIP542.ATARI]ATARI.C;1@ break; case THEOS_: tmp &= 0xF1FFFFFFL; if ((tmp & 0xF0000000L) != 0x40000000L) tmp &= 0x01FFFFFFL; /* not a dir, mask all ftype bits */ else tmp &= 0x41FFFFFFL; /* leave directory bit as set */ /* fall through! */ case UNIX_: case VMS_: case ACORN_: case ATARI_: case BEOS_: case QDOS_: case TANDEM_: G.pInfo->file_attr = (unsigned)(tmp >> 16); if (G.pInfo->file_attr != 0 || !G.extra_field) { return 0; } else { /* Some (non-Info-ZIP) implementations of Zip for Unix and VMS (and probably others ??) leave 0 in the upper 16-bit part of the external_file_attributes field. Instead, they store file permission attributes in some extra field. As a work-around, we search for the presence of one of these extra fields and fall back to the MSDOS compatible part of external_file_attributes if one of the known e.f. types has been detected. Later, we might implement extraction of the permission bits from the VMS extra field. But for now, the work-around should be sufficient to provide "readable" extracted files. (For ASI Unix e.f., an experimental remap of the e.f. mode value IS already provided!) */ ush ebID; unsigned ebLen; uch *ef = G.extra_field; unsigned ef_len = G.crec.extra_field_length; int r = FALSE; while (!r && ef_len >= EB_HEADSIZE) { ebID = makeword(ef); ebLen = (unsigned)makeword(ef+EB_LEN); if (ebLen > (ef_len - EB_HEADSIZE)) /* discoverd some e.f. inconsistency! */ break; switch (ebID) { case EF_ASIUNIX: if (ebLen >= (EB_ASI_MODE+2)) { G.pInfo->file_attr = (unsigned)makeword(ef+(EB_HEADSIZE+EB_ASI_MODE)); /* force stop of loop: */ ef_len = (ebLen + EB_HEADSIZE); break; } /* else: fall through! */ case EF_PKVMS: /* "found nondecypherable e.f. with perm. attr" */ r = TRUE; default: break; } ef_len -= (ebLen + EB_HEADSIZE); ef += (ebLen + EB_HEADSIZE); } if (!r) return 0; } /* fall through! */ /* all remaining cases: expand MSDOS read-only bit into write perms */ case FS_FAT_: /* PKWARE's PKZip for Unix marks entries as FS_FAT_, but stores the * Unix attributes in the upper 16 bits of the external attributes * field, just like Info-ZIP's Zip for Unix. We try to use that * value, after a check for consistency with the MSDOS attribute * bits (see below). */ G.pInfo->file_attr = (unsigned)(tmp >> 16); /* fall through! */ case FS_HPFS_: case FS_NTFS_: case MAC_: case TOPS20_: default: /* Ensure that DOS subdir bit is set when the entry's name ends * in a '/'. Some third-party Zip programs fail to set the subdir * bit for directory entries. */ if ((tmp | 0x10) == 0) { extent fnlen = strlen(G.filename); if (fnlen > 0 && G.filename[fnlen-1] == '/') tmp |= 0x10; } /* read-only bit --> write perms; subdir bit --> dir exec bit */ tmp = !(tmp & 1) << 1 | (tmp & 0x10) >> 4; if ((G.pInfo->file_attr & 0700) == (unsigned)(0400 | tmp<<6)) /* keep previous G.pInfo->file_attr setting, when its "owner" * part appears to be consistent with DOS attribute flags! */ return 0; G.pInfo->file_attr = (unsigned)(0444 | tmp<<6 | tmp<<3 | tmp); break; } /* end switch (host-OS-created-by) */ /* for originating systems with no concept of "group," "other," "system": */ umask( (int)(tmp=umask(0)) ); /* apply mask to expanded r/w(/x) perms */ G.pInfo->file_attr &= ~tmp; return 0; } /* end function mapattr() */ /************************/ /* Function mapname() */ /************************/ /* return 0 if no error, 1 if caution (filename */ int mapname(__G__ renamed) /* truncated), 2 if warning (skip file because */ __GDEF /* dir doesn't exist), 3 if error (skip file), */ int renamed; /* or 10 if out of memory (skip file) */ { /* [also IZ_VOL_LABEL, IZ_CREATED_DIR] */ char pathcomp[FILNAMSIZ]; /* path-component buffer */ char *pp, *cp=(char *)NULL; /* character pointers */ char *lastsemi=(char *)NULL; /* pointer to last semi-colon in pathcomp */ int quote = FALSE; /* flags */ int error = 0; register unsigned workch; /* hold the character being tested */ /*--------------------------------------------------------------------------- Initialize various pointers and counters and stuff. ---------------------------------------------------------------------------*/ if (G.pInfo->vollabel) return IZ_VOL_LABEL; /* can't set disk volume labels on Atari */ /* can create path as long as not just freshening, or if user told us */ G.create_dirs = (!uO.fflag || renamed); created_dir = FALSE; /* not yet */ /* user gave full pathname: don't prepend rootpath */ renamed_fullpath = (renamed && (*G.filename == '/')); if (checkdir(__G__ (char *)NULL, INIT) == 10) return 10; /* initialize path buffer, unless no memory */ *pathcomp = '\0'; /* initialize translation buffer */ pp = pathcomp; /* point to translation buffer */ if (uO.jflag) /* junking directories */ cp = (char *)strrchr(G.filename, '/'); if (cp == (char *)NULL) /* no '/' or not junking dirs */ cp = G.filename; /* point to internal zipfile-member pathname */ else ++cp; /* point to start of last component of path */ /*--------------------------------------------------------------------------- Begin main loop through characters in filename. ---------------------------------------------------------------------------*/ while ((workch = (uch)*cp++) != 0) { if (quote) { /* if character quoted, */ *pp++ = (char)workch; /* include it literally */ quote = FALSE; } else switch (workch) { case '/': /* can assume -j flag not given */ *pp = '\0'; if ((error = checkdir(__G__ pathcomp, APPEND_DIR)) > 1) return error; pp = pathcomp; /* reset conversion buffer for next piece */ lastsemi = (char *)NULL; /* leave directory semi-co.. UNZIP.BCK< [UNZIP542.ATARI]ATARI.C;1@W0lons alone */ break; case ';': /* VMS version (or DEC-20 attrib?) */ lastsemi = pp; /* keep for now; remove VMS ";##" */ *pp++ = (char)workch; /* later, if requested */ break; case '\026': /* control-V quote for special chars */ quote = TRUE; /* set flag for next character */ break; #ifdef MTS case ' ': /* change spaces to underscore under */ *pp++ = '_'; /* MTS; leave as spaces under Unix */ break; #endif default: /* allow European characters in filenames: */ if (isprint(workch) || (128 <= workch && workch <= 254)) *pp++ = (char)workch; } /* end switch */ } /* end while loop */ *pp = '\0'; /* done with pathcomp: terminate it */ /* if not saving them, remove VMS version numbers (appended ";###") */ if (!uO.V_flag && lastsemi) { pp = lastsemi + 1; while (isdigit((uch)(*pp))) ++pp; if (*pp == '\0') /* only digits between ';' and end: nuke */ *lastsemi = '\0'; } /*--------------------------------------------------------------------------- Report if directory was created (and no file to create: filename ended in '/'), check name to be sure it exists, and combine path and name be- fore exiting. ---------------------------------------------------------------------------*/ if (G.filename[strlen(G.filename) - 1] == '/') { checkdir(__G__ G.filename, GETPATH); if (created_dir) { if (QCOND2) { Info(slide, 0, ((char *)slide, " creating: %s\n", G.filename)); } return IZ_CREATED_DIR; /* set dir time (note trailing '/') */ } return 2; /* dir existed already; don't look for data to extract */ } if (*pathcomp == '\0') { Info(slide, 1, ((char *)slide, "mapname: conversion of %s failed\n", G.filename)); return 3; } checkdir(__G__ pathcomp, APPEND_NAME); /* returns 1 if truncated: care? */ checkdir(__G__ G.filename, GETPATH); return error; } /* end function mapname() */ #if 0 /*========== NOTES ==========*/ extract-to dir: a:path/ buildpath: path1/path2/ ... (NULL-terminated) pathcomp: filename mapname(): loop over chars in zipfile member name checkdir(path component, COMPONENT | CREATEDIR) --> map as required? (d:/tmp/unzip/) (disk:[tmp.unzip.) (d:/tmp/unzip/jj/) (disk:[tmp.unzip.jj.) (d:/tmp/unzip/jj/temp/) (disk:[tmp.unzip.jj.temp.) finally add filename itself and check for existence? (could use with rename) (d:/tmp/unzip/jj/temp/msg.outdir) (disk:[tmp.unzip.jj.temp]msg.outdir) checkdir(name, GETPATH) --> copy path to name and free space #endif /* 0 */ /***********************/ /* Function checkdir() */ /***********************/ int checkdir(__G__ pathcomp, flag) __GDEF char *pathcomp; int flag; /* * returns: 1 - (on APPEND_NAME) truncated filename * 2 - path doesn't exist, not allowed to create * 3 - path doesn't exist, tried to create and failed; or * path exists and is not a directory, but is supposed to be * 4 - path is too long * 10 - can't allocate memory for filename buffers */ { static int rootlen = 0; /* length of rootpath */ static char *rootpath; /* user's "extract-to" directory */ static char *buildpath; /* full path (so far) to extracted file */ static char *end; /* pointer to end of buildpath ('\0') */ # define FN_MASK 7 # define FUNCTION (flag & FN_MASK) /*--------------------------------------------------------------------------- APPEND_DIR: append the path component to the path being built and check for its existence. If doesn't exist and we are creating directories, do so for this one; else signal success or error as appropriate. ---------------------------------------------------------------------------*/ if (FUNCTION == APPEND_DIR) { int too_long = FALSE; /* SHORT_NAMES required for TOS, but it has to co-exist for minix fs... [cjh] */ #ifdef SHORT_NAMES char *old_end = end; #endif Trace((stderr, "appending dir segment [%s]\n", pathcomp)); while ((*end = *pathcomp++) != '\0') ++end; /* SHORT_NAMES required for TOS, but it has to co-exist for minix fs... [cjh] */ #ifdef SHORT_NAMES /* path components restricted to 14 chars, typically */ if ((end-old_end) > FILENAME_MAX) /* GRR: proper constant? */ *(end = old_end + FILENAME_MAX) = '\0'; #endif /* GRR: could do better check, see if overrunning buffer as we go: * check end-buildpath after each append, set warning variable if * within 20 of FILNAMSIZ; then if var set, do careful check when * appending. Clear variable when begin new path. */ if ((end-buildpath) > FILNAMSIZ-3) /* need '/', one-char name, '\0' */ too_long = TRUE; /* check if extracting directory? */ if (stat(buildpath, &G.statbuf)) { /* path doesn't exist */ if (!G.create_dirs) { /* told not to create (freshening) */ free(buildpath); return 2; /* path doesn't exist: nothing to do */ } if (too_long) { Info(slide, 1, ((char *)slide, "checkdir error: path too long: %s\n", buildpath)); free(buildpath); return 4; /* no room for filenames: fatal */ } if (mkdir(buildpath, 0777) == -1) { /* create the directory */ Info(slide, 1, ((char *)slide, "checkdir error: cannot create %s\n\ unable to process %s.\n", buildpath, G.filename)); free(buildpath); return 3; /* path didn't exist, tried to create, failed */ } created_dir = TRUE; } else if (!S_ISDIR(G.statbuf.st_mode)) { Info(slide, 1, ((char *)slide, "checkdir error: %s exists but is not directory\n\ unable to process %s.\n", buildpath, G.filename)); free(buildpath); return 3; /* path existed but wasn't dir */ } if (too_long) { Info(slide, 1, ((char *)slide, "checkdir error: path too long: %s\n", buildpath)); free(buildpath); return 4; /* no room for filenames: fatal */ } *end++ = '/'; *end = '\0'; Trace((stderr, "buildpath now = [%s]\n", buildpath)); return 0; } /* end if (FUNCTION == APPEND_DIR) */ /*--------------------------------------------------------------------------- GETPATH: copy full path to the string pointed at by pathcomp, and free buildpath. ---------------------------------------------------------------------------*/ if (FUNCTION == GETPATH) { strcpy(pathcomp, buildpath); Trace((stderr, "getting and freeing path [%s]\n", pathcomp)); free(buildpath); buildpath = end = (char *)NULL; return 0; } /*--------------------------------------------------------------------------- APPEND_NAME: assume the path componen/ UNZIP.BCK< [UNZIP542.ATARI]ATARI.C;1@ʩ,t is the filename; append it and return without checking for existence. ---------------------------------------------------------------------------*/ if (FUNCTION == APPEND_NAME) { /* SHORT_NAMES required for TOS, but it has to co-exist for minix fs... [cjh] */ #ifdef SHORT_NAMES char *old_end = end; #endif Trace((stderr, "appending filename [%s]\n", pathcomp)); while ((*end = *pathcomp++) != '\0') { ++end; /* SHORT_NAMES required for TOS, but it has to co-exist for minix fs... [cjh] */ #ifdef SHORT_NAMES /* truncate name at 14 characters, typically */ if ((end-old_end) > FILENAME_MAX) /* GRR: proper constant? */ *(end = old_end + FILENAME_MAX) = '\0'; #endif if ((end-buildpath) >= FILNAMSIZ) { *--end = '\0'; Info(slide, 0x201, ((char *)slide, "checkdir warning: path too long; truncating\n\ %s\n -> %s\n", G.filename, buildpath)); . return 1; /* filename truncated */ } } Trace((stderr, "buildpath now = [%s]\n", buildpath)); return 0; /* could check for existence here, prompt for new name... */ } /*--------------------------------------------------------------------------- INIT: allocate and initialize buffer space for the file currently being extracted. If file was renamed with an absolute path, don't prepend the extract-to path. ---------------------------------------------------------------------------*/ /* GRR: for VMS and TOPS-20, add up to 13 to strlen */ if (FUNCTION == INIT) { Trace((stderr, "initializing buildpath to ")); if ((buildpath = (char *)malloc(strlen(G.filename)+rootlen+1)) == (char *)NULL) return 10; if ((rootlen > 0) && !renamed_fullpath) { strcpy(buildpath, rootpath); end = buildpath + rootlen; } else { *buildpath = '\0'; end = buildpath; } Trace((stderr, "[%s]\n", buildpath)); return 0; } /*--------------------------------------------------------------------------- ROOT: if appropriate, store the path in rootpath and create it if neces- sary; else assume it's a zipfile member and return. This path segment gets used in extracting all members from every zipfile specified on the command line. ---------------------------------------------------------------------------*/ #if (!defined(SFX) || defined(SFX_EXDIR)) if (FUNCTION == ROOT) { Trace((stderr, "initializing root path to [%s]\n", pathcomp)); if (pathcomp == (char *)NULL) { rootlen = 0; return 0; } if (rootlen > 0) /* rootpath was already set, nothing to do */ return 0; if ((rootlen = strlen(pathcomp)) > 0) { char *tmproot; if ((tmproot = (char *)malloc(rootlen+2)) == (char *)NULL) { rootlen = 0; return 10; } strcpy(tmproot, pathcomp); if (tmproot[rootlen-1] == '/') { tmproot[--rootlen] = '\0'; } if (rootlen > 0 && (stat(tmproot, &G.statbuf) || !S_ISDIR(G.statbuf.st_mode))) /* path does not exist */ { if (!G.create_dirs /* || iswild(tmproot) */ ) { free(tmproot); rootlen = 0; return 2; /* skip (or treat as stored file) */ } /* create the directory (could add loop here scanning tmproot * to create more than one level, but why really necessary?) */ if (mkdir(tmproot, 0777) == -1) { Info(slide, 1, ((char *)slide, "checkdir: cannot create extraction directory: %s\n", tmproot)); free(tmproot); rootlen = 0; /* path didn't exist, tried to create, and */ return 3; /* failed: file exists, or 2+ levels required */ } } tmproot[rootlen++] = '/'; tmproot[rootlen] = '\0'; if ((rootpath = (char *)realloc(tmproot, rootlen+1)) == NULL) { free(tmproot); rootlen = 0; return 10; } Trace((stderr, "rootpath now = [%s]\n", rootpath)); } return 0; } #endif /* !SFX || SFX_EXDIR */ /*--------------------------------------------------------------------------- END: free rootpath, immediately prior to program exit. ---------------------------------------------------------------------------*/ if (FUNCTION == END) { Trace((stderr, "freeing rootpath\n")); if (rootlen > 0) { free(rootpath); rootlen = 0; } return 0; } return 99; /* should never reach */ } /* end function checkdir() */ /****************************/ /* Function close_outfile() */ /****************************/ void close_outfile(__G) /* GRR: change to return PK-style warning level */ __GDEF { #ifdef USE_EF_UT_TIME unsigned eb_izux_flg; iztimes zt; #endif ztimbuf tp; /*--------------------------------------------------------------------------- If symbolic links are supported, allocate a storage area, put the uncom- pressed "data" in it, and create the link. Since we know it's a symbolic link to start with, we shouldn't have to worry about overflowing unsigned ints with unsigned longs. ---------------------------------------------------------------------------*/ /* symlinks allowed on minix filesystems [cjh] * Hopefully this will work properly... We won't bother to try if * MiNT isn't present; the symlink should fail if we're on a TOS * filesystem. * BUG: should we copy the original file to the "symlink" if the * link fails? */ if (G.symlnk) { unsigned ucsize = (unsigned)G.lrec.ucsize; char *linktarget = (char *)malloc((unsigned)G.lrec.ucsize+1); fclose(G.outfile); /* close "data" file... */ G.outfile = fopen(G.filename, FOPR); /* ...and reopen for reading */ if (!linktarget || (fread(linktarget, 1, ucsize, G.outfile) != (int)ucsize)) { Info(slide, 0x201, ((char *)slide, "warning: symbolic link (%s) failed\n", G.filename)); if (linktarget) free(linktarget); fclose(G.outfile); return; } fclose(G.outfile); /* close "data" file for good... */ unlink(G.filename); /* ...and delete it */ linktarget[ucsize] = '\0'; if (QCOND2) Info(slide, 0, ((char *)slide, "-> %s ", linktarget)); if (symlink(linktarget, G.filename)) /* create the real link */ perror("symlink error"); free(linktarget); return; /* can't set time on symlinks */ } fclose(G.outfile); /*--------------------------------------------------------------------------- Convert from MSDOS-format local time and date to Unix-format 32-bit GMT time: adjust base year from 1980 to 1970, do usual conversions from yy/mm/dd hh:mm:ss to elapsed seconds, and account for timezone and day- light savings time differences. ---------------------------------------------------------------------------*/ #ifdef USE_EF_UT_T0pI UNZIP.BCK< [UNZIP542.ATARI]ATARI.C;1@6p ;IME eb_izux_flg = (G.extra_field #ifdef IZ_CHECK_TZ && G.tz_is_valid #endif ? ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0, G.lrec.last_mod_dos_datetime, &zt, NULL) : 0); if (eb_izux_flg & EB_UT_FL_MTIME) { tp.modtime = zt.mtime; TTrace((stderr, "\nclose_outfile: Unix e.f. modif. time = %ld\n", tp.modtime)); } else { tp.modtime = dos_to_unix_time(G.lrec.last_mod_dos_datetime); } if (eb_izux_flg & EB_UT_FL_ATIME) { tp.actime = zt.atime; TTrace((stderr, "close_outfile: Unix e.f. access time = %ld\n", tp.actime)); } else { tp.actime = tp.modtime; TTrace((stderr, "\nclose_outfile: modification/access times = %ld\n", tp.modtime)); } #else /* !USE_EF_UT_TIME */ tp.actime = tp.modtime = dos_to_unix_time(G.lrec.last_mod_dos_datetime); TTrace((stderr, "\nclose_outfile: modification/access times = %ld\n", tp.modtime)); #endif /* ?USE_EF_UT_TIME */ /* set the file's access and modification times */ if (utime(G.filename, &tp)) Info(slide, 0x201, ((char *)slide, "warning: cannot set the time for %s\n", G.filename)); /*--------------------------------------------------------------------------- Change the file permissions from default ones to those stored in the zipfile. ---------------------------------------------------------------------------*/ #ifndef NO_CHMOD if (chmod(G.filename, 0xffff & G.pInfo->file_attr)) perror("chmod (file attributes) error"); #endif } /* end function close_outfile() */ #ifdef TIMESTAMP /***************************/ /* Function stamp_file() */ /***************************/ int stamp_file(fname, modtime) ZCONST char *fname; time_t modtime; { ztimbuf tp; tp.modtime = tp.actime = modtime; return (utime(fname, &tp)); } /* end function stamp_file() */ #endif /* TIMESTAMP */ #ifndef SFX /************************/ /* Function version() */ /************************/ void version(__G) __GDEF { #ifdef __TURBOC__ char buf[40]; #endif sprintf((char *)slide, LoadFarString(CompiledWith), #ifdef __GNUC__ "gcc ", __VERSION__, #else # if 0 "cc ", (sprintf(buf, " version %d", _RELEASE), buf), # else # ifdef __TURBOC__ "Turbo C", (sprintf(buf, " (0x%04x = %d)", __TURBOC__, __TURBOC__), buf), # else "unknown compiler", "", # endif # endif #endif #ifdef __MINT__ "Atari TOS/MiNT", #else "Atari TOS", #endif " (Atari ST/TT/Falcon030)", #ifdef __DATE__ " on ", __DATE__ #else "", "" #endif ); (*G.message)((zvoid *)&G, slide, (ulg)strlen((char *)slide), 0); } /* end function version() */ #endif /* !SFX */ *[UNZIP542.ATARI]CONTENTS.;1+,cV./ 4[- 0@123KPWO56zӧ27zӧ289GHJContents of the "atari" sub-archive for UnZip 5.3 and later: Contents this file README.old old notes on compiling UnZip, from author of Atari port Makefile.old makefile for GNU C compiler and MiNT libraries Makefile newer, Unix-based makefile (lots of unnecessary baggage :-( ) make_unz.mup script file for invoking makefile(s)? atari.c Atari-specific routines The maintainers of the Atari port have fallen behind in their duties; the code *probably* compiles, but it has not been tested recently. Feel free to send zip-bugs e-mail about this sorry state of affairs. u*[UNZIP542.ATARI]MAKEFILE.;1+,dO./ 4~- 0@123KPWO56U"C7U"C89GHJ #============================================================================== # Makefile for UnZip, UnZipSFX and fUnZip: Atari ("real" makes only) # Version: 5.41 28 April 2000 #============================================================================== # INSTRUCTIONS (such as they are): # # "make" -- makes UnZip on a generic Atari # # CF are flags for the C compiler. LF are flags for the loader. LF2 are more # flags for the loader, if they need to be at the end of the line instead of at # the beginning (for example, some libraries). FL and FL2 are the corre- # sponding flags for fUnZip. LOCAL_UNZIP is an environment variable that can # be used to add default C flags to your compile without editing the Makefile # (e.g., -DDEBUG_STRUC, or -FPi87 on PCs using Microsoft C). # # Be sure to test your new UnZip (and UnZipSFX and fUnZip); successful compila- # tion does not always imply a working program. ##################### # MACRO DEFINITIONS # ##################### # Defaults most systems use (use LOCAL_UNZIP in environment to add flags, # such as -DDOSWILD). # UnZip flags CC = gcc# try using "gcc" target rather than changing this (if you do, LD = $(CC)# you MUST change LD, too--else "unresolved symbol: ___main") LOC = $(LOCAL_UNZIP) CF = $(CFLAGS) $(LOC) LF = -o unzip$E LF2 = -s # UnZipSFX flags SL = -o unzipsfx$E SL2 = $(LF2) # fUnZip flags FL = -o funzip$E FL2 = $(LF2) # general-purpose stuff CP = ln -s LN = ln RM = rm -f CHMOD = chmod STRIP = strip E = .ttp O = .o M = atari SHELL = /bin/sh # object files OBJS1 = unzip$O crc32$O crctab$O crypt$O envargs$O explode$O OBJS2 = extract$O fileio$O globals$O inflate$O list$O match$O OBJS3 = process$O ttyio$O unreduce$O unshrink$O zipinfo$O OBJS = $(OBJS1) $(OBJS2) $(OBJS3) $M$O LOBJS = $(OBJS) OBJSDLL = $(OBJS) api$O OBJX = unzipsfx$O crc32$O crctab$O crypt$O extract_$O fileio$O globals$O \ inflate$O match$O process_$O ttyio$O $M_$O LOBJX = $(OBJX) OBJF = funzip$O crc32$O crypt_$O globals_$O inflate_$O ttyio_$O #OBJS_OS2 = $(OBJS1:.o=.obj) $(OBJS2:.o=.obj) os2.obj #OBJF_OS2 = $(OBJF:.o=.obj) UNZIP_H = unzip.h unzpriv.h globals.h # installation INSTALL = cp# probably can change this to 'install' if you have it # on some systems, manext=l and MANDIR=/usr/man/man$(manext) may be appropriate manext = 1 prefix = /usr/local BINDIR = $(prefix)/bin# where to install executables MANDIR = $(prefix)/man/man$(manext)# where to install man pages INSTALLEDBIN = $(BINDIR)/funzip$E $(BINDIR)/zipinfo$E $(BINDIR)/unzipsfx$E \ $(BINDIR)/unzip$E INSTALLEDMAN = $(MANDIR)/unzip.$(manext) $(MANDIR)/funzip.$(manext) \ $(MANDIR)/unzipsfx.$(manext) $(MANDIR)/zipinfo.$(manext) # UNZIPS = unzip$E funzip$E unzipsfx$E # this is a little ugly...well, no, it's a lot ugly: MANS = man/unzip.1 man/unzipsfx.1 man/zipinfo.1 man/funzip.1 DOCS = unzip.txt unzipsfx.txt zipinfo.txt funzip.txt ############################################### # BASIC COMPILE INSTRUCTIONS AND DEPENDENCIES # ######################################1p UNZIP.BCKdO NZIP542.ATARI]MAKEFILE.;1o######### # this is for GNU make; comment out and notify zip-bugs if it causes errors .SUFFIXES: .c .o .obj # yes, we should be able to use the $O macro to combine these two, but it # fails on some brain-damaged makes (e.g., AIX's)...no big deal .c.o: $(CC) -c $(CF) $*.c .c.obj: $(CC) -c $(CF) $*.c #################### # DEFAULT HANDLING # #################### all: unzips unzips: $(UNZIPS) docs: $(DOCS) unzipsman: unzips docs unzipsdocs: unzips docs unzip$E: $(OBJS) $(LD) $(LF) $(LOBJS) $(LF2) unzipsfx$E: $(OBJX) $(LD) $(SL) $(LOBJX) $(SL2) funzip$E: $(OBJF) $(LD) $(FL) $(OBJF) $(FL2) crc32$O: crc32.c $(UNZIP_H) zip.h crctab$O: crctab.c $(UNZIP_H) zip.h crypt$O: crypt.c $(UNZIP_H) zip.h crypt.h ttyio.h envargs$O: envargs.c $(UNZIP_H) explode$O: explode.c $(UNZIP_H) extract$O: extract.c $(UNZIP_H) crypt.h fileio$O: fileio.c $(UNZIP_H) crypt.h ttyio.h ebcdic.h funzip$O: funzip.c $(UNZIP_H) crypt.h ttyio.h tables.h globals$O: globals.c $(UNZIP_H) inflate$O: inflate.c inflate.h $(UNZIP_H) list$O: list.c $(UNZIP_H) match$O: match.c $(UNZIP_H) process$O: process.c $(UNZIP_H) ttyio$O: ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h unreduce$O: unreduce.c $(UNZIP_H) unshrink$O: unshrink.c $(UNZIP_H) unzip$O: unzip.c $(UNZIP_H) crypt.h version.h consts.h zipinfo$O: zipinfo.c $(UNZIP_H) crypt_$O: crypt.c $(UNZIP_H) zip.h crypt.h ttyio.h # funzip only $(CP) crypt.c crypt_.c $(CC) -c $(CF) -DFUNZIP crypt_.c $(RM) crypt_.c extract_$O: extract.c $(UNZIP_H) crypt.h # unzipsfx only $(CP) extract.c extract_.c $(CC) -c $(CF) -DSFX extract_.c $(RM) extract_.c globals_$O: globals.c $(UNZIP_H) # funzip only $(CP) globals.c globals_.c $(CC) -c $(CF) -DFUNZIP globals_.c $(RM) globals_.c inflate_$O: inflate.c inflate.h $(UNZIP_H) crypt.h # funzip only $(CP) inflate.c inflate_.c $(CC) -c $(CF) -DFUNZIP inflate_.c $(RM) inflate_.c ttyio_$O: ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h # funzip only $(CP) ttyio.c ttyio_.c $(CC) -c $(CF) -DFUNZIP ttyio_.c $(RM) ttyio_.c process_$O: process.c $(UNZIP_H) # unzipsfx only $(CP) process.c process_.c $(CC) -c $(CF) -DSFX process_.c $(RM) process_.c atari_$O: atari.c $(UNZIP_H) $(CP) atari.c atari_.c $(CC) -c $(CF) -DSFX atari_.c $(RM) atari_.c unzipsfx$O: unzip.c $(UNZIP_H) crypt.h version.h consts.h # unzipsfx only $(CP) unzip.c unzipsfx.c $(CC) -c $(CF) -DSFX unzipsfx.c $(RM) unzipsfx.c # this really only works for Unix targets, unless specify E and O on cmd line clean: @echo "" @echo ' This is a Unix-specific target. (Just so you know.)' @echo "" rm -f $(OBJS) api$O apihelp$O unzipstb$O $(OBJF) $(OBJX) $(UNZIPS) install: $(UNZIPS) $(MANS) $(INSTALL) $(UNZIPS) $(BINDIR) $(RM) $(BINDIR)/zipinfo$E $(LN) $(BINDIR)/unzip$E $(BINDIR)/zipinfo$E $(INSTALL) man/unzip.1 $(MANDIR)/unzip.$(manext) $(INSTALL) man/unzipsfx.1 $(MANDIR)/unzipsfx.$(manext) $(INSTALL) man/zipinfo.1 $(MANDIR)/zipinfo.$(manext) $(INSTALL) man/funzip.1 $(MANDIR)/funzip.$(manext) $(CHMOD) 755 $(INSTALLEDBIN) $(CHMOD) 644 $(INSTALLEDMAN) # alternatively, could use zip method: -cd $(BINDIR); rm -f $(UNZIPS) [etc.] uninstall: rm -f $(INSTALLEDBIN) $(INSTALLEDMAN) TESTZIP = testmake.zip # the test zipfile # test some basic features of the build test: check check: unzips @echo ' This is a Unix-specific target. (Just so you know.)' if test ! -f $(TESTZIP); then \ echo " error: can't find test file $(TESTZIP)"; exit 1; fi # echo " testing extraction" ./unzip -b $(TESTZIP) testmake.zipinfo if test $? ; then \ echo " error: file extraction from $(TESTZIP) failed"; exit 1; fi # echo ' testing zipinfo (unzip -Z)' ./unzip -Z $(TESTZIP) > testmake.unzip-Z if diff testmake.unzip-Z testmake.zipinfo; then ;; else \ echo ' error: zipinfo output doesn't match stored version'; fi $(RM) testmake.unzip-Z testmake.zipinfo # echo ' testing unzip -d exdir option' ./unzip -b $(TESTZIP) -d testun cat testun/notes # echo ' testing unzip -o and funzip (ignore funzip warning)' ./unzip -boq $(TESTZIP) notes -d testun ./funzip < $(TESTZIP) > testun/notes2 if diff testun/notes testun/notes2; then ;; else \ echo 'error: funzip output disagrees with unzip'; fi # echo ' testing unzipsfx (self-extractor)' cat unzipsfx $(TESTZIP) > testsfx $(CHMOD) 0700 testsfx ./testsfx -b notes if diff notes testun/notes; then ;; else \ echo ' error: unzipsfx file disagrees with unzip'; fi $(RM) testsfx notes testun/notes testun/notes2 rmdir testun # echo ' testing complete.' ################################ # INDIVIDUAL MACHINE MAKERULES # ################################ # these are left over for backward compatibility/convenience generic: unzips atari: unzips *[UNZIP542.ATARI]MAKEFILE.OLD;1+,e,. / 4 - 0@123KPWO 56 make_all.mup #fixstk 32K pgp.ttp prgflags 017 007 *.ttp -*[UNZIP542.ATARI]README.OLD;1+,I./ 4h- 0@123KPWO56!b7!b89GHJ Here it is... the UnZip 5.1 port for the Atari ST/TT/Falcon! This took me longer than I expected thanks to a difference between the MiNT library and most UNIX libraries... symlinks are 0x16000 instead of 0xa000... I'm told this isn't even defined in POSIX, so I can't really complain. At least we've got a filesystem that can use symlinks! This port requires GNU C and allows you to build an unzip/zipinfo/funzip that supports long filenames (on appropriate filesystems, thanks to the MiNT library), as well as symlinks. It also does "proper" (ie, DOS-style) translation of text-file end-of-line characters. The programs also build as shared-text binaries, so you can start unzipping several files at once in the background and only a small part of unzip will be duplicated in memory. I build unzip with the MiNT library, GNU C 2.5.8 (2.5.7 and lower have a rather sever problem in the optimiser that affects 68000 code only; it adds 68020-only instructions to the 68000 code). Oh, and I tested it extensively under MiNT's minix filesystem as well as the bogus DOS filesystem that "normal" Atari partitions have. The Makefile won't need any editing if you want to built unzip et al. on a minix filesystem; if you want to install it on a DOS filesystem, use "cp" instead of "ln" for zipinfo. [Or, to save disk space, make a script/ command-file which invokes "unzip -Z ...". --CN] This is such a good idea that I'm annoyed that Greg thought of it and I didn't... ;-) If you're using a shell worth your while, you can alias zipinfo to 'unzip -Z' and then forget all about this paragraph. If you want to compile this using Turbo C (aka Pure C in North America) you're on your own... That's ok, I'll make a nice binary version of unzip available as soon as the official 5.1 version is released (give or take a few days). Enjoy! Cave Newt should be given kudos for keeping this monster easy to port... ;-) [Hah! But thanks anyway. :-) --CN] PLEASE email me to tell me if you've uploaded the source or binary versions of Unzip 5.x to any BBS systems or commercial online systems so we can update the WHERE file! -Chris Herborth- 3ߨ܇ UNZIP.BCK  [UNZIP542]BEOS.DIR;1?z*[UNZIP542]BEOS.DIR;1+, ./ 4- 0123 KPWO56h$'!a7h$'!a89GHJIBEOS.C*BEOS.HK BEOSMAIN.CPP6 CONTENTS.2 MAKEFILE.3README.2 UNZIP.RSC' UNZIPSFX.RSCD*[UNZIP542.BEOS]BEOS.C;1+,*.U/ 4UU- 0@123KPWOV56 7 89GHJ/* Copyright (c) 1990-2000 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*--------------------------------------------------------------------------- beos.c BeOS-specific routines for use with Info-ZIP's UnZip 5.30 and later. (based on unix/unix.c) Contains: do_wild() <-- generic enough to put in fileio.c? mapattr() mapname() checkdir() close_outfile() set_direc_attribs() stamp_file() version() scanBeOSexfield() set_file_attrs() setBeOSexfield() printBeOSexfield() assign_MIME() ---------------------------------------------------------------------------*/ #define UNZIP_INTERNAL #include "unzip.h" #include "beos.h" #include /* Just make sure we've got a few things... */ #include #include #include #include /* For the new post-DR8 file attributes */ #include #include #include static uch *scanBeOSexfield OF((const uch *ef_ptr, unsigned ef_len)); static int set_file_attrs( const char *, const unsigned char *, const off_t ); static void setBeOSexfield OF((const char *path, uch *extra_field)); #ifdef BEOS_USE_PRINTEXFIELD static void printBeOSexfield OF((int isdir, uch *extra_field)); #endif #ifdef BEOS_ASSIGN_FILETYPE static void assign_MIME( const char * ); #endif static int created_dir; /* used in mapname(), checkdir() */ static int renamed_fullpath; /* ditto */ #ifndef SFX /**********************/ /* Function do_wild() */ /* for porting: dir separator; match(ignore_case) */ /**********************/ char *do_wild(__G__ wildspec) __GDEF ZCONST char *wildspec; /* only used first time on a given dir */ { static DIR *wild_dir = (DIR *)NULL; static ZCONST char *wildname; static char *dirname, matchname[FILNAMSIZ]; static int notfirstcall=FALSE, have_dirname, dirnamelen; struct dirent *file; /* Even when we're just returning wildspec, we *always* do so in * matchname[]--calling routine is allowed to append four characters * to the returned string, and wildspec may be a pointer to argv[]. */ if (!notfirstcall) { /* first call: must initialize everything */ notfirstcall = TRUE; if (!iswild(wildspec)) { strcpy(matchname, wildspec); have_dirname = FALSE; wild_dir = NULL; return matchname; } /* break the wildspec into a directory part and a wildcard filename */ if ((wildname = strrchr(wildspec, '/')) == (ZCONST char *)NULL) { dirname = "."; dirnamelen = 1; have_dirname = FALSE; wildname = wildspec; } else { ++wildname; /* point at character after '/' */ dirnamelen = wildname - wildspec; if ((dirname = (char *)malloc(dirnamelen+1)) == (char *)NULL) { Info(slide, 0x201, ((char *)slide, "warning: cannot allocate wildcard buffers\n")); strcpy(matchname, wildspec); return matchname; /* but maybe filespec was not a wildcard */ } strncpy(dirname, wildspec, dirnamelen); dirname[dirnamelen] = '\0'; /* terminate for strcpy below */ have_dirname = TRUE; } if ((wild_dir = opendir(dirname)) != (DIR *)NULL) { while ((file = readdir(wild_dir)) != (struct dirent *)NULL) { if (file->d_name[0] == '.' && wildname[0] != '.') continue; /* Unix: '*' and '?' do not match leading dot */ if (match(file->d_name, wildname, 0)) { /* 0 == case sens. */ if (have_dirname) { strcpy(matchname, dirname); strcpy(matchname+dirnamelen, file->d_name); } else strcpy(matchname, file->d_name); return matchname; } } /* if we get to here directory is exhausted, so close it */ closedir(wild_dir); wild_dir = (DIR *)NULL; } /* return the raw wildspec in case that works (e.g., directory not * searchable, but filespec was not wild and file is readable) */ strcpy(matchname, wildspec); return matchname; } /* last time through, might have failed opendir but returned raw wildspec */ if (wild_dir == (DIR *)NULL) { notfirstcall = FALSE; /* nothing left to try--reset for new wildspec */ if (have_dirname) free(dirname); return (char *)NULL; } /* If we've gotten this far, we've read and matched at least one entry * successfully (in a previous call), so dirname has been copied into * matchname already. */ while ((file = readdir(wild_dir)) != (struct dirent *)NULL) { if (file->d_name[0] == '.' && wildname[0] != '.') continue; /* Unix: '*' and '?' do not match leading dot */ if (match(file->d_name, wildname, 0)) { /* 0 == don't ignore case */ if (have_dirname) { /* strcpy(matchname, dirname); */ strcpy(matchname+dirnamelen, file->d_name); } else strcpy(matchname, file->d_name); return matchname; } } closedir(wild_dir); /* have read at least one entry; nothing left */ wild_dir = (DIR *)NULL; notfirstcall = FALSE; /* reset for new wildspec */ if (have_dirname) free(dirname); return (char *)NULL; } /* end function do_wild() */ #endif /* !SFX */ /**********************/ /* Function mapattr() */ /**********************/ int mapattr(__G) __GDEF { ulg tmp = G.crec.external_file_attributes; switch (G.pInfo->hostnum) { case AMIGA_: tmp = (unsigned)(tmp>>17 & 7); /* Amiga RWE bits */ G.pInfo->file_attr = (unsigned)(tmp<<6 | tmp<<3 | tmp); break; case THEOS_: tmp &= 0xF1FFFFFFL; if ((tmp & 0xF0000000L) != 0x40000000L) tmp &= 0x01FFFFFFL; /* not a dir, mask all ftype bits */ else 41 UNZIP.BCK* [UNZIP542.BEOS]BEOS.C;1U tmp &= 0x41FFFFFFL; /* leave directory bit as set */ /* fall through! */ case BEOS_: case UNIX_: case VMS_: case ACORN_: case ATARI_: case QDOS_: case TANDEM_: G.pInfo->file_attr = (unsigned)(tmp >> 16); if (G.pInfo->file_attr != 0 || !G.extra_field) { return 0; } else { /* Some (non-Info-ZIP) implementations of Zip for Unix and VMS (and probably others ??) leave 0 in the upper 16-bit part of the external_file_attributes field. Instead, they store file permission attributes in some extra field. As a work-around, we search for the presence of one of these extra fields and fall back to the MSDOS compatible part of external_file_attributes if one of the known e.f. types has been detected. Later, we might implement extraction of the permission bits from the VMS extra field. But for now, the work-around should be sufficient to provide "readable" extracted files. (For ASI Unix e.f., an experimental remap of the e.f. mode value IS already provided!) */ ush ebID; unsigned ebLen; uch *ef = G.extra_field; unsigned ef_len = G.crec.extra_field_length; int r = FALSE; while (!r && ef_len >= EB_HEADSIZE) { ebID = makeword(ef); ebLen = (unsigned)makeword(ef+EB_LEN); if (ebLen > (ef_len - EB_HEADSIZE)) /* discoverd some e.f. inconsistency! */ break; switch (ebID) { case EF_ASIUNIX: if (ebLen >= (EB_ASI_MODE+2)) { G.pInfo->file_attr = (unsigned)makeword(ef+(EB_HEADSIZE+EB_ASI_MODE)); /* force stop of loop: */ ef_len = (ebLen + EB_HEADSIZE); break; } /* else: fall through! */ case EF_PKVMS: /* "found nondecypherable e.f. with perm. attr" */ r = TRUE; default: break; } ef_len -= (ebLen + EB_HEADSIZE); ef += (ebLen + EB_HEADSIZE); } if (!r) return 0; } /* fall through! */ /* all remaining cases: expand MSDOS read-only bit into write perms */ case FS_FAT_: /* PKWARE's PKZip for Unix marks entries as FS_FAT_, but stores the * Unix attributes in the upper 16 bits of the external attributes * field, just like Info-ZIP's Zip for Unix. We try to use that * value, after a check for consistency with the MSDOS attribute * bits (see below). */ G.pInfo->file_attr = (unsigned)(tmp >> 16); /* fall through! */ case FS_HPFS_: case FS_NTFS_: case MAC_: case TOPS20_: default: /* Ensure that DOS subdir bit is set when the entry's name ends * in a '/'. Some third-party Zip programs fail to set the subdir * bit for directory entries. */ if ((tmp | 0x10) == 0) { extent fnlen = strlen(G.filename); if (fnlen > 0 && G.filename[fnlen-1] == '/') tmp |= 0x10; } /* read-only bit --> write perms; subdir bit --> dir exec bit */ tmp = !(tmp & 1) << 1 | (tmp & 0x10) >> 4; if ((G.pInfo->file_attr & 0700) == (unsigned)(0400 | tmp<<6)) /* keep previous G.pInfo->file_attr setting, when its "owner" * part appears to be consistent with DOS attribute flags! */ return 0; G.pInfo->file_attr = (unsigned)(0444 | tmp<<6 | tmp<<3 | tmp); break; } /* end switch (host-OS-created-by) */ /* for originating systems with no concept of "group," "other," "system": */ umask( (int)(tmp=umask(0)) ); /* apply mask to expanded r/w(/x) perms */ G.pInfo->file_attr &= ~tmp; return 0; } /* end function mapattr() */ /************************/ /* Function mapname() */ /************************/ /* return 0 if no error, 1 if caution (filename */ int mapname(__G__ renamed) /* truncated), 2 if warning (skip file because */ __GDEF /* dir doesn't exist), 3 if error (skip file), */ int renamed; /* or 10 if out of memory (skip file) */ { /* [also IZ_VOL_LABEL, IZ_CREATED_DIR] */ char pathcomp[FILNAMSIZ]; /* path-component buffer */ char *pp, *cp=(char *)NULL; /* character pointers */ char *lastsemi=(char *)NULL; /* pointer to last semi-colon in pathcomp */ int quote = FALSE; /* flags */ int error = 0; register unsigned workch; /* hold the character being tested */ /*--------------------------------------------------------------------------- Initialize various pointers and counters and stuff. ---------------------------------------------------------------------------*/ if (G.pInfo->vollabel) return IZ_VOL_LABEL; /* can't set disk volume labels in BeOS */ /* can create path as long as not just freshening, or if user told us */ G.create_dirs = (!uO.fflag || renamed); created_dir = FALSE; /* not yet */ /* user gave full pathname: don't prepend rootpath */ renamed_fullpath = (renamed && (*G.filename == '/')); if (checkdir(__G__ (char *)NULL, INIT) == 10) return 10; /* initialize path buffer, unless no memory */ *pathcomp = '\0'; /* initialize translation buffer */ pp = pathcomp; /* point to translation buffer */ if (uO.jflag) /* junking directories */ cp = (char *)strrchr(G.filename, '/'); if (cp == (char *)NULL) /* no '/' or not junking dirs */ cp = G.filename; /* point to internal zipfile-member pathname */ else ++cp; /* point to start of last component of path */ /*--------------------------------------------------------------------------- Begin main loop through characters in filename. ---------------------------------------------------------------------------*/ while ((workch = (uch)*cp++) != 0) { if (quote) { /* if character quoted, */ *pp++ = (char)workch; /* include it literally */ quote = FALSE; } else switch (workch) { case '/': /* can assume -j flag not given */ *pp = '\0'; if ((error = checkdir(__G__ pathcomp, APPEND_DIR)) > 1) return error; pp = pathcomp; /* reset conversion buffer for next piece */ lastsemi = (char *)NULL; /* leave directory semi-colons alone */ break; case ';': /* VMS version (or DEC-20 attrib?) */ lastsemi = pp; *pp++ = ';'; /* keep for now; remove VMS ";##" */5sM) UNZIP.BCK* [UNZIP542.BEOS]BEOS.C;1U$ break; /* later, if requested */ case '\026': /* control-V quote for special chars */ quote = TRUE; /* set flag for next character */ break; default: /* allow European characters in filenames: */ if (isprint(workch) || (128 <= workch && workch <= 254)) *pp++ = (char)workch; } /* end switch */ } /* end while loop */ *pp = '\0'; /* done with pathcomp: terminate it */ /* if not saving them, remove VMS version numbers (appended ";###") */ if (!uO.V_flag && lastsemi) { pp = lastsemi + 1; while (isdigit((uch)(*pp))) ++pp; if (*pp == '\0') /* only digits between ';' and end: nuke */ *lastsemi = '\0'; } /*--------------------------------------------------------------------------- Report if directory was created (and no file to create: filename ended in '/'), check name to be sure it exists, and combine path and name be- fore exiting. ---------------------------------------------------------------------------*/ if (G.filename[strlen(G.filename) - 1] == '/') { checkdir(__G__ G.filename, GETPATH); if (created_dir) { if (QCOND2) { Info(slide, 0, ((char *)slide, " creating: %s\n", G.filename)); } if (!uO.J_flag) { /* Handle the BeOS extra field if present. */ void *ptr = scanBeOSexfield( G.extra_field, G.lrec.extra_field_length ); if (ptr) { setBeOSexfield( G.filename, ptr ); } } #ifndef NO_CHMOD /* set approx. dir perms (make sure can still read/write in dir) */ if (chmod(G.filename, (0xffff & G.pInfo->file_attr) | 0700)) perror("chmod (directory attributes) error"); #endif return IZ_CREATED_DIR; /* set dir time (note trailing '/') */ } /* TODO: should we re-write the BeOS extra field data in case it's */ /* changed? The answer is yes. [Sept 1999 - cjh] */ if (!uO.J_flag) { /* Handle the BeOS extra field if present. */ void *ptr = scanBeOSexfield( G.extra_field, G.lrec.extra_field_length ); if (ptr) { setBeOSexfield( G.filename, ptr ); } } return 2; /* dir existed already; don't look for data to extract */ } if (*pathcomp == '\0') { Info(slide, 1, ((char *)slide, "mapname: conversion of %s failed\n", G.filename)); return 3; } checkdir(__G__ pathcomp, APPEND_NAME); /* returns 1 if truncated: care? */ checkdir(__G__ G.filename, GETPATH); return error; } /* end function mapname() */ /***********************/ /* Function checkdir() */ /***********************/ int checkdir(__G__ pathcomp, flag) __GDEF char *pathcomp; int flag; /* * returns: 1 - (on APPEND_NAME) truncated filename * 2 - path doesn't exist, not allowed to create * 3 - path doesn't exist, tried to create and failed; or * path exists and is not a directory, but is supposed to be * 4 - path is too long * 10 - can't allocate memory for filename buffers */ { static int rootlen = 0; /* length of rootpath */ static char *rootpath; /* user's "extract-to" directory */ static char *buildpath; /* full path (so far) to extracted file */ static char *end; /* pointer to end of buildpath ('\0') */ # define FN_MASK 7 # define FUNCTION (flag & FN_MASK) /*--------------------------------------------------------------------------- APPEND_DIR: append the path component to the path being built and check for its existence. If doesn't exist and we are creating directories, do so for this one; else signal success or error as appropriate. ---------------------------------------------------------------------------*/ if (FUNCTION == APPEND_DIR) { int too_long = FALSE; #ifdef SHORT_NAMES char *old_end = end; #endif Trace((stderr, "appending dir segment [%s]\n", pathcomp)); while ((*end = *pathcomp++) != '\0') ++end; #ifdef SHORT_NAMES /* path components restricted to 14 chars, typically */ if ((end-old_end) > FILENAME_MAX) /* GRR: proper constant? */ *(end = old_end + FILENAME_MAX) = '\0'; #endif /* GRR: could do better check, see if overrunning buffer as we go: * check end-buildpath after each append, set warning variable if * within 20 of FILNAMSIZ; then if var set, do careful check when * appending. Clear variable when begin new path. */ if ((end-buildpath) > FILNAMSIZ-3) /* need '/', one-char name, '\0' */ too_long = TRUE; /* check if extracting directory? */ if (stat(buildpath, &G.statbuf)) { /* path doesn't exist */ if (!G.create_dirs) { /* told not to create (freshening) */ free(buildpath); return 2; /* path doesn't exist: nothing to do */ } if (too_long) { Info(slide, 1, ((char *)slide, "checkdir error: path too long: %s\n", buildpath)); free(buildpath); return 4; /* no room for filenames: fatal */ } if (mkdir(buildpath, 0777) == -1) { /* create the directory */ Info(slide, 1, ((char *)slide, "checkdir error: cannot create %s\n\ unable to process %s.\n", buildpath, G.filename)); free(buildpath); return 3; /* path didn't exist, tried to create, failed */ } created_dir = TRUE; } else if (!S_ISDIR(G.statbuf.st_mode)) { Info(slide, 1, ((char *)slide, "checkdir error: %s exists but is not directory\n\ unable to process %s.\n", buildpath, G.filename)); free(buildpath); return 3; /* path existed but wasn't dir */ } if (too_long) { Info(slide, 1, ((char *)slide, "checkdir error: path too long: %s\n", buildpath)); free(buildpath); return 4; /* no room for filenames: fatal */ } *end++ = '/'; *end = '\0'; Trace((stderr, "buildpath now = [%s]\n", buildpath)); return 0; } /* end if (FUNCTION == APPEND_DIR) */ /*--------------------------------------------------------------------------- GETPATH: copy full path to the string pointed at by pathcomp, and free buildpath. ---------------------------------------------------------------------------*/ if (FUNCTION == GETPATH) { strcpy(pathcomp, buildpath); Trace((stderr, "getting and freeing path [%s]\n", pathcomp)); free(buildpath); buildpath = end = (char *)NULL; return 0; } /*--------------------------------------------------------------------------- APPEND_NAME: assume the path component is the filename; append it and return without checking for existence. ---------------------------------------------------------------------------*/ if (FUNCTION == APPEND_NAME) { #ifdef SHORT_NAMES char *old_end = end; #endif Trace((stderr, "appending filen6֒A UNZIP.BCK* [UNZIP542.BEOS]BEOS.C;1U,ame [%s]\n", pathcomp)); while ((*end = *pathcomp++) != '\0') { ++end; #ifdef SHORT_NAMES /* truncate name at 14 characters, typically */ if ((end-old_end) > FILENAME_MAX) /* GRR: proper constant? */ *(end = old_end + FILENAME_MAX) = '\0'; #endif if ((end-buildpath) >= FILNAMSIZ) { *--end = '\0'; Info(slide, 0x201, ((char *)slide, "checkdir warning: path too long; truncating\n\ %s\n -> %s\n", G.filename, buildpath)); return 1; /* filename truncated */ } } Trace((stderr, "buildpath now = [%s]\n", buildpath)); return 0; /* could check for existence here, prompt for new name... */ } /*--------------------------------------------------------------------------- INIT: allocate and initialize buffer space for the file currently being extracted. If file was renamed with an absolute path, don't prepend the extract-to path. ---------------------------------------------------------------------------*/ /* GRR: for VMS and TOPS-20, add up to 13 to strlen */ if (FUNCTION == INIT) { Trace((stderr, "initializing buildpath to ")); if ((buildpath = (char *)malloc(strlen(G.filename)+rootlen+1)) == (char *)NULL) return 10; if ((rootlen > 0) && !renamed_fullpath) { strcpy(buildpath, rootpath); end = buildpath + rootlen; } else { *buildpath = '\0'; end = buildpath; } Trace((stderr, "[%s]\n", buildpath)); return 0; } /*--------------------------------------------------------------------------- ROOT: if appropriate, store the path in rootpath and create it if neces- sary; else assume it's a zipfile member and return. This path segment gets used in extracting all members from every zipfile specified on the command line. ---------------------------------------------------------------------------*/ #if (!defined(SFX) || defined(SFX_EXDIR)) if (FUNCTION == ROOT) { Trace((stderr, "initializing root path to [%s]\n", pathcomp)); if (pathcomp == (char *)NULL) { rootlen = 0; return 0; } if (rootlen > 0) /* rootpath was already set, nothing to do */ return 0; if ((rootlen = strlen(pathcomp)) > 0) { char *tmproot; if ((tmproot = (char *)malloc(rootlen+2)) == (char *)NULL) { rootlen = 0; return 10; } strcpy(tmproot, pathcomp); if (tmproot[rootlen-1] == '/') { tmproot[--rootlen] = '\0'; } if (rootlen > 0 && (stat(tmproot, &G.statbuf) || !S_ISDIR(G.statbuf.st_mode))) /* path does not exist */ { if (!G.create_dirs /* || iswild(tmproot) */ ) { free(tmproot); rootlen = 0; return 2; /* skip (or treat as stored file) */ } /* create the directory (could add loop here scanning tmproot * to create more than one level, but why really necessary?) */ if (mkdir(tmproot, 0777) == -1) { Info(slide, 1, ((char *)slide, "checkdir: cannot create extraction directory: %s\n", tmproot)); free(tmproot); rootlen = 0; /* path didn't exist, tried to create, and */ return 3; /* failed: file exists, or 2+ levels required */ } } tmproot[rootlen++] = '/'; tmproot[rootlen] = '\0'; if ((rootpath = (char *)realloc(tmproot, rootlen+1)) == NULL) { free(tmproot); rootlen = 0; return 10; } Trace((stderr, "rootpath now = [%s]\n", rootpath)); } return 0; } #endif /* !SFX || SFX_EXDIR */ /*--------------------------------------------------------------------------- END: free rootpath, immediately prior to program exit. ---------------------------------------------------------------------------*/ if (FUNCTION == END) { Trace((stderr, "freeing rootpath\n")); if (rootlen > 0) { free(rootpath); rootlen = 0; } return 0; } return 99; /* should never reach */ } /* end function checkdir() */ /****************************/ /* Function close_outfile() */ /****************************/ void close_outfile(__G) /* GRR: change to return PK-style warning level */ __GDEF { iztimes zt; ush z_uidgid[2]; unsigned eb_izux_flg; /*--------------------------------------------------------------------------- If symbolic links are supported, allocate a storage area, put the uncom- pressed "data" in it, and create the link. Since we know it's a symbolic link to start with, we shouldn't have to worry about overflowing unsigned ints with unsigned longs. ---------------------------------------------------------------------------*/ #ifdef SYMLINKS if (G.symlnk) { unsigned ucsize = (unsigned)G.lrec.ucsize; char *linktarget = (char *)malloc((unsigned)G.lrec.ucsize+1); fclose(G.outfile); /* close "data" file... */ G.outfile = fopen(G.filename, FOPR); /* ...and reopen for reading */ if (!linktarget || fread(linktarget, 1, ucsize, G.outfile) != (int)ucsize) { Info(slide, 0x201, ((char *)slide, "warning: symbolic link (%s) failed\n", G.filename)); if (linktarget) free(linktarget); fclose(G.outfile); return; } fclose(G.outfile); /* close "data" file for good... */ unlink(G.filename); /* ...and delete it */ linktarget[ucsize] = '\0'; if (QCOND2) Info(slide, 0, ((char *)slide, "-> %s ", linktarget)); if (symlink(linktarget, G.filename)) /* create the real link */ perror("symlink error"); if (!uO.J_flag) { /* Symlinks can have attributes, too. */ void *ptr = scanBeOSexfield( G.extra_field, G.lrec.extra_field_length ); if (ptr) { setBeOSexfield( G.filename, ptr ); } } free(linktarget); return; /* can't set time on symlinks */ } #endif /* SYMLINKS */ fclose(G.outfile); /* handle the BeOS extra field if present */ if (!uO.J_flag) { void *ptr = scanBeOSexfield( G.extra_field, G.lrec.extra_field_length ); if (ptr) { setBeOSexfield( G.filename, ptr ); #ifdef BEOS_ASSIGN_FILETYPE } else { /* Otherwise, ask the system to try assigning a MIME type. */ assign_MIME( G.filename ); #endif } } /*--------------------------------------------------------------------------- Change the file permissions from default ones to those stored in the zipfile. ---------------------------------------------------------------------------*/ #ifndef NO_CHMOD if (chmod(G.filename, 0xffff & G.pInfo->file_attr)) perror("chmod (file attributes) error"); #endif /*--------------------------------------------------------7#Vyix8ss hC;1t}D;1 H9jB\Fs &O s,Uk,i*A163,n2.[vPW3 xE}r2m}J v&Ye<nnJY'`2b/./Rr _- @6'a7LpxuqSSQ &1|AwKabIetv#rlJJA^]T/Sq/;Rs5q,U +TF+?rPg>4 WLIU)c:AKx n^-'a5nz/Rj:/V*e1\qwmQQ CFM%*KC+.s$i? cC_KzB9@srx=g1`+lE3~.;{D2qp-:|b9K] {NPk>kh0t8 1hFY}5hFl+ G6KM}j+3|5"!^/3.aPVd)tv}= ! z l 0O=`}-Qe?/6SYSYFFI&h+dDpti& ;jz;[ ,p1fgg ~hXE@ K<9, QPUwgs^flUi&je\mp8_FmI^aK\0[J)9P}K"{]BT,oEJ+y!+5h>4RS9DPkda.\R#yvYb]uJ:&[Dp\agS*yd3TNYyNvO QjE < LL#~&qcH"XL3A:$jS m~p~vnjp~wzIR5"!Fzjz]+]~W1O7;\?0\.bMYwD 9-iz|5th%R& 0,)@OעR40\=ڙ %pSWG)mn-*0|p|/DMRl^SdlWRI,u] |-%ns\)5u +[y&Y'sg8[d@ + j>9|#n?;58l& d:0vy9#=t_Dus6meH$e,%C\=hVP.do|GaGN0mpc 8SSIHbg-^Vh^Z+61,f__x;- U;!hrDx>?K#bgT6WUemd'!P2 ..4+>OF5GhiSG_4D1=KF} x+<rb}uLb \KP\f:f}@^MrN?dMG))$`4#ar:YIV9'gPCg]>T 7+ 4#h:/{\g+-"Mk}tv3!s'm?oH3^"sPR ;o AhHCnMV W1Q\UY:sg?EokO8+%!_W$zKE!4{,M\w= 7jXfALCB*@ H:@|]YYXa-G,OJc/`#}: 6f8X@LhrKt_!gtuyhOW\+,32M/DI}df"K"5(.Y%=+WI1+FW =^ENKv}>Ox#eEdqNtRfpoCn^NtW4YO.M}9)0i kq G-obq.>j[[e1;=W J)v43R]QH z" CzjG :f%1M@sx]uZ1r#S1F."B:Id(|>UYh Vn f*+}9;xRov Ev#H^Wh){kp^,!(,? 6[ -*7b6 uP*BY'e1_0/\LJaS '0i i)VW^SPW8I@vKPfYgKe5 %tQZG!G~gPcDhO/ %ponM+P`pN>Z)~.Wxr(A3[ j=Pi1, KS$dW-'5 'SKV3,n%`nv_ Uk%/ $;f<[.D30wJNnNY=H5l1Eh\A%~X50W}6w Gyv{asVllKxx7J tTM3ZsDtCQvch>TLy,lg&'MV5YSOj/;(z\=`qEK>]j\yE\8#re,-HI`BZJArSQQ\HXNH,g= @$q':&2 2<. oXSZJTd)tl 3,B7e|twfaS ?}]":mpLeX/eH^{g E!3g8u+qx 7)Fxq3=i#2MAf2I 8Oh{ S!v{v>24-|#.]j 6~m?_oA.^T>h>*[n }A Bzt^3~$,0]>31[11(9>Cyr5'dPRXJSbV}B|)9Nhi]{Ofsex4* 8%~k_?j]oMU`Djb !m{P#UX! ,o-UKjk3`U9Lsb3HH/hT~AKI)3"#u=:zeM boG=w6%pNbh+RCkUBOp}5`&f_wV'sl`g`e8S}j ,B-kpr''^n|f`!;tpsenyo2F-!+fCAZC@^tF NB\C]Tb++NXHK*MeL.F3n~M xzR>7nNp&o b EMeD\(u2#O[=5\-2CJRnIZA([C.B 7-)d/}XFS!dG$po;s'NCK^= b,n*fmJZL${$-TtzTbl y!@";huO0T_((vSIRNv\W, -ABVaI>U[JTbXV!n,$_EuM Lz.(3-O'cRl(}*A8/@q+trqpSm"g*x~nfq_3 yo9Vmx}`1O,,j#6y@v>0a5y=J|CBjMM8w&qZ\P@8h@N7 IqOf ^@dg3_!:UoCBJ(FC|[AP;QUM6KC]U}\A7K ] C>T#B F qljcZu_z -p)~Kuqk}%@jyh2&)7) VTqT[vHJg2m," y_QE0(S}4y`?>M QF][A cW8v_p#n5rf}DtSY@m ,"Eb";g~}e t+3a~%NT@0,O3mm5DE[Urh,<G^d`[6R?dOItj10J=VX F?v~Kql4?o%O1dr>9yZ~w*E3m)=>89g*&4xY' W2U_LXR= m@t#r 6AM1J![ -{gp^`"\'&Of[U|qD[8&A o'G%?H UO# 9mD8X|uR|l R^&LVaTISR(\CYznANCX=+w}9)L;TiP4*"] umIzq<1.~rt$5sl|3@e+}F`+x '0b3+l r2$'7jE:akUgFYLF&Qshk'a3m:VpS~$un~>1 cq?{3pk9R$}3*zVg08y,f175imIOn-V9lnz r[/ awZ!cr'&4-nd2nctr'QFt\};$7{sŗh{p!Ld>zL:z/APY`s>(JcDH2EjF@X4 wy:4v@aicM59b"'slI2SY0 mw!nfT@CZ~ QTY:q#%wg[ l;IMOIV*-w5!HI'RFg[c=$s7C%;F(70h:#u9];V) _OnXv@GJEEg@ <JFw2JQVb~m []J MQbj&budlFo>1g;m^ HYZoDL+)A5UNFXN]G^>J |_/c)8OiqgF\sza9W*!KVXPw34 @NcA \C l$F90y{!UT9SRQgH G'(HAJ+Yw"~v#JN]5:P29,k 02)O ."<}r{42<_ Y #*MV:!FPzObi8OS'w5{'TuY\GBv 6iSVeI`bi9Klk:rVq2>|.S0eiYBUV0\F;fhL0ZZVaZ ,I+a5p2n<_dQ651 A%)= Tuj^Ep;5ju,-f=nRoP}r?9!"92MX?HFC[p Bv|ztJ.Q$ F7tz2DD$'ECs_8c(uK=Yjl1#(w0 .K ^pX/Q% p|/RQDZ?Zhv+tPLYAUu8$PEK[}2GssOQNs$K2XT_2R7s~?jjdBYP4)U$aJ$1!KF%r> 5qsA@EKW!JR/~ >HYtBpoo ,$F{vq({7 eVsYG-K YDz`Ey`<U|i#g5=C AhQIhJJW:lk@q0Ax4Q|JodUh|_ (K2K hg,],QBI&3VwqE)Q.H; 8n9% xU%"IZqVWPi.[PYE^v.98O)<<ey/td8(P.\RV#GJ6K;YASB#5qDXYNm'X'93kwT?`/>)'mgu-Q@?MqI#~PT]dv$3q2I~g^a9 / 8GB_P%>?t)I ReA ln Kl"9H* |MVJi^ KP)Vl0-j(Hd\ObLcV.1`lMLCy;Y@aLz{^M,$~{b@ 1 ^P Gp>a_:@$ei1/=bYq)ow gQ](/a8,^wBWF=M& uc!Mxpuf;eV>IJ_Y8@=&lb'uS.DQ</7@j]cqHc(20OdAIL[(K-VVi" A]-lIrX

^,Cv{2SZu@,QbUQf8@!Z"3@A!Uu=t, E| T ]MTjg3o_{>Y^^bc|HFt9lI!MSL [djZk|t@cLkcm98fPC58} 3V6(N{8`6!eQVV"( dtX\]hu\sG >-O18i# B3W*p25D{!:$I[7D)ME#A^No >( 6H ;" A61R8!/-RN] lL/PC9'C, Fa5KxL-^N&(N1pl<'!/3K kD2$HJOFSPi& ,VCfAh5+`G}GP<@&d~9OUlo cSOe ()jR/!meX} liJ&Jkl,E&b.#w")8b:YhxIR;x)z[IZhNMt9>{q0A\Xi5O rJNw,? mZte %NTZs T^O OA90_SK]E.# ym:< d+q,IFqn/e~tJM Qow Ag] QyjsX!PPN$o&df?}j!7j|j(7U |tr>$wQ}mS?hgwlgt219Ft&oqHHp#K]K_C`Iy[OWGk@x=$&BZ&@A<C > :GRiZq n=oj/mW Haf\A'oON _Wk v<)fF3> NDB{ qaAMMQD=VOZJ7AMkJk;q2FGCOU^UY7fk\1Yc!Ve,1`(#jy^RE>\Yc$ngfe#VPF\FE}################8 UNZIP.BCK* [UNZIP542.BEOS]BEOS.C;1U,;------------------- Convert from MSDOS-format local time and date to Unix-format 32-bit GMT time: adjust base year from 1980 to 1970, do usual conversions from yy/mm/dd hh:mm:ss to elapsed seconds, and account for timezone and day- light savings time differences. If we have a Unix extra field, however, we're laughing: both mtime and atime are ours. On the other hand, we then have to check for restoration of UID/GID. --------------------------------------------------------------<-------------*/ eb_izux_flg = (G.extra_field ? ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0, G.lrec.last_mod_dos_datetime, #ifdef IZ_CHECK_TZ (G.tz_is_valid ? &zt : NULL), #else &zt, #endif z_uidgid) : 0); if (eb_izux_flg & EB_UT_FL_MTIME) { TTrace((stderr, "\nclose_outfile: Unix e.f. modif. time = %ld\n", zt.mtime)); } else { zt.mtime = dos_to_unix_time(G.lrec.last_mod_dos_datetime); } if (eb_izux_flg & EB_UT_FL_ATIME) { TTrace((stderr, "close_outfile: Unix e.f. access time = %ld\n", zt.atime)); } else { zt.atime = zt.mtime; TTrace((stderr, "\nclose_outfile: modification/access times = %ld\n", zt.mtime)); } /* if -X option was specified and we have UID/GID info, restore it */ if (uO.X_flag && eb_izux_flg & EB_UX2_VALID) { TTrace((stderr, "close_outfile: restoring Unix UID/GID info\n")); if (chown(G.filename, (uid_t)z_uidgid[0], (gid_t)z_uidgid[1])) { if (uO.qflag) Info(slide, 0x201, ((char *)slide, "warning: cannot set UID %d and/or GID %d for %s\n", z_uidgid[0], z_uidgid[1], G.filename)); else Info(slide, 0x201, ((char *)slide, " (warning) cannot set UID %d and/or GID %d", z_uidgid[0], z_uidgid[1])); } } /* set the file's access and modification times */ if (utime(G.filename, (struct utimbuf *)&zt)) { if (uO.qflag) Info(slide, 0x201, ((char *)slide, "warning: cannot set time for %s\n", G.filename)); else Info(slide, 0x201, ((char *)slide, " (warning) cannot set time")); } } /* end function close_outfile() */ #ifdef SET_DIR_ATTRIB /* messages of code for setting directory attributes */ static char Far DirlistUidGidFailed[] = "warning: cannot set UID %d and/or GID %d for %s\n"; static char Far DirlistUtimeFailed[] = "warning: cannot set modification, access times for %s\n"; # ifndef NO_CHMOD static char Far DirlistChmodFailed[] = "warning: cannot set permissions for %s\n"; # endif int set_direc_attribs(__G__ d) __GDEF dirtime *d; { int errval = PK_OK; if (d->have_uidgid && chown(d->fn, (uid_t)d->uidgid[0], (gid_t)d->uidgid[1])) { Info(slide, 0x201, ((char *)slide, LoadFarString(DirlistUidGidFailed), d->uidgid[0], d->uidgid[1], d->fn)); if (!errval) errval = PK_WARN; } if (utime(d->fn, (const struct utimbuf *)&d->u.t2)) { Info(slide, 0x201, ((char *)slide, LoadFarString(DirlistUtimeFailed), d->fn)); if (!errval) errval = PK_WARN; } #ifndef NO_CHMOD if (chmod(d->fn, 0xffff & d->perms)) { Info(slide, 0x201, ((char *)slide, LoadFarString(DirlistChmodFailed), d->fn)); /* perror("chmod (file attributes) error"); */ if (!errval) errval = PK_WARN; } #endif /* !NO_CHMOD */ return errval; } /* end function set_directory_attributes() */ #endif /* SET_DIR_ATTRIB */ #ifdef TIMESTAMP /***************************/ /* Function stamp_file() */ /***************************/ int stamp_file(fname, modtime) ZCONST char *fname; time_t modtime; { struct utimbuf tp; tp.modtime = tp.actime = modtime; return (utime(fname, &tp)); } /* end function stamp_file() */ #endif /* TIMESTAMP */ #ifndef SFX /************************/ /* Function version() */ /************************/ void version(__G) __GDEF { sprintf((char *)slide, LoadFarString(CompiledWith), #if defined(__MWERKS__) "Metrowerks CodeWarrior", "", #elif defined(__GNUC__) "GNU C ", __VERSION__, #endif "BeOS ", #ifdef __POWERPC__ "(PowerPC)", #else # ifdef __INTEL__ "(x86)", # else "(unknown)", /* someday we may have other architectures... */ # endif #endif #ifdef __DATE__ " on ", __DATE__ #else "", "" #endif ); (*G.message)((zvoid *)&G, slide, (ulg)strlen((char *)slide), 0); } /* end function version() */ #endif /* !SFX */ /******************************/ /* Extra field functions */ /******************************/ /* ** Scan the extra fields in extra_field, and look for a BeOS EF; return a ** pointer to that EF, or NULL if it's not there. */ static uch *scanBeOSexfield( const uch *ef_ptr, unsigned ef_len ) { while( ef_ptr != NULL && ef_len >= EB_HEADSIZE ) { unsigned eb_id = makeword(EB_ID + ef_ptr); unsigned eb_len = makeword(EB_LEN + ef_ptr); if (eb_len > (ef_len - EB_HEADSIZE)) { Trace((stderr, "scanBeOSexfield: block length %u > rest ef_size %u\n", eb_len, ef_len - EB_HEADSIZE)); break; } if( eb_id == EF_BEOS && eb_len >= EB_BEOS_HLEN ) { return (uch *)ef_ptr; } ef_ptr += (eb_len + EB_HEADSIZE); ef_len -= (eb_len + EB_HEADSIZE); } return NULL; } /* Used by setBeOSexfield(): Set a file/directory's attributes to the attributes passed in. If set_file_attrs() fails, an error will be returned: EOK - no errors occurred (other values will be whatever the failed function returned; no docs yet, or I'd list a few) */ static int set_file_attrs( const char *name, const unsigned char *attr_buff, const off_t attr_size ) { int retval = EOK; unsigned char *ptr; const unsigned char *guard; int fd; ptr = (unsigned char *)attr_buff; guard = ptr + attr_size; fd = open( name, O_RDWR | O_NOTRAVERSE ); if( fd < 0 ) { return errno; /* should it be -fd ? */ } while( ptr < guard ) { ssize_t wrote_bytes; struct attr_info fa_info; const char *attr_name; unsigned char *attr_data; attr_name = (char *)&(ptr[0]); ptr += strlen( attr_name ) + 1; /* The attr_info data is stored in big-endian format because the */ /* PowerPC port was here first. */ memcpy( &fa_info, ptr, sizeof( struct attr_info ) ); fa_info.type = (uint32)B_BENDIAN_TO_HOST_INT32( fa_info.type ); fa_info.size = (off_t)B_BENDIAN_TO_HOST_INT64( fa_info.size ); ptr += sizeof( struct attr_info ); if( fa_info.size < 0LL ) { Info(slide, 0x201, ((char *)slide, "warning: skipping attribute with invalid length (%Ld)\n", fa_info.size)); break; } attr_data = ptr; ptr += fa_info.size; if( ptr > guard ) { /* We've got a truncated attribute. */ Info(slide, 0x201, ((char *)slide, "warning: truncated attribute\n")); break; } /* Wave the magic wand... this will swap Be-known ty9 UNZIP.BCK* [UNZIP542.BEOS]BEOS.C;1UnJpes properly. */ (void)swap_data( fa_info.type, attr_data, fa_info.size, B_SWAP_BENDIAN_TO_HOST ); wrote_bytes = fs_write_attr( fd, attr_name, fa_info.type, 0, attr_data, fa_info.size ); if( wrote_bytes != fa_info.size ) { Info(slide, 0x201, ((char *)slide, "warning: wrote %ld attribute bytes of %ld\n", (unsigned long)wrote_bytes,(unsigned long)fa_info.size)); } } close( fd ); return retval; } static void setBeOSexfield( const char *path, uch *extra_field ) { uch *ptr = extra_field; ush id = 0; ush size = 0; ulg full_size = 0; uch flags = 0; uch *attrbuff = NULL; int retval; if( extra_field == NULL ) { return; } /* Collect the data from the extra field buffer. */ id = makeword( ptr ); ptr += 2; /* we don't use this... */ size = makeword( ptr ); ptr += 2; full_size = makelong( ptr ); ptr += 4; flags = *ptr; ptr++; /* Do a little sanity checking. */ if( flags & EB_BE_FL_BADBITS ) { /* corrupted or unsupported */ Info(slide, 0x201, ((char *)slide, "Unsupported flags set for this BeOS extra field, skipping.\n")); return; } if( size <= EB_BEOS_HLEN ) { /* corrupted, unsupported, or truncated */ Info(slide, 0x201, ((char *)slide, "BeOS extra field is %d bytes, should be at least %d.\n", size, EB_BEOS_HLEN)); return; } if( full_size < ( size - EB_BEOS_HLEN ) ) { /* possible old archive? will this screw up on valid archives? */ Info(slide, 0x201, ((char *)slide, "Skipping attributes: BeOS extra field is %d bytes, " "data size is %ld.\n", size - EB_BEOS_HLEN, full_size)); return; } /* Find the BeOS file attribute data. */ if( flags & EB_BE_FL_UNCMPR ) { /* Uncompressed data */ attrbuff = ptr; } else { /* Compressed data */ attrbuff = (uch *)malloc( full_size ); if( attrbuff == NULL ) { /* No memory to uncompress attributes */ Info(slide, 0x201, ((char *)slide, "Can't allocate memory to uncompress file attributes.\n")); return; } retval = memextract( __G__ attrbuff, full_size, ptr, size - EB_BEOS_HLEN ); if( retval != PK_OK ) { /* error uncompressing attributes */ Info(slide, 0x201, ((char *)slide, "Error uncompressing file attributes.\n")); /* Some errors here might not be so bad; we should expect */ /* some truncated data, for example. If the data was */ /* corrupt, we should _not_ attempt to restore the attrs */ /* for this file... there's no way to detect what attrs */ /* are good and which are bad. */ free( attrbuff ); return; } } /* Now attempt to set the file attributes on the extracted file. */ retval = set_file_attrs( path, attrbuff, (off_t)full_size ); if( retval != EOK ) { Info(slide, 0x201, ((char *)slide, "Error writing file attributes.\n")); } /* Clean up, if necessary */ if( attrbuff != ptr ) { free( attrbuff ); } return; } #ifdef BEOS_USE_PRINTEXFIELD static void printBeOSexfield( int isdir, uch *extra_field ) { uch *ptr = extra_field; ush id = 0; ush size = 0; ulg full_size = 0; uch flags = 0; /* Tell picky compilers to be quiet. */ isdir = isdir; if( extra_field == NULL ) { return; } /* Collect the data from the buffer. */ id = makeword( ptr ); ptr += 2; size = makeword( ptr ); ptr += 2; full_size = makelong( ptr ); ptr += 4; flags = *ptr; ptr++; if( id != EF_BEOS ) { /* not a 'Be' field */ printf("\t*** Unknown field type (0x%04x, '%c%c')\n", id, (char)(id >> 8), (char)id); } if( flags & EB_BE_FL_BADBITS ) { /* corrupted or unsupported */ printf("\t*** Corrupted BeOS extra field:\n"); printf("\t*** unknown bits set in the flags\n"); printf("\t*** (Possibly created by an old version of zip for BeOS.\n"); } if( size <= EB_BEOS_HLEN ) { /* corrupted, unsupported, or truncated */ printf("\t*** Corrupted BeOS extra field:\n"); printf("\t*** size is %d, should be larger than %d\n", size, EB_BEOS_HLEN ); } if( flags & EB_BE_FL_UNCMPR ) { /* Uncompressed data */ printf("\tBeOS extra field data (uncompressed):\n"); printf("\t\t%ld data bytes\n", full_size); } else { /* Compressed data */ printf("\tBeOS extra field data (compressed):\n"); printf("\t\t%d compressed bytes\n", size - EB_BEOS_HLEN); printf("\t\t%ld uncompressed bytes\n", full_size); } } #endif #ifdef BEOS_ASSIGN_FILETYPE /* Note: This will no longer be necessary in BeOS PR4; update_mime_info() */ /* will be updated to build its own absolute pathname if it's not given one. */ static void assign_MIME( const char *file ) { char *fullname; char buff[PATH_MAX], cwd_buff[PATH_MAX]; int retval; if( file[0] == '/' ) { fullname = (char *)file; } else { sprintf( buff, "%s/%s", getcwd( cwd_buff, PATH_MAX ), file ); fullname = buff; } retval = update_mime_info( fullname, FALSE, TRUE, TRUE ); } #endif c*[UNZIP542.BEOS]BEOS.H;1+,K./ 4|- 0@123KPWO56= 7= 89GHJ/* Copyright (c) 1990-2000 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /* beos.h -- A few handy things for the BeOS port. */ /* (c) 1997 Chris Herborth (chrish@qnx.com) */ /* This is covered under the usual Info-ZIP copyright. */ /* "#define EF_BE_FL_UNCMPR 0x01" has been moved into unzpriv.h */ #define EB_BE_FL_BADBITS 0xfe /* bits currently undefined */ #define BEOS_ASSIGN_FILETYPE 1 /* call update_mime_info() */ /* DR9 'Be' extra-field layout: 'Be' - signature ef_size - size of data in this EF (little-endian unsigned short) full_size - uncompressed data size (little-endian unsigned long) flag - flags (byte) flags & EB_BE_FL_UNCMPR = the data is not compressed flag:eS UNZIP.BCKK [UNZIP542.BEOS]BEOS.H;1s & EB_BE_FL_BADBITS = the data is corrupted or we can't handle it properly data - compressed or uncompressed file attribute data If flag & EB_BE_FL_UNCMPR, the data is not compressed; this optimisation is necessary to prevent wasted space for files with small attributes (which appears to be quite common on the Advanced Access DR9 release). In this case, there should be ( ef_size - EB_L_BE_LEN ) bytes of data, and full_size should equal ( ef_size - EB_L_BE_LEN ). If the data is compressed, there will be ( ef_size - EB_L_BE_LEN ) bytes of compressed data, and full_size bytes of uncompressed data. If a file has absolutely no attributes, there will not be a 'Be' extra field. The uncompressed data is arranged like this: attr_name\0 - C string struct attr_info (fields in big-endian format) attr_data (length in attr_info.size) */ *[UNZIP542.BEOS]BEOSMAIN.CPP;1+,6./ 4$- 0@123KPWO56 7 89GHJ// -*- C++ -*- /* Copyright (c) 1990-2000 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ // // WARNING: This is C++, not C! GNU C is not supported here! // // beos_init.cpp // // BeOS-specific C++ routines for use with Info-ZIP's UnZip 5.30 or later. // // This is necessary because we need to have an app_server connection to be // able to ask the system to assign a MIME type to an un-typed file. Strange // but true (the update_mime_info() call needs to send/receive messages). // // If you're writing your own Zip application, you probably DO NOT want to // include this file! #include #ifdef SFX const static char *unzip_signature = "application/x-vnd.Info-ZIP.UnZipSFX"; #else const static char *unzip_signature = "application/x-vnd.Info-ZIP.UnZip"; #endif extern "C" int main_stub( int argc, char *argv[] ); int main( int argc, char **argv ) { BApplication app( unzip_signature ); int retval = main_stub( argc, argv ); app.PostMessage( B_QUIT_REQUESTED ); app.Run(); return retval; } *[UNZIP542.BEOS]CONTENTS.;1+,2./ 4<- 0@123KPWO56M7M89GHJContents of the "beos" sub-directory for UnZip 5.4 and later: Contents this file README notes from the author of the BeOS port Makefile makefile for building UnZip (sorry, no project files) beos.c BeOS-specific routines (similar to the Unix ones) beos.h structures for the BeOS extra field beosmain.cpp BeOS-specific C++ routines unzip.rsc BeOS resources for UnZip unzipsfx.rsc BeOS resources for UnZipSFX This port supports both Metrowerks CodeWarrior (PowerPC and x86) and GNU C. - Chris Herborth (chrish@qnx.com) *[UNZIP542.BEOS]MAKEFILE.;1+,3./ 4- 0@123KPWO56CnC7CnC89GHJ ###################################################################### # # Makefile for Info-ZIP's unzip, unzipsfx, and funzip on BeOS # # Copyright (c) 1998-2000 Info-ZIP # Chris Herborth (chrish@qnx.com) # # This is the new New and Improved Makefile for BeOS; it will: # # 1) automatically detect your platform (PowerPC or x86) if none is # specified; the default compiler is CodeWarrior for PowerPC, or # gcc for x86 # # 2) let you cross-compile for the other platform (PowerPC or x86), in # theory # # 3) let you use Metrowerks CodeWarrior (default) or GNU C to build with # for either platfor, in theory # # To choose a specific architecture, define the ARCH environment # variable on the make command-line: # # ARCH=what make -f beos/Makefile # # where "what" can be "powerpc" or "x86". # # To choose a specific compiler, define the CC environment variable on # the make command-line: # # CC=compiler make -f beos/Makefile # # where "compiler" can be "mwcc" or "x86". # # Of course, you can combine these two: # # ARCH=powerpc CC=mwcc make -f beos/Makefile # # or: # # CC=gcc ARCH=x86 make -f beos/Makefile # # To automatically install the fresh new unzip, use the "install" target: # # make -f beos/Makefile install ###################################################################### # Things that don't change: SHELL = /bin/sh # Punish those of you not running on SMP hardware... MAKE = make -j 4 -f beos/Makefile LOC=$(LOCAL_UNZIP) -DPASSWD_FROM_STDIN AF=$(LOC) # UnZipSfx flags SL = -o unzipsfx SL2 = $(LF2) # fUnZip flags FL = -o funzip FL2 = $(LF2) # general-purpose stuff CP = cp RM = rm -f LN = ln -sf E = O = .o M = beos # defaults for crc32 stuff and system-dependent headers CRC32 = crc32 OSDEP_H = beos/beos.h # object files OBJS1 = unzip$O $(CRC32)$O crctab$O crypt$O envargs$O explode$O OBJS2 = extract$O fileio$O globals$O inflate$O list$O match$O OBJS3 = process$O ttyio$O unreduce$O unshrink$O zipinfo$O OBJS = $(OBJS1) $(OBJS2) $(OBJS3) $M$O $(BEOS_MAIN) LOBJS = $(OBJS) OBJSDLL = $(OBJS) api$O OBJX = unzipsfx$O $(CRC32)$O crctab$O crypt$O extract_$O fileio$O globals$O \ inflate$O match$O process_$O ttyio$O $M_$O $(BEOS_MAIN) LOBJX = $(OBJX) OBJF = funzip$O $(CRC32)$O crypt_$O globals_$O inflate_$O ttyio_$O UNZIP_H = unzip.h unzpriv.h globals.h $(OSDEP_H) # installation INSTALL = install # on some systems, manext=l and MANDIR=/usr/man/man$(manext) may be appropriate manext = 1 prefix = /boot/home/config BINDIR = $(prefix)/bin# where to install executables MANDIR = $(prefix)/man/man$(manext)# where to install man pages INSTALLEDBIN = $(BINDIR)/funzip$E $(BINDIR)/zipinfo$E $(BINDIR)/unzipsfx$E \ $(BINDIR)/unzip$E INSTALLEDMAN = $(MANDIR)/unzip.$(manext) $(MANDIR)/funzip.$(manext) \ $(MANDIR)/unzipsfx.$(manext) $(MANDIR)/zipinfo.$(manext) # UNZIPS = unzip$E funzip$E unzipsfx$E zipinfo$E # this is a little ugly...well, no, it's a lot ugly: MANS = man/unzip.1 man/unzipsfx.1 man/zipinfo.1 man/funzip.1 man/zipgrep.1 DOCS = unzip.txt unzipsfx.txt zipinfo.txt funzip.txt zipgrep.txt ###########; UNZIP.BCK3 [UNZIP542.BEOS]MAKEFILE.;1xO########################################################### # Things that change: # Select an architecture: ifndef ARCH MACHINE=$(shell uname -m) ifeq "$(MACHINE)" "BePC" ARCH=x86 CC=gcc else ARCH=powerpc CC=mwcc endif endif # Now select compiler flags and whatnot based on the ARCH and CC: WHAT=$(ARCH)-$(CC) ifeq "$(WHAT)" "powerpc-mwcc" CC=mwccppc LD=mwccppc CF=-w9 -O7 -opt schedule604 -rostr -I. $(LOC) LF=-o unzip LF2=-warn -L/boot/develop/lib/ppc -lbe -lroot BEOS_MAIN=beosmain$O TARGET=$(UNZIPS) endif ifeq "$(WHAT)" "powerpc-gcc" CC=gcc LD=gcc CF=-O3 -mcpu=604 -Wall -ansi -I. -I/boot/develop/headers/be/support \ -I/boot/develop/headers/be/storage $(LOC) LF=-o unzip LF2=-L/boot/develop/lib/ppc -lbe -lroot BEOS_MAIN=beosmain$O TARGET=$(UNZIPS) endif # This isn't likely to happen for R4 or later... ifeq "$(WHAT)" "x86-mwcc" CC=mwccx86 LD=mwccx86 CF=-O2 -w9 -I. $(LOC) LF=-o unzip LF2=-warn -L/boot/develop/lib/x86 -lbe -lroot BEOS_MAIN=beosmain$O TARGET=$(UNZIPS) endif ifeq "$(WHAT)" "x86-gcc" CC=gcc LD=gcc CF=-O3 -mpentiumpro \ -Wall -Wno-multichar -Wno-trigraphs \ -ansi -I. -I/boot/develop/headers/be/support \ -I/boot/develop/headers/be/storage $(LOC) LF=-o unzip LF2=-L/boot/develop/lib/x86 -lbe -lroot BEOS_MAIN=beosmain$O TARGET=$(UNZIPS) endif ifndef TARGET TARGET=help endif ###################################################################### # Helpful targets all: @echo 'TARGET = $(TARGET)' @echo 'ARCH = $(ARCH)' @echo 'CC = $(CC)' if [ -n "$(TARGET)" ] ; then \ $(MAKE) CC=$(CC) CF="$(CF)" LD="$(LD)" \ LF="$(LF)" LF2="$(LF2)" CCPP="$(CC)" CPPF="$(CF)" \ OBJS="$(OBJS)" LOBJS="$(LOBJS)" OBJX="$(OBJX)" \ LOBJX="$(LOBJX)" $(TARGET) ; \ else \ $(MAKE) help ; \ fi help: @echo '' @echo "This Makefile lets you build Info-ZIP's zip." @echo '' @echo 'To build zip for this computer using the default compiler, just do:' @echo '' @echo ' make -f beos/Makefile' @echo '' @echo 'To build zip for a specific architecture using a specific' @echo 'compiler, do:' @echo '' @echo ' ARCH=cpu CC=compiler make -f beos/Makefile' @echo '' @echo 'Where:' @echo ' cpu is either "powerpc" or "x86"' @echo ' compiler is either "mwcc" or "gcc"' @echo '' ###################################################################### # Basic compile instructions and dependencies # this is for GNU make; comment out and notify zip-bugs if it causes errors .SUFFIXES: .c .o # default for compiling C files .c.o: $(CC) -c $(CF) $*.c unzips: $(UNZIPS) objs: $(OBJS) objsdll: $(OBJSDLL) docs: $(DOCS) unzipsman: unzips docs unzipsdocs: unzips docs unzip$E: $(OBJS) beos/unzip.rsc $(LD) $(LF) $(LOBJS) $(LF2) chmod +x unzip$E xres -o unzip$E beos/unzip.rsc mimeset -f -all unzip$E unzipsfx$E: $(OBJX) beos/unzipsfx.rsc $(LD) $(SL) $(LOBJX) $(SL2) chmod +x unzipsfx$E xres -o unzipsfx$E beos/unzipsfx.rsc mimeset -f -all unzipsfx funzip$E: $(OBJF) $(LD) $(FL) $(OBJF) $(FL2) chmod +x funzip$E zipinfo$E: unzip$E $(LN) unzip$E zipinfo$E crc32$O: crc32.c $(UNZIP_H) zip.h crctab$O: crctab.c $(UNZIP_H) zip.h crypt$O: crypt.c $(UNZIP_H) zip.h crypt.h ttyio.h envargs$O: envargs.c $(UNZIP_H) explode$O: explode.c $(UNZIP_H) extract$O: extract.c $(UNZIP_H) crypt.h fileio$O: fileio.c $(UNZIP_H) crypt.h ttyio.h ebcdic.h funzip$O: funzip.c $(UNZIP_H) crypt.h ttyio.h tables.h globals$O: globals.c $(UNZIP_H) inflate$O: inflate.c inflate.h $(UNZIP_H) list$O: list.c $(UNZIP_H) match$O: match.c $(UNZIP_H) process$O: process.c $(UNZIP_H) ttyio$O: ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h unreduce$O: unreduce.c $(UNZIP_H) unshrink$O: unshrink.c $(UNZIP_H) unzip$O: unzip.c $(UNZIP_H) crypt.h version.h consts.h zipinfo$O: zipinfo.c $(UNZIP_H) crypt_$O: crypt.c $(UNZIP_H) zip.h crypt.h ttyio.h # funzip only $(CP) crypt.c crypt_.c $(CC) -c $(CF) -DFUNZIP crypt_.c $(RM) crypt_.c extract_$O: extract.c $(UNZIP_H) crypt.h # unzipsfx only $(CP) extract.c extract_.c $(CC) -c $(CF) -DSFX extract_.c $(RM) extract_.c globals_$O: globals.c $(UNZIP_H) # funzip only $(CP) globals.c globals_.c $(CC) -c $(CF) -DFUNZIP globals_.c $(RM) globals_.c inflate_$O: inflate.c inflate.h $(UNZIP_H) crypt.h # funzip only $(CP) inflate.c inflate_.c $(CC) -c $(CF) -DFUNZIP inflate_.c $(RM) inflate_.c ttyio_$O: ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h # funzip only $(CP) ttyio.c ttyio_.c $(CC) -c $(CF) -DFUNZIP ttyio_.c $(RM) ttyio_.c process_$O: process.c $(UNZIP_H) # unzipsfx only $(CP) process.c process_.c $(CC) -c $(CF) -DSFX process_.c $(RM) process_.c beos$O: beos/beos.c $(UNZIP_H) version.h # BeOS only $(CC) -c $(CF) beos/beos.c beosmain$O: beos/beosmain.cpp $(UNZIP_H) version.h # BeOS only $(CCPP) -c $(CPPF) beos/beosmain.cpp # version() not used by unzipsfx, so no version.h dependency beos_$O: beos/beos.c $(UNZIP_H) # unzipsfx only $(CP) beos/beos.c beos_.c $(CC) -c $(CF) -Ibeos -DSFX beos_.c $(RM) beos_.c beosmain_$O: beos/beosmain.cpp $(UNZIP_H) $(CP) beos/beosmain.cpp beosmain_.cpp $(CCPP) -c $(CPPF) -Ibeos -DSFX beosmain_.cpp $(RM) beosmain_.cpp unzipsfx$O: unzip.c $(UNZIP_H) crypt.h version.h consts.h # unzipsfx only $(CP) unzip.c unzipsfx.c $(CC) -c $(CF) -DSFX unzipsfx.c $(RM) unzipsfx.c # this really only works for Unix targets, unless E and O specified on cmd line clean: -rm -f $(UNZIPS) $(OBJS) $(OBJF) $(OBJX) api$O apihelp$O crc_gcc$O \ unzipstb$O beosmain.o beosmain_.o install: all $(INSTALL) -m 755 $(UNZIPS) $(BINDIR) mimeset -f -all $(BINDIR)/unzip mimeset -f -all $(BINDIR)/unzipsfx $(RM) $(BINDIR)/zipinfo$E $(LN) unzip$E $(BINDIR)/zipinfo$E $(RM) $(BINDIR)/zipgrep$E $(INSTALL) -m 755 unix/zipgrep $(BINDIR)/zipgrep$E $(INSTALL) -m 644 man/unzip.1 $(MANDIR)/unzip.$(manext) $(INSTALL) -m 644 man/unzipsfx.1 $(MANDIR)/unzipsfx.$(manext) $(INSTALL) -m 644 man/zipinfo.1 $(MANDIR)/zipinfo.$(manext) $(INSTALL) -m 644 man/funzip.1 $(MANDIR)/funzip.$(manext) $(INSTALL) -m 644 man/zipgrep.1 $(MANDIR)/zipgrep.$(manext) $(INSTALL) -m 644 $(DOCS) $(MANDIR) # alternatively, could use zip method: -cd $(BINDIR); rm -f $(UNZIPS) [etc.] uninstall: rm -f $(INSTALLEDBIN) $(INSTALLEDMAN) TESTZIP = testmake.zip # the test zipfile # test some basic features of the build test: check check: unzips @echo ' This is a Unix-specific target. (Just so you know.)' @echo ' (Should work ok on BeOS... [cjh])' if test ! -f $(TESTZIP); then \ echo " error: can't find test file $(TESTZIP)"; exit 1; fi # echo " testing extraction" ./unzip -b $(TESTZIP) testmake.zipinfo if test $? ; then \ echo " error: file extraction from $(TESTZIP) failed"; exit 1; fi # echo ' testing zipinfo (unzip -Z)' ./unzip -Z $(TESTZIP) > testmake.unzip-Z if diff testmake.unzip-Z testmake.zipinfo; then ;; else \ echo ' error: zipinfo output doesn't match stored version'; fi $(RM) testmake.unzip-Z testmake.zipinfo # echo ' testing unzip -d exdir option' ./unzip -b $(TESTZIP) -d testun cat testun/notes # echo ' testing unzip -o and funzip (ignore funzip warning)' ./unzip -boq $(TESTZIP) notes -d testun ./funzip < $(TESTZIP) > testun/notes2 if diff testun/notes testun/notes2; then ;; else \ echo 'error: funzip output disagrees with unzip'; fi # echo ' testing unzipsfx (self-extractor)' cat unzipsfx $(TESTZIP) > testsfx $(CHMOD) 0700 testsfx ./testsfx -b notes if diff notes testun/notes; then ;; else \ echo ' error: unzipsfx file disagrees with unzip'; fi $(RM) testsfx notes testun/notes testun/notes2 rmdir testun # echo ' testing complete.' <tb UNZIP.BCK2 [UNZIP542.BEOS]README.;1*[UNZIP542.BEOS]README.;1+,2./ 4<- 0@123KPWO56q7q89GHJ UnZip 5.4 for BeOS NOTE: If you want to build UnZip 5.4 or later from the source, you'll need to have the "xres" tool installed (unless you remove the "xres" lines in the beos/Makefile). This will cease to be a problem when BeOS R4 ships this fall. Until then, you can get xres from ftp://ftp.be.com/pub/experimental/tools/xres-102.zip. HISTORY UnZip 5.30 was the first official release of Info-ZIP's UnZip to support the filesystem in BeOS. UnZip 5.31 added support for the new filesystem that appeared in the Advanced Access Preview (aka DR9) Release of BeOS. UnZip 5.32 added several important bug fixes. UnZip 5.4: - supports BeOS on x86 hardware (and cross-compiling, if a compiler is present) - ask the Registrar to assign a file type to files that don't have one - adds a new -J option on BeOS; this lets you extract the data for a file without restoring its file attributes (handy if you stumble on really old BeOS ZIP archives... from before BeOS Preview Release) - will restore attributes properly on symbolic links (you'll need zip 2.21 or later to create ZIP files that store attributes for symbolic links) *** WARNING *** You may find some extremely old BeOS zip archives that store their file attributes differently; these will be from DR8 and earlier (when BeOS copied the MacOS type/creator fields instead of using the current extremely flexible scheme). You can still unpack the _data_ in older zip files, but you won't be able to recover the file attributes in those archives. Use the -J option with these files or you'll get "compressed EA data missing" and "zipfile probably corrupt" errors, even though the data is intact! The new scheme makes handling BeOS file attributes much more robust, and allows for possible future expansion without another round of incompatibilities. That's life on the edge! *** WARNING *** The new filesystem allows for huge files (up to several terabytes!) with huge amounts of meta-data (up to several terabytes!). The existing ZIP format was designed when this much data on a personal computer was science fiction; as a result, it's quite possible that large amounts of file attributes (more than maybe 100+K bytes) could be truncated. Zip and UnZip try to deal with this in a fairly sensible way, working on the assumption that the data in the file is more important than the data in the file attributes. One way to run into this problem is to mount an HFS volume and zip some Mac files that have large resources attached to them. This happens more often than you'd expect; I've seen several 0-byte files that had over four megabytes of resources. Even more stupid, these resources were _data_ (sound for a game), and could have been easily stored as data... KNOWN BUGS None! Yahoo! Please report any bugs to Zip-Bugs@lists.wku.edu. - Chris Herborth (chrish@qnx.com) November 2/1998 *[UNZIP542.BEOS]UNZIP.RSC;1+,'./ 4P- 0@123KPWO56b.7b.89GHJ RSODDDDDh !6 application/x-vnd.Info-ZIP.UnZip1BOF66 RTSCtypesapplication/zipGNInfo-ZIP's UnZipExtract, test and view ZIP archives. Read the COPYING file for copyright details. http://www.cdrom.com/pub/infozip/PWTWp@@WW W X8W Zl߰XXXXXXXpYX@ X`cati Y((XXXB XC0SMIM BEOS:APP_SIGGGSMBEOS:FILE_TYPESVPPABEOS:APP_VERSIONFPPABEOS:APP_FLAGSr:*[UNZIP542.BEOS]UNZIPSFX.RSC;1+,D./ 4/- 0@123KPWO56%.7%.89GHJRSODDDDDh $ =3-ny UNZIP.BCKD [UNZIP542.BEOS]UNZIPSFX.RSC;1application/x-vnd.Info-ZIP.UnZipSFX1BOFInfo-ZIP's UnZipSFXStub for creating self-extracting ZIP archives.HPw T߰߰HHw  TwyHHw HHw s?xxx P߰xx߰zlyxx` x` s4w PszlyxB PxSMIM BEOS:APP_SIGGGSMBEOS:FILE_TYPESVPPABEOS:APP_VERSIONFPPABEOS:APP_FLAGSr:*[UNZIP542]BUGS.;1+, .. / 4 - 0@123KPWO 56QuU7QuU89GHJBogus bugs (not our fault!): --------------------------- By far THE BIGGEST source of bug reports to Info-ZIP/zip-bugs is the incorrect transfer of zipfiles (or of the UnZip executable itself). ALWAYS TRANSFER IN BINARY MODE! This includes ftp transfers and *both* ends of a Kermit connection ("set file type binary"). If your copy isn't exactly the same size as the original, you made a mistake. Another common source of errors such as "compression method 8 not sup- ported" is the existence of an old version of UnZip somewhere in your path. Make sure you're using the version you think you're using; give the full path explicitly if necessary. Executing "unzip" without any options will print a help screen, at the top of which is the UnZip version number and release date; and executing "unzip -v" without any zipfile or other options will give information about what compiler was used, the target operating system, any special UnZip options, and the date of compilation--only for version 5.11 and later, though! (Also, under Unix C shell and some Bourne shells, "which unzip" will print the path of the unzip you're actually using. Under OS/2 and MS-DOS, whch21gr.zip [on Simtel mirror sites] will do the same thing; in addi- tion, "which -a unzip" will show *all* copies of "unzip" in your path.) Bugs (real and/or imagined): --------------------------- - [OS/2 DLL] when trying to use the REXX function UzUnZipToStem to extract a file with `&' in its name, the DLL crashes (but UzUnZipToVar still works) [Daniel H, 961215] - UnZip has problems with archives bigger than 2GB; it may print "note: didn't find end-of-central-dir signature at end of central dir" (harmless) or may not be able to seek to member files [James Lemley 970107, Iris Spaniol 970206, ...] - fix overwrite behavior: hidden/system problems?; etc. - 32-bit DOS UnZip still unable to set volume labels? - 32-bit DOS UnZip under OS/2 doesn't extract all wildcard zipfiles? [DOS box: unzip386 (ver 5.12) x:\32bit\unix\emx09a\*.zip, Hobbes 3/95] - 32-bit DOS UnZip under OS/2 doesn't set timestamp when overwriting files on HPFS partition? (go32 and pmode/w both; emx/rsx OK) [Eberhard Mattes 950726] - USE_FWRITE still causes occasional CRC errors when extracting on Pyramid? [Kevin Fritz 931102] - still NT/W95 bug with "unzip -v d:*.zip" not matching properly? [Steve S 940527] 980427: bug no longer exists, Opendir() must have been corrected by someone - when ^Z received in no-echo mode, echo is not restored (works OK if resume, however) - signal() handler disabled after first use with one of BSD/SysV? - MKS Korn shell: unzip assumes the MKS-style command-line environment options are relevant to it, but this is not the case if unzip was called by another program (e.g., from a .BAT file). A fix for this exists for Borland compilers but not for MSC, Watcom, djgpp, etc. - OS/2: for paths with one long component, the .LONGNAME EA may be saved for all components (waste of disk space): how to check?? - VMS: for extracting to other directories, only the VMS-style "-d [.foo]" format is accepted; "-d foo" should also be allowed. Long filenames are not automatically truncated to 39.39. - Novell Netware: Netware drives may clear the archive bit on extracted files under OS/2 and/or MS-DOS. UnZip always *tries* to set the archive bit, however. [pynq@uchicago, 940527] - DEC Ultrix: on long zipfiles, unzip will sometimes fail (bad CRC, not always reproducible); this is apparently due either to a hardware bug (cache mem) or OS bug (page faults?) [Igor, Jean-loup, bottom of BUGS.long] - funzip/more/decryption/no-echo bug: race condition(?) causes terminal to be "reset" to no-echo state - Macintosh (100200), Atari (020000) external file attributes not interpreted correctly (both unzip and zipinfo) - pkbug error: zipfile with incorrect csize and/or ucsize--check for end of compressed (csize) data in uncompression routines: unreduce.c: while (((outpos + outcnt) < ucsize) && (!zipeof)) { [James Birdsall, Mark, bottom of BUGS.long] - OS/2: directory EAs not restored if directory exists [Kai Uwe, KG27515@uark] (subsequent note: no way to determine which EAs are newer ==> cannot restore without user input) (update: as of UnZip 5.30, option -o forces restoring of directory EAs) - MS-DOS: Borland executables don't allow other than 80-column, 25/43/50-line screen modes (Borland bug) [Michael Stillwell] m*[UNZIP542]CMSMVS.DIR;1+, (./ 4- 0123 KPWO56(!a7(!a89GHJI>;)av UNZIP.BCK ( [UNZIP542]CMSMVS.DIR;1 CCUNZIP.EXEC4 INSTALL.CMSBMC.EXECTMVS.MKIu README.CMS. README.MVS' UNZIP.EXECNUNZIP.MAKEFILE) UNZMVSC.JOB@ UNZVMC.EXEC[VMMVS.C?VMMVS.H7VMSTAT.H' WHATSNEW.CMS{ ZIPINFO.EXECx*[UNZIP542.CMSMVS]CCUNZIP.EXEC;1+,4./ 4n- (0@123KPWO567d77d89GHJ/* CCUNZIP EXEC Compile unzip 5.4 for VM/CMS */ /* Author: George Petrov, 11 Apr 1995 (VMCOMPIL EXEC) */ /* Modified for IBM C V3R1 by Ian E. Gorman, 2 Nov 1998 Facilities for compiling and testing were provided by OmniMark Technologies Corporation, Ottawa, Canada */ Address Command Signal On Error /* Allow longnames, compile re-entrant code. global.c and vmmvs.c require EXTENDED features */ CCopts = 'LONGNAME RENT LANGLVL(EXTENDED) NOEXECOPS' /* UNZIP options -- VM_CMS, REENTRANT */ CCopts = CCopts 'DEFINE(VM_CMS,REENTRANT)' /* Link the load module to run in more or less than 16MB memory */ LINKopts = 'AMODE ANY RMODE ANY RLDSAVE' 'GLOBAL TXTLIB SCEELKED CMSLIB' 'GLOBAL LOADLIB SCEERUN' /* produce the TEXT (object) files */ linklist='' modname='UNZIP' Say 'Building' modname 'MODULE...' Call Compile 'UNZIP' Call Compile 'CRC32' Call Compile 'CRCTAB' Call Compile 'CRYPT' Call Compile 'ENVARGS' Call Compile 'EXPLODE' Call Compile 'EXTRACT' Call Compile 'FILEIO' Call Compile 'GLOBALS' Call Compile 'INFLATE' Call Compile 'PROCESS' Call Compile 'LIST' Call Compile 'MATCH' Call Compile 'TTYIO' Call Compile 'UNREDUCE' Call Compile 'UNSHRINK' Call Compile 'ZIPINFO' Call Compile 'VMMVS' Say 'Linking...' 'EXEC CMOD' linklist '(MODNAME' modname LINKopts Say modname 'built successfully.' /* Make ZIPINFO from UNZIP */ modname = 'ZIPINFO' 'COPYFILE UNZIP MODULE A ZIPINFO MODULE A (OLDDATE REPLACE' Say modname 'built successfully.' Say 'Done.' Exit rc error: Say 'Error' rc 'during compilation!' Say 'Error in line' sigl':' Say ' 'Sourceline(sigl) Exit rc Compile: Procedure Expose CCopts LINKopts linklist Parse arg filename filetype filemode . If filetype='' Then filetype='C' linklist = linklist filename Say 'Compiling' filename filetype filemode '...' 'EXEC CC' filename filetype filemode '('CCopts Return rc *[UNZIP542.CMSMVS]INSTALL.CMS;1+,B. / 4 - (0@123KPWO 56⦵@7⦵@89GHJ----------------------------------------------------------------------- [Installation notes for VM/CMS port of UNZIP 5.32 and ZIP 2.2] Additional notes from Ian E. Gorman (4/98): I have not fully tested ZIP and UNZIP in VM (for example, I have not tried all the options), so ZIP 2.2 for VM and UNZIP 5.32 for VM should be regarded as beta versions. Try them out before you decide that you can depend on them. Most of the work for the VM port has been done by others, but I have made some changes and compiled on a more recent version of VM/CMS. It is possible that I have introduced new problems or undone some of the solutions found by previous authors. Installation ============ The executables are stored in CMS "PACK" format instead of being stored in ZIP archives. This format takes a little longer to download, but installation is slightly simpler. Installing UNZIP ---------------- The UNZIP executable is supplied as the binary file UNZIP.MOD, in the CMS "PACK" format. You must get the UNZIP.MOD file on to your system as a binary file in fixed recording mode, block size 1024. If you are using FTP in CMS, you can get the file in the correct format with the LOCSITE and BINARY commands. Assuming that the UNZIP executable is stored on the remote site as unz532vm.mod, you could issue the following commands FTP where.ever.com BINARY LOCSITE FIX 1024 GET unz532vm.mod QUIT If you are using a 3270 terminal session to upload from a PC, you can upload the file in the correct format with the SEND command: SEND unz532vm.mod A: unz532vm mod a1 (RECFM F LRECL 1024 If your 3270 emulator does not have the SEND command, but is a GUI application, it may allow you to upload from the menu bar. If so, set your options to binary, VM/CMS, fixed record length, and a length of 1024 before you upload. When you get the PACKed file on your CMS minidisk, you convert it to an executable module by using the COPY command with the UNPACK option: COPY unz532vm mod a unzip module a1 (UNPACK OLDDATE REPLACE You can omit the OLDDATE and REPLACE options if you want to. Installing ZIP -------------- The ZIP executable is supplied as the binary file ZIP.MOD, in the CMS "PACK" format. You must get the ZIP.MOD file on to your system as a binary file in fixed recording mode, block size 1024. Assuming that the file is stored as zip22vm.mod, you can get the file the same way you got the UNZIP.MOD file: Using FTP: FTP where.ever.com BINARY LOCSITE FIX 1024 GET zip22vm.mod QUIT Using 3270 file transfer: SEND unz532vm.mod A: unz532vm mod a1 (RECFM F LRECL 1024 When you get the PACKed file on your CMS minidisk, you convert it to an executable module by using the COPY command with the UNPACK option: COPY zip22vm mod a zip module a1 (UNPACK OLDDATE REPLACE Installing Documentation ------------------------ Once you have UNZIP running, you can use it to extract documentation from ZIP archives. You can transfer the ZIP archives to VMV/CMS as a binary file with any record length. A record length of 1 will work fine: via FTP: FTP where.ever.com BINARY LOCSITE FIX 1 GET zip22vm.zip zipdoc.zip GET unz532vm.zip unzipdoc.zip QUIT via 3270 session: SEND zip22vm.zip A: unzipdoc zip a1 (RECFM F LRECL 1 SEND unz532vm.zip A: zipdoc zip a1 (RECFM F LRECL 1 Once you have the ZIP archives, extract the documentation to the minidisk of your choice by using the -d option: unzip -a -d A2 unzipdoc.zip unzip -a -d A2 zipdoc.zip The "-a" option is required because the documents are archived as ASCII text files, but they must be converted to EBCDIC to read them in VM/CMS. Notes ===== Different EBCDIC Character Sets ------------------------------- The documentation may look strange on your system, because UNZIP translates from ASCII to "Open Systems" EBCDIC (IBM-1047). Unless you are a software developer, you are probably using a different kind of EBCDIC (like US EBCDIC, IBM-037). This causes some character codes to display as different characters. For example, the character codes that display as square brackets in IBM-1047 will display as e-acute and a-grave in IBM-037. You can use the IBM ICONV utility to translate documents from one character set to another: ICONV old doc a new doc a1 (FROMCODE IBM-1047 TOCODE IBM-037 IND$FILE?]B; UNZIP.BCKB ([UNZIP542.CMSMVS]INSTALL.CMS;1 ^  protocol ----------------- This is the method by which files are transferred via 3270 sessions between PC and mainframe. If you know how to transfer files via 3270 session between PC and mainframe, you know as much as you need to know about IND$FILE. If your mainframe has IND$FILE, and your 3270 emulator does file transfers, you can use your emulator to transfer files between PC and mainframe. *[UNZIP542.CMSMVS]MC.EXEC;1+,T./ 4- (0@123KPWO56vU7vU89GHJ /* MAKECPIP EXEC Make program to build a C/370 module */ /* Author: George Petrov, 29 Sep 1994 */ arg fn . '(' cparms /* Filter name */ 'pipe (end ?) < 'fn' makefile', /* get all source files from */ '| frlab GLOBALS:'||, '| drop', '| strip', '| var globals' cparms = cparms globals say '' say 'Compile options : 'cparms say '' if pos('REB',cparms) > 0 then do parse var cparms cp1 'REB' . ' ' cp2 /* REBuild options specified ? */ cparms = cp1||cp2 pipe1=, 'pipe (end ?) < 'fn' makefile', /* get all source files from */ '| nfind *'||, /* the makefile and compile */ '| frlab TEXT:'||, /* only the those who are */ '| r: tolab MODULE:'||, /* changed or never compiled */ '| drop', '| o: fanout', '| chop before str /(/', '| statew', '| c: fanout', /* compiled */ '| specs /Compiling / 1 w1-3 n / .../ n', '| cons' end else do pipe1=, 'pipe (end ?) < 'fn' makefile', /* get all source files from */ '| nfind *'||, /* the makefile and compile */ '| frlab TEXT:'||, /* only the those who are */ '| r: tolab MODULE:'||, /* changed or never compiled */ '| drop', '| o: fanout', '| specs w1 1 /C/ nw w3 nw write w1 1 /TEXT A/ nw', '| chop before str /(/', '| statew', '| change (57 66) / /0/', '| sort 1.8 d', /* sort the date and time */ '| uniq 1-17 singles', /* if the first is a source */ '| sort 1.8 d 64.2 d 57.2 d 60.2 d 66.8 d', /* sort the date */ '| uniq 1-8 first', /* if the first is a source */ '| locate 9.8 /C /', /* program then it has to be */ '| c: fanout', /* compiled */ '| specs /Compiling / 1 w1-3 n / .../ n', '| cons' end pipe2= '?', 'r:', '| drop', '| specs w1 1', /* save the module name in var */ '| var module', '?', 'o:', '| specs w1 1', '| join * / /', '| var texts', /* save all the text file names */ '?', /* for later include */ 'c:', '| specs /CC / 1 w1-3 n /(NOTERM 'cparms'/ nw', /* compile! */ '| err: cms | cons', '?', 'err:', '| nfind 0'||, '| var err', '| specs /----> Errors found! RC=/ 1 1-* n', '| cons' /* '| g: gate'*/ pipe1 pipe2 say '' if symbol('err') = 'VAR' & err ^= 0 then do say 'Errors found in source files - link aborted! RC = 'err exit err end say 'Generating module 'module 'pipe cms cmod' fn texts' | > 'fn' LINK A' exit rc error: say 'Error in REXX detected!' Say 'Syntax error on line' Sigl':' Sourceline(Sigl) Say 'Error was:' Errortext(RC) return rc *[UNZIP542.CMSMVS]MVS.MKI;1+,u. / 4 - (0@123KPWO 56rfl7rfl89GHJ# Makefile for the MVS (OS/390 Base) version of UNZIP 5.4 # Produced for C/C++ V3R2 in OS/390 1.2.0 by Ian E. Gorman, 2 Nov 1998 # Facilities for compiling and testing were made available by # OmniMark Technologies Corporation, Ottawa, Canada # NOTES # # The only tabs in this file are in the first character of each recipe # line, where they are required by make. # # Run this makefile in OpenMVS (OS/390 POSIX) using source files in the # HFS file system. You can write the load module to either HFS file # system or to a PDS in the native MVS file system. The PDS must have # sufficient free space to hold the load module. # # To compile to a member of a PDS: # make # or # make unzip.mvs # # To compile a test version into the HFS file system: # make hfs # UNZIP options -- MVS, REENTRANT ZIPOPTS=-DMVS # directories # generic source code SRC=.. SRC_P=$(SRC)/ # source code for MVS CMSMVS=../cmsmvs CMSMVS_P=$(CMSMVS)/ # include files INCLS=-I$(SRC) -I$(CMSMVS) # object files and load modules BLD_P=../mvs/ # Other options # Suffixes (E and O must be different) E= O=.o # Need EXTENDED features for global.c and vmvms.c, so not using c89 CC=cc CFLAGS=-D_OPEN_SYS $(ZIPOPTS) $(INCLS) LD=cc LDFLAGS= # Files # object (TEXT) files OBJECTS= $(BLD_P)unzip$(O) $(BLD_P)crc32$(O) $(BLD_P)crctab$(O) \ $(BLD_P)crypt$(O) $(BLD_P)envargs$(O) $(BLD_P)explode$(O) \ $(BLD_P)extract$(O) $(BLD_P)fileio$(O) $(BLD_P)globals$(O) \ $(BLD_P)inflate$(O) $(BLD_P)process$(O) $(BLD_P)list$(O) \ $(BLD_P)match$(O) $(BLD_P)ttyio$(O) $(BLD_P)unreduce$(O) \ $(BLD_P)unshrink$(O) $(BLD_P)zipinfo$(O) $(BLD_P)vmmvs$(O) # Header files HFILES= $(SRC_P)consts.h $(SRC_P)crypt.h $(SRC_P)ebcdic.h \ $(SRC_P)globals.h $(SRC_P)inflate.h $(SRC_P)tables.h \ $(SRC_P)ttyio.h $(SRC_P)unzip.h $(SRC_P)unzpriv.h \ $(SRC_P)version.h $(SRC_P)zip.h $(CMSMVS_P)vmmvs.h \ $(CMSMVS_P)vmstat.h # Rules all: $(BLD_P)unzip.mvs$(E) hfs: $(BLD_P)unzip$(E) # link $(BLD_P)unzip.mvs$(E): $(OBJECTS) $(LD) -o "//INFOZIP.LOAD(UNZIP)" $(LDFLAGS) $^ echo "tso call \"infozip(unzip)\" \"'\"\"""$$""@""\"\"'\"" > $% chmod a+x $% $(BLD_P)unzip$(E): $(OBJECTS) $(LD) -o $% $(LDFLAGS) $^ # compile $(BLD_P)api$(O): $(SRC_P)api.c $(HFILES) $(CC) -c -o $% $(CFLAGS) $(SRC_P)api.c $(BLD_P)apihelp$(O): $(SRC_P)apihelp.c $(HFILES) $(CC) -c -o $% $(CFLAGS) $(SRC_P)apihelp.c $(BLD_P)crc32$(O): $(SRC_P)crc32.c $(HFILES) $(CC) -c -o $% $(CFLAGS) $(SRC_P)crc32.c $(BLD_P)crctab$(O): $(SRC_P)crctab.c $(HFILES) $(CC) -c -o $% $(CFLAGS) $(SRC_P)crctab.c $(BLD_P)crypt$(O): $(SRC_P)crypt.c $(HFILES) $(CC) -c -o $% $(CFLAGS) $(SRC_P)crypt.c $(BLD_P)envargs$(O): $(SRC_P)envargs.c $(HFILES) $(CC) -c -o $% $(CFLAGS) $(SRC_P)envargs.c $(BLD_P)explode$(O): $(SRC_P)explode.c $(HFILES) $(CC) -c -o $% $(CFLAGS) $(SRC_P)explode.c $(BLD_P)extract$(O): $(SRC_P)extract.c $(HFILES) $(CC) -c -o $% $(CFLAGS) $(SRC_P)extract.c $(BLD_P)fileio$(O): $(SRC_P)fileio.c $(HFILES) $(CC) -c -o $% $(CFLAGS) $(SRC_P)fileio.c $(BLD_P)funzip$(O): $(SRC_P)funzip.c $(HFILES) $(CC) -c -o $% $(CFLAGS) $(SRC_P)funzip.c $(BLD_P)globals$(O): $(SRC_P)globals.c $(HFILES) $(CC) -c -o $% $(CFLAGS) $(SRC_P)globals.c $(BLD_P)inflate$(O): $(SRC_P)inflate.c $(HFILES) $(CC) -c -o $% $(CFLAGS) $(SRC_P)inflate.c $(BLD_P)list$(O): $(SRC_P)list.c $(HFILES) $(CC) -c -o $% $(CFLAGS) $(SRC_P)list.c $(BLD_P)match$(O): @T UNZIP.BCKu ([UNZIP542.CMSMVS]MVS.MKI;1 \$(SRC_P)match.c $(HFILES) $(CC) -c -o $% $(CFLAGS) $(SRC_P)match.c $(BLD_P)process$(O): $(SRC_P)process.c $(HFILES) $(CC) -c -o $% $(CFLAGS) $(SRC_P)process.c $(BLD_P)ttyio$(O): $(SRC_P)ttyio.c $(HFILES) $(CC) -c -o $% $(CFLAGS) $(SRC_P)ttyio.c $(BLD_P)unreduce$(O): $(SRC_P)unreduce.c $(HFILES) $(CC) -c -o $% $(CFLAGS) $(SRC_P)unreduce.c $(BLD_P)unshrink$(O): $(SRC_P)unshrink.c $(HFILES) $(CC) -c -o $% $(CFLAGS) $(SRC_P)unshrink.c $(BLD_P)unzip$(O): $(SRC_P)unzip.c $(HFILES) $(CC) -c -o $% $(CFLAGS) $(SRC_P)unzip.c $(BLD_P)unzipstb$(O): $(SRC_P)unzipstb.c $(HFILES) $(CC) -c -o $% $(CFLAGS) $(SRC_P)unzipstb.c $(BLD_P)zipinfo$(O): $(SRC_P)zipinfo.c $(HFILES) $(CC) -c -o $% $(CFLAGS) $(SRC_P)zipinfo.c $(BLD_P)vmmvs$(O): $(CMSMVS_P)vmmvs.c $(HFILES) $(CC) -c -o $% $(CFLAGS) $(CMSMVS_P)vmmvs.c *[UNZIP542.CMSMVS]README.CMS;1+,..!/ 4!!- (0@123KPWO"56B\7B\89GHJUsing ZIP and UNZIP on VM/CMS ============================= Installing executables ---------------------- The following CMS MODULEs are available: ZIP ZIPNOTE ZIPCLOAK ZIPSPLIT UNZIP In addition to these, each MODULE file also has an EXEC with the same name. These EXECs are front-ends to the MODULES that will attempt to set up the required runtime libraries before running the MODULE. All the EXECs are identical. Only their names are different. They are stored as plain text files. The CMS MODULE files have been packed using the COPYFILE command to allow their file format to be properly restored, since variable length binary files will not currently unzip properly (see below for details). The MODULEs are shipped with a filetype or extension of CMO (for CMS MODULE). Their names may vary on the distribution disk to indicate their level, etc. To restore them to executable MODULEs on CMS, do the following: 1. Upload them to CMS with a Fixed record length with LRECL 1024. Example, from a DOS or OS/2 window, type this: SEND unzip.cmo A:unzip module a (RECFM F LRECL 1024 Example, using FTP from CMS, type this: BINARY FIXED 1024 GET unzip.cmo unzip.module.a Note: Replace "unzip.cmo" with the actual name. 2. Use COPYFILE to unpack the file. Example, in CMS type this: COPYFILE UNZIP MODULE A (UNPACK REPLACE OLDDATE 3. Repeat steps 1-2 for each of the programs. 4. Build the ZIPINFO module by typing this: COPYFILE UNZIP MODULE A ZIPINFO MODULE A (OLDDATE 5. Upload the EXECs to CMS as text files (with ASCII-to-EBCDIC translation). Example, from a DOS or OS/2 window, type this: SEND unzip.exc A:unzip exec a (CRLF Example, using FTP from CMS, type this: GET unzip.exc unzip.exec.a 6. Repeat steps 4 for each of the EXECs. Preparing the environment ------------------------- The executables provided were compiled with IBM C 3.1.0 and require the the Language Environment (LE) runtime libraries. To provide access to the runtime libraries: 1. Link to the disk containing the Language Environment files, if necessary. 2. Use the command "GLOBAL LOADLIB SCEERUN" These commands can be placed in your PROFILE EXEC. Note: EXECs have been provided called ZIP, UNZIP, etc. that issue the GLOBAL LOADLIB statement. This was done to alleviate frustration of users that don't have the GLOBAL LOADLIB statement in their PROFILE EXEC. These EXECs may require changing for your system. Unfortunately, there is no way, using IBM C, to produce a MODULE that doesn't require a runtime library. Testing ------- To test the MODULEs, just type ZIP or UNZIP. They should show help information on using the commands. If you see something like this: DMSLIO201W The following names are undefined: CEEEV003 DMSABE155T User abend 4093 called from 00DCD298 reason code 000003EB Then you don't have access to the proper runtime libraries, as described above. Here is additional information on the ZIP and UNZIP programs that may assist support personnel: - Compiled with IBM C V3R1M0 on VM/ESA 2.2.0 with CMS level 13 Service Level 702. - Require the SCEERUN LOADLIB runtime library. This is part of the Language Environment (LE). - Linked with options RMODE ANY AMODE ANY RLDSAVE. If you continue to have trouble, report the problem to Zip-Bugs (see the bottom of this document). Compiling the source on VM/CMS ------------------------------ The source has been successfully compiled previously using C/370 2.1 and 2.2. The source has been recently compiled using IBM C 3.1.0 on VM/ESA 2.2.0 with CMS level 13. I don't have access to an MVS system so the code hasn't been tested there in a while. 1. Unzip the source files required for CMS. The root-level files inside the ZIP file and the files in the CMSMVS subdirectory are needed. Example (use both commands): unzip -aj zip23.zip -x */* -dc unzip -aj zip23.zip cmsmvs/* -dc This example unzips the files to the C-disk, while translating character data and ignoring paths. If you don't already have a working UNZIP MODULE on CMS you will have to unzip the files on another system and transport them to CMS. All the required files are plain text so they can be transferred with ASCII-to-EBCDIC translations. 2. Repeat step 1 with the zip file containing the UNZIP code. Unzip the files to a different disk than the disk used for the ZIP code. 3. To compile the ZIP code, run the supplied CCZIP EXEC. To compile the UNZIP code, run the supplied CCUNZIP EXEC. NOTE: Some of the ZIP and UNZIP source files have the same name. It is recommended that you keep the source from each on separate disks and move the disk you are building from ahead of the other in the search order. For example, you may have a 192 disk with the ZIP source code and a 193 disk with the UNZIP source code. To compile ZIP, access the 192 disk as B, then run CCZIP. This will create the following modules: ZIP, ZIPNOTE, ZIPSPLIT, ZIPCLOAK. To compile UNZIP, access 193 as B, then run CCUNZIP. This will create the following modules: UNZIP, ZIPINFO (a copy of UNZIP). ========================================================================= Using ZIP/UNZIP --------------- Documentation for the commands is in MANUAL NONAME (for ZIP) and in UNZIP DOC UNZIP. INFOZIP DOC describes the use of the -Z option of UNZIP. The rest of this section explains special notes concerning the VM/CMS version of ZIP and UNZIP. Filenames and directories ------------------------- 1. Specifying filenames a. When specifying CMS files, use filename.filetype.filemode format (separate the three parts of the name with a period and use no spaces). Example: profile.exec.a Unfortunately, this prevents you from using ZIP from FILELIST. To unzip a zip file, however, you can type something like this next to it in FILELIST: unzip /n -d c This will unzip theAJ] UNZIP.BCK. ([UNZIP542.CMSMVS]README.CMS;1!: contents of the current file to a C-disk. b. It is possible to use DD names with ZIP and UNZIP on CMS, though it can be cumbersome. Example: filedef out disk myzip zip a zip dd:out file1.txt file2.txt While you can also use a DD name for the input files, ZIP currently does not correctly resolve the filename and will store something like "dd:in" inside the ZIP file. A file stored in this manor cannot easily be unzipped, as "dd:in" is an invalid filename. c. In places where a directory name would be used on a PC, such as for the ZIP -b (work path) option or the UNZIP -d (destination path) options, use a filemode letter for CMS. For example, to unzip files onto a C-disk, you might type something like this: unzip myzip.zip -d c Currently, ZIP uses the A-disk for work files. When zipping large files, you may want to specify a larger disk for work files. This example will use a C-disk for work files. zip -b C myzip.zip.c test.dat.a 2. Filename conversions a. Filemode letters are never stored into the zip file or take from a zip file. Only the filename and filetype are used. ZIP removes the filemode when storing the filename into the zip file. UNZIP assumes "A" for the filemode unless the -d option is used. b. When unzipping, any path names are removed from the fileid and the last two period-separated words are used as the filename and filetype. These are truncated to a maximum of eight characters, if necessary. If the filetype (extension) is missing, then UNZIP uses "NONAME" for the filetype. Any '(' or ')' characters are removed from the fileid. c. All files are created in upper-case. Files in mixed-case cannot currently be stored into a ZIP file. d. Shared File System (SFS) directories are not supported. Files are always accessed by fn.ft.fm. To use an SFS disk, Assign it a filemode, then it can be used. 3. Wildcards in file names a. Wildcards are not supported in the zip filename. The full filename of the zip file must be given (but the .zip is not necessary). So, you can't do this: unzip -t *.zip b. Wildcards CAN be used with UNZIP to select (or exclude) files inside a zip file. Examples: unzip myzip *.c - Unzip all .c files. unzip myzip *.c -x z*.c - Unzip all .c files but those starting with Z. c. Wildcards cannot currently be used to select files with ZIP. So, you can't do this: zip -a myzip *.exec I expect to fix this for CMS in the future. 4. File timestamps a. The dates and times of files being zipped or unzipped are not currently read or set. When a file is zipped, the timestamp inside the zip file will always be the current system date and time. Likewise, when unzipping, the date and time of files being unzipped will always be the current system date/time. b. Existing files are assumed to be newer than files inside a zip file when using the -f freshen option of UNZIP. This will prevent overwriting files that may be newer than the files inside the zip file, but also effectively prevents the -f option from working. 5. ASCII, EBCDIC, and binary data Background ---------- Most systems create data files as just a stream of bytes. Record breaks happen when certain characters (new line and/or carriage return characters) are encountered in the data. How to interpret the data in a file is up to the user. The system must be told to either notice new line characters in the data or to assume that the data in the file is binary data and should be read or written as-is. CMS and MVS are record-based systems. All files are composed of data records. These can be stored in fixed-length files or in variable length files. With fixed-length files, each record is the same length. The record breaks are implied by the LRECL (logical record length) attribute associated with the file. With variable-length files, each record contains the length of that record. The separation of records are not part of the data, but part of the file structure. This means you can store any type of data in either type of file structure without having to worry about the data being interpreted as a record break. Fixed-length files may have padding at the end of the file to make up a full record. Variable-length files have no padding, but require extra record length data be stored with the file data. Storing fixed-length files into a zip file is simple, because all the data can just be dumped into the zip file and the record format (RECFM) and logical record length (LRECL) can be stored in the extra data area of the zip file so they can be restored when UNZIP is used. Storing variable-length data is harder. There is no place to put the record length data needed for each record of the file. This data could be written to the zip file as the first two bytes of each record and interpreted that way by UNZIP. That would make the data unusable on systems other than CMS and MVS, though. Currently, there isn't a solution to this problem. Each record is written to the zip file and the record length information is discarded. Binary data stored in variable-length files can't be put into a zip file then later unzipped back into the proper records. This is fine for binary data that will be read as a stream of bytes but not OK where the records matter, such as with CMS MODULEs. If the data is text (character data), there is a solution. This data can be converted into ASCII when it's stored into a zip file. The end of each record is now marked in the file by new line characters. Another advantage of this method is that the data is now accessible to non-EBCDIC systems. When the data is unzipped on CMS or MVS, it is converted back into EBCDIC and the records are recreated into a variable-length file. So, here's what we have... a. To store readable text data into a zip file that can be used on other platforms, use the -a option with ZIP to convert the data to ASCII. These files will unzip into variable-length files on CMS and should not contain binary data or corruption may occur. b. Files that were zipped on an ASCII-based system will be automatically translated to EBCDIC when unzipped. To prevent this (to unzip binary data on CMS that was sent from an ASCII-based system), use the -B option with UNZIP to force Binary mode. To zip binary files on CMS, use the -B option with ZIP to force Binary mode. This will prevent any data conversions from taking place. c. When using the ZIP program without specifying the "-a" or "-B" option, ZIP defaults to "native" (EBCDIC) mode and tries to preserve the file information (RECFM, LRECL, and BLKSIZE). So when you unzip a file zipped with ZIP under CMS or MVS, UNZIP restores the file info. The output will be fixed-length if the original was fixed and variable-length if the original was variable. If UNZIP gives a "write error (disk full?)" message, you may be trying to unzip a binary file that was zipped as a text file (without using the -B option) B?0s| foU?]]S;1 2Xyr"Rg{4{lLv@i\cAOş3Exp W+9T"&qB+qP6B GQό|T_Zd5(󖇰%mД1t8kz件o ˤցqY'0`whdNtľE9Td"ˇ bcP>s:i ꄒ^ FssWE= r)M%)˚+ _De?⽟{(YE$*Q#-o7̙&Kz{MRX43{N#$W$  5[}W9Qַc'VC*QZ>s]d})ٹ*Cwzy=dĩ%^ٌv8km`P_3 //c<mGphTƯ4dMt/w6ؒldjW>l@ZXdiu4ш1H# !D+Ӻ}2$}WtKSCjpe* @]]ՙM3:~ndgρ_v ~&Ma=ח|q#a"[ƺ/^lrdDžz\Vee *;/B-ţ5HlK ]Au9"gxݵ^m3aVj*B04jVtV1m1TuUܱa|cFC kΙtu5*5^&o$3V[}tO$).Qɋ2Zu`栥o3iY7?H͛(Lms B (:0`~'¶ 6D.3T1BRU&S푳ђ:c%ÍTqVze#厭ko&, տT/i\y<^ ,ye%uߎ7Fd,YzjңH.1Mma-Gv7dȜkdZfO真JS_OQǃӆ%* QiBR1#;k㴌U ;(d^8Rc01ZJVǬ/>tgr32JbTY'Rcgo`om Vls܃TH0lg~{;#bC弮wlMDB྾,C J R#L1r&8y{KvF{Shs~9p+|&)gGP &=K"<`:w qo"1fnIShiy)"Q L!=V\WsS CP9RR1OOZYQ*^Jo}Lxw.Rc qov?8iҋL ?sHY^׎|a" ǿdGYuT@$+PT; wKh(u%klo}H]k$1k.)a%8*HD(/?6O)fUK',6c}`vp[ 2q2g) ;fJcovd;AFJQ\^vE Xkc^V4=zRʪpUO88j1})~S{Z7CApF"E*rXn2擷ljwd8?cI7U_- s+$1}IO2hS1-3K!"ENc0s- )+vv{%d|^~ a4bھz3%4IrRllmo`LEycBYdm=2 j0Lqrl).h f_.Ws%aW>>EzQ +LpyjOG6p\VViB WZ$uepbp]v5y'RE\1!KLo,^kdC*7+v@BUc[`MmoyUarIHT(Zu]qk|BeB>YX)*Dg7A"f `?x*%>(BUjgm7l5MJR`J-|*M+UlO5PW`nO<hJ %!Aayb-( V5b7.#ETd[mH x&{-W6^ d,qr2H OPRi94Kt'mE$uf^KSluMIa h7)CJP}W|!DHM 9KE45RS-YF a:$fK?^#H B1n4 .VY(.Vc&7*@{_afwbAa[-UyUW!L2C*k=l5g`z4>@r/QO, *VFE;\k9d<|\%yhwWr"1,#}i4%_]lzvS#|j\7gXpzvo,h}H&u%//fB.gvbnn8t}2?H/'YF~R =5:\)3yL0,1z^7!C[B\s/ WE sm ]WS::O3^NKRz :gwGJU/#ibUp~"Y_#J;m?U 8;_4z72zBuj v?xS]XAFsha8LG2^IȱQF'Յ]}VMky鉏WmVz7ج!SWp>ܞ$&|VbεE~p! ?׌|s!d%_5U2.xNGFSvxw@GohG UX?G;D w8 7i=3k~+elg9 _kUn:|5cC Td$+N:Q{wonM+5ILZ`هv/lQ RޜG76Rq+>t4{` M1d9y3L{ <[4b"l2ЖgpL(̓~,iD<Hc2ݍﴪ\*D*D?v,BriT V_O$iqЄΰc4 41 ׄ,oU0f܋`6 9TZ TsYںY%\ E)ݶ*8!%/LϊA @¥xJxd3ÈW&.FLdtVj R&?;Ŕaa.@_4kȦƕ@zBbFPP]B~!TxÆ9|; 9Y%V䙈L#j!L%CV4($u\T9h+Eu/S{)ߺ^@3.zi'q(lGکPK&mC{(ms-cj*- U'$i?7ىE-5|]_WńJ a_r7)ehpseh)yjCɁq_sk7qX{KQvcw“ˋjJ^&X2Ľ0lEWP唂iMU+;=ԻDpOď!Od! "7QX׍OuMm_q *>)cEㄺdhRw8 ъ[4)X$5y@6>-uQcGɊ/]@/;M[PŖKBf$襚iHQj;Ҳ_jSmQ 7ռo: y `ہq +K [?We㚏2={eʛvO#)h+^5Y^ B=X^K7j3B7Ļ G> NE.1aQB]Q^eۊӘEubr@p1)] X਻:q?% nTot3;cP>o;=Y%]QR D]gJk!E>4ELXN1Bz`qA$#0W1.c5~vMUf9 ,I%dsrJ%^ x5uJVP !D(]xB!(yQR>3y{OhP@? fuZOZlPz'3tR7z 1 5,=NUqxA; -0;F^9vs*jD:K:Zi[4Y3Y+=w|".H`>%hOqe|*Ei8i4$j}{ s3C> g3s5f6o'hBAJ~myKN]s;8!#N8WQWm}l7m^dsP)Bfve0_/O'ynn65h2,1/lq!o!-+kZpGNKm ()ATEp&M^ImyDECP)3x,8W$.wpaW,"Y2/Z>mKpk OhfWBk ?`4X#=[!SRaqq#S,GB[&x6\.GOI}uo0/X k=efE0c6ԕ7t"=z BC7(HvV[M]xx[:^e$`m e;u^_{Sѧs!e$wKON#O6||.*_'6 :/֑3H;4&V;-\p@lQ1,IOYYpojI{+Saqg~l@{?[([#/C\9eFb?nXrW(R\=A/x&O Q XG j}5q,IpB-[5( FUDs\w:i|eNpo*GV\ANpG=+R=0LBTp9sD Q>wR+ ~\9[d'g`+C? h[]Oa#NibNGi:.W_pu|.`D@J r$|6;WQ)s0lVAY 5s>T hiE }A9*dEF\djk pv |)y>am />/8J$ :hayeZAiaHi| -hNh%/s16cm)z}SyvfA|JK a8 zK,7jmM<5+ #mjmxa;,( 1}xI6ޏMI3.pִ)AD~ivLjų yz뿗sO20<['.>7見XuXe˥C!=F-PW H`4uN?ڽeY8rDX] J>;,Y.Ҋ40D&ϸ(GJ3M;T3Z惮1x5lكjw_33E~3i\03@Rf̀J8yS5"07rKl=/ t}tЉA3'8m9G}zzk!P>4.?Zj'y1 MG?yz= `"~#k3:mLf1>XV[? oUQOE'(p$2}0=}I+*)&jCs18* NZ?yCt]!%z084,LE'tSwkeZA#Oo9{\Lv$El ofyvf`:}1 G,ECq]/DJaBV)<yqOFI-@WI [ y/6(lv/jpnUFCRy#EO: bo_m LDP_."E`tdfileC7/M UNZIP.BCK. ([UNZIP542.CMSMVS]README.CMS;1!I  Summary ------- Here's how to ZIP the different types of files. RECFM F text Use the -a option with ZIP to convert to ASCII for use with other platforms or no options for use on EBCDIC systems only. RECFM V text Use the -a option with ZIP to convert to ASCII for use with other platforms or no options for use on EBCDIC systems only. RECFM F binary Use the -B option with ZIP (upper-case "B"). RECFM V binary Use the -B option with ZIP. Can be zipped OK but the record structure is destroyed when unzipped. This is OK for data files read as binary streams but not OK for files such as CMS MODULEs. 6. Character Sets If you are used to running UNZIP on systems like UNIX, DOS, OS/2 or Windows, you will may have some problems with differences in the character set. There are a number of different EBCDIC code pages, like there are a number of different ASCII code pages. For example, there is a US EBCDIC, a German EBCDIC, and a Swedish EBCDIC. As long as you are working with other people who use the same EBCDIC code page, you will have no trouble. If you work with people who use ASCII, or who use a different EBCDIC code page, you may need to do some translation. UNZIP translates ASCII text files to and from Open Systems EBCDIC (IBM-1047), which may not be the EBCDIC that you are using. For example, US EBCDIC (IBM-037) uses different character codes for square brackets. In such cases, you can use the ICONV utility (supplied with IBM C) to translate between your EBCDIC character set and IBM-1047. If your installation does not use IBM-1047 EBCDIC, messages from UNZIP may look a little odd. For example, in a US EBCDIC installation, an opening square bracket will become an i-acute and a closing square bracket will become a u-grave. The supplied ZIP and UNZIP EXECs attempt to correct this by setting CMS INPUT and OUTPUT translations to adjust the display of left and right brackets. You may need to change this if brackets don't display correctly on your system. 7. You can unzip using VM/CMS PIPELINES so unzip can be used as a pipeline filter. Example: 'PIPE COMMAND UNZIP -p test.zip george.test | Count Lines | Cons' Please report all bugs and problems to: Zip-Bugs@lists.wku.edu ----------------------------------------------------------------------- Original CMS/MVS port by George Petrov. e-mail: c888090@nlevdpsb.snads.philips.nl tel: +31-40-781155 Philips C&P Eindhoven The Netherlands ----------------------------------------------------------------------- Additional fixes and README re-write (4/98) by Greg Hartwig. e-mail: ghartwig@ix.netcom.com ghartwig@vnet.ibm.com ----------------------------------------------------------------------- Additional notes from Ian E. Gorman. e-mail: ian@iosphere.net *[UNZIP542.CMSMVS]README.MVS;1+,'. / 4 - (0@123KPWO56H7H89GHJThank you for trying this port of UNZIP for VM/CMS and MVS! Using under MVS: ------------------------- 1. To use the Info-ZIP's UNZIP under MVS you need: - C/370 ver 2.1 compiler or another compatible compiler supporting long names for function/variable names. 2. To compile the program under MVS do : - unzip all the files from unz54vm.zip file. They are stored as ASCII format so you have to unzip them first on PC or other system that already have UNZIP, and then upload them to the mainframe with ASCII to EBCDIC conversion. - Copy all the .C files in the PDS called USERID.UNZIP.C - Copy all the .H files in the PDS called USERID.UNZIP.H - adjust the job UNZMVSC.JOB to work on your site. Change USERID to your userid. You might need to change the CEE dataset names to match your OS/390 system. - Preallocate PDS datasets named: USERID.UNZIP.OBJ and USERID.UNZIP.LOAD - execute the job UNZMVSC to compile and link all the sources. - if everything is ok you will get an UNZIP MODULE 3. Using UNZIP - Just read the UNZIP.TXT - A few exceptions concerning MVS 3.0. There are different ways to invoke UNZIP. - allocating UNZIP.LOAD dataset to your ISPLLIB if you want to invoke UNZIP under ISPF. Then just type UNZIP ...parms... to get it work - You can also call it directly with : TSO CALL 'userid.UNZIP.LOAD(UNZIP)' '...parms...' (notice to quotes!) - You can even call it from a batch job like: //MYZIP JOB (account) //STEP1 EXEC PGM=UNZIP,PARM='-l mytestz.zip *.c' //STEPLIB DD DSN=userid.UNZIP.LOAD,DISP=SHR //SYSPRINT DD SYSOUT=* This will list all the .c files from the zip file mytestz.zip 3.1. If the ZIP file has been zipped on an ASCII based system it will be automatically translated to EBCDIC ( I hope I got all those translation tables OK :-). You can force ASCII to EBCDIC conversion with the -a flag. 3.2. The date/time of the output files is set to the current system date/time - not according the date/time in the zip file. 3.3. You can even unzip using TSO/E PIPELINES so unzip can be used as pipeline filter: 'pipe cms unzip -p test.zip george.test | count lines | cons' ( we do also a lot of pipethinking here ;-) 3.4. If you got also the ZIP program (see ZIP21VM.ZIP) you can do zipping and unzipping without translating to ASCII the ZIP also preserves the file informations (LRECL,BLKSIZE..) So when you UNZIP a file zipped with ZIP under MVS it restores the file info. There currently some problems with file with RECFM=V* I don't save the length of each record yet :-) 3.5. No wildcards are supported in the input zip name you have to give the real name (.zip is not necessary) So you CAN'T use things like: unzip -t *.zip 3.6. But you CAN use wildcards as filename selection like: unzip -t myzip *.c - OK or even unzip -t myzip *.c -x z*.c - to exclude all files matching z*.c 3.7. You can unzip to a PDS using the -d parameter, for example: unzip -dmyzip myzip *.c This will unzip all .c files that are in the zip file in a PDS directory called MYZIP.C BE AWARE that the extension of every files is being placed as last identifier on the PDS name, so if you have a file in the zipfile called 'testp.doc' and you use '-d mypds' the PDS name will become 'mypds.doc(testp)' Depending on which options IBM chose for C this week, unzip may or may not prefix output files with your userid and/or TSO prefix. To prevent this, quote the filename to -d, for example //UNZIP EXEC PGM=UNZIP, // PARM='/-a -o ''userid.zip''D UNZIP.BCK' ([UNZIP542.CMSMVS]README.MVS;1 .  -d ''hlq.test'' *' //STEPLIB DD DSN=USERID.UNZIP.LOAD,DISP=SHR //SYSPRINT DD SYSOUT=* //SYSOUT DD SYSOUT=* The above JCL converts from ASCII to EBCDIC (-a), always overwrites existing members (-o), extracts from 'userid.zip', writes to files starting with 'hlq.test', all members (*). Note the double quotes because PARM= requires single quotes. 3.8. The rules for output DCBs are a little messy. If the output file already exists (remember the -d option) then unzip uses the existing DCB and space values. If the output file does not exist and the input zip came from MVS then unzip makes its best attempt at preserving the original DCB. However there is not enough information stored in the zip file to do this correctly for all file types, some file types may be corrupted. If the output file does not exist and the input zip does not contain MVS DCB information then unzip uses RECFM=U, LRECL=32760 for binary data, RECFM=V, LRECL=133 for text. Text includes ASCII to EBCDIC conversion. As soon as the output file is created, unzip uses the same output DCB for all following members, even if the input is a mixture of text and binary. In all cases, unzip has no built in parameters for space. For a preallocated file this is not a problem. If unzip creates an output file you get a default space allocation which is site dependent. It is far better to preallocate the output files with the correct space and DCB values then use the -d option to point to those files. 3.9. All '+','_' or '-' signs are skipped from the filenames Please repport all bugs and problems to : Zip-Bugs@lists.wku.edu That's all for now. Have fun! George Petrov e-mail: c888090@nlevdpsb.snads.philips.nl tel: +31-40-781155 Philips C&P Eindhoven The Netherlands Updated by: Keith Owens *[UNZIP542.CMSMVS]UNZIP.EXEC;1+,N./ 4- (0@123KPWO56,}U7,}U89GHJ /***********************************************************************/ /* */ /* Front-end EXEC to set up linkage to the C runtime libraries */ /* before executing a MODULE generated from C code. */ /* */ /* Copy this file as an EXEC with a filename matching the C MODULE. */ /* */ /* Greg Hartwig (ghartwig@vnet.ibm.com) 7/31/97, 4/24/98. */ /* */ /***********************************************************************/ Address Command Parse Arg argstring Parse Source . . myname . /* Set output and input character translation so brackets show up */ 'SET OUTPUT AD' 'BA'x 'SET OUTPUT BD' 'BB'x 'SET INPUT BA AD' 'SET INPUT BB BD' Call CLIB If rc<>0 Then Do Say 'The required C runtime libraries don''t appear to be available.' Say myname 'can not run.' Exit 12 End /* Run the command */ myname argstring Exit rc /* Contents of the CLIB EXEC, modified for RC checking. */ /* Removed TXTLIB setting. Only LOADLIB needed for execution. */ CLIB: /***************************************************/ /* SET UP LIBRARIES FOR LE for MVS & VM */ /***************************************************/ Address COMMAND loadlib ='EDCLINK' /* C/370 runtime */ loadlib ='SCEERUN' /* LE runtime */ theirs=queued() /* old stack contentsM068*/ 'QUERY LOADLIB ( LIFO' /* old setting M068*/ LoadlibList='' /* init list M068*/ rc=0 Do while queued()^=theirs /* all lines from cmdM068*/ Parse upper pull 'LOADLIB' '=' Ltemp /* get one line M068*/ LoadlibList= Ltemp Loadliblist /* was stacked LIFO M068*/ End /*M068*/ If loadlibList='NONE' , Then Do 'GLOBAL LOADLIB' Loadlib /* enforce what we need */ End Else Do Do xx=1 to Words(loadlib) If Find(loadliblist,word(loadlib,xx)) = 0 , then loadliblist = loadliblist word(loadlib,xx) End 'GLOBAL LOADLIB' loadliblist /* enforce what we need */ End Return P!*[UNZIP542.CMSMVS]UNZIP.MAKEFILE;1+,)./ 4Q- (0@123KPWO56_P7_P89GHJ* This is a comment * this makefile compiles filter UNZIP GLOBALS: long def(VM_CMS) TEXT: unzip c crc32 c crctab c crypt c envargs c explode c extract c fileio c globals c inflate c list c match c process c ttyio c unreduce c unshrink c zipinfo c vmmvs c MODULE: unzip module t*[UNZIP542.CMSMVS]UNZMVSC.JOB;1+,@. / 4 - (0@123KPWO56M 7M 89GHJ//* //* LE COMPILE FOR UNZIP541. //* ALL STEPS SHOULD GET COND CODE 0 EXCEPT FOR PLINK.PLKED WHICH GETS 4. //* //CBC JCLLIB ORDER=CBC.SCBCPRC //UNZIP EXEC EDCC,COND=(0,NE),CREGSIZ='0M', // INFILE='USERID.UNZIP.C(UNZIP)', // OUTFILE='USERID.UNZIP.OBJ(UNZIP),DISP=SHR', // CPARM='LONG,NOTERM,LIST,XREF,SOURCE', // CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT' //COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR //CRC32 EXEC EDCC,COND=(0,NE),CREGSIZ='0M', // INFILE='USERID.UNZIP.C(CRC32)', // OUTFILE='USERID.UNZIP.OBJ(CRC32),DISP=SHR', // CPARM='LONG,NOTERM,LIST,XREF,SOURCE', // CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT' //COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR //CRCTAB EXEC EDCC,COND=(0,NE),CREGSIZ='0M', // INFILE='USERID.UNZIP.C(CRCTAB)', // OUTFILE='USERID.UNZIP.OBJ(CRCTAB),DISP=SHR', // CPARM='LONG,NOTERM,LIST,XREF,SOURCE', // CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT' //COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR //CRYPT EXEC EDCC,COND=(0,NE),CREGSIZ='0M', // INFIE*[ UNZIP.BCK@ ([UNZIP542.CMSMVS]UNZMVSC.JOB;1 LE='USERID.UNZIP.C(CRYPT)', // OUTFILE='USERID.UNZIP.OBJ(CRYPT),DISP=SHR', // CPARM='LONG,NOTERM,LIST,XREF,SOURCE', // CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT' //COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR //ENVARGS EXEC EDCC,COND=(0,NE),CREGSIZ='0M', // INFILE='USERID.UNZIP.C(ENVARGS)', // OUTFILE='USERID.UNZIP.OBJ(ENVARGS),DISP=SHR', // CPARM='LONG,NOTERM,LIST,XREF,SOURCE', // CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT' //COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR //EXPLODE EXEC EDCC,COND=(0,NE),CREGSIZ='0M', // INFILE='USERID.UNZIP.C(EXPLODE)', // OUTFILE='USERID.UNZIP.OBJ(EXPLODE),DISP=SHR', // CPARM='LONG,NOTERM,LIST,XREF,SOURCE', // CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT' //COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR //EXTRACT EXEC EDCC,COND=(0,NE),CREGSIZ='0M', // INFILE='USERID.UNZIP.C(EXTRACT)', // OUTFILE='USERID.UNZIP.OBJ(EXTRACT),DISP=SHR', // CPARM='LONG,NOTERM,LIST,XREF,SOURCE', // CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT' //COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR //FILEIO EXEC EDCC,COND=(0,NE),CREGSIZ='0M', // INFILE='USERID.UNZIP.C(FILEIO)', // OUTFILE='USERID.UNZIP.OBJ(FILEIO),DISP=SHR', // CPARM='LONG,NOTERM,LIST,XREF,SOURCE', // CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT' //COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR //GLOBALS EXEC EDCC,COND=(0,NE),CREGSIZ='0M', // INFILE='USERID.UNZIP.C(GLOBALS)', // OUTFILE='USERID.UNZIP.OBJ(GLOBALS),DISP=SHR', // CPARM='LONG,NOTERM,LIST,XREF,SOURCE', // CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT' //COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR //INFLATE EXEC EDCC,COND=(0,NE),CREGSIZ='0M', // INFILE='USERID.UNZIP.C(INFLATE)', // OUTFILE='USERID.UNZIP.OBJ(INFLATE),DISP=SHR', // CPARM='LONG,NOTERM,LIST,XREF,SOURCE', // CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT' //COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR //LIST EXEC EDCC,COND=(0,NE),CREGSIZ='0M', // INFILE='USERID.UNZIP.C(LIST)', // OUTFILE='USERID.UNZIP.OBJ(LIST),DISP=SHR', // CPARM='LONG,NOTERM,LIST,XREF,SOURCE', // CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT' //COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR //MATCH EXEC EDCC,COND=(0,NE),CREGSIZ='0M', // INFILE='USERID.UNZIP.C(MATCH)', // OUTFILE='USERID.UNZIP.OBJ(MATCH),DISP=SHR', // CPARM='LONG,NOTERM,LIST,XREF,SOURCE', // CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT' //COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR //PROCESS EXEC EDCC,COND=(0,NE),CREGSIZ='0M', // INFILE='USERID.UNZIP.C(PROCESS)', // OUTFILE='USERID.UNZIP.OBJ(PROCESS),DISP=SHR', // CPARM='LONG,NOTERM,LIST,XREF,SOURCE', // CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT' //COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR //TTYIO EXEC EDCC,COND=(0,NE),CREGSIZ='0M', // INFILE='USERID.UNZIP.C(TTYIO)', // OUTFILE='USERID.UNZIP.OBJ(TTYIO),DISP=SHR', // CPARM='LONG,NOTERM,LIST,XREF,SOURCE', // CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT' //COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR //UNREDUCE EXEC EDCC,COND=(0,NE),CREGSIZ='0M', // INFILE='USERID.UNZIP.C(UNREDUCE)', // OUTFILE='USERID.UNZIP.OBJ(UNREDUCE),DISP=SHR', // CPARM='LONG,NOTERM,LIST,XREF,SOURCE', // CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT' //COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR //UNSHRINK EXEC EDCC,COND=(0,NE),CREGSIZ='0M', // INFILE='USERID.UNZIP.C(UNSHRINK)', // OUTFILE='USERID.UNZIP.OBJ(UNSHRINK),DISP=SHR', // CPARM='LONG,NOTERM,LIST,XREF,SOURCE', // CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT' //COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR //ZIPINFO EXEC EDCC,COND=(0,NE),CREGSIZ='0M', // INFILE='USERID.UNZIP.C(ZIPINFO)', // OUTFILE='USERID.UNZIP.OBJ(ZIPINFO),DISP=SHR', // CPARM='LONG,NOTERM,LIST,XREF,SOURCE', // CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT' //COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR //VMMVS EXEC EDCC,COND=(0,NE),CREGSIZ='0M', // INFILE='USERID.UNZIP.C(VMMVS)', // OUTFILE='USERID.UNZIP.OBJ(VMMVS),DISP=SHR', // CPARM='LONG,NOTERM,LIST,XREF,SOURCE', // CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT' //COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR //PLINK EXEC PROC=EDCPL,COND=(4,LT), // OUTFILE='USERID.UNZIP.LOAD(UNZIP),DISP=SHR', // PPARM='NONCAL,MAP,MEMORY', // LPARM='LIST,MAP,XREF' //SYSPRINT DD SYSOUT=* //PLKED.SYSIN DD DSN=USERID.UNZIP.OBJ(UNZIP),DISP=SHR // DD DSN=USERID.UNZIP.OBJ(CRC32),DISP=SHR // DD DSN=USERID.UNZIP.OBJ(CRCTAB),DISP=SHR // DD DSN=USERID.UNZIP.OBJ(CRYPT),DISP=SHR // DD DSN=USERID.UNZIP.OBJ(ENVARGS),DISP=SHR // DD DSN=USERID.UNZIP.OBJ(EXPLODE),DISP=SHR // DD DSN=USERID.UNZIP.OBJ(EXTRACT),DISP=SHR // DD DSN=USERID.UNZIP.OBJ(FILEIO),DISP=SHR // DD DSN=USERID.UNZIP.OBJ(GLOBALS),DISP=SHR // DD DSN=USERID.UNZIP.OBJ(INFLATE),DISP=SHR // DD DSN=USERID.UNZIP.OBJ(LIST),DISP=SHR // DD DSN=USERID.UNZIP.OBJ(MATCH),DISP=SHR // DD DSN=USERID.UNZIP.OBJ(PROCESS),DISP=SHR // DD DSN=USERID.UNZIP.OBJ(TTYIO),DISP=SHR // DD DSN=USERID.UNZIP.OBJ(UNREDUCE),DISP=SHR // DD DSN=USERID.UNZIP.OBJ(UNSHRINK),DISP=SHR // DD DSN=USERID.UNZIP.OBJ(ZIPINFO),DISP=SHR // DD DSN=USERID.UNZIP.OBJ(VMMVS),DISP=SHR //LKED.SYSLIB DD DISP=SHR,DSN=CEE.SCEELKED *[UNZIP542.CMSMVS]UNZVMC.EXEC;1+,[./ 4- (0@123KPWO56 <\7 <\89GHJ/* VMCOMPIL EXEC Unzip compile for VM/CMS */ /* Author : George Petrov, 11 Apr 1995 */ signal on error parms = '(long def(VM_CMS)' /* Add local options */ /* "TARGET(COMPAT)" is required for V2.2 compiler */ parms = parms 'TARGET(COMPAT) SOURCE' say 'Compiling UNZIP C...' 'cc unzip c 'parms say 'Compiling CRC32 C...' 'cc crc32 c 'parms say 'Compiling CRCTAB C...' 'cc crctab c 'parms say 'Compiling CRYPT C...' 'cc crypt c 'parms say 'Compiling ENVARGS C...' 'cc envargs c 'parms say 'Compiling EXPLODE C...' 'cc explode c 'parms say 'Compiling EXTRACT C...' 'cc extract c 'parms say 'Compiling FILEIO C...' 'cc fileio c 'parms say 'Compiling GLOBALS C...' 'cc globals c 'parms say 'Compiling INFLATE C...' 'cc inflate c 'parms say 'Compiling PROCESS C...' 'cc process c 'parms say 'Compiling LIST C...' 'cc list c 'parms say 'Compiling MATCH C...' 'cc match c 'parms say 'Compiling TTYIO C...' 'cc ttyio c 'parms say 'Compiling UNREDUCE C...' 'cc unreduce c 'parms say 'Compiling UNSHRINK C...' 'cc unshrink c 'parms say 'Compiling ZIPINFO C...' 'cc zipinfo c 'parms say 'Compiling VMMVS C...' 'cc vmmvs c 'parms say 'Linking all files...' 'cmod unzip unzip crc32 crctab crypt envargs explode extract fileio globals', 'inflate list match process ttyio unreduce unshrink zipinfo vmmvs' say 'All Done!' say "To run enter : UNZIP parms" exit rc error: say 'Error during compilation!' exit rc *[UNZIP542.CMSMVS]VMMVS.C;1+,?.%/ 4%%8- (0@123KPWO&56X 7X 89GHJF& UNZIP.BCK? ([UNZIP542.CMSMVS]VMMVS.C;1%(/* Copyright (c) 1990-2000 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*--------------------------------------------------------------------------- vmmvs.c (for both VM/CMS and MVS) Contains: vmmvs_open_infile() open_outfile() close_outfile() close_infile() getVMMVSexfield() do_wild() mapattr() mapname() checkdir() check_for_newer() stat() version() ---------------------------------------------------------------------------*/ #define __VMMVS_C /* identifies this source module */ #define UNZIP_INTERNAL #include "unzip.h" /********************************/ /* Function vmmvs_open_infile() */ /********************************/ FILE *vmmvs_open_infile(__G) __GDEF { FILE *fzip; G.tempfn = NULL; fzip = fopen(G.zipfn, FOPR); #if 0 /* Let's try it without the convert for a while -- RG Hartwig */ if ((fzip = fopen(G.zipfn,"rb,recfm=fb")) == NULL) { size_t cnt; char *buf; FILE *in, *out; if ((buf = (char *)malloc(32768)) == NULL) return NULL; if ((G.tempfn = tmpnam(NULL)) == NULL) return NULL; if ((in = fopen(G.zipfn,"rb")) != NULL && (out = fopen(G.tempfn,"wb,recfm=fb,lrecl=1")) != NULL) { Trace((stdout,"Converting ZIP file to fixed record format...\n")); while (!feof(in)) { cnt = fread(buf,1,32768,in); if (cnt) fwrite(buf,1,cnt,out); } } else { free(buf); fclose(out); fclose(in); return NULL; } free(buf); fclose(out); fclose(in); fzip = fopen(G.tempfn,"rb,recfm=fb"); if (fzip == NULL) return NULL; /* Update the G.ziplen value since it might have changed after the reformatting copy. */ fseek(fzip,0L,SEEK_SET); fseek(fzip,0L,SEEK_END); G.ziplen = ftell(fzip); } #endif return fzip; } /***************************/ /* Function open_outfile() */ /***************************/ int open_outfile(__G) /* return 1 if fail */ __GDEF { char type[100]; char *mode = NULL; #ifdef MVS /* Check if the output file already exists and do not overwrite its DCB */ char basefilename[PATH_MAX], *p; FILE *exists; /* Get the base file name, without any member name */ strcpy(basefilename, G.filename); if ((p = strchr(basefilename, '(')) != NULL) { if (basefilename[0] == '\'') *p++ = '\''; *p = '\0'; } exists = fopen(basefilename, FOPR); if (exists) { if (G.pInfo->textmode) mode = FOPWTE; /* Text file, existing */ else mode = FOPWE; /* Binary file, existing */ fclose(exists); } else /* continued on next line */ #endif /* MVS */ if (G.pInfo->textmode) { if (mode == NULL) mode = FOPWT; } else if (G.lrec.extra_field_length > 0 && G.extra_field != NULL) { unsigned lef_len = (unsigned)(G.lrec.extra_field_length); uch *lef_buf = G.extra_field; while (lef_len > EB_HEADSIZE) { unsigned eb_id = makeword(&lef_buf[EB_ID]); unsigned eb_dlen = makeword(&lef_buf[EB_LEN]); if (eb_dlen > (lef_len - EB_HEADSIZE)) { /* Discovered some extra field inconsistency! */ TTrace((stderr, "open_outfile: block length %u > rest lef_size %u\n", eb_dlen, lef_len - EB_HEADSIZE)); break; } if ((eb_id == EF_VMCMS || eb_id == EF_MVS) && (getVMMVSexfield(type, lef_buf, eb_dlen) > 0)) { mode = type; break; } /* Skip this extra field block */ lef_buf += (eb_dlen + EB_HEADSIZE); lef_len -= (eb_dlen + EB_HEADSIZE); } } if (mode == NULL) mode = FOPW; Trace((stderr, "Output file='%s' opening with '%s'\n", G.filename, mode)); if ((G.outfile = fopen(G.filename, mode)) == NULL) { Info(slide, 0x401, ((char *)slide, "\nerror: cannot create %s\n", G.filename)); Trace((stderr, "error %d: '%s'\n", errno, strerror(errno))); return 1; } return 0; } /* end function open_outfile() */ /****************************/ /* Function close_outfile() */ /****************************/ void close_outfile(__G) __GDEF { fclose(G.outfile); } /* end function close_outfile() */ /***************************/ /* Function close_infile() */ /***************************/ void close_infile(__G) __GDEF { fclose(G.zipfd); /* If we're working from a temp file, erase it now */ if (G.tempfn) remove(G.tempfn); } /* end function close_infile() */ /******************************/ /* Function getVMMVSexfield() */ /******************************/ extent getVMMVSexfield(type, ef_block, datalen) char *type; uch *ef_block; unsigned datalen; { fldata_t *fdata = (fldata_t *) &ef_block[4]; if (datalen < sizeof(fldata_t)) return 0; strcpy(type, "w"); strcat(type, fdata->__openmode == __TEXT ? "" :fdata->__openmode == __BINARY ? "b" :fdata->__openmode == __RECORD ? "b,type=record" : ""); strcat(type, ",recfm="); strcat(type, fdata->__recfmF? "F" :fdata->__recfmV? "V" :fdata->__recfmU? "U" : "?"); if (fdata->__recfmBlk) strcat(type, "B"); if (fdata->__recfmS) strcat(type, "S"); if (fdata->__recfmASA) strcat(type, "A"); if (fdata->__recfmM) strcat(type, "M"); sprintf(type+strlen(type), ",lrecl=%ld", fdata->__recfmV ? fdata->__maxreclen+4 : fdata->__maxreclen); #ifdef VM_CMS /* For CMS, use blocksize for FB files only */ if (fdata->__recfmBlk) sprintf(type+strlen(type), ",blksize=%ld", fdata->__blksize); #else /* For MVS, always use blocksize */ sprintf(type+strlen(type), ",blksize=%ld", fdata->__blksize); #endif return strlen(type); } /* end function getVMMVSexfield() */ #ifndef SFX /**********************/ /* Function do_wild() */ /* for porting: dir separator; match(ignore_case) */ /**********************/ char *do_wild(__G__ wld) __GDEF ZCONST char *wld; /* only used first time on a given dir */ { static int First = 0; static char filename[256]; if (First == 0) { First = 1; strcpy( filename, wld ); return filename; } else return (char *)NULL; } /* end function do_wild() */ #endif /* !SFX */ /************************/ /* Function mapattr() */ /************************/ int mapattr(__G) __GDEF { return 0; } /************************/ /* Function mapname() */ /************************/ int mapname(__G__ renamed) /* returns: */ /* 0 (PK_COOL) if no error, */ /* 1 (PK_WARN) if caution (filename trunc), */ /* 2 (PK_ERR) if warning (skip file because dir doesn't exist), */ /* 3 (PK_BADERR) if error (skip file), */ /* 10 if no memory (skip fiG7 UNZIP.BCK? ([UNZIP542.CMSMVS]VMMVS.C;1%cle) */ /* 78 (IZ_VOL_LABEL) if path was volume label (skip it) */ __GDEF int renamed; { char newname[FILNAMSIZ], *lbar; #ifdef MVS char *pmember; #endif int name_changed = 0; if (G.pInfo->vollabel) return IZ_VOL_LABEL; /* can't set disk volume labels in CMS_MVS */ #ifdef MVS /* Remove bad characters for MVS from the filename */ while ((lbar = strpbrk(G.filename, "_+-")) != NULL) { /* Must use memmove() here because data overlaps. */ /* strcpy() gives undefined behavior in this case. */ memmove(lbar, lbar+1, strlen(lbar)); name_changed = 1; } #endif /* Remove bad characters for MVS/CMS from the filename */ while ((lbar = strpbrk(G.filename, "()")) != NULL) { memmove(lbar, lbar+1, strlen(lbar)); name_changed = 1; } #ifdef VM_CMS if ((lbar = strrchr(G.filename, '/')) != NULL) { strcpy(newname, lbar+1); Trace((stderr, "File '%s' renamed to '%s'\n", G.filename, newname)); strcpy(G.filename, newname); name_changed = 1; } #else /* MVS */ if ((pmember = strrchr(G.filename, '/')) == NULL) pmember = G.filename; else pmember++; /* search for extension in file name */ if ((lbar = strrchr(pmember, '.')) != NULL) { *lbar++ = '\0'; strcpy(newname, pmember); strcpy(pmember, lbar); strcat(pmember, "("); strcat(pmember, newname); strcat(pmember, ")"); } /* Remove all 'internal' dots '.', to prevent false consideration as * MVS path delimiters! */ while ((lbar = strrchr(G.filename, '.')) != NULL) { memmove(lbar, lbar+1, strlen(lbar)); name_changed = 1; } /* Finally, convert path delimiters from internal '/' to external '.' */ while ((lbar = strchr(G.filename, '/')) != NULL) *lbar = '.'; #endif /* ?VM_CMS */ #ifndef MVS if ((lbar = strchr(G.filename, '.')) == NULL) { printf("WARNING: file '%s' has no extension - renamed to '%s.NONAME'\n"\ ,G.filename, G.filename); strcat(G.filename, ".NONAME"); name_changed = 1; } #endif checkdir(__G__ G.filename, GETPATH); return name_changed; } /* end function mapname() */ int checkdir(__G__ pathcomp, flag) __GDEF char *pathcomp; int flag; /* * returns: 1 - (on APPEND_NAME) truncated filename * 2 - path doesn't exist, not allowed to create * 3 - path doesn't exist, tried to create and failed; or * path exists and is not a directory, but is supposed to be * 4 - path is too long * 10 - can't allocate memory for filename buffers */ { static int rootlen = 0; /* length of rootpath */ static char *rootpath; /* user's "extract-to" directory */ # define FN_MASK 7 # define FUNCTION (flag & FN_MASK) /*--------------------------------------------------------------------------- ROOT: if appropriate, store the path in rootpath and create it if neces- sary; else assume it's a zipfile member and return. This path segment gets used in extracting all members from every zipfile specified on the command line. Note that under OS/2 and MS-DOS, if a candidate extract-to directory specification includes a drive letter (leading "x:"), it is treated just as if it had a trailing '/'--that is, one directory level will be created if the path doesn't exist, unless this is otherwise pro- hibited (e.g., freshening). ---------------------------------------------------------------------------*/ #if (!defined(SFX) || defined(SFX_EXDIR)) if (FUNCTION == ROOT) { Trace((stderr, "initializing root path to [%s]\n", pathcomp)); if (pathcomp == (char *)NULL) { rootlen = 0; } else if ((rootlen = strlen(pathcomp)) > 0) { if ((rootpath = (char *)malloc(rootlen+1)) == NULL) { rootlen = 0; return 10; } strcpy(rootpath, pathcomp); Trace((stderr, "rootpath now = [%s]\n", rootpath)); } return 0; } #endif /* !SFX || SFX_EXDIR */ /*--------------------------------------------------------------------------- GETPATH: copy full path to the string pointed at by pathcomp, and free buildpath. ---------------------------------------------------------------------------*/ if (FUNCTION == GETPATH) { if (rootlen > 0) { #ifdef VM_CMS /* put the exdir after the filename */ strcat(pathcomp, "."); /* used as minidisk to be save on */ strcat(pathcomp, rootpath); #else /* MVS */ char newfilename[PATH_MAX]; char *start_fname; int quoted = 0; strcpy(newfilename, rootpath); if (newfilename[0] == '\'') { quoted = strlen(newfilename) - 1; if (newfilename[quoted] == '\'') newfilename[quoted] = '\0'; else quoted = 0; } if (strchr(pathcomp, '(') == NULL) { if ((start_fname = strrchr(pathcomp, '.')) == NULL) { start_fname = pathcomp; } else { *start_fname++ = '\0'; strcat(newfilename, "."); strcat(newfilename, pathcomp); } strcat(newfilename, "("); strcat(newfilename, start_fname); strcat(newfilename, ")"); } else { strcat(newfilename, "."); strcat(newfilename, pathcomp); } if (quoted) strcat(newfilename, "'"); Trace((stdout, "new dataset : %s\n", newfilename)); strcpy(pathcomp, newfilename); #endif /* ?VM_CMS */ } return 0; } /*--------------------------------------------------------------------------- END: free rootpath, immediately prior to program exit. ---------------------------------------------------------------------------*/ if (FUNCTION == END) { Trace((stderr, "freeing rootpath\n")); if (rootlen > 0) { free(rootpath); rootlen = 0; } return 0; } return 99; /* should never reach */ } /* end function checkdir() */ /******************************/ /* Function check_for_newer() */ /* used for overwriting/freshening/updating */ /******************************/ int check_for_newer(__G__ filename) /* return 1 if existing file is newer */ __GDEF /* or equal; 0 if older; -1 if doesn't */ char *filename; /* exist yet */ { FILE *stream; if ((stream = fopen(filename, FOPR)) != NULL) { fclose(stream); /* File exists, assume it is "newer" than archive entry. */ return EXISTS_AND_NEWER; } /* File does not exist. */ return DOES_NOT_EXIST; } /* end function check_for_newer() */ /*********************/ /* Function stat() */ /*********************/ int stat(const char *path, struct stat *buf) { FILE *fp; char fname[PATH_MAX]; time_t ltime; if ((fp = fopen(path, FOPR)) != NULL) { fldata_t fdata; if (fldata( fp, fname, &fdata ) == 0) { buf->st_dev = fdata.__device; buf->st_mode = *(short *)(&fdata); } /* Determine file size by seeking to EOF */ fseek(fp,0L,SEEK_END); buf->st_size = ftell(fp); fclose(fp); /* set time fields in stat buf to current time. */ time(<ime); buf->st_atime = buf->sHk UNZIP.BCK? ([UNZIP542.CMSMVS]VMMVS.C;1%R1t_mtime = buf->st_ctime = ltime; /* File exists, return success */ return 0; } return 1; } #ifdef STAND_ALONE /***************************/ /* Function main_vmmvs() */ /***************************/ /* This function is called as main() to parse arguments */ /* into argc and argv. This is required for stand-alone */ /* execution. This calls the "real" main() when done. */ int MAIN_VMMVS(void) { int argc=0; char *argv[50]; int iArgLen; char argstr[256]; char **pEPLIST, *pCmdStart, *pArgStart, *pArgEnd; /* Get address of extended parameter list from S/370 Register 0 */ pEPLIST = (char **)__xregs(0); /* Null-terminate the argument string */ pCmdStart = *(pEPLIST+0); pArgStart = *(pEPLIST+1); pArgEnd = *(pEPLIST+2); iArgLen = pArgEnd - pCmdStart + 1; /* Make a copy of the command string */ memcpy(argstr, pCmdStart, iArgLen); argstr[iArgLen] = '\0'; /* Null-terminate */ /* Store first token (cmd) */ argv[argc++] = strtok(argstr, " "); /* Store the rest (args) */ while (argv[argc-1]) argv[argc++] = strtok(NULL, " "); argc--; /* Back off last NULL entry */ /* Call "real" main() function */ return MAIN(argc, argv); } #endif /* STAND_ALONE */ #ifndef SFX /************************/ /* Function version() */ /************************/ void version(__G) __GDEF { int len; char liblvlmsg [50+1]; char *compiler = "?"; char *platform = "?"; char complevel[64]; /* Map the runtime library level information */ union { unsigned int iVRM; struct { unsigned int pd:4; /* Product designation */ unsigned int vv:4; /* Version */ unsigned int rr:8; /* Release */ unsigned int mm:16; /* Modification level */ } xVRM; } VRM; /* Break down the runtime library level */ VRM.iVRM = __librel(); sprintf(liblvlmsg, "Using runtime library level %s V%dR%dM%d", (VRM.xVRM.pd==1 ? "LE" : "CE"), VRM.xVRM.vv, VRM.xVRM.rr, VRM.xVRM.mm); /* Note: LE = Language Environment, CE = Common Env. (C/370). */ /* This refers ONLY to the current runtimes, not the compiler. */ #ifdef VM_CMS platform = "VM/CMS"; #ifdef __IBMC__ compiler = "IBM C"; #else compiler = "C/370"; #endif #endif #ifdef MVS platform = "MVS"; #ifdef __IBMC__ compiler = "IBM C/C++"; #else compiler = "C/370"; #endif #endif #ifdef __COMPILER_VER__ VRM.iVRM = __COMPILER_VER__; sprintf(complevel," V%dR%dM%d", VRM.xVRM.vv, VRM.xVRM.rr, VRM.xVRM.mm); #else #ifdef __IBMC__ sprintf(complevel," V%dR%d", __IBMC__ / 100, (__IBMC__ % 100)/10); #else complevel[0] = '\0'; #endif #endif /* Output is in the form "Compiled with %s%s for %s%s%s%s." */ len = sprintf((char *)slide, LoadFarString(CompiledWith), /* Add compiler name and level */ compiler, complevel, /* Add compile environment */ platform, /* Add timestamp */ #ifdef __DATE__ " on " __DATE__ #ifdef __TIME__ " at " __TIME__ #endif #endif ".\n", "", liblvlmsg ); (*G.message)((zvoid *)&G, slide, (ulg)len, 0); } /* end function version() */ #endif /* !SFX */ *[UNZIP542.CMSMVS]VMMVS.H;1+,7./ 4- (0@123KPWO56 7 89GHJ /* Copyright (c) 1990-2000 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /* vmmvs.h: include file for both VM/CMS and MVS ports of UnZip */ #ifndef __vmmvs_h /* prevent multiple inclusions */ #define __vmmvs_h #ifndef NULL # define NULL (zvoid *)0 #endif #ifdef MVS # define _POSIX_SOURCE /* tell MVS we want full definitions */ # define NO_STRNICMP /* MVS has no strnicmp() */ # include /* MVS complains if a function has the same name as a csect. */ # if defined(__UNZIP_C) # pragma csect(STATIC,"unzip_s") # elif defined(__CRC32_C) # pragma csect(STATIC,"crc32_s") # elif defined(__ENVARGS_C) # pragma csect(STATIC,"envarg_s") # elif defined(__EXPLODE_C) # pragma csect(STATIC,"explod_s") # elif defined(__INFLATE_C) # pragma csect(STATIC,"inflat_s") # elif defined(__MATCH_C) # pragma csect(STATIC,"match_s") # elif defined(__UNREDUCE_C) # pragma csect(STATIC,"unredu_s") # elif defined(__UNSHRINK_C) # pragma csect(STATIC,"unshri_s") # elif defined(__ZIPINFO_C) # pragma csect(STATIC,"zipinf_s") # endif #endif /* MVS */ #include /* the usual non-BSD time functions */ #ifdef VM_CMS # include "vmstat.h" #endif #ifdef MVS # include #endif #define PASSWD_FROM_STDIN /* Kludge until we know how to open a non-echo tty channel */ #define EBCDIC #define __EBCDIC 2 /* treat EBCDIC as binary! */ /* In the context of Info-ZIP, a portable "text" mode file implies the use of an ASCII-compatible (ISO 8859-1, or other extended ASCII) code page. */ #ifdef MORE # undef MORE #endif /* Workarounds for missing RTL functionality */ #define isatty(t) 1 #ifdef UNZIP /* definitions for UNZIP */ #define INBUFSIZ 8192 #define USE_STRM_INPUT #define USE_FWRITE #define PATH_MAX 128 #ifndef QUERY_TRNEWLN # define QUERY_TRNEWLN /* terminate interaction queries with '\n' */ #endif #ifndef DATE_FORMAT # define DATE_FORMAT DF_MDY #endif #define lenEOL 1 /* The use of "ebcdic[LF]" is not reliable; VM/CMS C/370 uses the * EBCDIC specific "NL" ('NewLine') control character (and not the EBCDIC * equivalent of the ASCII "LF" ('LineFeed')) as line terminator! * To work around this problem, we explicitely emit the C compiler's native * '\n' line terminator. */ #if 0 #define PutNativeEOL *q++ = native(LF); #else #define PutNativeEOL *q++ = '\n'; #endif #endif /* UNZIP */ #endif /* !__vmmvs_h */ *[UNZIP542.CMSMVS]VMSTAT.H;1+,'./ 4- (0@123KPWO56; 7; 89GHJ/* Copyright (c) 1990-2000 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ #ifndef __vmstat_h #define __vmstat_h /* stat.h definitions */ #ifndef _INO_T_DEFINED typedef unsigned short ino_t; /* i-node number (not used on DIma UNZIP.BCK' (NZIP542.CMSMVS]VMSTAT.H;1OS) */ #define _INO_T_DEFINED #endif #ifndef _DEV_T_DEFINED typedef short dev_t; /* device code */ #define _DEV_T_DEFINED #endif #ifndef _OFF_T_DEFINED typedef long off_t; /* file offset value */ #define _OFF_T_DEFINED #endif #ifndef _STAT_DEFINED struct stat { dev_t st_dev; ino_t st_ino; short st_mode; short st_nlink; int st_uid; int st_gid; off_t st_size; time_t st_atime; time_t st_mtime; time_t st_ctime; }; #define _STAT_DEFINED #endif int stat(const char *path, struct stat *buf); int fstat(int fd, struct stat *buf); #define S_IFMT 0xFFFF #define _FLDATA(m) (*(fldata_t *) &m) #define S_ISDIR(m) (_FLDATA(m).__dsorgPDSdir) #define S_ISREG(m) (_FLDATA(m).__dsorgPO | \ _FLDATA(m).__dsorgPDSmem | \ _FLDATA(m).__dsorgPS) #define S_ISBLK(m) (_FLDATA(m).__recfmBlk) #define S_ISMEM(m) (_FLDATA(m).__dsorgMem) #endif /* __vmstat_h */ *[UNZIP542.CMSMVS]WHATSNEW.CMS;1+,{./ 4N- (0@123KPWO56+}U7+}U89GHJImportant Changes made for ZIP 2.3b and UNZIP 5.33c executables: 1. WARNING: These executables have been compiled for the Language Environment (LE). You must now have access to the file SCEERUN LOADLIB in order to run ZIP and UNZIP on CMS. You no longer need access to EDCLINK LOADLIB. The provided ZIP and UNZIP EXECs have been changed to issue a new GLOBAL LOADLIB command. You may need to modify these EXECs for your installation. You may want to change any GLOBAL LOADLIB command you may have in your PROFILE EXEC. Versions could be made available for the older EDCLINK LOADLIB runtimes upon request. 2. ZIP files will now be variable length files rather than fixed length files. 3. Help information for ZIP and UNZIP has been changed to show "fm" rather than "path" on CMS with certain options. 4. README CMS has been entirely rewritten. It now contains all information for ZIP and UNZIP. ----------------------------------------------------------------------- Greg Hartwig, April 1998. e-mail: ghartwig@ix.netcom.com ghartwig@vnet.ibm.com *[UNZIP542.CMSMVS]ZIPINFO.EXEC;1+,x./ 4- (0@123KPWO56,}U7,}U89GHJ /***********************************************************************/ /* */ /* Front-end EXEC to set up linkage to the C runtime libraries */ /* before executing a MODULE generated from C code. */ /* */ /* Copy this file as an EXEC with a filename matching the C MODULE. */ /* */ /* Greg Hartwig (ghartwig@vnet.ibm.com) 7/31/97, 4/24/98. */ /* */ /***********************************************************************/ Address Command Parse Arg argstring Parse Source . . myname . /* Set output and input character translation so brackets show up */ 'SET OUTPUT AD' 'BA'x 'SET OUTPUT BD' 'BB'x 'SET INPUT BA AD' 'SET INPUT BB BD' Call CLIB If rc<>0 Then Do Say 'The required C runtime libraries don''t appear to be available.' Say myname 'can not run.' Exit 12 End /* Run the command */ myname argstring Exit rc /* Contents of the CLIB EXEC, modified for RC checking. */ /* Removed TXTLIB setting. Only LOADLIB needed for execution. */ CLIB: /***************************************************/ /* SET UP LIBRARIES FOR LE for MVS & VM */ /***************************************************/ Address COMMAND loadlib ='EDCLINK' /* C/370 runtime */ loadlib ='SCEERUN' /* LE runtime */ theirs=queued() /* old stack contentsM068*/ 'QUERY LOADLIB ( LIFO' /* old setting M068*/ LoadlibList='' /* init list M068*/ rc=0 Do while queued()^=theirs /* all lines from cmdM068*/ Parse upper pull 'LOADLIB' '=' Ltemp /* get one line M068*/ LoadlibList= Ltemp Loadliblist /* was stacked LIFO M068*/ End /*M068*/ If loadlibList='NONE' , Then Do 'GLOBAL LOADLIB' Loadlib /* enforce what we need */ End Else Do Do xx=1 to Words(loadlib) If Find(loadliblist,word(loadlib,xx)) = 0 , then loadliblist = loadliblist word(loadlib,xx) End 'GLOBAL LOADLIB' loadliblist /* enforce what we need */ End Return P*[UNZIP542]CONSTS.H;1+, ./ 4- 0@123KPWO56789GHJ/* Copyright (c) 1990-2000 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*--------------------------------------------------------------------------- consts.h This file contains global, initialized variables that never change. It is included by unzip.c and windll/windll.c. ---------------------------------------------------------------------------*/ /* And'ing with mask_bits[n] masks the lower n bits */ ZCONST ush near mask_bits[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff }; ZCONST char Far VersionDate[] = UZ_VERSION_DATE; /* now defined in version.h */ #ifndef SFX ZCONST char Far EndSigMsg[] = "\nnote: didn't find end-of-central-dir signature at end of central dir.\n"; #endif ZCONST char Far CentSigMsg[] = "error: expected central file header signature not found (file #%lu).\n"; ZCONST char Far SeekMsg[] = "error [%s]: attempt to seek before beginning of zipfile\n%s"; ZCONST char Far FilenameNotMatched[] = "caution: filename not matched: %s\n"; ZCONST char Far ExclFilenameNotMatched[] = "caution: excluded filename not matched: %s\n"; #ifdef VMS ZCONST char Far ReportMsg[] = "\ (please check tJa UNZIP.BCK  [UNZIP542]CONSTS.H;1}hat you have transferred or created the zipfile in the\n\ appropriate BINARY mode--this includes ftp, Kermit, AND unzip'd zipfiles)\n"; #else ZCONST char Far ReportMsg[] = "\ (please check that you have transferred or created the zipfile in the\n\ appropriate BINARY mode and that you have compiled UnZip properly)\n"; #endif #ifndef SFX ZCONST char Far Zipnfo[] = "zipinfo"; ZCONST char Far CompiledWith[] = "Compiled with %s%s for %s%s%s%s.\n\n"; #endif *[UNZIP542]CONTENTS.;1+,}^. / 4 - 0@123KPWO 56F7F89GHJContents of the UnZip 5.42 source archive. The OS-specific subdirectories at the end contain their own Contents listings: Contents this file README what UnZip is; general information LICENSE Info-ZIP license; terms for using and distributing UnZip COPYING.OLD historic copyrights and distribution policy (obsolete) INSTALL how to compile and install UnZip and related utilities WHERE where Zip/UnZip and encryption/decryption support can be found History.540 new features and fixes of the last major release History.541 new features and fixes in the previous maintance release History.542 new features and fixes in this release ToDo rough priority list of new features to be added in next release BUGS known bugs, problems, and (possible) other features to be added unzip.txt UnZip manual page, human-readable format unzipsfx.txt UnZipSFX manual page, human-readable format zipinfo.txt ZipInfo manual page, human-readable format zipgrep.txt ZipGrep manual page, human-readable format funzip.txt fUnZip manual page, human-readable format file_id.diz BBS-oriented file describing this archive testmake.zip test archive for checking whether newly compiled UnZip works api.c generic DLL entry points, support functions (required for DLLs) apihelp.c API help text for DLL versions (currently OS/2 only) consts.h global, initialized variables that never change (required) crc32.c code for calculation 32bit CRC of a string buffer (required*) crc_i386.S fast assembler replacement for crc32.c (Intel 386 and newer) crctab.c supplies polynomial table for CRC calculation crypt.c de-/encryption routines (required*) crypt.h de-/encryption header file (required*) ebcdic.h static lookup table for ASCII <-> EBCDIC translation (required) envargs.c code to read options from environment variables (required) explode.c code for exploding (required) extract.c high-level extraction and decryption code (required) fileio.c file manipulation and password code (required) funzip.c filter unzip: extracts in a pipe from stdin to stdout globals.c code to support global variables with reentrancy (required) globals.h definition of global structure G (required) inflate.c code for inflating (required*) inflate.h header file for inflating (required*) list.c UnZip listing routines, non-ZipInfo mode (required) match.c pattern-matching code for filename wildcards (required) process.c zipfile headers code (required) tables.h static lookup tables used in fileio.c and funzip.c (required*) timezone.c timezone and timestamp functions (required) timezone.h header file for interface to "internal" tz functions (required) ttyio.c code for handling nonecho tty input: password, pager (required) ttyio.h header file for nonecho tty input: password, pager (required) unreduce.c code for unreducing (required) unshrink.c code for unshrinking (required) unzip.c UnZip main(), usage and options code (required) unzip.h public half of main UnZip header file (required*) unzipstb.c minimal UnZip "stub" file demonstrating use of DLL versions unzpriv.h private (internal) half of main UnZip header file (required*) version.h header with UnZip/UnZipSFX and ZipInfo version info (required) zip.h dummy header for use with crypt.c (required*) zipinfo.c UnZip listing routines, ZipInfo mode (required) acorn/ support files for compiling under Acorn RISC OS amiga/ support files for compiling under AmigaDOS aosvs/ support files for compiling under Data General AOS/VS atari/ support files for compiling under Atari TOS beos/ support files for compiling under BeOS cmsmvs/ support files for compiling under VM/CMS and MVS flexos/ support files for compiling under FlexOS human68k/ support files for compiling under X68000/Human68K macos/ support files for compiling under Macintosh OS msdos/ support files for compiling under MS-DOS novell/ support files for compiling for Novell Netware NLM os2/ support files for compiling under OS/2 (includes DLL stuff) qdos/ support files for compiling under SMS/QDOS tandem/ support files for compiling under Tandem NSK theos/ support files for compiling under Theos tops20/ support files for compiling under TOPS-20 unix/ support files for compiling under Unix vms/ support files for compiling under VMS win32/ support files for compiling under Windows 9x and Windows NT wince/ support files for compiling under Windows CE (GUI version) windll/ support files for compiling Windows 3.x/9x/NT DLLs man/ nroff man-page sources for the main user documentation proginfo/ programming docs, additional technical info, contributor list Files marked "required*" are also needed to compile fUnZip. The normal UnZip makefile targets now make both UnZipSFX and fUnZip, except in a few cases; ZipInfo is now incorporated into UnZip (see zipinfo.txt for usage). *[UNZIP542]COPYING.OLD;1+,y B./ 4- 0@123KPWO56lӞ7lӞ89GHJ__________________________________________________________________________ This is the Info-ZIP file COPYING (for UnZip), last updated 17 Jul 2000. __________________________________________________________________________ FIRST NOTE: This file contains some details about the copyright history of contributions to the UnZip project. Additionally, it summarises some exceptions to the general BSD-like copyright found in LICENSE that covers our generic code and most of the system specific ports. Please read LICENSE first to find out what is allowed to do with Info-ZIP's UnZip code. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - There are currently two explicit copyrights on portions of UnZip code (at least, of which Info-ZIP is aware): Jim Luther's Mac OS File Manager interface code; and Christopher Evans' MacBinaryIII coding code (for the MacOS port).. These copyrights are discussed in more detail below. All remaining code is now (startKN UNZIP.BCKy B [UNZIP542]COPYING.OLD;1ing with UnZip version 5.41) covered by the new Info-ZIP license. For details, please read the acompaning file LICENSE. The terms and conditions in this license supersede the copyright conditions of the contributions by Igor Mandrichenko (vms/vms.c), Greg Roelofs (zipinfo.c, new version of unshrink.c), Mike White (Windows DLL code in "windll/*"), Steve P. Miller (Pocket UnZip GUI "wince/*"), and Mark Adler (inflate/explode decompresseion core routines, previously put into the public domain). All these Info-ZIP contributors (or "primary" authors) have permitted us to replace their copyright notes by the Info-ZIP License. Frequently Asked Questions regarding (re)distribution of Zip and UnZip are near the end of this file. There are no known patents on any of the code in UnZip. Unisys claims a patent on LZW encoding and on LZW decoding _in an apparatus that performs LZW encoding_, but the patent appears to exempt a stand- alone decoder (as in UnZip's unshrink.c). Unisys has publicly claimed otherwise, but the issue has never been tested in court. Since this point is unclear, unshrinking is not enabled by default. It is the responsibility of the user to make his or her peace with Unisys and its licensing requirements. (unshrink.c may be removed from future releases altogether.) __________________________________________________________________________ The original unzip source code has been extensively modified and almost entirely rewritten (changes include random zipfile access rather than sequential; replacement of unimplode() with explode(); replacement of old unshrink() with new (unrelated) unshrink(); re- placement of output routines; addition of inflate(), wildcards, filename-mapping, text translation, ...; etc.). As far as we can tell, only the core code of the unreduce method remained substantially similar to Mr. Smith's original source. As of UnZip 5.42, the complete core code is now covered by the Info-ZIP Licence. Therefore, support for the reduce method has been removed. The drop of the reduce method should only affect some test archives, reducing was never used in any publically distributed Zip program. For pathologic cases where support for reduced archive entries is needed, the unreduce code copyrighted by Samuel H. Smith is available as a separate distribution (the restricted copyright of this code is cited below in the "historical" section). The following copyright applies to the Mac OS File Manager interface code (macos/source/macstuff.[ch]), distributed with UnZip 5.4 and later: * MoreFiles * * A collection of File Manager and related routines * * by Jim Luther (Apple Macintosh Developer Technical Support Emeritus) * with significant code contributions by Nitin Ganatra * (Apple Macintosh Developer Technical Support Emeritus) * Copyright 1992-1998 Apple Computer, Inc. * Portions copyright 1995 Jim Luther * All rights reserved. * The Package "More Files" is distributed under the following * license terms: * * "You may incorporate this sample code into your * applications without restriction, though the * sample code has been provided "AS IS" and the * responsibility for its operation is 100% yours. * However, what you are not permitted to do is to * redistribute the source as "DSC Sample Code" after * having made changes. If you're going to * redistribute the source, we require that you make * it clear in the source that the code was descended * from Apple Sample Code, but that you've made * changes." The usage terms of this copyright note are compatible with the Info-ZIP license, they do not add further restrictions. The following copyright applies to the Mac OS "macbin3" decoding code (extra field compatibility with ZipIt): * MacBinaryIII.h * * Copyright 1997 Christopher Evans (cevans@poppybank.com) * * Basic encoding and decoding of Macintosh files to the * MacBinary III spec. * ---------------------------------------------------------------------- * This source is copyrighted by Christopher Evans (cevans@poppybank.com) * (available at ftp://ftp.lazerware.com/MacBinaryIII_src_C.sit * homepage of Leonard Rosenthol leonardr@netcom.com) This copyright note does not contain any usage terms. So, we assume that this code is freely reusable until we are proved wrong... -------------------------------------------------------------------------- The remaining copyright notes have been superseeded by the new Info-ZIP license, with explicit permission from the respective original authors. They are cited here for historical reasons, only: The following copyright applies to the full-featured unreduce.c (now distributed separately): * Copyright 1989 Samuel H. Smith; All rights reserved * * Do not distribute modified versions without my permission. * Do not remove or alter this notice or any other copyright notice. * If you use this in your own program you must distribute source code. * Do not use any of this in a commercial product. Regarding the first stipulation, Mr. Smith was tracked down in southern California some years back [Samuel H. Smith, The Tool Shop; as of mid- May 1994, (213) 851-9969 (voice), (213) 887-2127(?) (subscription BBS), 71150.2731@compuserve.com]: "He says that he thought that whoever contacted him understood that he has no objection to the Info-ZIP group's inclusion of his code. His primary concern is that it remain freely distributable, he said." Despite the fact that our "normal" code has been entirely rewritten and by default no longer contains any of Mr. Smith's code, Info-ZIP remains indebted and grateful to him. We hope he finds our contribu- tions as useful as we have his. Note that the third and fourth stipulations still apply to any com- pany that wishes to incorporate the unreduce code into its products; if you wish to do so, you must contact Mr. Smith directly regarding licensing. ----- The following copyright applied to most of the VMS code in vms.c, distributed with UnZip version 4.2 and later: * Copyright (c) 1992-93 Igor Mandrichenko. * Permission is granted to any individual or institution to use, copy, * or redistribute this software so long as all of the original files * are included unmodified and that this copyright notice is retained. ----- The following copyright applied to the new version of unshrink.c, distributed with UnZip version 5.2 and later: * Copyright (c) 1994 Greg Roelofs. * Permission is granted to any individual/institution/corporate * entity to use, copy, redistribute or modify this software for * any purpose whatsoever, subject to the conditions noted in the * Frequently Asked Questions section below, plus one additional * condition: namely, that my name not be removed from the source * code. (Other names may, of course, be added as modifications * are made.) Corporate legal staff (like at IBM :-) ) who have * problems understanding this can contact me through Zip-Bugs... ----- The following copyright applied to the Windows DLL code (windll/*), distributed with UnZip version 5.2 and later: * Copyright (c) 1996 Mike White. * PermissioL - UNZIP.BCKy B [UNZIP542]COPYING.OLD;1zn is granted to any individual or institution to use, * copy, or redistribute this software so long as all of the original * files are included, that it is not sold for profit, and that this * copyright notice is retained. ----- The following copyright applied to the Windows CE GUI port, ``Pocket UnZip,'' distributed with UnZip version 5.3 and later: * All the source files for Pocket UnZip, except for components * written by the Info-ZIP group, are copyrighted 1997 by Steve P. * Miller. The product "Pocket UnZip" itself is property of the * author and cannot be altered in any way without written consent * from Steve P. Miller. ----- The remaining code was written by many people associated with the Info-ZIP group, with large contributions from (but not limited to): Greg Roelofs (overall program logic, ZipInfo, unshrink, filename mapping/portability, etc.), Mark Adler (inflate, explode, funzip), Kai Uwe Rommel (OS/2), John Bush and Paul Kienitz (Amiga), Antoine Verheijen (Macintosh), Hunter Goatley (more VMS), Mike White (Windows DLLs), Christian Spieler (overall logic, optimization, VMS, etc.) and others. See the file CONTRIBS in the source distribution for a much more complete list of contributors. The decompression core code for the deflate method (inflate.[ch], explode.c) was originally written by Mark Adler who submitted it as public domain code. -------------------------------------------------------------------------- *[UNZIP542]CRC32.C;1+, ./ 4?- 0@123KPWO56V\7V\89GHJ/* Copyright (c) 1990-2000 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in zip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /* crc32.c -- compute the CRC-32 of a data stream * Copyright (C) 1995 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* $Id: crc32.c,v 1.5 1996/01/13 14:55:12 spc Exp $ */ #define __CRC32_C /* identifies this source module */ #include "zip.h" #ifndef USE_ZLIB #ifndef ASM_CRC #ifndef ZCONST # define ZCONST const #endif #ifdef CRC32 # undef CRC32 #endif #define CRC32(c, b) (crc_table[((int)(c) ^ (b)) & 0xff] ^ ((c) >> 8)) #define DO1(buf) crc = CRC32(crc, *buf++) #define DO2(buf) DO1(buf); DO1(buf) #define DO4(buf) DO2(buf); DO2(buf) #define DO8(buf) DO4(buf); DO4(buf) /* ========================================================================= */ ulg crc32(crc, buf, len) register ulg crc; /* crc shift register */ register ZCONST uch *buf; /* pointer to bytes to pump through */ extent len; /* number of bytes in buf[] */ /* Run a set of bytes through the crc shift register. If buf is a NULL pointer, then initialize the crc shift register contents instead. Return the current crc in either case. */ { register ZCONST ulg near *crc_table; if (buf == NULL) return 0L; crc_table = get_crc_table(); crc = crc ^ 0xffffffffL; #ifndef NO_UNROLLED_LOOPS while (len >= 8) { DO8(buf); len -= 8; } #endif if (len) do { DO1(buf); } while (--len); return crc ^ 0xffffffffL; /* (instead of ~c for 64-bit machines) */ } #endif /* !ASM_CRC */ #endif /* !USE_ZLIB */ l*[UNZIP542]CRCTAB.C;1+, 7./ 4{- 0@123KPWO56aǜ7aǜ89GHJ /* Copyright (c) 1990-2000 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in zip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /* crctab.c -- supply the CRC table needed for CRC-32 calculations. * Copyright (C) 1995 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* $Id: crctab.c,v 1.4 1996/01/08 14:55:12 jloup Exp $ */ /* Generate a table for a byte-wise 32-bit CRC calculation on the polynomial: x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. Polynomials over GF(2) are represented in binary, one bit per coefficient, with the lowest powers in the most significant bit. Then adding polynomials is just exclusive-or, and multiplying a polynomial by x is a right shift by one. If we call the above polynomial p, and represent a byte as the polynomial q, also with the lowest power in the most significant bit (so the byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, where a mod b means the remainder after dividing a by b. This calculation is done using the shift-register method of multiplying and taking the remainder. The register is initialized to zero, and for each incoming bit, x^32 is added mod p to the register if the bit is a one (where x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by x (which is shifting right by one and adding x^32 mod p if the bit shifted out is a one). We start with the highest power (least significant bit) of q and repeat for all eight bits of q. The table is simply the CRC of all possible eight bit values. This is all the information needed to generate CRC's on data a byte at a time for all combinations of CRC register values and incoming bytes. */ #define __CRCTAB_C /* identifies this source module */ #include "zip.h" #if (!defined(USE_ZLIB) || defined(USE_OWN_CRCTAB)) #ifndef ZCONST # define ZCONST const #endif #ifdef DYNAMIC_CRC_TABLE /* ========================================================================= * Make the crc table. This function is needed only if you want to compute * the table dynamically. */ local void make_crc_table OF((void)); #if (defined(DYNALLOC_CRCTAB) && defined(REENTRANT)) error: Dynamic allocation of CRC table not safe with reentrant code. #endif /* DYNALLOC_CRCTAB && REENTRANT */ #ifdef DYNALLOC_CRCTAB local ulg near *crc_table = NULL; # if 0 /* not used, since sizeof("near *") <= sizeof(int) */ /* Use this section when access to a "local int" is faster than access to a "local pointer" (e.g.: i86 16bit code with far pointers). */ local int crc_table_empty = 1; # define CRC_TABLE_IS_EMPTY (crc_table_empty != 0) # define MARK_CRCTAB_FILLED crc_table_empty = 0 # define MARK_CRCTAB_EMPTY crc_table_empty = 1 # else /* Use this section on sM@@ K0 ssuuOD).S[~B;1q$d5h!)svZXos,g${:Da?D0D?fe4 ka5'e"rhx3k9Q`p@^a=-GJ3B#xahJp9 nk:J26^U,2HgCb_ SH! a1F\< ^ LZ`vp}H.3,n; nU4?Z-25`9=$3tu S. Mi ),9h>QQNP>Fr:k8<Jrej-&c'CZ/4'5 rZs$=nUB`wOTo0K X- $`RK66%%fW{k]T5Rm`Y? )9fH6 $9nbSbb$**,]A/|/FDV7F[ .rn>m2.Njy3SxP,X._pqM~ 0ik99Zy${ i6WQ+zX @rFT~_W4S.oVr1*|@^|2ESYvd./C15|[A} x<(}W)w?S`YX ,V$R0>)mFKOH)z'\$@GigRC?g$KLV%su{E=K |vyTygkF}W"ocXtMl[Q Rr$ en) 9R (Os&3BG11kf,b 6_G]~-K"|3~xR hrK- p@!"6i)2k1<_ rI+3:*H~2?,S3~I4 h};%^qN~;3LV^9JGfRV[b>8BMGs"9mrVkKJ}uU[al3bh.=+dz& =#&O{4g$`cXn Velk|VHHw`GiA}'SomE}W?j8d#`|ђ?Qu Zi; PSIH~G?fg9KqJLT$W|- =%q}w&$RƉ:r Xza 9 z+-H*v|>47u6]S5 lU6,t|":n6o~Mr*X2HN;LNrY#IDhsYDbh?"V!,CZi':UMm,f^C3d4\B/~NQUrb`8y( vc.:[9)J%jp=);4|B%_u| hy.sM=[(0F|E<~! W< |`[-eENBXab q U $J?N:;\|uP}j:zk'Kl5 kCCz$5Np| o H-@ a 5;e+Z*%R%y/ m8Q 8$i2i] pHnZD N_q6 $M?mA/aWW0Ka"x^J9A C2m&)X,y|P9cCLk[5HXr4K  IqVPbI:v/bhh`&2'-s@+kspolmU\O ;&B'_`O=_S.j~,fGOb0^-SZ_'G&&yp;;!>[3@+HͥBPgA!>d^ROE5=EUYrW{mZ$J0+c#x%}I"U|J `aEa2K1Se1ah6;>d9&z"*;# 2ounS fQ}hET_S'g-K@X'm*Pi#y0CIE; Q]Nv_og1;G"1j!a7`|< fy* iT}&W\tY@#U@!v8z ".8nhg~4>oD'?pRO"oP <=~2fv:J|of \ q54 e;rsx {cprSP$1Nd()=W{rH\k/SezUjA-oX| !G';k v3^H#$G9c]"QejK8sJ9*hta"6G , y fE 1-k1{1rC\LQ4gn4b7fDA? (-R=:p9wJ+!.] D!~t*gW'@2[7IZ(,HS(&(X5:>iwOtY`($u MIQnW)9:MjZ [>4u-EO&Q}|Q'I"F S[Sf:HNF8D.{GZfyX8k%vH,`Gd1gM{YUpMo  .Hc*g^8 G$'WEdk" _Zd[laDvhK1vF'+Jc`a&Tr`]**}V{]4Y{VqH+Zqa RJlG0'/0v!qfo {ENAtnPQa/ Rin]0>1?1USX2I ZxYk"JsSg k]Hb~[41e0Y& 1fvcw|b_*i2X9>)x2%6dvm`a@[mm!4#kkfkMK}l,PIH3gDHdK]_@"x\+R+k$5tjT -/`8ue/*9<99 94m} LWU;%! wJd S4};zKT[g gpL`}hq{_(\|zO`V"*b.G7(%.%l=m+]yBg=|^nam7bvH; =gI a7f~F(ly@|'FYf ym+bm 1:"O'~dT qR7*ua(nGg|jV .5*js7ti}Vx80wf 5xFU|h`Pn84Jg5[/0X!jM>N{^_{ qy \+}ia8oLRd7Nkd}mkU.2Rj`2l{NLOqe,Gt%%>g}T4@])\g>lfe8Jc51psnv8ksIIvx.'re=RHhSAv|fqF"'PQ?|KC)z$'S|I-K+( cs[r*ZZ {XVVV W< ~jd1 %x1l["o9!D(n,+^U&pIgtL]\g];Md^w(,Ym.6k 2OJ{Lo UCguB: XoT~rD \m E2H*nZESg=Zx; S@l$bN7x5 ^*_R @[V?|cnPc';R/['bdYu'i-hp+>uAc)sv9;jjzJDUY-g!s)1226$- ^5iD PYOzV.j: 1on;1\s% crf{xwxx&Sj:ZPSY'QI[^%Z/ Phoj\gkCxsigx$+)jQIMO9;k3^_\Nn8x7} FQ!Pz.!inS${zmYlfJ7)d0aZ ^^R;[$np#3K5+UZJCU] oz3xv~45lA~0T;'tQ`GVl|iD '03D{B9Kp_b5vfo)'0Ed=Ynu1qnLb(xjl[Swx_?Py4sTuu+2}KWx?[N #?BmAu).e:%kGFq 7-*eGK9 w {h j3 (= aA]yx .v iDi0f'iX iIp]0fuR(? Y3ygW2LG*zx(9e|R_CA( F_do1\T,EVE2,Q[ SW K[Wt^21aJ   K8EW'nq!%gy N @+4dM )k]U#'**R]O*=,t;^75~#vWFWal|8xRc;W:X|DK{>\&S|Z~T3:#/,Cz! X F$[G3K!1vKk:/hCulh_#',(+-i7N>oeO/~,FV7u~scYE "n. dTO}*ILI`#uzc1~SOrnora>>/Q_ECUzoB| 5D \T D w#N(֍1G&*%/:sii_3j4 UC$FY.Wwu?@8 z5(C/x ycoa'-*?-_zTG u6W0Lhzd&V=tt Nl3FR ]L7&F{WzLpC""e>\ |@=Xs?=q~qmWpv (97E<x6T||UU r]_p{YSf0la0mkL*N$\&PH}7-w_^}Az9F]^i_O Ez\,ns7F"y-KpIfVNq,Ioe(Z-1) BaY`~<{.-SJS]tSkKWDTvCU J%S87adk|V+yrOF[I%RorqUAE b?Zb8~@$Ml ]&)&Is+ccO`h_I4Yo{?\{j 5>(<DKP2yOM(*U_h-*'G;p92er+&C .l<%3wS<, dzH$yl%le\TJ(JC#2TD%ub-BH\qO GWv$ A)lUfxX,&i\};911g2CZ \xnn31`M#InS?mL37YEQ~.wf$&ilFp}oBkcRVe %o.LI6( zYyJ#RA6"C?S,ss LoQ$6}wu0@N]kS&%9+Lv}U\<}m Wh `?wp/J='K%=.2>l&!(6&9*ZSIxG &8$Mlx?j//,sIt{n8)F T XeD\dy96k(l-q=P.*X[^$0fVl|~C=WG{*+y|{3?)Fn3-m=}P?ygyn]RVo'/ECYAAmH (rKqcST! 1]7*M:#U^,iJUb h=MuTOa{+0LK\4?D]&>,Q{OgebETj,Y9`N:tPM0Y]BVA S6ir /g&uA/2Ck`Kt>4Q mHQyWml #5K` Z)p- T}Jv(Zi&ysxV$u( +e2GqKO@( 4.5oun"fM0RDVdvDfx%t)WO=wA7EnZSh3zk16sbE9 Gw s~V QW^>Ilv~MO$][Ow&k&%']| QX>v Gh"q= M$:,<7y1q8!a$xw.[. IQZwRM_X!ZkG6S]MnZqZ"`u.bR,*qd",pS>-tz Ya2 kEY>B"`/?bBo{E$J!I`:88}%J,I[$/ CMx $ M Nch7Y #w@OFgyhDOfb:$v3\]@119-;%6C!@}y Bx&&xt&N\ne'_H42a'wp4 ><U8X"m;jB|U)<X%8vq"wCmOp(4!M[& >|EqRs+B-Tb$";zg.3oW #hw*b}cp;z2w.GP*6nYV8(\TM@ H7jBL3 ")$F.Yj~D& fR?d)qmiBGVDQ`BC7MU$Vj V hfC!em\S^%Q[k>&~zd ~)( -dA~TOUD_z)Y)BbzaiDJTi1tQV ]~U]o>1l1OArZ5\x0&__sq (#&zpeYynv[)3'/)@mjwq6sR}71bgC_,F8Dt :E2-z%tYWy*^z"sv*),#)]j4l;a>(yf4>K!Wug[wXT_8w}]U i&>YjHL**kRCC>87ghR`Gf euROU_B D1?ZF$ 'HK17/9"$35.pdWdaq1% ym6b.; lNcavvQe+DF;-eJb8 <7kQ6rH7&_VO 7FT}H/%_eL]2J .I7%@8JB@MoyG ,Ut 7&!0~/'STVP2.(mxc:~rs: 2S]v&Idz!j&5H[Q~NRidT#]a.^U"e$GN*baYqBE|&J2',!J6=? C1f\p'haiVmSS~y- otBU= 'UBl-*+yLQ30DbA70`a)+/"X_xz6fI<:iVTuArsK6?/+TGS`Z}!NzT;iqjE0D]1f"-h-7o5w0 (;aQ=)`wy)VmuP ,p15i57.h>h,RSuBJMFK~uR+O_W=hYOp L>1).!4'nN|67K }( LxMSKYLFn66OeiSs q'467 r\0=cm c8Y4$K{1,V)rF,ZK 2+V+O={|rZY0FyO~xG T}#; ~#sC%KGm3pUt3SxeKW Kcmp'7MX_>fd|**I tUG3 0i ]8>/U Nk;v\\)`! z^HVioCQ9/<<X~VK /tef[,gi:X*>WOCGC~m02?Vu4Fs#5|0)y^'#L}zLI` uN# 4?{VH}'Kj O=4A C-Y XVmu "3*qxPD~w'VkZiduS1k"4,EYnn1eY|R=L5bvmIyDHg R {nX&l|k=E>$R(wXnJ00eb@ALUV .5uG&fV]]uUYa<{s [<,.\;+&Ge;47( sN!?1}z go,7/CVfUn9e;dq4 F3|f|njG!}q7 w,Bl-]A,6_3 CDS LlQ&-L+:G"]g b4LGq$-v|U2G_=XI>:PKd.l+/HU0/C??&@!Hr81_/2K)nk3{YB 6vA:> 1) : c >> 1; crctab_p[n] = c; } MARK_CRCTAB_FILLED; } #else /* !DYNAMIC_CRC_TABLE */ #ifdef DYNALLOC_CRCTAB error: Inconsistent flags, DYNALLOC_CRCTAB without DYNAMIC_CRC_TABLE. #endif /* ======================================================================== * Table of CRC-32's of all single-byte values (made by make_crc_table) */ local ZCONST ulg near crc_table[256] = { 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL }; #endif /* ?DYNAMIC_CRC_TABLE */ /* use "OF((void))" here to work around a Borland TC++ 1.0 problem */ #ifdef USE_ZLIB ZCONST uLongf *get_crc_table OF((void)) #else ZCONST ulg near *get_crc_table OF((void)) #endif { #ifdef DYNAMIC_CRC_TABLE if (CRC_TABLE_IS_EMPTY) make_crc_table(); #endif #ifdef USE_ZLIB return (ZCONST uLongf *)crc_table; #else return (ZCONST ulg near *)crc_table; #endif } #ifdef DYNALLOC_CRCTAB void free_crc_table() { if (!CRC_TABLE_IS_EMPTY) { nearfree((ulg near *)crc_table); MARK_CRCTAB_EMPTY; } } #endif #endif /* !USE_ZLIB || USE_OWN_CRCTAB */ *[UNZIP542]CRC_I386.S;1+, ./ 4- 0@123KPWO56 !7 !89GHJ/* Copyright (c) 1990-2000 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in zip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /* * crc_i386.S, optimized CRC calculation function for Zip and UnZip, * created by Paul Kienitz and Christian Spieler. Last revised 24 Dec 98. * * GRR 961110:Owuh UNZIP.BCK  [UNZIP542]CRC_I386.S;142  incorporated Scott Field optimizations from win32/crc_i386.asm * => overall 6% speedup in "unzip -tq" on 9MB zipfile (486-66) * * SPC 970402: revised for Rodney Brown's optimizations (32-bit-wide * aligned reads for most of the data from buffer), can be * disabled by defining the macro NO_32_BIT_LOADS * * SPC 971012: added Rodney Brown's additional tweaks for 32-bit-optimized * CPUs (like the Pentium Pro, Pentium II, and probably some * Pentium clones). This optimization is controlled by the * preprocessor switch "__686" and is disabled by default. * (This default is based on the assumption that most users * do not yet work on a Pentium Pro or Pentium II machine ...) * * FLAT memory model assumed. Calling interface: * - args are pushed onto the stack from right to left, * - return value is given in the EAX register, * - all other registers (with exception of EFLAGS) are preserved. (With * GNU C 2.7.x, %edx and %ecx are `scratch' registers, but preserving * them nevertheless adds only 4 single byte instructions.) * * This source generates the function * ulg crc32(ulg crc, ZCONST uch *buf, ulg len). * * The loop unrolling can be disabled by defining the macro NO_UNROLLED_LOOPS. * This results in shorter code at the expense of reduced performance. */ /* This file is NOT used in conjunction with zlib. */ #ifndef USE_ZLIB /* Preprocess with -DNO_UNDERLINE if your C compiler does not prefix * external symbols with an underline character '_'. */ #if defined(NO_UNDERLINE) || defined(__ELF__) # define _crc32 crc32 # define _get_crc_table get_crc_table #endif /* Use 16-byte alignment if your assembler supports it. Warning: gas * uses a log(x) parameter (.align 4 means 16-byte alignment). On SVR4 * the parameter is a number of bytes. */ #ifndef ALIGNMENT # define ALIGNMENT .align 4,0x90 #endif #if defined(i386) || defined(_i386) || defined(_I386) || defined(__i386) /* This version is for 386 Unix, OS/2, MSDOS in 32 bit mode (gcc & gas). * Warning: it uses the AT&T syntax: mov source,dest * This file is only optional. If you want to use the C version, * remove -DASM_CRC from CFLAGS in Makefile and set OBJA to an empty string. */ .file "crc_i386.S" #if defined(NO_STD_STACKFRAME) && defined(USE_STD_STACKFRAME) # undef USE_STACKFRAME #else /* The default is to use standard stack frame entry, because it * results in smaller code! */ # ifndef USE_STD_STACKFRAME # define USE_STD_STACKFRAME # endif #endif #ifdef USE_STD_STACKFRAME # define _STD_ENTRY pushl %ebp ; movl %esp,%ebp # define arg1 8(%ebp) # define arg2 12(%ebp) # define arg3 16(%ebp) # define _STD_LEAVE popl %ebp #else /* !USE_STD_STACKFRAME */ # define _STD_ENTRY # define arg1 24(%esp) # define arg2 28(%esp) # define arg3 32(%esp) # define _STD_LEAVE #endif /* ?USE_STD_STACKFRAME */ /* * These two (three) macros make up the loop body of the CRC32 cruncher. * registers modified: * eax : crc value "c" * esi : pointer to next data byte (or lword) "buf++" * registers read: * edi : pointer to base of crc_table array * scratch registers: * ebx : index into crc_table array * (requires upper three bytes = 0 when __686 is undefined) */ #ifndef __686 /* optimize for 386, 486, Pentium */ #define Do_CRC /* c = (c >> 8) ^ table[c & 0xFF] */\ movb %al, %bl ;/* tmp = c & 0xFF */\ shrl $8, %eax ;/* c = (c >> 8) */\ xorl (%edi, %ebx, 4), %eax ;/* c ^= table[tmp] */ #else /* __686 : optimize for Pentium Pro and compatible CPUs */ #define Do_CRC /* c = (c >> 8) ^ table[c & 0xFF] */\ movzbl %al, %ebx ;/* tmp = c & 0xFF */\ shrl $8, %eax ;/* c = (c >> 8) */\ xorl (%edi, %ebx, 4), %eax ;/* c ^=table[tmp] */ #endif /* ?__686 */ #define Do_CRC_byte /* c = (c >> 8) ^ table[(c^*buf++)&0xFF] */\ xorb (%esi), %al ;/* c ^= *buf */\ incl %esi ;/* buf++ */\ Do_CRC #ifndef NO_32_BIT_LOADS #define Do_CRC_lword \ xorl (%esi), %eax ;/* c ^= *(ulg *)buf */\ addl $4, %esi ;/* ((ulg *)buf)++ */\ Do_CRC \ Do_CRC \ Do_CRC \ Do_CRC #endif /* !NO_32_BIT_LOADS */ .text .globl _crc32 _crc32: /* ulg crc32(ulg crc, uch *buf, extent len) */ _STD_ENTRY pushl %edi pushl %esi pushl %ebx pushl %edx pushl %ecx movl arg2, %esi /* 2nd arg: uch *buf */ subl %eax, %eax /* > if (!buf) */ testl %esi, %esi /* > return 0; */ jz .L_fine /* > else { */ call _get_crc_table movl %eax, %edi movl arg1, %eax /* 1st arg: ulg crc */ #ifndef __686 subl %ebx, %ebx /* ebx=0; bl usable as dword */ #endif movl arg3, %ecx /* 3rd arg: extent len */ notl %eax /* > c = ~crc; */ testl %ecx, %ecx #ifndef NO_UNROLLED_LOOPS jz .L_bail # ifndef NO_32_BIT_LOADS /* Assert now have positive length */ .L_align_loop: testl $3, %esi /* Align buf on lword boundary */ jz .L_aligned_now Do_CRC_byte decl %ecx jnz .L_align_loop .L_aligned_now: # endif /* !NO_32_BIT_LOADS */ movl %ecx, %edx /* save len in edx */ shrl $3, %ecx /* ecx = len / 8 */ jz .L_No_Eights /* align loop head at start of 486 internal cache line !! */ ALIGNMENT .L_Next_Eight: # ifndef NO_32_BIT_LOADS /* Do_CRC_lword */ xorl (%esi), %eax ;/* c ^= *(ulg *)buf */ addl $4, %esi ;/* ((ulg *)buf)++ */ Do_CRC Do_CRC Do_CRC Do_CRC /* Do_CRC_lword */ xorl (%esi), %eax ;/* c ^= *(ulg *)buf */ addl $4, %esi ;/* ((ulg *)buf)++ */ Do_CRC Do_CRC Do_CRC Do_CRC # else /* NO_32_BIT_LOADS */ Do_CRC_byte Do_CRC_byte Do_CRC_byte Do_CRC_byte Do_CRC_byte Do_CRC_byte Do_CRC_byte Do_CRC_byte # endif /* ?NO_32_BIT_LOADS */ decl %ecx jnz .L_Next_Eight .L_No_Eights: movl %edx, %ecx andl $7, %ecx /* ecx = len % 8 */ #endif /* !NO_UNROLLED_LOOPS */ jz .L_bail /* > if (len) */ /* align loop head at start of 486 internal cache line !! */ ALIGNMENT .L_loupe: /* > do { P)Q? UNZIP.BCK  [UNZIP542]CRC_I386.S;1 */ Do_CRC_byte /* c = CRC32(c, *buf++); */ decl %ecx /* > } while (--len); */ jnz .L_loupe .L_bail: /* > } */ notl %eax /* > return ~c; */ .L_fine: popl %ecx popl %edx popl %ebx popl %esi popl %edi _STD_LEAVE ret #else error: this asm version is for 386 only #endif /* i386 || _i386 || _I386 || __i386 */ #endif /* !USE_ZLIB */ *[UNZIP542]CRYPT.C;1+, .(/ 4((_- 0@123KPWO)56789GHJ/* Copyright (c) 1990-2000 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in zip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /* crypt.c (full version) by Info-ZIP. Last revised: [see crypt.h] This encryption/decryption source code for Info-Zip software was originally written in Europe. The whole source package can be freely distributed, including from the USA. (Prior to January 2000, re-export from the US was a violation of US law.) NOTE on copyright history: Previous versions of this source package (up to version 2.8) were not copyrighted and put in the public domain. If you cannot comply with the Info-Zip LICENSE, you may want to look for one of those public domain versions. */ /* This encryption code is a direct transcription of the algorithm from Roger Schlafly, described by Phil Katz in the file appnote.txt. This file (appnote.txt) is distributed with the PKZIP program (even in the version without encryption capabilities). */ #define ZCRYPT_INTERNAL #include "zip.h" #include "crypt.h" #include "ttyio.h" #if CRYPT #ifndef FALSE # define FALSE 0 #endif #ifdef ZIP /* For the encoding task used in Zip (and ZipCloak), we want to initialize the crypt algorithm with some reasonably unpredictable bytes, see the crypthead() function. The standard rand() library function is used to supply these `random' bytes, which in turn is initialized by a srand() call. The srand() function takes an "unsigned" (at least 16bit) seed value as argument to determine the starting point of the rand() pseudo-random number generator. This seed number is constructed as "Seed = Seed1 .XOR. Seed2" with Seed1 supplied by the current time (= "(unsigned)time()") and Seed2 as some (hopefully) nondeterministic bitmask. On many (most) systems, we use some "process specific" number, as the PID or something similar, but when nothing unpredictable is available, a fixed number may be sufficient. NOTE: 1.) This implementation requires the availability of the following standard UNIX C runtime library functions: time(), rand(), srand(). On systems where some of them are missing, the environment that incorporates the crypt routines must supply suitable replacement functions. 2.) It is a very bad idea to use a second call to time() to set the "Seed2" number! In this case, both "Seed1" and "Seed2" would be (almost) identical, resulting in a (mostly) "zero" constant seed number passed to srand(). The implementation environment defined in the "zip.h" header should supply a reasonable definition for ZCR_SEED2 (an unsigned number; for most implementations of rand() and srand(), only the lower 16 bits are significant!). An example that works on many systems would be "#define ZCR_SEED2 (unsigned)getpid()". The default definition for ZCR_SEED2 supplied below should be regarded as a fallback to allow successful compilation in "beta state" environments. */ # include /* time() function supplies first part of crypt seed */ /* "last resort" source for second part of crypt seed pattern */ # ifndef ZCR_SEED2 # define ZCR_SEED2 (unsigned)3141592654L /* use PI as default pattern */ # endif # ifdef GLOBAL /* used in Amiga system headers, maybe others too */ # undef GLOBAL # endif # define GLOBAL(g) g #else /* !ZIP */ # define GLOBAL(g) G.g #endif /* ?ZIP */ #ifdef UNZIP /* char *key = (char *)NULL; moved to globals.h */ # ifndef FUNZIP local int testp OF((__GPRO__ ZCONST uch *h)); local int testkey OF((__GPRO__ ZCONST uch *h, ZCONST char *key)); # endif #endif /* UNZIP */ #ifndef UNZIP /* moved to globals.h for UnZip */ local ulg keys[3]; /* keys defining the pseudo-random sequence */ #endif /* !UNZIP */ #ifndef Trace # ifdef CRYPT_DEBUG # define Trace(x) fprintf x # else # define Trace(x) # endif #endif #ifndef CRC_32_TAB # define CRC_32_TAB crc_32_tab #endif #define CRC32(c, b) (CRC_32_TAB[((int)(c) ^ (b)) & 0xff] ^ ((c) >> 8)) /*********************************************************************** * Return the next byte in the pseudo-random sequence */ int decrypt_byte(__G) __GDEF { unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an * unpredictable manner on 16-bit systems; not a problem * with any known compiler so far, though */ temp = ((unsigned)GLOBAL(keys[2]) & 0xffff) | 2; return (int)(((temp * (temp ^ 1)) >> 8) & 0xff); } /*********************************************************************** * Update the encryption keys with the next byte of plain text */ int update_keys(__G__ c) __GDEF int c; /* byte of plain text */ { GLOBAL(keys[0]) = CRC32(GLOBAL(keys[0]), c); GLOBAL(keys[1]) += GLOBAL(keys[0]) & 0xff; GLOBAL(keys[1]) = GLOBAL(keys[1]) * 134775813L + 1; { register int keyshift = (int)(GLOBAL(keys[1]) >> 24); GLOBAL(keys[2]) = CRC32(GLOBAL(keys[2]), keyshift); } return c; } /*********************************************************************** * Initialize the encryption keys and the random header according to * the given password. */ void init_keys(__G__ passwd) __GDEF ZCONST char *passwd; /* password string with which to modify keys */ { GLOBAL(keys[0]) = 305419896L; GLOBAL(keys[1]) = 591751049L; GLOBAL(keys[2]) = 878082192L; while (*passwd != '\0') { update_keys(__G__ (int)*passwd); passwd++; } } #ifdef ZIP /*********************************************************************** * Write encryption header to file zfile using the password passwd * and the cyclic redundancy check crc. */ voQ UNZIP.BCK  [UNZIP542]CRYPT.C;1(? id crypthead(passwd, crc, zfile) ZCONST char *passwd; /* password string */ ulg crc; /* crc of file being encrypted */ FILE *zfile; /* where to write header */ { int n; /* index in random header */ int t; /* temporary */ int c; /* random byte */ int ztemp; /* temporary for zencoded value */ uch header[RAND_HEAD_LEN-2]; /* random header */ static unsigned calls = 0; /* ensure different random header each time */ /* First generate RAND_HEAD_LEN-2 random bytes. We encrypt the * output of rand() to get less predictability, since rand() is * often poorly implemented. */ if (++calls == 1) { srand((unsigned)time(NULL) ^ ZCR_SEED2); } init_keys(passwd); for (n = 0; n < RAND_HEAD_LEN-2; n++) { c = (rand() >> 7) & 0xff; header[n] = (uch)zencode(c, t); } /* Encrypt random header (last two bytes is high word of crc) */ init_keys(passwd); for (n = 0; n < RAND_HEAD_LEN-2; n++) { ztemp = zencode(header[n], t); putc(ztemp, zfile); } ztemp = zencode((int)(crc >> 16) & 0xff, t); putc(ztemp, zfile); ztemp = zencode((int)(crc >> 24) & 0xff, t); putc(ztemp, zfile); } #ifdef UTIL /*********************************************************************** * Encrypt the zip entry described by z from file source to file dest * using the password passwd. Return an error code in the ZE_ class. */ int zipcloak(z, source, dest, passwd) struct zlist far *z; /* zip entry to encrypt */ FILE *source, *dest; /* source and destination files */ ZCONST char *passwd; /* password string */ { int c; /* input byte */ int res; /* result code */ ulg n; /* holds offset and counts size */ ush flag; /* previous flags */ int t; /* temporary */ int ztemp; /* temporary storage for zencode value */ /* Set encrypted bit, clear extended local header bit and write local header to output file */ if ((n = (ulg)ftell(dest)) == (ulg)-1L) return ZE_TEMP; z->off = n; flag = z->flg; z->flg |= 1, z->flg &= ~8; z->lflg |= 1, z->lflg &= ~8; z->siz += RAND_HEAD_LEN; if ((res = putlocal(z, dest)) != ZE_OK) return res; /* Initialize keys with password and write random header */ crypthead(passwd, z->crc, dest); /* Skip local header in input file */ if (fseek(source, (long)(4 + LOCHEAD + (ulg)z->nam + (ulg)z->ext), SEEK_CUR)) { return ferror(source) ? ZE_READ : ZE_EOF; } /* Encrypt data */ for (n = z->siz - RAND_HEAD_LEN; n; n--) { if ((c = getc(source)) == EOF) { return ferror(source) ? ZE_READ : ZE_EOF; } ztemp = zencode(c, t); putc(ztemp, dest); } /* Skip extended local header in input file if there is one */ if ((flag & 8) != 0 && fseek(source, 16L, SEEK_CUR)) { return ferror(source) ? ZE_READ : ZE_EOF; } if (fflush(dest) == EOF) return ZE_TEMP; return ZE_OK; } /*********************************************************************** * Decrypt the zip entry described by z from file source to file dest * using the password passwd. Return an error code in the ZE_ class. */ int zipbare(z, source, dest, passwd) struct zlist far *z; /* zip entry to encrypt */ FILE *source, *dest; /* source and destination files */ ZCONST char *passwd; /* password string */ { int c0, c1; /* last two input bytes */ ulg offset; /* used for file offsets */ ulg size; /* size of input data */ int r; /* size of encryption header */ int res; /* return code */ ush flag; /* previous flags */ /* Save position and skip local header in input file */ if ((offset = (ulg)ftell(source)) == (ulg)-1L || fseek(source, (long)(4 + LOCHEAD + (ulg)z->nam + (ulg)z->ext), SEEK_CUR)) { return ferror(source) ? ZE_READ : ZE_EOF; } /* Initialize keys with password */ init_keys(passwd); /* Decrypt encryption header, save last two bytes */ c1 = 0; for (r = RAND_HEAD_LEN; r; r--) { c0 = c1; if ((c1 = getc(source)) == EOF) { return ferror(source) ? ZE_READ : ZE_EOF; } Trace((stdout, " (%02x)", c1)); zdecode(c1); Trace((stdout, " %02x", c1)); } Trace((stdout, "\n")); /* If last two bytes of header don't match crc (or file time in the * case of an extended local header), back up and just copy. For * pkzip 2.0, the check has been reduced to one byte only. */ #ifdef ZIP10 if ((ush)(c0 | (c1<<8)) != (z->flg & 8 ? (ush) z->tim & 0xffff : (ush)(z->crc >> 16))) { #else c0++; /* avoid warning on unused variable */ if ((ush)c1 != (z->flg & 8 ? (ush) z->tim >> 8 : (ush)(z->crc >> 24))) { #endif if (fseek(source, offset, SEEK_SET)) { return ferror(source) ? ZE_READ : ZE_EOF; } if ((res = zipcopy(z, source, dest)) != ZE_OK) return res; return ZE_MISS; } /* Clear encrypted bit and local header bit, and write local header to output file */ if ((offset = (ulg)ftell(dest)) == (ulg)-1L) return ZE_TEMP; z->off = offset; flag = z->flg; z->flg &= ~9; z->lflg &= ~9; z->siz -= RAND_HEAD_LEN; if ((res = putlocal(z, dest)) != ZE_OK) return res; /* Decrypt data */ for (size = z->siz; size; size--) { if ((c1 = getc(source)) == EOF) { return ferror(source) ? ZE_READ : ZE_EOF; } zdecode(c1); putc(c1, dest); } /* Skip extended local header in input file if there is one */ if ((flag & 8) != 0 && fseek(source, 16L, SEEK_CUR)) { return ferror(source) ? ZE_READ : ZE_EOF; } if (fflush(dest) == EOF) return ZE_TEMP; return ZE_OK; } #else /* !UTIL */ /*********************************************************************** * If requested, encrypt the data in buf, and in any case call fwrite() * with the arguments to zfwrite(). Return what fwrite() returns. */ unsigned zfwrite(buf, item_size, nb, f) zvoid *buf; /* data buffer */ extent item_size; /* size of each item in bytes */ extent nb; /* number of items */ FILE *f; /* file to write to */ { int t; /* temporary */ if (key != (char *)NULL) { /* key is the global password pointer */ ulg size; /* buffer size */ char *p = (char*)buf; /* steps through buffer */ /* Encrypt data in buffer */ for (size = item_size*(ulg)nb; size != 0; p++, size--) { *p = (char)zencode(*p, t); } } /* Write the buffer out */ return fwrite(buf, item_size, nb, f); } #endif /* ?UTIL */ #endif /* ZIP */ #if (defined(UNZIP) && !defined(FUNZIP)) /*********************************************************************** * Get the password and set up keys for current zipfile member. * Return PK_ class error. */ int decrypt(__G__ passwrd) __GDEF ZCONST char *passwrd; { ush b; int n, r; uch h[RAND_HEAD_LEN]; Trace((stdout, "\n[incnt = %d]: ", GLOBAL(incnt))); /* get header once (turn off "encrypted" flag temporarily so we don't * try to decrypt the same data twice) */ GLOBAL(pInfo->encrypted) = FALSE; defR;Z UNZIP.BCK  [UNZIP542]CRYPT.C;1(er_leftover_input(__G); for (n = 0; n < RAND_HEAD_LEN; n++) { b = NEXTBYTE; h[n] = (uch)b; Trace((stdout, " (%02x)", h[n])); } undefer_input(__G); GLOBAL(pInfo->encrypted) = TRUE; if (GLOBAL(newzip)) { /* this is first encrypted member in this zipfile */ GLOBAL(newzip) = FALSE; if (passwrd != (char *)NULL) { /* user gave password on command line */ if (!GLOBAL(key)) { if ((GLOBAL(key) = (char *)malloc(strlen(passwrd)+1)) == (char *)NULL) return PK_MEM2; strcpy(GLOBAL(key), passwrd); GLOBAL(nopwd) = TRUE; /* inhibit password prompting! */ } } else if (GLOBAL(key)) { /* get rid of previous zipfile's key */ free(GLOBAL(key)); GLOBAL(key) = (char *)NULL; } } /* if have key already, test it; else allocate memory for it */ if (GLOBAL(key)) { if (!testp(__G__ h)) return PK_COOL; /* existing password OK (else prompt for new) */ else if (GLOBAL(nopwd)) return PK_WARN; /* user indicated no more prompting */ } else if ((GLOBAL(key) = (char *)malloc(IZ_PWLEN+1)) == (char *)NULL) return PK_MEM2; /* try a few keys */ n = 0; do { r = (*G.decr_passwd)((zvoid *)&G, &n, GLOBAL(key), IZ_PWLEN+1, GLOBAL(zipfn), GLOBAL(filename)); if (r == IZ_PW_ERROR) { /* internal error in fetch of PW */ free (GLOBAL(key)); GLOBAL(key) = NULL; return PK_MEM2; } if (r != IZ_PW_ENTERED) { /* user replied "skip" or "skip all" */ *GLOBAL(key) = '\0'; /* We try the NIL password, ... */ n = 0; /* and cancel fetch for this item. */ } if (!testp(__G__ h)) return PK_COOL; if (r == IZ_PW_CANCELALL) /* User replied "Skip all" */ GLOBAL(nopwd) = TRUE; /* inhibit any further PW prompt! */ } while (n > 0); return PK_WARN; } /* end function decrypt() */ /*********************************************************************** * Test the password. Return -1 if bad, 0 if OK. */ local int testp(__G__ h) __GDEF ZCONST uch *h; { int r; char *key_translated; /* On systems with "obscure" native character coding (e.g., EBCDIC), * the first test translates the password to the "main standard" * character coding. */ #ifdef STR_TO_CP1 /* allocate buffer for translated password */ if ((key_translated = malloc(strlen(GLOBAL(key)) + 1)) == (char *)NULL) return -1; /* first try, test password translated "standard" charset */ r = testkey(__G__ h, STR_TO_CP1(key_translated, GLOBAL(key))); #else /* !STR_TO_CP1 */ /* first try, test password as supplied on the extractor's host */ r = testkey(__G__ h, GLOBAL(key)); #endif /* ?STR_TO_CP1 */ #ifdef STR_TO_CP2 if (r != 0) { #ifndef STR_TO_CP1 /* now prepare for second (and maybe third) test with translated pwd */ if ((key_translated = malloc(strlen(GLOBAL(key)) + 1)) == (char *)NULL) return -1; #endif /* second try, password translated to alternate ("standard") charset */ r = testkey(__G__ h, STR_TO_CP2(key_translated, GLOBAL(key))); #ifdef STR_TO_CP3 if (r != 0) /* third try, password translated to another "standard" charset */ r = testkey(__G__ h, STR_TO_CP3(key_translated, GLOBAL(key))); #endif #ifndef STR_TO_CP1 free(key_translated); #endif } #endif /* STR_TO_CP2 */ #ifdef STR_TO_CP1 free(key_translated); if (r != 0) { /* last resort, test password as supplied on the extractor's host */ r = testkey(__G__ h, GLOBAL(key)); } #endif /* STR_TO_CP1 */ return r; } /* end function testp() */ local int testkey(__G__ h, key) __GDEF ZCONST uch *h; /* decrypted header */ ZCONST char *key; /* decryption password to test */ { ush b; #ifdef ZIP10 ush c; #endif int n; uch *p; uch hh[RAND_HEAD_LEN]; /* decrypted header */ /* set keys and save the encrypted header */ init_keys(__G__ key); memcpy(hh, h, RAND_HEAD_LEN); /* check password */ for (n = 0; n < RAND_HEAD_LEN; n++) { zdecode(hh[n]); Trace((stdout, " %02x", hh[n])); } Trace((stdout, "\n lrec.crc= %08lx crec.crc= %08lx pInfo->ExtLocHdr= %s\n", GLOBAL(lrec.crc32), GLOBAL(pInfo->crc), GLOBAL(pInfo->ExtLocHdr) ? "true":"false")); Trace((stdout, " incnt = %d unzip offset into zipfile = %ld\n", GLOBAL(incnt), GLOBAL(cur_zipfile_bufstart)+(GLOBAL(inptr)-GLOBAL(inbuf)))); /* same test as in zipbare(): */ #ifdef ZIP10 /* check two bytes */ c = hh[RAND_HEAD_LEN-2], b = hh[RAND_HEAD_LEN-1]; Trace((stdout, " (c | (b<<8)) = %04x (crc >> 16) = %04x lrec.time = %04x\n", (ush)(c | (b<<8)), (ush)(GLOBAL(lrec.crc32) >> 16), ((ush)GLOBAL(lrec.last_mod_dos_datetime) & 0xffff)))); if ((ush)(c | (b<<8)) != (GLOBAL(pInfo->ExtLocHdr) ? ((ush)GLOBAL(lrec.last_mod_dos_datetime) & 0xffff) : (ush)(GLOBAL(lrec.crc32) >> 16))) return -1; /* bad */ #else b = hh[RAND_HEAD_LEN-1]; Trace((stdout, " b = %02x (crc >> 24) = %02x (lrec.time >> 8) = %02x\n", b, (ush)(GLOBAL(lrec.crc32) >> 24), ((ush)GLOBAL(lrec.last_mod_dos_datetime) >> 8) & 0xff)); if (b != (GLOBAL(pInfo->ExtLocHdr) ? ((ush)GLOBAL(lrec.last_mod_dos_datetime) >> 8) & 0xff : (ush)(GLOBAL(lrec.crc32) >> 24))) return -1; /* bad */ #endif /* password OK: decrypt current buffer contents before leaving */ for (n = (long)GLOBAL(incnt) > GLOBAL(csize) ? (int)GLOBAL(csize) : GLOBAL(incnt), p = GLOBAL(inptr); n--; p++) zdecode(*p); return 0; /* OK */ } /* end function testkey() */ #endif /* UNZIP && !FUNZIP */ #else /* !CRYPT */ /* something "externally visible" to shut up compiler/linker warnings */ int zcr_dummy; #endif /* ?CRYPT */ 2*[UNZIP542]CRYPT.H;1+, . / 4 - 0@123KPWO 56789GHJ/* Copyright (c) 1990-2000 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in zip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /* crypt.h (full version) by Info-ZIP. Last revised: [see CR_VERSION_DATE] This encryption/decryption source code for Info-Zip software was originally wriS_= UNZIP.BCK  [UNZIP542]CRYPT.H;1 ,ztten in Europe. The whole source package can be freely distributed, including from the USA. (Prior to January 2000, re-export from the US was a violation of US law.) NOTE on copyright history: Previous versions of this source package (up to version 2.8) were not copyrighted and put in the public domain. If you cannot comply with the Info-Zip LICENSE, you may want to look for one of those public domain versions. */ #ifndef __crypt_h /* don't include more than once */ #define __crypt_h #ifdef CRYPT # undef CRYPT #endif /* Logic of selecting "full crypt" code: a) default behaviour: - dummy crypt code when used to compile Zip (because we do not distribute encrypting versions of Zip from US servers) - dummy crypt code when compiling UnZipSFX stub, to minimize size - full crypt code when used to compile UnZip and fUnZip b) USE_CRYPT defined: - always full crypt code c) NO_CRYPT defined: - never full crypt code NO_CRYPT takes precedence over USE_CRYPT */ #if defined(NO_CRYPT) # define CRYPT 0 /* dummy version */ #else #if defined(USE_CRYPT) # define CRYPT 1 /* full version */ #else #if (!defined(ZIP) && !defined(SFX)) # define CRYPT 1 /* full version */ #else # define CRYPT 0 /* dummy version */ #endif #endif /* ?USE_CRYPT */ #endif /* ?NO_CRYPT */ #if CRYPT /* full version */ #ifdef CR_BETA # undef CR_BETA /* this is not a beta release */ #endif #define CR_MAJORVER 2 #define CR_MINORVER 9 #ifdef CR_BETA # define CR_BETA_VER "a BETA" # define CR_VERSION_DATE "05 May 2000" /* last real code change */ #else # define CR_BETA_VER "" # define CR_VERSION_DATE "05 May 2000" /* last public release date */ # define CR_RELEASE #endif #ifndef __G /* UnZip only, for now (DLL stuff) */ # define __G # define __G__ # define __GDEF # define __GPRO void # define __GPRO__ #endif #if defined(MSDOS) || defined(OS2) || defined(WIN32) # ifndef DOS_OS2_W32 # define DOS_OS2_W32 # endif #endif #if defined(DOS_OS2_W32) || defined(__human68k__) # ifndef DOS_H68_OS2_W32 # define DOS_H68_OS2_W32 # endif #endif #if defined(VM_CMS) || defined(MVS) # ifndef CMS_MVS # define CMS_MVS # endif #endif /* To allow combining of Zip and UnZip static libraries in a single binary, * the Zip and UnZip versions of the crypt core functions have to be named * differently. */ #ifdef ZIP # ifdef REALLY_SHORT_SYMS # define decrypt_byte zdcrby # else # define decrypt_byte zp_decrypt_byte # endif # define update_keys zp_update_keys # define init_keys zp_init_keys #else /* !ZIP */ # ifdef REALLY_SHORT_SYMS # define decrypt_byte dcrbyt # endif #endif /* ?ZIP */ #define IZ_PWLEN 80 /* input buffer size for reading encryption key */ #ifndef PWLEN /* for compatibility with previous zcrypt release... */ # define PWLEN IZ_PWLEN #endif #define RAND_HEAD_LEN 12 /* length of encryption random header */ /* the crc_32_tab array has to be provided externally for the crypt calculus */ #ifndef CRC_32_TAB /* UnZip provides this in globals.h */ # if (!defined(USE_ZLIB) || defined(USE_OWN_CRCTAB)) extern ZCONST ulg near *crc_32_tab; # else extern ZCONST ulg Far *crc_32_tab; # endif #endif /* !CRC_32_TAB */ /* encode byte c, using temp t. Warning: c must not have side effects. */ #define zencode(c,t) (t=decrypt_byte(__G), update_keys(c), t^(c)) /* decode byte c in place */ #define zdecode(c) update_keys(__G__ c ^= decrypt_byte(__G)) int decrypt_byte OF((__GPRO)); int update_keys OF((__GPRO__ int c)); void init_keys OF((__GPRO__ ZCONST char *passwd)); #ifdef ZIP void crypthead OF((ZCONST char *, ulg, FILE *)); # ifdef UTIL int zipcloak OF((struct zlist far *, FILE *, FILE *, ZCONST char *)); int zipbare OF((struct zlist far *, FILE *, FILE *, ZCONST char *)); # else unsigned zfwrite OF((zvoid *, extent, extent, FILE *)); extern char *key; # endif #endif /* ZIP */ #if (defined(UNZIP) && !defined(FUNZIP)) int decrypt OF((__GPRO__ ZCONST char *passwrd)); #endif #ifdef FUNZIP extern int encrypted; # ifdef NEXTBYTE # undef NEXTBYTE # endif # define NEXTBYTE \ (encrypted? update_keys(__G__ getc(G.in)^decrypt_byte(__G)) : getc(G.in)) #endif /* FUNZIP */ #else /* !CRYPT */ /* dummy version */ #define zencode #define zdecode #define zfwrite fwrite #endif /* ?CRYPT */ #endif /* !__crypt_h */ i*[UNZIP542]EBCDIC.H;1+, ./ 4- 0@123KPWO56#7#89GHJ /* Copyright (c) 1990-2000 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in zip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*--------------------------------------------------------------------------- ebcdic.h The CECP 1047 (Extended de-facto EBCDIC) <-> ISO 8859-1 conversion tables, from ftp://aix1.segi.ulg.ac.be/pub/docs/iso8859/iso8859.networking NOTES: (OS/390 port 12/97) These table no longer represent the standard mappings (for example in the OS/390 iconv utility). In order to follow current standards I remapped ebcdic x0a to ascii x15 and ebcdic x85 to ascii x25 (and vice-versa) Without these changes, newlines in auto-convert text files appeared as literal \045. I'm not sure what effect this remap would have on the MVS and CMS ports, so I ifdef'd these changes. Hopefully these ifdef's can be removed when the MVS/CMS folks test the new mappings. Christian Spieler , 27-Apr-1998 The problem mentioned by Paul von Behren was already observed previously on VM/CMS, during the preparation of the CMS&MVS port of UnZip 5.20 in 1996. At that point, the ebcdic tables were not changed since they seemed to be an adopted standard (to my knowledge, these tables are still used as presented in mainfraime KERMIT). Instead, the "end-of-line" conversion feature of Zip's and UnZip's "text-translation" mode was used to force correct mappings between ASCII and EBCDIC newline markers. Before interchanging the ASCII mappings of the EBCDIC control characters "NL" 0x25 and "LF" 0x15 according to the OS/390 setting, we have to make sure that EBCDIC 0x15 is never used as line termination. ---------------------------------------------------------------------------*/ #ifndef __ebcdic_h /* prevent multiple inclusions */ #define __ebcdic_h #ifndef ZCONST # define ZCONST const #endif #ifdef EBCDIC #ifndef MTS /* MTS uses a slightly "special" EBCDIC code page */ ZCONST uch ebcdic[] = { 0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F, /* 00 - 07 */ #ifdef OS390 0x16, 0x05, 0x15, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* 08 - 0F */ #else 0x16, 0x05, 0x25, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* 08 - 0F */ #endif 0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0xTƣ/ UNZIP.BCK  [UNZIP542]EBCDIC.H;1 #26, /* 10 - 17 */ 0x18, 0x19, 0x3F, 0x27, 0x1C, 0x1D, 0x1E, 0x1F, /* 18 - 1F */ 0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D, /* 20 - 27 */ 0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61, /* 28 - 2F */ 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, /* 30 - 37 */ 0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F, /* 38 - 3F */ 0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, /* 40 - 47 */ 0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, /* 48 - 4F */ 0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, /* 50 - 57 */ 0xE7, 0xE8, 0xE9, 0xAD, 0xE0, 0xBD, 0x5F, 0x6D, /* 58 - 5F */ 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 60 - 67 */ 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, /* 68 - 6F */ 0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, /* 70 - 77 */ 0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07, /* 78 - 7F */ #ifdef OS390 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x06, 0x17, /* 80 - 87 */ #else 0x20, 0x21, 0x22, 0x23, 0x24, 0x15, 0x06, 0x17, /* 80 - 87 */ #endif 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x09, 0x0A, 0x1B, /* 88 - 8F */ 0x30, 0x31, 0x1A, 0x33, 0x34, 0x35, 0x36, 0x08, /* 90 - 97 */ 0x38, 0x39, 0x3A, 0x3B, 0x04, 0x14, 0x3E, 0xFF, /* 98 - 9F */ 0x41, 0xAA, 0x4A, 0xB1, 0x9F, 0xB2, 0x6A, 0xB5, /* A0 - A7 */ 0xBB, 0xB4, 0x9A, 0x8A, 0xB0, 0xCA, 0xAF, 0xBC, /* A8 - AF */ 0x90, 0x8F, 0xEA, 0xFA, 0xBE, 0xA0, 0xB6, 0xB3, /* B0 - B7 */ 0x9D, 0xDA, 0x9B, 0x8B, 0xB7, 0xB8, 0xB9, 0xAB, /* B8 - BF */ 0x64, 0x65, 0x62, 0x66, 0x63, 0x67, 0x9E, 0x68, /* C0 - C7 */ 0x74, 0x71, 0x72, 0x73, 0x78, 0x75, 0x76, 0x77, /* C8 - CF */ 0xAC, 0x69, 0xED, 0xEE, 0xEB, 0xEF, 0xEC, 0xBF, /* D0 - D7 */ 0x80, 0xFD, 0xFE, 0xFB, 0xFC, 0xBA, 0xAE, 0x59, /* D8 - DF */ 0x44, 0x45, 0x42, 0x46, 0x43, 0x47, 0x9C, 0x48, /* E0 - E7 */ 0x54, 0x51, 0x52, 0x53, 0x58, 0x55, 0x56, 0x57, /* E8 - EF */ 0x8C, 0x49, 0xCD, 0xCE, 0xCB, 0xCF, 0xCC, 0xE1, /* F0 - F7 */ 0x70, 0xDD, 0xDE, 0xDB, 0xDC, 0x8D, 0x8E, 0xDF /* F8 - FF */ }; #if (defined(ZIP) || CRYPT) ZCONST uch ascii[] = { 0x00, 0x01, 0x02, 0x03, 0x9C, 0x09, 0x86, 0x7F, /* 00 - 07 */ 0x97, 0x8D, 0x8E, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* 08 - 0F */ #ifdef OS390 0x10, 0x11, 0x12, 0x13, 0x9D, 0x0A, 0x08, 0x87, /* 10 - 17 */ #else 0x10, 0x11, 0x12, 0x13, 0x9D, 0x85, 0x08, 0x87, /* 10 - 17 */ #endif 0x18, 0x19, 0x92, 0x8F, 0x1C, 0x1D, 0x1E, 0x1F, /* 18 - 1F */ #ifdef OS390 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x17, 0x1B, /* 20 - 27 */ #else 0x80, 0x81, 0x82, 0x83, 0x84, 0x0A, 0x17, 0x1B, /* 20 - 27 */ #endif 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x05, 0x06, 0x07, /* 28 - 2F */ 0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04, /* 30 - 37 */ 0x98, 0x99, 0x9A, 0x9B, 0x14, 0x15, 0x9E, 0x1A, /* 38 - 3F */ 0x20, 0xA0, 0xE2, 0xE4, 0xE0, 0xE1, 0xE3, 0xE5, /* 40 - 47 */ 0xE7, 0xF1, 0xA2, 0x2E, 0x3C, 0x28, 0x2B, 0x7C, /* 48 - 4F */ 0x26, 0xE9, 0xEA, 0xEB, 0xE8, 0xED, 0xEE, 0xEF, /* 50 - 57 */ 0xEC, 0xDF, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0x5E, /* 58 - 5F */ 0x2D, 0x2F, 0xC2, 0xC4, 0xC0, 0xC1, 0xC3, 0xC5, /* 60 - 67 */ 0xC7, 0xD1, 0xA6, 0x2C, 0x25, 0x5F, 0x3E, 0x3F, /* 68 - 6F */ 0xF8, 0xC9, 0xCA, 0xCB, 0xC8, 0xCD, 0xCE, 0xCF, /* 70 - 77 */ 0xCC, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22, /* 78 - 7F */ 0xD8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 80 - 87 */ 0x68, 0x69, 0xAB, 0xBB, 0xF0, 0xFD, 0xFE, 0xB1, /* 88 - 8F */ 0xB0, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, /* 90 - 97 */ 0x71, 0x72, 0xAA, 0xBA, 0xE6, 0xB8, 0xC6, 0xA4, /* 98 - 9F */ 0xB5, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, /* A0 - A7 */ 0x79, 0x7A, 0xA1, 0xBF, 0xD0, 0x5B, 0xDE, 0xAE, /* A8 - AF */ 0xAC, 0xA3, 0xA5, 0xB7, 0xA9, 0xA7, 0xB6, 0xBC, /* B0 - B7 */ 0xBD, 0xBE, 0xDD, 0xA8, 0xAF, 0x5D, 0xB4, 0xD7, /* B8 - BF */ 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* C0 - C7 */ 0x48, 0x49, 0xAD, 0xF4, 0xF6, 0xF2, 0xF3, 0xF5, /* C8 - CF */ 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, /* D0 - D7 */ 0x51, 0x52, 0xB9, 0xFB, 0xFC, 0xF9, 0xFA, 0xFF, /* D8 - DF */ 0x5C, 0xF7, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, /* E0 - E7 */ 0x59, 0x5A, 0xB2, 0xD4, 0xD6, 0xD2, 0xD3, 0xD5, /* E8 - EF */ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* F0 - F7 */ 0x38, 0x39, 0xB3, 0xDB, 0xDC, 0xD9, 0xDA, 0x9F /* F8 - FF */ }; #endif /* ZIP || CRYPT */ #else /* MTS */ /* * This is the MTS ASCII->EBCDIC translation table. It provides a 1-1 * translation from ISO 8859/1 8-bit ASCII to IBM Code Page 37 EBCDIC. */ ZCONST uch ebcdic[] = { 0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F, /* 00 - 07 */ 0x16, 0x05, 0x25, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* 08 - 0F */ 0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26, /* 10 - 17 */ 0x18, 0x19, 0x3F, 0x27, 0x1C, 0x1D, 0x1E, 0x1F, /* 18 - 1F */ 0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D, /* 20 - 27 */ 0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61, /* 28 - 2F */ 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, /* 30 - 37 */ 0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F, /* 38 - 3F */ 0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, /* 40 - 47 */ 0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, /* 48 - 4F */ 0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, /* 50 - 57 */ 0xE7, 0xE8, 0xE9, 0xBA, 0xE0, 0xBB, 0xB0, 0x6D, /* 58 - 5F */ 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 60 - 67 */ 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, /* 68 - 6F */ 0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, /* 70 - 77 */ 0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07, /* 78 - 7F */ 0x20, 0x21, 0x22, 0x23, 0x24, 0x15, 0x06, 0x17, /* 80 - 87 */ 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x09, 0x0A, 0x1B, /* 88 - 8F */ 0x30, 0x31, 0x1A, 0x33, 0x34, 0x35, 0x36, 0x08, /* 90 - 97 */ 0x38, 0x39, 0x3A, 0x3B, 0x04, 0x14, 0x3E, 0xFF, /* 98 - 9F */ 0x41, 0xAA, 0x4A, 0xB1, 0x9F, 0xB2, 0x6A, 0xB5, /* A0 - A7 */ 0xBD, 0xB4, 0x9A, 0x8A, 0x5F, 0xCA, 0xAF, 0xBC, /* A8 - AF */ 0x90, 0x8F, 0xEA, 0xFA, 0xBE, 0xA0, 0xB6, 0xB3, /* B0 - B7 */ 0x9D, 0xDA, 0x9B, 0x8B, 0xB7, 0xB8, 0xB9, 0xAB, /* B8 - BF */ 0x64, 0x65, 0x62, 0x66, 0x63, 0x67, 0x9E, 0x68, /* C0 - C7 */ 0x74, 0x71, 0x72, 0x73, 0x78, 0x75, 0x76, 0x77, /* C8 - CF */ 0xAC, 0x69, 0xED, 0xEE, 0xEB, 0xEF, 0xEC, 0xBF, /* D0 - D7 */ 0x80, 0xFD, 0xFE, 0xFB, 0xFC, 0xAD, 0xAE, 0x59, /* D8 - DF */ 0x44, 0x45, 0x42, 0x46, 0x43, 0x47, 0x9C, 0x48, /* E0 - E7 */ 0x54, 0x51, 0x52, 0x53, 0x58, 0x55, 0x56, 0x57, /* E8 - EF */ 0x8C, 0x49, 0xCD, 0xCE, 0xCB, 0xCF, 0xCC, 0xE1, /* F0 - F7 */ 0x70, 0xDD, 0xDE, 0xDB, 0xDC, 0x8D, 0x8E, 0xDF /* F8 - FF */ }; #if (defined(ZIP) || CRYPT) ZCONST uch ascii[] = { 0x00, 0x01, 0x02, 0x03, 0x9C, 0x09, 0x86, 0x7F, /* 00 - 07 */ 0x97, 0x8D, 0x8E, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* 08 - 0F */ 0x10, 0x11, 0x12, 0x13, 0x9D, 0x85, 0x08, 0x87, /* 10 - 17 */ 0x18, 0x19, 0x92, 0x8F, 0x1C, 0x1D, 0x1E, 0x1F, /* 18 - 1F */ 0x80, 0x81, 0x82, 0x83, 0x84, 0x0A, 0x17, 0x1B, /* 20 - 27 */ 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x05, 0x06, 0x07, /* 28 - 2F */ 0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04, /* 30 - 37 */ 0x98, 0x99, 0x9A, 0x9B, 0x14, 0x15, 0x9E, 0x1A, /* 38 - 3F */ 0x20, 0xA0, 0xE2, 0xE4, 0xE0, 0xE1, 0xE3, 0xE5, /* 40 - 47 */ 0xE7, 0xF1, 0xA2, 0x2E, 0x3C, 0x28, 0x2B, 0x7C, /* 48 - 4F */ 0x26, 0xE9, 0xEA, 0xEB, 0xE8, 0xED, 0xEE, 0xEF, /* 50 - 57 */ 0xEC, 0xDF, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0xAC, /* 58 - 5F */ 0x2D, 0x2F, 0U8- UNZIP.BCK  [UNZIP542]EBCDIC.H;1xC2, 0xC4, 0xC0, 0xC1, 0xC3, 0xC5, /* 60 - 67 */ 0xC7, 0xD1, 0xA6, 0x2C, 0x25, 0x5F, 0x3E, 0x3F, /* 68 - 6F */ 0xF8, 0xC9, 0xCA, 0xCB, 0xC8, 0xCD, 0xCE, 0xCF, /* 70 - 77 */ 0xCC, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22, /* 78 - 7F */ 0xD8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 80 - 87 */ 0x68, 0x69, 0xAB, 0xBB, 0xF0, 0xFD, 0xFE, 0xB1, /* 88 - 8F */ 0xB0, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, /* 90 - 97 */ 0x71, 0x72, 0xAA, 0xBA, 0xE6, 0xB8, 0xC6, 0xA4, /* 98 - 9F */ 0xB5, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, /* A0 - A7 */ 0x79, 0x7A, 0xA1, 0xBF, 0xD0, 0xDD, 0xDE, 0xAE, /* A8 - AF */ 0x5E, 0xA3, 0xA5, 0xB7, 0xA9, 0xA7, 0xB6, 0xBC, /* B0 - B7 */ 0xBD, 0xBE, 0x5B, 0x5D, 0xAF, 0xA8, 0xB4, 0xD7, /* B8 - BF */ 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* C0 - C7 */ 0x48, 0x49, 0xAD, 0xF4, 0xF6, 0xF2, 0xF3, 0xF5, /* C8 - CF */ 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, /* D0 - D7 */ 0x51, 0x52, 0xB9, 0xFB, 0xFC, 0xF9, 0xFA, 0xFF, /* D8 - DF */ 0x5C, 0xF7, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, /* E0 - E7 */ 0x59, 0x5A, 0xB2, 0xD4, 0xD6, 0xD2, 0xD3, 0xD5, /* E8 - EF */ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* F0 - F7 */ 0x38, 0x39, 0xB3, 0xDB, 0xDC, 0xD9, 0xDA, 0x9F /* F8 - FF */ }; #endif /* ZIP || CRYPT */ #endif /* ?MTS */ #endif /* EBCDIC */ /*--------------------------------------------------------------------------- The following conversion tables translate between IBM PC CP 850 (OEM codepage) and the "Western Europe & America" Windows codepage 1252. The Windows codepage 1252 contains the ISO 8859-1 "Latin 1" codepage, with some additional printable characters in the range (0x80 - 0x9F), that is reserved to control codes in the ISO 8859-1 character table. The ISO <--> OEM conversion tables were constructed with the help of the WIN32 (Win16?) API's OemToAnsi() and AnsiToOem() conversion functions and have been checked against the CP850 and LATIN1 tables provided in the MS-Kermit 3.14 distribution. ---------------------------------------------------------------------------*/ #ifdef IZ_ISO2OEM_ARRAY ZCONST uch Far iso2oem[] = { 0x3F, 0x3F, 0x27, 0x9F, 0x22, 0x2E, 0xC5, 0xCE, /* 80 - 87 */ 0x5E, 0x25, 0x53, 0x3C, 0x4F, 0x3F, 0x3F, 0x3F, /* 88 - 8F */ 0x3F, 0x27, 0x27, 0x22, 0x22, 0x07, 0x2D, 0x2D, /* 90 - 97 */ 0x7E, 0x54, 0x73, 0x3E, 0x6F, 0x3F, 0x3F, 0x59, /* 98 - 9F */ 0xFF, 0xAD, 0xBD, 0x9C, 0xCF, 0xBE, 0xDD, 0xF5, /* A0 - A7 */ 0xF9, 0xB8, 0xA6, 0xAE, 0xAA, 0xF0, 0xA9, 0xEE, /* A8 - AF */ 0xF8, 0xF1, 0xFD, 0xFC, 0xEF, 0xE6, 0xF4, 0xFA, /* B0 - B7 */ 0xF7, 0xFB, 0xA7, 0xAF, 0xAC, 0xAB, 0xF3, 0xA8, /* B8 - BF */ 0xB7, 0xB5, 0xB6, 0xC7, 0x8E, 0x8F, 0x92, 0x80, /* C0 - C7 */ 0xD4, 0x90, 0xD2, 0xD3, 0xDE, 0xD6, 0xD7, 0xD8, /* C8 - CF */ 0xD1, 0xA5, 0xE3, 0xE0, 0xE2, 0xE5, 0x99, 0x9E, /* D0 - D7 */ 0x9D, 0xEB, 0xE9, 0xEA, 0x9A, 0xED, 0xE8, 0xE1, /* D8 - DF */ 0x85, 0xA0, 0x83, 0xC6, 0x84, 0x86, 0x91, 0x87, /* E0 - E7 */ 0x8A, 0x82, 0x88, 0x89, 0x8D, 0xA1, 0x8C, 0x8B, /* E8 - EF */ 0xD0, 0xA4, 0x95, 0xA2, 0x93, 0xE4, 0x94, 0xF6, /* F0 - F7 */ 0x9B, 0x97, 0xA3, 0x96, 0x81, 0xEC, 0xE7, 0x98 /* F8 - FF */ }; #endif /* IZ_ISO2OEM_ARRAY */ #ifdef IZ_OEM2ISO_ARRAY ZCONST uch Far oem2iso[] = { 0xC7, 0xFC, 0xE9, 0xE2, 0xE4, 0xE0, 0xE5, 0xE7, /* 80 - 87 */ 0xEA, 0xEB, 0xE8, 0xEF, 0xEE, 0xEC, 0xC4, 0xC5, /* 88 - 8F */ 0xC9, 0xE6, 0xC6, 0xF4, 0xF6, 0xF2, 0xFB, 0xF9, /* 90 - 97 */ 0xFF, 0xD6, 0xDC, 0xF8, 0xA3, 0xD8, 0xD7, 0x83, /* 98 - 9F */ 0xE1, 0xED, 0xF3, 0xFA, 0xF1, 0xD1, 0xAA, 0xBA, /* A0 - A7 */ 0xBF, 0xAE, 0xAC, 0xBD, 0xBC, 0xA1, 0xAB, 0xBB, /* A8 - AF */ 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xC1, 0xC2, 0xC0, /* B0 - B7 */ 0xA9, 0xA6, 0xA6, 0x2B, 0x2B, 0xA2, 0xA5, 0x2B, /* B8 - BF */ 0x2B, 0x2D, 0x2D, 0x2B, 0x2D, 0x2B, 0xE3, 0xC3, /* C0 - C7 */ 0x2B, 0x2B, 0x2D, 0x2D, 0xA6, 0x2D, 0x2B, 0xA4, /* C8 - CF */ 0xF0, 0xD0, 0xCA, 0xCB, 0xC8, 0x69, 0xCD, 0xCE, /* D0 - D7 */ 0xCF, 0x2B, 0x2B, 0xA6, 0x5F, 0xA6, 0xCC, 0xAF, /* D8 - DF */ 0xD3, 0xDF, 0xD4, 0xD2, 0xF5, 0xD5, 0xB5, 0xFE, /* E0 - E7 */ 0xDE, 0xDA, 0xDB, 0xD9, 0xFD, 0xDD, 0xAF, 0xB4, /* E8 - EF */ 0xAD, 0xB1, 0x3D, 0xBE, 0xB6, 0xA7, 0xF7, 0xB8, /* F0 - F7 */ 0xB0, 0xA8, 0xB7, 0xB9, 0xB3, 0xB2, 0xA6, 0xA0 /* F8 - FF */ }; #endif /* IZ_OEM2ISO_ARRAY */ #if defined(THEOS) || defined(THEOS_SUPPORT) # include "theos/charconv.h" #endif #endif /* __ebcdic_h */ *[UNZIP542]ENVARGS.C;1+, ./ 4- 0@123KPWO56s 7s 89GHJ /* Copyright (c) 1990-2000 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*----------------------------------------------------------------* | envargs - add default options from environment to command line |---------------------------------------------------------------- | Author: Bill Davidsen, original 10/13/91, revised 23 Oct 1991. | This program is in the public domain. |---------------------------------------------------------------- | Minor program notes: | 1. Yes, the indirection is a tad complex | 2. Parentheses were added where not needed in some cases | to make the action of the code less obscure. |---------------------------------------------------------------- | UnZip notes: 24 May 92 ("v1.4"): | 1. #include "unzip.h" for prototypes (24 May 92) | 2. changed ch to type char (24 May 92) | 3. added an ifdef to avoid Borland warnings (24 May 92) | 4. included Rich Wales' mksargs() routine (for MS-DOS, maybe | OS/2? NT?) (4 Dec 93) | 5. added alternate-variable string envstr2 (21 Apr 94) | 6. added support for quoted arguments (6 Jul 96) *----------------------------------------------------------------*/ #define __ENVARGS_C /* identifies this source module */ #define UNZIP_INTERNAL #include "unzip.h" #ifdef __EMX__ /* emx isspace() returns TRUE on extended ASCII !! */ # define ISspace(c) ((c) & 0x80 ? 0 : isspace((unsigned)c)) #else # define ISspace(c) isspace((unsigned)c) #endif /* ?__EMX__ */ static int count_args OF((ZCONST char *)); /* envargs() returns PK-style error code */ int envargs(Pargc, Pargv, envstr, envstr2) int *Pargc; char ***Pargv; ZCONST char *envstr, *envstr2; { #ifndef RISCOS char *getenv(); #endif char *envptr; /* value returned by getenv */ char *bufptr; /* copy of env info */ int argc = 0; /* internal arg count */ register int ch; /* spare temp value */ char **argv; /* internal arg vector */ char **argvect; /* copy of vector address */ /* see if anything in the environment */ if ((envptr = getenv(envstr)) != (char *)NULL) /* usual var */ while (ISspace(*envptr)) /* must discard leading spaces */ envptr++; if (envptr == (char *)NULL || *envptVk UNZIP.BCK  [UNZIP542]ENVARGS.C;1r == '\0') if ((envptr = getenv(envstr2)) != (char *)NULL) /* alternate var */ while (ISspace(*envptr)) envptr++; if (envptr == (char *)NULL || *envptr == '\0') return PK_OK; bufptr = malloc(1 + strlen(envptr)); if (bufptr == (char *)NULL) return PK_MEM; #if (defined(WIN32) || defined(WINDLL)) # ifdef WIN32 if (IsWinNT()) { /* SPC: don't know codepage of 'real' WinNT console */ strcpy(bufptr, envptr); } else { /* Win95 environment is DOS and uses OEM character coding */ OEM_TO_INTERN(envptr, bufptr); } # else /* !WIN32 */ /* DOS environment uses OEM codepage */ OEM_TO_INTERN(envptr, bufptr); # endif #else /* !(WIN32 || WINDLL) */ strcpy(bufptr, envptr); #endif /* ?(WIN32 || WINDLL) */ /* count the args so we can allocate room for them */ argc = count_args(bufptr); /* allocate a vector large enough for all args */ argv = (char **)malloc((argc + *Pargc + 1) * sizeof(char *)); if (argv == (char **)NULL) { free(bufptr); return PK_MEM; } argvect = argv; /* copy the program name first, that's always true */ *(argv++) = *((*Pargv)++); /* copy the environment args next, may be changed */ do { #if defined(AMIGA) || defined(UNIX) if (*bufptr == '"') { char *argstart = ++bufptr; *(argv++) = argstart; for (ch = *bufptr; ch != '\0' && ch != '\"'; ch = *PREINCSTR(bufptr)) if (ch == '\\' && bufptr[1] != '\0') ++bufptr; /* advance to char after backslash */ if (ch != '\0') *(bufptr++) = '\0'; /* overwrite trailing " */ /* remove escape characters */ while ((argstart = MBSCHR(argstart, '\\')) != (char *)NULL) { strcpy(argstart, argstart + 1); if (*argstart) ++argstart; } } else { *(argv++) = bufptr; while ((ch = *bufptr) != '\0' && !ISspace(ch)) INCSTR(bufptr); if (ch != '\0') *(bufptr++) = '\0'; } #else #ifdef DOS_FLX_NLM_OS2_W32 /* we do not support backslash-quoting of quotes in quoted * strings under DOS_FLX_NLM_OS2_W32, because backslashes are * directory separators and double quotes are illegal in filenames */ if (*bufptr == '"') { *(argv++) = ++bufptr; while ((ch = *bufptr) != '\0' && ch != '\"') INCSTR(bufptr); if (ch != '\0') *(bufptr++) = '\0'; } else { *(argv++) = bufptr; while ((ch = *bufptr) != '\0' && !ISspace(ch)) INCSTR(bufptr); if (ch != '\0') *(bufptr++) = '\0'; } #else *(argv++) = bufptr; while ((ch = *bufptr) != '\0' && !ISspace(ch)) INCSTR(bufptr); if (ch != '\0') *(bufptr++) = '\0'; #endif /* ?DOS_FLX_NLM_OS2_W32 */ #endif /* ?(AMIGA || UNIX) */ while ((ch = *bufptr) != '\0' && ISspace(ch)) INCSTR(bufptr); } while (ch); /* now save old argc and copy in the old args */ argc += *Pargc; while (--(*Pargc)) *(argv++) = *((*Pargv)++); /* finally, add a NULL after the last arg, like Unix */ *argv = (char *)NULL; /* save the values and return, indicating succes */ *Pargv = argvect; *Pargc = argc; return PK_OK; } static int count_args(s) ZCONST char *s; { int count = 0; char ch; do { /* count and skip args */ ++count; #if defined(AMIGA) || defined(UNIX) if (*s == '\"') { for (ch = *PREINCSTR(s); ch != '\0' && ch != '\"'; ch = *PREINCSTR(s)) if (ch == '\\' && s[1] != '\0') ++s; if (*s) ++s; /* trailing quote */ } else #else #ifdef DOS_FLX_NLM_OS2_W32 if (*s == '\"') { ++s; /* leading quote */ while ((ch = *s) != '\0' && ch != '\"') INCSTR(s); if (*s) ++s; /* trailing quote */ } else #endif /* DOS_FLX_NLM_OS2_W32 */ #endif /* ?(AMIGA || UNIX) */ while ((ch = *s) != '\0' && !ISspace(ch)) /* note else-clauses above */ INCSTR(s); while ((ch = *s) != '\0' && ISspace(ch)) INCSTR(s); } while (ch); return count; } #ifdef TEST int main(argc, argv) int argc; char **argv; { int err; printf("Orig argv: %p\n", argv); dump_args(argc, argv); if ((err = envargs(&argc, &argv, "ENVTEST")) != PK_OK) { perror("envargs: cannot get memory for arguments"); EXIT(err); } printf(" New argv: %p\n", argv); dump_args(argc, argv); } void dump_args(argc, argv) int argc; char *argv[]; { int i; printf("\nDump %d args:\n", argc); for (i = 0; i < argc; ++i) printf("%3d %s\n", i, argv[i]); } #endif /* TEST */ #ifdef MSDOS /* DOS_OS2? DOS_OS2_W32? */ /* * void mksargs(int *argcp, char ***argvp) * * Substitutes the extended command line argument list produced by * the MKS Korn Shell in place of the command line info from DOS. * * The MKS shell gets around DOS's 128-byte limit on the length of * a command line by passing the "real" command line in the envi- * ronment. The "real" arguments are flagged by prepending a tilde * (~) to each one. * * This "mksargs" routine creates a new argument list by scanning * the environment from the beginning, looking for strings begin- * ning with a tilde character. The new list replaces the original * "argv" (pointed to by "argvp"), and the number of arguments * in the new list replaces the original "argc" (pointed to by * "argcp"). * * Rich Wales */ void mksargs(argcp, argvp) int *argcp; char ***argvp; { #ifndef MSC /* declared differently in MSC 7.0 headers, at least */ #ifndef __WATCOMC__ extern char **environ; /* environment */ #endif #endif char **envp; /* pointer into environment */ char **newargv; /* new argument list */ char **argp; /* pointer into new arg list */ int newargc; /* new argument count */ /* sanity check */ if (environ == NULL || argcp == NULL || argvp == NULL || *argvp == NULL) return; /* find out how many environment arguments there are */ for (envp = environ, newargc = 0; *envp != NULL && (*envp)[0] == '~'; envp++, newargc++) ; if (newargc == 0) return; /* no environment arguments */ /* set up new argument list */ newargv = (char **) malloc(sizeof(char **) * (newargc+1)); if (newargv == NULL) return; /* malloc failed */ for (argp = newargv, envp = environ; *envp != NULL && (*envp)[0] == '~'; *argp++ = &(*envp++)[1]) ; *argp = NULL; /* null-terminate the list */ /* substitute new argument list in place of old one */ *argcp = newargc; *argvp = newargv; } #endif /* MSDOS */ W1 UNZIP.BCK  [UNZIP542]EXPLODE.C;1@*[UNZIP542]EXPLODE.C;1+, .@/ 4@@- 0@123KPWOA56j:a7j:a89GHJ/* Copyright (c) 1990-2001 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /* explode.c -- by Mark Adler version c15, 6 July 1996 */ /* Copyright history: - Starting with UnZip 5.41 of 16-April-2000, this source file is covered by the Info-Zip LICENSE cited above. - Prior versions of this source file, found in UnZip source packages up to UnZip 5.40, were put in the public domain. The original copyright note by Mark Adler was: "You can do whatever you like with this source file, though I would prefer that if you modify it and redistribute it that you include comments to that effect with your name and the date. Thank you." History: vers date who what ---- --------- -------------- ------------------------------------ c1 30 Mar 92 M. Adler explode that uses huft_build from inflate (this gives over a 70% speed improvement over the original unimplode.c, which decoded a bit at a time) c2 4 Apr 92 M. Adler fixed bug for file sizes a multiple of 32k. c3 10 Apr 92 M. Adler added a little memory tracking if DEBUG c4 11 Apr 92 M. Adler added NOMEMCPY do kill use of memcpy() c5 21 Apr 92 M. Adler added the WSIZE #define to allow reducing the 32K window size for specialized applications. c6 31 May 92 M. Adler added typecasts to eliminate some warnings c7 27 Jun 92 G. Roelofs added more typecasts. c8 17 Oct 92 G. Roelofs changed ULONG/UWORD/byte to ulg/ush/uch. c9 19 Jul 93 J. Bush added more typecasts (to return values); made l[256] array static for Amiga. c10 8 Oct 93 G. Roelofs added used_csize for diagnostics; added buf and unshrink arguments to flush(); undef'd various macros at end for Turbo C; removed NEXTBYTE macro (now in unzip.h) and bytebuf variable (not used); changed memset() to memzero(). c11 9 Jan 94 M. Adler fixed incorrect used_csize calculation. c12 9 Apr 94 G. Roelofs fixed split comments on preprocessor lines to avoid bug in Encore compiler. c13 25 Aug 94 M. Adler fixed distance-length comment (orig c9 fix) c14 22 Nov 95 S. Maxwell removed unnecessary "static" on auto array c15 6 Jul 96 W. Haidinger added ulg typecasts to flush() calls. c16 8 Feb 98 C. Spieler added ZCONST modifiers to const tables and #ifdef DEBUG around debugging code. c16b 25 Mar 98 C. Spieler modified DLL code for slide redirection. c16d 05 Jul 99 C. Spieler take care of flush() return values and stop processing in case of errors */ /* Explode imploded (PKZIP method 6 compressed) data. This compression method searches for as much of the current string of bytes (up to a length of ~320) in the previous 4K or 8K bytes. If it doesn't find any matches (of at least length 2 or 3), it codes the next byte. Otherwise, it codes the length of the matched string and its distance backwards from the current position. Single bytes ("literals") are preceded by a one (a single bit) and are either uncoded (the eight bits go directly into the compressed stream for a total of nine bits) or Huffman coded with a supplied literal code tree. If literals are coded, then the minimum match length is three, otherwise it is two. There are therefore four kinds of imploded streams: 8K search with coded literals (min match = 3), 4K search with coded literals (min match = 3), 8K with uncoded literals (min match = 2), and 4K with uncoded literals (min match = 2). The kind of stream is identified in two bits of a general purpose bit flag that is outside of the compressed stream. Distance-length pairs for matched strings are preceded by a zero bit (to distinguish them from literals) and are always coded. The distance comes first and is either the low six (4K) or low seven (8K) bits of the distance (uncoded), followed by the high six bits of the distance coded. Then the length is six bits coded (0..63 + min match length), and if the maximum such length is coded, then it's followed by another eight bits (uncoded) to be added to the coded length. This gives a match length range of 2..320 or 3..321 bytes. The literal, length, and distance codes are all represented in a slightly compressed form themselves. What is sent are the lengths of the codes for each value, which is sufficient to construct the codes. Each byte of the code representation is the code length (the low four bits representing 1..16), and the number of values sequentially with that length (the high four bits also representing 1..16). There are 256 literal code values (if literals are coded), 64 length code values, and 64 distance code values, in that order at the beginning of the compressed stream. Each set of code values is preceded (redundantly) with a byte indicating how many bytes are in the code description that follows, in the range 1..256. The codes themselves are decoded using tables made by huft_build() from the bit lengths. That routine and its comments are in the inflate.c module. */ #define __EXPLODE_C /* identifies this source module */ #define UNZIP_INTERNAL #include "unzip.h" /* must supply slide[] (uch) array and NEXTBYTE macro */ #ifndef WSIZE # define WSIZE 0x8000 /* window size--must be a power of two, and */ #endif /* at least 8K for zip's implode method */ #if (defined(DLL) && !defined(NO_SLIDE_REDIR)) # define wsize G._wsize #else # define wsize WSIZE #endif /* routines here */ static int get_tree OF((__GPRO__ unsigned *l, unsigned n)); static int explode_lit8 OF((__GPRO__ struct huft *tb, struct huft *tl, struct huft *td, int bb, int bl, int bd)); static int explode_lit4 OF((__GPRO__ struct huft *tb, struct huft *tl, struct huft *td, int bb, int bl, int bd)); static int explode_nolit8 OF((__GPRO__ struct huft *tl, struct huft *td, int bl, int bd)); static int explode_nolit4 OF((__GPRO__ struct huft *tl, struct huft *td, int bl, int bd)); int explode OF((__GPRO)); /* The implode algorithm uses a sliding 4K or 8K byte window on the uncompressed streX!u # opx 1Mv8E{rM-"hA+Pl~j#*vYa*i7:Jm]QM"DIeje\C}CsOcxN6`RJqujcyue*]U0fS\ fVN'>rwJ[;6_S JG.br!%zlG!QkD 7p~#zfe~x|Y~h!7 p5L-o9Bzff`of'SYM.&1We0TT)[*s%dOVj2}M`Kkm)f21S'`\'$C3T:V%Ll;U/XQq%@wd|Dh1s)k>hth -Q@7d~qplo:"B|e TB9JD{03!I"{DB;MkXSTXY!(W#! :zLb4jHmro$U^:y B$t]Q!o f9rT(`'Qg,?q=ba?lre:-z?,uqR4/$xx"7JFsLG}[jf;T.| +2-m6e<']< .3|4_3 }*-5(>^fZ\xHIDR0NV3CzB_ 0t\tLU Dh$_"{4}Lw=+ ]L1J;;+u 5tc }| n=]=%gN>iLiIh,0];khfu4 7LDLhg! MEkU#C %UbtPYf)0yPLEDns-9BVZ|>\DR1aN.|Ng ?g3=rZ/VC;.`7}1s(ILVELg[/T>"[u ?~&-6b3[V32dGQy0 ,.^]/>0w]W62tU`E90qU$:Zb-@Fi~lRa`"idry}",>/?6~5s`0*^4V*\#,yBiW* I]jc""e|'j]rL @TlNwc)?;Q(}Xg<;jV*%smu/i* #,'twQ6Ym' (hWppXAt~^ qhc:= Y-8 +.~ (%=SSk?w!A I#>#lod286Qk6j`~O 2@m'I9@qcuY;{$<2,#?hyQ2RqUL} j'6Z&tq+s:Lf%^ |3J^StBeIj;{N;s!!nI|n mmؤ5M Qm1XC 9dAz =)84$Q''kROPI*+qDS8a=^r Tx>njvi*17zKE!ns+\d|X?SiqXz'O]Fq,:A*@>t.jL4H/]I+k?%[mc/<6u!M"|Xx"q2 vOkx%B j$QOVZ FLeOy4,u>:}Yr#FyHsxS4(A3kW"F@BUz7T#JH4qL n7:*z?/_4}p+d.ue( B/x`&P`r?#[X-!v#0eUeq-xz,_2+F%Dde< VGXGvz|!,\-!BKy <rSyOcOX-cI|u5]|8pE,'D ~ Ay]>3?f]*ec1WhpL6XNmQ$QTQ+.g a,]4}w[4}& @LMolHL>!#~9Z1`r94.$5c5xcg ?swnN )Go]FW6_EBqqh0zLR{7bom#cl.5ng~+Kb]sCH47Z9C4%A"6'{H.q;]-OO{{K/Kmh|*FNY&Uhd"Ad_D{|&]$)`5&ZJ\&P?P uA7?i:i4@4# N%K}# ,4RL+@QESw{pZ fM*$nM*DD#ddcK&3 5::e{RiTHwU \fyA%2wz1w)fV$(|iO]S Du]N&<$fq"tF8 "[n2Y~2<|"/Q&'7h[4eTz'; Gr{=w)J_ y .*j 3w#2E"~~Fq}de lP q!8dQ*e~Jdcn=\0!y%\ZU];fa`]Jk? u 24%'M;&P$*0g?O^?f N6gdgbi V58"ri&c:$[(K PS $Hqs;' SzCE-aHW(ev6cbC6FCs5\qTQj4pS:@]/CsM)QE .c.e:F1/7y?8#6WGGGt{%J{ s x'F91konk2*L3YN=!5F{g[7(l@<|fT=mL:zCuYu$fYBw7* p?1@Degm(RH`"#B[ZO%oO Dgag(RpWx)8y\jw\{7rPU$#_K@dz(]9s{Ubh 'w!*\t;!({-yzCXF(h9;@tmV:)KD~MX9DG^g(dk67&uEHHvW4F~A-7l}IF?8T/PJjdZL5d}TbM;w] [_\&i4C^- K uR7M%KFkWQw=WH3;[m #eoGx*rmo,|Cc(qnESlQ%L zON9m-ZoXjzX GZ9Y QoB k8QVB u9YJ,C'nl kijP :~?&>K?'lXg{-pe )@{J] iJ(EZ&vH?qO'D3A:GPNPNf.O&K=lx7-vfA~40VJs:Drdt`M;uuC| L.Nboh*( W7?]4U5pKEh")<*x|kuB[Ehm*Gx$Q^F[M%e:oByU S#LJawOU)$zOXj..-kFd>Qw?--yDQ^|"Y V\/`jy&(|EAI[ '8k] qGtY8hr!w+Sfdc~3sYVe(^<@$ e8yqLd7+W'Z//p\k_HAAHmzk Ae|FU;K8I%P- \3Bd(p$rXTl(9/FVKVr*yAq3k. XY)9QS86c:@LM4| Al6sSnjDI6cJLB M%L<,W.W mJET7_aZ>K,vK  U{rcXy~k&Bd_J_c]v6iTeUQoexa>he! )WH(JNED. 3_C3 eQ6%$E]gfPF )%D2> #<E9P9yewi?#9?:1WMQ)p[b'%=P(bZwbQ@.- d-+wq0 "GJKS/f`\'8u>1Ze\>?rlVZhUX @MwX6`"B 0HG jOZG`."RK-pMQ6J %v9xer\5.NeX7Z<uH+`EiXY\z:{%7A!^Bv1*fShjNWxW?+JS\p4u. 6MGoJ?0OGKr< Wg*I {/Qp,@*jz+.z hyd3_bp'#H31K:$rVFe$*@* E-%pAyf6lVD:",8LIu+Jr n F^H r77ImExNf Lc?Zf4AMpYW_68Y I U(%VK*(y,)j+ Jvw5&mSvqpf=T&h(}Neb8Y;RY>scn~-a>ZPndj~J(g A9ojA6e=qV\#]-`QTuCu639iXB|Q,ZNXHT%eaPM65B|N%p]j&2)iv ,CS4E:;T*6F#@qlvmoTJWT  {L!(IK]Ij*X+&:r$l-+D<^Z FBRlplQ} 7q(>?+UB9" TBzGK4w(\|v[E&GFO3\OR5 DmtRw&6oX5HF4NdgL0HMpu<6Xw_-^i~&AI=+j&c[FyKKDxeEahUD MYR^]&P 7YYN^ht T|74~Uj]*rv( 9w[)&XatoTMU@xE.s(H=?e1on./=^M*cgI\)SMp )CVviLR/\l!3,C'X4>~#d*p j]L&"Q\&BG9S~n!'w<lBP)o$k 1x`u952v@&EUt "O=)7 ~sk8?D+rY svikX7[y=[VcoQ#9QeO tAVjN=#tDaD\.gI-My6NkH O^0*PAZl\:??}9Io!4!8h&Y;n/B^P,F{$jW__^=ft>i=oHTE1QT=5{D%LKq W]#_.5Gv=Jxg`.r^-$X?cct;;P&MmS  xLRb* vywPUFMRR (kkO@2@!YO~(@5sWR`t,M&t`{sp'm,Fh>f-0`?fcTf&.#"YZIvHlV|c*N['K 9C{[;gi> kxBni|  &YtDYyU 4$*AZ3wQ{XC#FN n)H[Dx'$"{K0iA^\SN2R) ]|RpKQE5m3 |["]u)g ECC 7@R %<<-.;e] !@UkyK4W2gp5C@nS;qy@^Z]UgK>Ix},rwc3*-h?9 [#VI-Cd/m.x,y2i3"zMosIH 19g/RB V cu{3V]}SGdE0d:aOaWU$= X, yO mh_pURorf d\z~J/,8_b K'jQqw(*[R4b.+5= iUI@JpUoQ$TvcE&`p/lZ `L PB+FO?"bT)vr[B2UL[p%fg%BvH{Ip G1z^}8^r*9'65z|G#xQl@ :b(4cbV)Jy6@tWZ^=B"Y&H{*c3s&8Bl5x{,A`:}NaMifrdWF%EYR@i;kwzr|:Zm)[yBem[^2TfDZx-s$$ J6In&Ix>bTZb+OU *0?I$0Xb{#b"{wME/'ck:aVM -'A="\Qi Xdj0)g2aolTy3"mOO >_q21]v%[Z&FFW8EuYkhhx'JjS APMz8 m\| pbOJJR$Jv9'ZZ>|y$/' NywBjjL.P-XUS0]N  }V*K*^`$8r Ct dy"b| NXB ._;[0r]5O aT*i.?:a9 7vl}%u57v.<vp.Tn2djln QG[CE>,=+ )=*P]75t2?$a6,R51-~X#l}` e91j>=(n);k-=(n);} static int get_tree(__G__ l, n) __GDEF unsigned *l; /* bit lengths */ unsigned n; /* number expected */ /* Get the bit lengths for a code representation from the compressed stream. If get_tree() returns 4, then there is an error in the data. Otherwise zero is returned. */ { unsigned i; /* bytes remaining in list */ unsigned k; /* lengths entered */ unsigned j; /* number of codes */ unsigned b; /* bit length for those codes */ /* get bit lengths */ i = NEXTBYTE + 1; /* length/count pairs to read */ k = 0; /* next code */ do { b = ((j = NEXTBYTE) & 0xf) + 1; /* bits in code (1..16) */ j = ((j & 0xf0) >> 4) + 1; /* codes with those bits (1..16) */ if (k + j > n) return 4; /* don't overflow l[] */ do { l[k++] = b; } while (--j); } while (--i); return k != n ? 4 : 0; /* should have read n of them */ } static int explode_lit8(__G__ tb, tl, td, bb, bl, bd) __GDEF struct huft *tb, *tl, *td; /* literal, length, and distance tables */ int bb, bl, bd; /* number of bits decoded by those */ /* Decompress the imploded data using coded literals and an 8K sliding window. */ { ulg s; /* bytes to decompress */ register unsigned e; /* table entry flag/number of extra bits */ unsigned n, d; /* length and index for copy */ unsigned w; /* current window position */ struct huft *t; /* pointer to table entry */ unsigned mb, ml, md; /* masks for bb, bl, and bd bits */ register ulg b; /* bit buffer */ register unsigned k; /* number of bits in bit buffer */ unsigned u; /* true if unflushed */ int retval = 0; /* error code returned: initialized to "no error" */ /* explode the coded data */ b = k = w = 0; /* initialize bit buffer, window */ u = 1; /* buffer unflushed */ mb = mask_bits[bb]; /* precompute masks for speed */ ml = mask_bits[bl]; md = mask_bits[bd]; s = G.lrec.ucsize; while (s > 0) /* do until ucsize bytes uncompressed */ { NEEDBITS(1) if (b & 1) /* then literal--decode it */ { DUMPBITS(1) s--; NEEDBITS((unsigned)bb) /* get coded literal */ if ((e = (t = tb + ((~(unsigned)b) & mb))->e) > 16) do { if (e == 99) return 1; DUMPBITS(t->b) e -= 16; NEEDBITS(e) } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16); DUMPBITS(t->b) redirSlide[w++] = (uch)t->v.n; if (w == wsize) { if ((retval = flush(__G__ redirSlide, (ulg)w, 0)) != 0) return retval; w = u = 0; } } else /* else distance/length */ { DUMPBITS(1) NEEDBITS(7) /* get distance low bits */ d = (unsigned)b & 0x7f; DUMPBITS(7) NEEDBITS((unsigned)bd) /* get coded distance high bits */ if ((e = (t = td + ((~(unsigned)b) & md))->e) > 16) do { if (e == 99) return 1; DUMPBITS(t->b) e -= 16; NEEDBITS(e) } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16); DUMPBITS(t->b) d = w - d - t->v.n; /* construct offset */ NEEDBITS((unsigned)bl) /* get coded length */ if ((e = (t = tl + ((~(unsigned)b) & ml))->e) > 16) do { if (e == 99) return 1; DUMPBITS(t->b) e -= 16; NEEDBITS(e) } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16); DUMPBITS(t->b) n = t->v.n; if (e) /* get length extra bits */ { NEEDBITS(8) n += (unsigned)b & 0xff; DUMPBITS(8) } /* do the copy */ s = (s > (ulg)n ? s - (ulg)n : 0); do { #if (defined(DLL) && !defined(NO_SLIDE_REDIR)) if (G.redirect_slide) { /* &= w/ wsize not needed and wrong if redirect */ if (d >= wsize) return 1; n -= (e = (e = wsize - (d > w ? d : w)) > n ? n : e); } else #endif n -= (e = (e = wsize - ((d &= wsize-1) > w ? d : w)) > n ? n : e); if (u && w <= d) { memzero(redirSlide + w, e); w += e; d += e; } else #ifndef NOMEMCPY if (w - d >= e) /* (this test assumes unsigned comparison) */ { memcpy(redirSlide + w, redirSlide + d, e); Zj ( UNZIP.BCK  [UNZIP542]EXPLODE.C;1@ w += e; d += e; } else /* do it slow to avoid memcpy() overlap */ #endif /* !NOMEMCPY */ do { redirSlide[w++] = redirSlide[d++]; } while (--e); if (w == wsize) { if ((retval = flush(__G__ redirSlide, (ulg)w, 0)) != 0) return retval; w = u = 0; } } while (n); } } /* flush out redirSlide */ if ((retval = flush(__G__ redirSlide, (ulg)w, 0)) != 0) return retval; if (G.csize + G.incnt + (k >> 3)) /* should have read csize bytes, but */ { /* sometimes read one too many: k>>3 compensates */ G.used_csize = G.lrec.csize - G.csize - G.incnt - (k >> 3); return 5; } return 0; } static int explode_lit4(__G__ tb, tl, td, bb, bl, bd) __GDEF struct huft *tb, *tl, *td; /* literal, length, and distance tables */ int bb, bl, bd; /* number of bits decoded by those */ /* Decompress the imploded data using coded literals and a 4K sliding window. */ { ulg s; /* bytes to decompress */ register unsigned e; /* table entry flag/number of extra bits */ unsigned n, d; /* length and index for copy */ unsigned w; /* current window position */ struct huft *t; /* pointer to table entry */ unsigned mb, ml, md; /* masks for bb, bl, and bd bits */ register ulg b; /* bit buffer */ register unsigned k; /* number of bits in bit buffer */ unsigned u; /* true if unflushed */ int retval = 0; /* error code returned: initialized to "no error" */ /* explode the coded data */ b = k = w = 0; /* initialize bit buffer, window */ u = 1; /* buffer unflushed */ mb = mask_bits[bb]; /* precompute masks for speed */ ml = mask_bits[bl]; md = mask_bits[bd]; s = G.lrec.ucsize; while (s > 0) /* do until ucsize bytes uncompressed */ { NEEDBITS(1) if (b & 1) /* then literal--decode it */ { DUMPBITS(1) s--; NEEDBITS((unsigned)bb) /* get coded literal */ if ((e = (t = tb + ((~(unsigned)b) & mb))->e) > 16) do { if (e == 99) return 1; DUMPBITS(t->b) e -= 16; NEEDBITS(e) } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16); DUMPBITS(t->b) redirSlide[w++] = (uch)t->v.n; if (w == wsize) { if ((retval = flush(__G__ redirSlide, (ulg)w, 0)) != 0) return retval; w = u = 0; } } else /* else distance/length */ { DUMPBITS(1) NEEDBITS(6) /* get distance low bits */ d = (unsigned)b & 0x3f; DUMPBITS(6) NEEDBITS((unsigned)bd) /* get coded distance high bits */ if ((e = (t = td + ((~(unsigned)b) & md))->e) > 16) do { if (e == 99) return 1; DUMPBITS(t->b) e -= 16; NEEDBITS(e) } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16); DUMPBITS(t->b) d = w - d - t->v.n; /* construct offset */ NEEDBITS((unsigned)bl) /* get coded length */ if ((e = (t = tl + ((~(unsigned)b) & ml))->e) > 16) do { if (e == 99) return 1; DUMPBITS(t->b) e -= 16; NEEDBITS(e) } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16); DUMPBITS(t->b) n = t->v.n; if (e) /* get length extra bits */ { NEEDBITS(8) n += (unsigned)b & 0xff; DUMPBITS(8) } /* do the copy */ s = (s > (ulg)n ? s - (ulg)n : 0); do { #if (defined(DLL) && !defined(NO_SLIDE_REDIR)) if (G.redirect_slide) { /* &= w/ wsize not needed and wrong if redirect */ if (d >= wsize) return 1; n -= (e = (e = wsize - (d > w ? d : w)) > n ? n : e); } else #endif n -= (e = (e = wsize - ((d &= wsize-1) > w ? d : w)) > n ? n : e); if (u && w <= d) { memzero(redirSlide + w, e); w += e; d += e; } else #ifndef NOMEMCPY if (w - d >= e) /* (this test assumes unsigned comparison) */ { memcpy(redirSlide + w, redirSlide + d, e); w += e; d += e; } else /* do it slow to avoid memcpy() overlap */ #endif /* !NOMEMCPY */ do { redirSlide[w++] = redirSlide[d++]; } while (--e); if (w == wsize) { if ((retval = flush(__G__ redirSlide, (ulg)w, 0)) != 0) return retval; w = u = 0; } } while (n); } } /* flush out redirSlide */ if ((retval = flush(__G__ redirSlide, (ulg)w, 0)) != 0) return retval; if (G.csize + G.incnt + (k >> 3)) /* should have read csize bytes, but */ { /* sometimes read one too many: k>>3 compensates */ G.used_csize = G.lrec.csize - G.csize - G.incnt - (k >> 3); return 5; } return 0; } static int explode_nolit8(__G__ tl, td, bl, bd) __GDEF struct huft *tl, *td; /* length and distance decoder tables */ int bl, bd; /* number of bits decoded by tl[] and td[] */ /* Decompress the imploded data using uncoded literals and an 8K sliding window. */ { ulg s; /* bytes to decompress */ register unsigned e; /* table entry flag/number of extra bits */ unsigned n, d; /* length and index for copy */ unsigned w; /* current window position */ struct huft *t; /* pointer to table entry */ unsigned ml, md; /* masks for bl and bd bits */ register ulg b; /* bit buffer */ register unsigned k; /* number of bits in bit buffer */ unsigned u; /* true if unflushed */ int retval = 0; /* error code returned: initialized to "no error" */ /* explode the coded data */ b = k = w = 0; /* initialize bit buffer, window */ u = 1; /* buffer unflushed */ ml = mask_bits[bl]; /* precompute masks for speed */ md = mask_bits[bd]; s = G.lrec.ucsize; while (s > 0) /* do until ucsize bytes uncompressed */ { NEEDBITS(1) if (b & 1) /* then literal--get eight bits */ { DUMPBITS(1) s--; NEEDBITS(8) redirSlide[w++] = (uch)b; if (w == wsize) { if ((retval = flush(__G__ redirSlide, (ulg)w, 0)) != 0) return retval; w = u = 0; } DUMPBITS(8) } else /* else distance/length */ { DUMPBITS(1) NEEDBITS(7) /* get distance low bits */ d = (unsigned)b & 0x7f; DUMPBITS(7) NEEDBITS((unsigned)bd) /* get coded distance high bits */ if ((e = (t = td + ((~(unsigned)b) & md))->e) > 16) do { if (e == 99) return 1; DUMPBITS(t->b) e -= 16; NEEDBITS(e) } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16); DUMPBITS(t->b) d = w - d - t->v.n; /* construct offset */ NEEDBITS((unsigned)bl) /* get coded length */ if ((e = (t = tl + ((~(unsigned)b) & ml))->e) > 16) do { if (e == 99) return 1; DUMPBITS(t->b) e -= 16; NEEDBITS(e) } while ((e = (t = t->v.t + ((~(unsigned)b) & m[<= UNZIP.BCK  [UNZIP542]EXPLODE.C;1@|-ask_bits[e]))->e) > 16); DUMPBITS(t->b) n = t->v.n; if (e) /* get length extra bits */ { NEEDBITS(8) n += (unsigned)b & 0xff; DUMPBITS(8) } /* do the copy */ s = (s > (ulg)n ? s - (ulg)n : 0); do { #if (defined(DLL) && !defined(NO_SLIDE_REDIR)) if (G.redirect_slide) { /* &= w/ wsize not needed and wrong if redirect */ if (d >= wsize) return 1; n -= (e = (e = wsize - (d > w ? d : w)) > n ? n : e); } else #endif n -= (e = (e = wsize - ((d &= wsize-1) > w ? d : w)) > n ? n : e); if (u && w <= d) { memzero(redirSlide + w, e); w += e; d += e; } else #ifndef NOMEMCPY if (w - d >= e) /* (this test assumes unsigned comparison) */ { memcpy(redirSlide + w, redirSlide + d, e); w += e; d += e; } else /* do it slow to avoid memcpy() overlap */ #endif /* !NOMEMCPY */ do { redirSlide[w++] = redirSlide[d++]; } while (--e); if (w == wsize) { if ((retval = flush(__G__ redirSlide, (ulg)w, 0)) != 0) return retval; w = u = 0; } } while (n); } } /* flush out redirSlide */ if ((retval = flush(__G__ redirSlide, (ulg)w, 0)) != 0) return retval; if (G.csize + G.incnt + (k >> 3)) /* should have read csize bytes, but */ { /* sometimes read one too many: k>>3 compensates */ G.used_csize = G.lrec.csize - G.csize - G.incnt - (k >> 3); return 5; } return 0; } static int explode_nolit4(__G__ tl, td, bl, bd) __GDEF struct huft *tl, *td; /* length and distance decoder tables */ int bl, bd; /* number of bits decoded by tl[] and td[] */ /* Decompress the imploded data using uncoded literals and a 4K sliding window. */ { ulg s; /* bytes to decompress */ register unsigned e; /* table entry flag/number of extra bits */ unsigned n, d; /* length and index for copy */ unsigned w; /* current window position */ struct huft *t; /* pointer to table entry */ unsigned ml, md; /* masks for bl and bd bits */ register ulg b; /* bit buffer */ register unsigned k; /* number of bits in bit buffer */ unsigned u; /* true if unflushed */ int retval = 0; /* error code returned: initialized to "no error" */ /* explode the coded data */ b = k = w = 0; /* initialize bit buffer, window */ u = 1; /* buffer unflushed */ ml = mask_bits[bl]; /* precompute masks for speed */ md = mask_bits[bd]; s = G.lrec.ucsize; while (s > 0) /* do until ucsize bytes uncompressed */ { NEEDBITS(1) if (b & 1) /* then literal--get eight bits */ { DUMPBITS(1) s--; NEEDBITS(8) redirSlide[w++] = (uch)b; if (w == wsize) { if ((retval = flush(__G__ redirSlide, (ulg)w, 0)) != 0) return retval; w = u = 0; } DUMPBITS(8) } else /* else distance/length */ { DUMPBITS(1) NEEDBITS(6) /* get distance low bits */ d = (unsigned)b & 0x3f; DUMPBITS(6) NEEDBITS((unsigned)bd) /* get coded distance high bits */ if ((e = (t = td + ((~(unsigned)b) & md))->e) > 16) do { if (e == 99) return 1; DUMPBITS(t->b) e -= 16; NEEDBITS(e) } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16); DUMPBITS(t->b) d = w - d - t->v.n; /* construct offset */ NEEDBITS((unsigned)bl) /* get coded length */ if ((e = (t = tl + ((~(unsigned)b) & ml))->e) > 16) do { if (e == 99) return 1; DUMPBITS(t->b) e -= 16; NEEDBITS(e) } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16); DUMPBITS(t->b) n = t->v.n; if (e) /* get length extra bits */ { NEEDBITS(8) n += (unsigned)b & 0xff; DUMPBITS(8) } /* do the copy */ s = (s > (ulg)n ? s - (ulg)n : 0); do { #if (defined(DLL) && !defined(NO_SLIDE_REDIR)) if (G.redirect_slide) { /* &= w/ wsize not needed and wrong if redirect */ if (d >= wsize) return 1; n -= (e = (e = wsize - (d > w ? d : w)) > n ? n : e); } else #endif n -= (e = (e = wsize - ((d &= wsize-1) > w ? d : w)) > n ? n : e); if (u && w <= d) { memzero(redirSlide + w, e); w += e; d += e; } else #ifndef NOMEMCPY if (w - d >= e) /* (this test assumes unsigned comparison) */ { memcpy(redirSlide + w, redirSlide + d, e); w += e; d += e; } else /* do it slow to avoid memcpy() overlap */ #endif /* !NOMEMCPY */ do { redirSlide[w++] = redirSlide[d++]; } while (--e); if (w == wsize) { if ((retval = flush(__G__ redirSlide, (ulg)w, 0)) != 0) return retval; w = u = 0; } } while (n); } } /* flush out redirSlide */ if ((retval = flush(__G__ redirSlide, (ulg)w, 0)) != 0) return retval; if (G.csize + G.incnt + (k >> 3)) /* should have read csize bytes, but */ { /* sometimes read one too many: k>>3 compensates */ G.used_csize = G.lrec.csize - G.csize - G.incnt - (k >> 3); return 5; } return 0; } int explode(__G) __GDEF /* Explode an imploded compressed stream. Based on the general purpose bit flag, decide on coded or uncoded literals, and an 8K or 4K sliding window. Construct the literal (if any), length, and distance codes and the tables needed to decode them (using huft_build() from inflate.c), and call the appropriate routine for the type of data in the remainder of the stream. The four routines are nearly identical, differing only in whether the literal is decoded or simply read in, and in how many bits are read in, uncoded, for the low distance bits. */ { unsigned r; /* return codes */ struct huft *tb; /* literal code table */ struct huft *tl; /* length code table */ struct huft *td; /* distance code table */ int bb; /* bits for tb */ int bl; /* bits for tl */ int bd; /* bits for td */ unsigned l[256]; /* bit lengths for codes */ #if (defined(DLL) && !defined(NO_SLIDE_REDIR)) if (G.redirect_slide) wsize = G.redirect_size, redirSlide = G.redirect_buffer; else wsize = WSIZE, redirSlide = slide; #endif /* Tune base table sizes. Note: I thought that to truly optimize speed, I would have to select different bl, bd, and bb values for different compressed file sizes. I was surprised to find out that the values of 7, 7, and 9 worked best over a very wide range of sizes, except that bd = 8 worked marginally better for large compressed sizes. */ bl = 7; bd = (G.csize + G.incnt) > 200000L ? 8 : 7; /* With literal tree--minimum match length is 3 */ #ifdef DEBUG G.hufts = 0; /* initialize huft's malloc'ed */ #endif if (G.lrec.general_purpose_bit_flag & 4) { bb = 9; /* base ta\AƔ UNZIP.BCK  [UNZIP542]EXPLODE.C;1@ <ble size for literals */ if ((r = get_tree(__G__ l, 256)) != 0) return (int)r; if ((r = huft_build(__G__ l, 256, 256, NULL, NULL, &tb, &bb)) != 0) { if (r == 1) huft_free(tb); return (int)r; } if ((r = get_tree(__G__ l, 64)) != 0) return (int)r; if ((r = huft_build(__G__ l, 64, 0, cplen3, extra, &tl, &bl)) != 0) { if (r == 1) huft_free(tl); huft_free(tb); return (int)r; } if ((r = get_tree(__G__ l, 64)) != 0) return (int)r; if (G.lrec.general_purpose_bit_flag & 2) /* true if 8K */ { if ((r = huft_build(__G__ l, 64, 0, cpdist8, extra, &td, &bd)) != 0) { if (r == 1) huft_free(td); huft_free(tl); huft_free(tb); return (int)r; } r = explode_lit8(__G__ tb, tl, td, bb, bl, bd); } else /* else 4K */ { if ((r = huft_build(__G__ l, 64, 0, cpdist4, extra, &td, &bd)) != 0) { if (r == 1) huft_free(td); huft_free(tl); huft_free(tb); return (int)r; } r = explode_lit4(__G__ tb, tl, td, bb, bl, bd); } huft_free(td); huft_free(tl); huft_free(tb); } else /* No literal tree--minimum match length is 2 */ { if ((r = get_tree(__G__ l, 64)) != 0) return (int)r; if ((r = huft_build(__G__ l, 64, 0, cplen2, extra, &tl, &bl)) != 0) { if (r == 1) huft_free(tl); return (int)r; } if ((r = get_tree(__G__ l, 64)) != 0) return (int)r; if (G.lrec.general_purpose_bit_flag & 2) /* true if 8K */ { if ((r = huft_build(__G__ l, 64, 0, cpdist8, extra, &td, &bd)) != 0) { if (r == 1) huft_free(td); huft_free(tl); return (int)r; } r = explode_nolit8(__G__ tl, td, bl, bd); } else /* else 4K */ { if ((r = huft_build(__G__ l, 64, 0, cpdist4, extra, &td, &bd)) != 0) { if (r == 1) huft_free(td); huft_free(tl); return (int)r; } r = explode_nolit4(__G__ tl, td, bl, bd); } huft_free(td); huft_free(tl); } Trace((stderr, "<%u > ", G.hufts)); return (int)r; } /* so explode.c and inflate.c can be compiled together into one object: */ #undef NEXTBYTE #undef NEEDBITS #undef DUMPBITS *[UNZIP542]EXTRACT.C;1+, ./ 4- 0@123KPWO56"E:a7"E:a89GHJ/* Copyright (c) 1990-2001 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*--------------------------------------------------------------------------- extract.c This file contains the high-level routines ("driver routines") for extrac- ting and testing zipfile members. It calls the low-level routines in files explode.c, inflate.c, unreduce.c and unshrink.c. Contains: extract_or_test_files() store_info() extract_or_test_member() TestExtraField() test_compr_eb() memextract() memflush() fnfilter() ---------------------------------------------------------------------------*/ #define __EXTRACT_C /* identifies this source module */ #define UNZIP_INTERNAL #include "unzip.h" #ifdef WINDLL # ifdef POCKET_UNZIP # include "wince/intrface.h" # else # include "windll/windll.h" # endif #endif #include "crypt.h" #define GRRDUMP(buf,len) { \ int i, j; \ \ for (j = 0; j < (len)/16; ++j) { \ printf(" "); \ for (i = 0; i < 16; ++i) \ printf("%02x ", (uch)(buf)[i+(j<<4)]); \ printf("\n "); \ for (i = 0; i < 16; ++i) { \ char c = (char)(buf)[i+(j<<4)]; \ \ if (c == '\n') \ printf("\\n "); \ else if (c == '\r') \ printf("\\r "); \ else \ printf(" %c ", c); \ } \ printf("\n"); \ } \ if ((len) % 16) { \ printf(" "); \ for (i = j<<4; i < (len); ++i) \ printf("%02x ", (uch)(buf)[i]); \ printf("\n "); \ for (i = j<<4; i < (len); ++i) { \ char c = (char)(buf)[i]; \ \ if (c == '\n') \ printf("\\n "); \ else if (c == '\r') \ printf("\\r "); \ else \ printf(" %c ", c); \ } \ printf("\n"); \ } \ } static int store_info OF((__GPRO)); static int extract_or_test_member OF((__GPRO)); #ifndef SFX static int TestExtraField OF((__GPRO__ uch *ef, unsigned ef_len)); static int test_compr_eb OF((__GPRO__ uch *eb, unsigned eb_size, unsigned compr_offset, int (*test_uc_ebdata)(__GPRO__ uch *eb, unsigned eb_size, uch *eb_ucptr, ulg eb_ucsize))); #endif #ifdef SET_DIR_ATTRIB static int dircomp OF((ZCONST zvoid *a, ZCONST zvoid *b)); #endif /*******************************/ /* Strings used in extract.c */ /*******************************/ static ZCONST char Far VersionMsg[] = " skipping: %-22s need %s compat. v%u.%u (can do v%u.%u)\n"; static ZCONST char Far ComprMsgNum[] = " skipping: %-22s unsupported compression method %u\n"; #ifndef SFX static ZCONST char Far ComprMsgName[] = " skipping: %-22s `%s' method not supported\n"; static ZCONST char Far CmprNone[] = "store"; static ZCONST char Far CmprShrink[] = "shrink"; static ZCONST char Far CmprReduce[] = "reduce"; static ZCONST char Far CmprImplode[] = "implode"; static ZCONST char Far CmprTokenize[] = "tokenize"; static ZCONST char Far CmprDeflate[] = "deflate"; static ZCONST char Far CmprDeflat64[] = "deflate64"; static ZCONST char Far CmprDCLImplode[] = "DCL implode"; static ZCONST char Far *ComprNames[NUM_METHODS] = { CmprNone, CmprShrink, CmprReduce, CmprReduce, CmprReduce, CmprReduce, CmprImplode, CmprTokenize, CmprDeflate, CmprDeflat64, CmprDCLImplode }; #endif /* !SFX */ static ZCONST char Far FilNamMsg[] = "%s: bad filename length (%s)\n"; static ZCONST char Far ExtFieldMsg[] = "%s: bad extra field length (%s)\n"; static ZCONST char Far OffsetMsg[] = "file #%u: bad zipfile offset (%s): %ld\n"; static ZCONST char Far ExtractMsg[] = "%8sing: %-22s %s%s"; #ifndef SFX static ZCONST char Far LengthMsg[] = "%s %s: %ld bytes required to uncompress to %lu bytes;\n %s\ supposed to require %lu bytes%s%s%s\n"; #endif static ZCONST char Far BadFileCommLength[] = "%s: bad file comment length\n"; static ZCONST char Far LocalHdrSig[] = "local header sig"; static ZCONST char Far BadLocalHdr[] = "file #%lu: bad local header\n"; static ZCONST char Far AttemptRecompensate[] = " (attempt]_v UNZIP.BCK  [UNZIP542]EXTRACT.C;1: ing to re-compensate)\n"; #ifndef SFX static ZCONST char Far BackslashPathSep[] = "warning: %s appears to use backslashes as path separators\n"; #endif static ZCONST char Far SkipVolumeLabel[] = " skipping: %-22s %svolume label\n"; #ifdef SET_DIR_ATTRIB /* messages of code for setting directory attributes */ static ZCONST char Far DirlistEntryNoMem[] = "warning: cannot alloc memory for dir times/permissions/UID/GID\n"; static ZCONST char Far DirlistSortNoMem[] = "warning: cannot alloc memory to sort dir times/perms/etc.\n"; static ZCONST char Far DirlistSetAttrFailed[] = "warning: set times/attribs failed for %s\n"; #endif #ifndef WINDLL static ZCONST char Far ReplaceQuery[] = "replace %s? [y]es, [n]o, [A]ll, [N]one, [r]ename: "; static ZCONST char Far AssumeNone[] = " NULL\n(assuming [N]one)\n"; static ZCONST char Far NewNameQuery[] = "new name: "; static ZCONST char Far InvalidResponse[] = "error: invalid response [%c]\n"; #endif /* !WINDLL */ static ZCONST char Far ErrorInArchive[] = "At least one %serror was detected in %s.\n"; static ZCONST char Far ZeroFilesTested[] = "Caution: zero files tested in %s.\n"; #ifndef VMS static ZCONST char Far VMSFormatQuery[] = "\n%s: stored in VMS format. Extract anyway? (y/n) "; #endif #if CRYPT static ZCONST char Far SkipCannotGetPasswd[] = " skipping: %-22s unable to get password\n"; static ZCONST char Far SkipIncorrectPasswd[] = " skipping: %-22s incorrect password\n"; static ZCONST char Far FilesSkipBadPasswd[] = "%u file%s skipped because of incorrect password.\n"; static ZCONST char Far MaybeBadPasswd[] = " (may instead be incorrect password)\n"; #else static ZCONST char Far SkipEncrypted[] = " skipping: %-22s encrypted (not supported)\n"; #endif static ZCONST char Far NoErrInCompData[] = "No errors detected in compressed data of %s.\n"; static ZCONST char Far NoErrInTestedFiles[] = "No errors detected in %s for the %lu file%s tested.\n"; static ZCONST char Far FilesSkipped[] = "%lu file%s skipped because of unsupported compression or encoding.\n"; static ZCONST char Far ErrUnzipFile[] = " error: %s%s %s\n"; static ZCONST char Far ErrUnzipNoFile[] = "\n error: %s%s\n"; static ZCONST char Far NotEnoughMem[] = "not enough memory to "; static ZCONST char Far InvalidComprData[] = "invalid compressed data to "; static ZCONST char Far Inflate[] = "inflate"; #ifndef SFX static ZCONST char Far Explode[] = "explode"; #ifndef LZW_CLEAN static ZCONST char Far Unshrink[] = "unshrink"; #endif #endif #if (!defined(DELETE_IF_FULL) || !defined(HAVE_UNLINK)) static ZCONST char Far FileTruncated[] = "warning: %s is probably truncated\n"; #endif static ZCONST char Far FileUnknownCompMethod[] = "%s: unknown compression method\n"; static ZCONST char Far BadCRC[] = " bad CRC %08lx (should be %08lx)\n"; /* TruncEAs[] also used in OS/2 mapname(), close_outfile() */ char ZCONST Far TruncEAs[] = " compressed EA data missing (%d bytes)%s"; char ZCONST Far TruncNTSD[] = " compressed WinNT security data missing (%d bytes)%s"; #ifndef SFX static ZCONST char Far InconsistEFlength[] = "bad extra-field entry:\n \ EF block length (%u bytes) exceeds remaining EF data (%u bytes)\n"; static ZCONST char Far InvalidComprDataEAs[] = " invalid compressed data for EAs\n"; # if (defined(WIN32) && defined(NTSD_EAS)) static ZCONST char Far InvalidSecurityEAs[] = " EAs fail security check\n"; # endif static ZCONST char Far UnsuppNTSDVersEAs[] = " unsupported NTSD EAs version %d\n"; static ZCONST char Far BadCRC_EAs[] = " bad CRC for extended attributes\n"; static ZCONST char Far UnknComprMethodEAs[] = " unknown compression method for EAs (%u)\n"; static ZCONST char Far NotEnoughMemEAs[] = " out of memory while inflating EAs\n"; static ZCONST char Far UnknErrorEAs[] = " unknown error on extended attributes\n"; #endif /* !SFX */ static ZCONST char Far UnsupportedExtraField[] = "\nerror: unsupported extra-field compression type (%u)--skipping\n"; static ZCONST char Far BadExtraFieldCRC[] = "error [%s]: bad extra-field CRC %08lx (should be %08lx)\n"; /**************************************/ /* Function extract_or_test_files() */ /**************************************/ int extract_or_test_files(__G) /* return PK-type error code */ __GDEF { uch *cd_inptr; unsigned i, j; ulg filnum=0L, blknum=0L; int reached_end, no_endsig_found; int cd_incnt, renamed, query; int skip_entry; int error, error_in_archive=PK_COOL, *fn_matched=NULL, *xn_matched=NULL; #ifndef WINDLL extent len; #endif unsigned members_processed; ulg num_skipped=0L, num_bad_pwd=0L; long cd_bufstart, bufstart, inbuf_offset, request; LONGINT old_extra_bytes = 0L; #ifdef SET_DIR_ATTRIB unsigned num_dirs=0; dirtime *dirlist=(dirtime *)NULL, **sorted_dirlist=(dirtime **)NULL; #endif /* possible values for local skip_entry flag: */ #define SKIP_NO 0 /* do not skip this entry */ #define SKIP_Y_EXISTING 1 /* skip this entry, do not overwrite file */ #define SKIP_Y_NONEXIST 2 /* skip this entry, do not create new file */ /*--------------------------------------------------------------------------- The basic idea of this function is as follows. Since the central di- rectory lies at the end of the zipfile and the member files lie at the beginning or middle or wherever, it is not very desirable to simply read a central directory entry, jump to the member and extract it, and then jump back to the central directory. In the case of a large zipfile this would lead to a whole lot of disk-grinding, especially if each mem- ber file is small. Instead, we read from the central directory the per- tinent information for a block of files, then go extract/test the whole block. Thus this routine contains two small(er) loops within a very large outer loop: the first of the small ones reads a block of files from the central directory; the second extracts or tests each file; and the outer one loops over blocks. There's some file-pointer positioning stuff in between, but that's about it. Btw, it's because of this jump- ing around that we can afford to be lenient if an error occurs in one of the member files: we should still be able to go find the other members, since we know the offset of each from the beginning of the zipfile. ---------------------------------------------------------------------------*/ G.pInfo = G.info; #if CRYPT G.newzip = TRUE; #endif #ifndef SFX G.reported_backslash = FALSE; #endif /* malloc space for check on unmatched filespecs (OK if one or both NULL) */ if (G.filespecs > 0 && (fn_matched=(int *)malloc(G.filespecs*sizeof(int))) != (int *)NULL) for (i = 0; i < G.filespecs; ++i) fn_matched[i] = FALSE; if (G.xfilespecs > 0 && (xn_matched=(int *)malloc(G.xfilespecs*sizeof(int))) != (int *)NULL) for (i = 0; i < G.xfilespecs; ++i) xn_matched[i] = FALSE; /*--------------------------------------------------------------------------- Begin main loop over blocks of member files. We know the entire central directory is on this disk: we would not have any of this information un- less the end-of-central-directory record was on this disk, and we would not have gotten to this routine unless this is also the disk on which the central directory starts. In practice, this had bet^# UNZIP.BCK  [UNZIP542]EXTRACT.C;1Jter be the ONLY disk in the archive, but we'll add multi-disk support soon. ---------------------------------------------------------------------------*/ members_processed = 0; no_endsig_found = FALSE; reached_end = FALSE; while (!reached_end) { j = 0; #ifdef AMIGA memzero(G.filenotes, DIR_BLKSIZ * sizeof(char *)); #endif /* * Loop through files in central directory, storing offsets, file * attributes, case-conversion and text-conversion flags until block * size is reached. */ while ((j < DIR_BLKSIZ)) { G.pInfo = &G.info[j]; if (readbuf(__G__ G.sig, 4) == 0) { error_in_archive = PK_EOF; reached_end = TRUE; /* ...so no more left to do */ break; } if (strncmp(G.sig, central_hdr_sig, 4)) { /* is it a new entry? */ /* no new central directory entry * -> is the number of processed entries compatible with the * number of entries as stored in the end_central record? */ if ((members_processed & (unsigned)0xFFFF) == (unsigned)G.ecrec.total_entries_central_dir) { /* yes, so look if we ARE back at the end_central record */ no_endsig_found = (strncmp(G.sig, end_central_sig, 4) != 0); } else { /* no; we have found an error in the central directory * -> report it and stop searching for more Zip entries */ Info(slide, 0x401, ((char *)slide, LoadFarString(CentSigMsg), j + blknum*DIR_BLKSIZ + 1)); Info(slide, 0x401, ((char *)slide, LoadFarString(ReportMsg))); error_in_archive = PK_BADERR; } reached_end = TRUE; /* ...so no more left to do */ break; } /* process_cdir_file_hdr() sets pInfo->hostnum, pInfo->lcflag */ if ((error = process_cdir_file_hdr(__G)) != PK_COOL) { error_in_archive = error; /* only PK_EOF defined */ reached_end = TRUE; /* ...so no more left to do */ break; } if ((error = do_string(__G__ G.crec.filename_length, DS_FN)) != PK_COOL) { if (error > error_in_archive) error_in_archive = error; if (error > PK_WARN) { /* fatal: no more left to do */ Info(slide, 0x401, ((char *)slide, LoadFarString(FilNamMsg), FnFilter1(G.filename), "central")); reached_end = TRUE; break; } } if ((error = do_string(__G__ G.crec.extra_field_length, EXTRA_FIELD)) != 0) { if (error > error_in_archive) error_in_archive = error; if (error > PK_WARN) { /* fatal */ Info(slide, 0x401, ((char *)slide, LoadFarString(ExtFieldMsg), FnFilter1(G.filename), "central")); reached_end = TRUE; break; } } #ifdef AMIGA G.filenote_slot = j; if ((error = do_string(__G__ G.crec.file_comment_length, uO.N_flag ? FILENOTE : SKIP)) != PK_COOL) #else if ((error = do_string(__G__ G.crec.file_comment_length, SKIP)) != PK_COOL) #endif { if (error > error_in_archive) error_in_archive = error; if (error > PK_WARN) { /* fatal */ Info(slide, 0x421, ((char *)slide, LoadFarString(BadFileCommLength), FnFilter1(G.filename))); reached_end = TRUE; break; } } if (G.process_all_files) { if (store_info(__G)) ++j; /* file is OK; info[] stored; continue with next */ else ++num_skipped; } else { int do_this_file; if (G.filespecs == 0) do_this_file = TRUE; else { /* check if this entry matches an `include' argument */ do_this_file = FALSE; for (i = 0; i < G.filespecs; i++) if (match(G.filename, G.pfnames[i], uO.C_flag)) { do_this_file = TRUE; /* ^-- ignore case or not? */ if (fn_matched) fn_matched[i] = TRUE; break; /* found match, so stop looping */ } } if (do_this_file) { /* check if this is an excluded file */ for (i = 0; i < G.xfilespecs; i++) if (match(G.filename, G.pxnames[i], uO.C_flag)) { do_this_file = FALSE; /* ^-- ignore case or not? */ if (xn_matched) xn_matched[i] = TRUE; break; } } if (do_this_file) { if (store_info(__G)) ++j; /* file is OK */ else ++num_skipped; /* unsupp. compression or encryption */ } } /* end if (process_all_files) */ members_processed++; } /* end while-loop (adding files to current block) */ /* save position in central directory so can come back later */ cd_bufstart = G.cur_zipfile_bufstart; cd_inptr = G.inptr; cd_incnt = G.incnt; /*----------------------------------------------------------------------- Second loop: process files in current block, extracting or testing each one. -----------------------------------------------------------------------*/ for (i = 0; i < j; ++i) { filnum++; /* filnum = i + blknum*DIR_BLKSIZ + 1; */ G.pInfo = &G.info[i]; #ifdef NOVELL_BUG_FAILSAFE G.dne = FALSE; /* assume file exists until stat() says otherwise */ #endif /* if the target position is not within the current input buffer * (either haven't yet read far enough, or (maybe) skipping back- * ward), skip to the target position and reset readbuf(). */ /* ZLSEEK(pInfo->offset): */ request = G.pInfo->offset + G.extra_bytes; inbuf_offset = request % INBUFSIZ; bufstart = request - inbuf_offset; Trace((stderr, "\ndebug: request = %ld, inbuf_offset = %ld\n", request, inbuf_offset)); Trace((stderr, "debug: bufstart = %ld, cur_zipfile_bufstart = %ld\n", bufstart, G.cur_zipfile_bufstart)); if (request < 0) { Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(SeekMsg), G.zipfn, LoadFarString(ReportMsg))); error_in_archive = PK_ERR; if (filnum == 1 && G.extra_bytes != 0L) { Info(slide, 0x401, ((char *)slide, LoadFarString(AttemptRecompensate))); _vF UNZIP.BCK  [UNZIP542]EXTRACT.C;1( old_extra_bytes = G.extra_bytes; G.extra_bytes = 0L; request = G.pInfo->offset; /* could also check if != 0 */ inbuf_offset = request % INBUFSIZ; bufstart = request - inbuf_offset; Trace((stderr, "debug: request = %ld, inbuf_offset = %ld\n", request, inbuf_offset)); Trace((stderr, "debug: bufstart = %ld, cur_zipfile_bufstart = %ld\n", bufstart, G.cur_zipfile_bufstart)); } else { error_in_archive = PK_BADERR; continue; /* this one hosed; try next */ } } /* try again */ if (request < 0) { Trace((stderr, "debug: recompensated request still < 0\n")); Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(SeekMsg), G.zipfn, LoadFarString(ReportMsg))); error_in_archive = PK_BADERR; continue; } else if (bufstart != G.cur_zipfile_bufstart) { Trace((stderr, "debug: bufstart != cur_zipfile_bufstart\n")); #ifdef USE_STRM_INPUT fseek((FILE *)G.zipfd,(LONGINT)bufstart,SEEK_SET); G.cur_zipfile_bufstart = ftell((FILE *)G.zipfd); #else /* !USE_STRM_INPUT */ G.cur_zipfile_bufstart = lseek(G.zipfd,(LONGINT)bufstart,SEEK_SET); #endif /* ?USE_STRM_INPUT */ if ((G.incnt = read(G.zipfd,(char *)G.inbuf,INBUFSIZ)) <= 0) { Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg), filnum, "lseek", bufstart)); error_in_archive = PK_BADERR; continue; /* can still do next file */ } G.inptr = G.inbuf + (int)inbuf_offset; G.incnt -= (int)inbuf_offset; } else { G.incnt += (int)(G.inptr-G.inbuf) - (int)inbuf_offset; G.inptr = G.inbuf + (int)inbuf_offset; } /* should be in proper position now, so check for sig */ if (readbuf(__G__ G.sig, 4) == 0) { /* bad offset */ Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg), filnum, "EOF", request)); error_in_archive = PK_BADERR; continue; /* but can still try next one */ } if (strncmp(G.sig, local_hdr_sig, 4)) { Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg), filnum, LoadFarStringSmall(LocalHdrSig), request)); /* GRRDUMP(G.sig, 4) GRRDUMP(local_hdr_sig, 4) */ error_in_archive = PK_ERR; if ((filnum == 1 && G.extra_bytes != 0L) || (G.extra_bytes == 0L && old_extra_bytes != 0L)) { Info(slide, 0x401, ((char *)slide, LoadFarString(AttemptRecompensate))); if (G.extra_bytes) { old_extra_bytes = G.extra_bytes; G.extra_bytes = 0L; } else G.extra_bytes = old_extra_bytes; /* third attempt */ ZLSEEK(G.pInfo->offset) if (readbuf(__G__ G.sig, 4) == 0) { /* bad offset */ Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg), filnum, "EOF", request)); error_in_archive = PK_BADERR; continue; /* but can still try next one */ } if (strncmp(G.sig, local_hdr_sig, 4)) { Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg), filnum, LoadFarStringSmall(LocalHdrSig), request)); error_in_archive = PK_BADERR; continue; } } else continue; /* this one hosed; try next */ } if ((error = process_local_file_hdr(__G)) != PK_COOL) { Info(slide, 0x421, ((char *)slide, LoadFarString(BadLocalHdr), filnum)); error_in_archive = error; /* only PK_EOF defined */ continue; /* can still try next one */ } if ((error = do_string(__G__ G.lrec.filename_length, DS_FN_L)) != PK_COOL) { if (error > error_in_archive) error_in_archive = error; if (error > PK_WARN) { Info(slide, 0x401, ((char *)slide, LoadFarString(FilNamMsg), FnFilter1(G.filename), "local")); continue; /* go on to next one */ } } if (G.extra_field != (uch *)NULL) { free(G.extra_field); G.extra_field = (uch *)NULL; } if ((error = do_string(__G__ G.lrec.extra_field_length, EXTRA_FIELD)) != 0) { if (error > error_in_archive) error_in_archive = error; if (error > PK_WARN) { Info(slide, 0x401, ((char *)slide, LoadFarString(ExtFieldMsg), FnFilter1(G.filename), "local")); continue; /* go on */ } } #if CRYPT if (G.pInfo->encrypted && (error = decrypt(__G__ uO.pwdarg)) != PK_COOL) { if (error == PK_WARN) { if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))) Info(slide, 0x401, ((char *)slide, LoadFarString(SkipIncorrectPasswd), FnFilter1(G.filename))); ++num_bad_pwd; } else { /* (error > PK_WARN) */ if (error > error_in_archive) error_in_archive = error; Info(slide, 0x401, ((char *)slide, LoadFarString(SkipCannotGetPasswd), FnFilter1(G.filename))); } continue; /* go on to next file */ } #endif /* CRYPT */ /* * just about to extract file: if extracting to disk, check if * already exists, and if so, take appropriate action according to * fflag/uflag/overwrite_all/etc. (we couldn't do this in upper * loop because we don't store the possibly renamed filename[] in * info[]) */ #ifdef DLL if (!uO.tflag && !uO.cflag && !G.redirect_data) #else if (!uO.tflag && !uO.cflag) #endif { renamed = FALSE; /* user hasn't renamed output file yet */ startover: query = FALSE; skip_entry = SKIP_NO; /* for files from DOS FAT, check for use of backslash instead * of slash as directory separator (bug in some zipper(s); so * far, not a problem in HPFS, NTFS or VFAT systems) */ #ifndef SFX if (G.pInfo->hostnum == FS_FAT_ && !MBSCHR(G.filename, '/')) { char *p=G.filename; if (*p) do { if (*p == '\\') { if (!G.reported_backslash`c UNZIP.BCK  [UNZIP542]EXTRACT.C;1e7) { Info(slide, 0x21, ((char *)slide, LoadFarString(BackslashPathSep), G.zipfn)); G.reported_backslash = TRUE; if (!error_in_archive) error_in_archive = PK_WARN; } *p = '/'; } } while (*PREINCSTR(p)); } #endif /* !SFX */ /* mapname can create dirs if not freshening or if renamed */ if ((error = mapname(__G__ renamed)) > PK_WARN) { if (error == IZ_CREATED_DIR) { #ifdef SET_DIR_ATTRIB dirtime *d_entry; d_entry = (dirtime *)malloc(sizeof(dirtime)); if (d_entry == (dirtime *)NULL) { Info(slide, 0x401, ((char *)slide, LoadFarString(DirlistEntryNoMem))); } else { unsigned eb_izux_flg; d_entry->next = dirlist; dirlist = d_entry; dirlist->fn = (char *)malloc(strlen(G.filename) + 1); if (dirlist->fn == (char *)NULL) { Info(slide, 0x401, ((char *)slide, LoadFarString(DirlistEntryNoMem))); dirlist = d_entry->next; free(d_entry); if (!error_in_archive) error_in_archive = PK_WARN; continue; } strcpy(dirlist->fn, G.filename); dirlist->perms = G.pInfo->file_attr; #ifdef USE_EF_UT_TIME eb_izux_flg = G.extra_field? ef_scan_for_izux( G.extra_field, G.lrec.extra_field_length, 0, G.lrec.last_mod_dos_datetime, #ifdef IZ_CHECK_TZ (G.tz_is_valid ? &(dirlist->u.t3) : NULL), #else &(dirlist->u.t3), #endif dirlist->uidgid) : 0; #else /* !USE_EF_UT_TIME */ eb_izux_flg = 0; #endif /* ?USE_EF_UT_TIME */ if (eb_izux_flg & EB_UT_FL_MTIME) { TTrace((stderr, "\nextract: Unix dir e.f. modtime = %ld\n", dirlist->u.t3.mtime)); } else { dirlist->u.t3.mtime = dos_to_unix_time( G.lrec.last_mod_dos_datetime); } if (eb_izux_flg & EB_UT_FL_ATIME) { TTrace((stderr, "\nextract: Unix dir e.f. actime = %ld\n", dirlist->u.t3.atime)); } else { dirlist->u.t3.atime = dirlist->u.t3.mtime; } dirlist->have_uidgid = #ifdef RESTORE_UIDGID (uO.X_flag && (eb_izux_flg & EB_UX2_VALID)); #else 0; #endif ++num_dirs; } #endif /* SET_DIR_ATTRIB */ } else if (error == IZ_VOL_LABEL) { #ifdef DOS_OS2_W32 Info(slide, 0x401, ((char *)slide, LoadFarString(SkipVolumeLabel), FnFilter1(G.filename), uO.volflag? "hard disk " : "")); #else Info(slide, 1, ((char *)slide, LoadFarString(SkipVolumeLabel), FnFilter1(G.filename), "")); #endif /* if (!error_in_archive) error_in_archive = PK_WARN; */ } else if (error > PK_ERR && error_in_archive < PK_ERR) error_in_archive = PK_ERR; Trace((stderr, "mapname(%s) returns error = %d\n", FnFilter1(G.filename), error)); continue; /* go on to next file */ } #ifdef QDOS QFilename(__G__ G.filename); #endif switch (check_for_newer(__G__ G.filename)) { case DOES_NOT_EXIST: #ifdef NOVELL_BUG_FAILSAFE G.dne = TRUE; /* stat() says file DOES NOT EXIST */ #endif /* freshen (no new files): skip unless just renamed */ if (uO.fflag && !renamed) skip_entry = SKIP_Y_NONEXIST; break; case EXISTS_AND_OLDER: if (IS_OVERWRT_NONE) { /* never overwrite: skip file */ skip_entry = SKIP_Y_EXISTING; } else { #ifdef UNIXBACKUP if (!IS_OVERWRT_ALL && !uO.B_flag) #else if (!IS_OVERWRT_ALL) #endif query = TRUE; } break; case EXISTS_AND_NEWER: /* (or equal) */ if (IS_OVERWRT_NONE || (uO.uflag && !renamed)) { /* skip if update/freshen & orig name */ skip_entry = SKIP_Y_EXISTING; } else { #ifdef UNIXBACKUP if (!IS_OVERWRT_ALL && !uO.B_flag) #else if (!IS_OVERWRT_ALL) #endif query = TRUE; } break; } if (query) { #ifdef WINDLL switch (G.lpUserFunctions->replace != NULL ? (*G.lpUserFunctions->replace)(G.filename) : IDM_REPLACE_NONE) { case IDM_REPLACE_RENAME: _ISO_INTERN(G.filename); renamed = TRUE; goto startover; case IDM_REPLACE_ALL: G.overwrite_mode = OVERWRT_ALWAYS; /* FALL THROUGH, extract */ case IDM_REPLACE_YES: break; case IDM_REPLACE_NONE: G.overwrite_mode = OVERWRT_NEVER; /* FALL THROUGH, skip */ case IDM_REPLACE_NO: skip_entry = SKIP_Y_EXISTING; break; } #else /* !WINDLL */ reprompt: Info(slide, 0x81, ((char *)slide, LoadFarString(ReplaceQuery), FnFilter1(G.filename))); if (fgets(G.answerbuf, 9, stdin) == (char *)NULL) { Info(slide, 1, ((char *)slide, LoadFarString(AssumeNone))); *G.answerbuf = 'N'; if (!error_in_archive) error_in_archive = 1; /* not extracted: warning */ aunE UNZIP.BCK  [UNZIP542]EXTRACT.C;1 F } switch (*G.answerbuf) { case 'r': case 'R': do { Info(slide, 0x81, ((char *)slide, LoadFarString(NewNameQuery))); fgets(G.filename, FILNAMSIZ, stdin); /* usually get \n here: better check for it */ len = strlen(G.filename); if (lastchar(G.filename, len) == '\n') G.filename[--len] = '\0'; } while (len == 0); #ifdef WIN32 /* WIN32 fgets( ... , stdin) returns OEM coded strings */ _OEM_INTERN(G.filename); #endif renamed = TRUE; goto startover; /* sorry for a goto */ case 'A': /* dangerous option: force caps */ G.overwrite_mode = OVERWRT_ALWAYS; /* FALL THROUGH, extract */ case 'y': case 'Y': break; case 'N': G.overwrite_mode = OVERWRT_NEVER; /* FALL THROUGH, skip */ case 'n': /* skip file */ skip_entry = SKIP_Y_EXISTING; break; default: Info(slide, 1, ((char *)slide, LoadFarString(InvalidResponse), *G.answerbuf)); goto reprompt; /* yet another goto? */ } /* end switch (*answerbuf) */ #endif /* ?WINDLL */ } /* end if (query) */ if (skip_entry != SKIP_NO) { #ifdef WINDLL if (skip_entry == SKIP_Y_EXISTING) { /* report skipping of an existing entry */ Info(slide, 0, ((char *)slide, ((IS_OVERWRT_NONE || !uO.uflag || renamed) ? "Target file exists.\nSkipping %s\n" : "Target file newer.\nSkipping %s\n"), FnFilter1(G.filename))); } #endif /* WINDLL */ continue; } } /* end if (extracting to disk) */ #ifdef DLL if ((G.statreportcb != NULL) && (*G.statreportcb)(__G__ UZ_ST_START_EXTRACT, G.zipfn, G.filename, NULL)) { if (fn_matched) free((zvoid *)fn_matched); if (xn_matched) free((zvoid *)xn_matched); return IZ_CTRLC; /* cancel operation by user request */ } #endif #ifdef MACOS /* MacOS is no preemptive OS, thus call event-handling by hand */ UserStop(); #endif #ifdef AMIGA G.filenote_slot = i; #endif G.disk_full = 0; if ((error = extract_or_test_member(__G)) != PK_COOL) { if (error > error_in_archive) error_in_archive = error; /* ...and keep going */ #ifdef DLL if (G.disk_full > 1 || error_in_archive == IZ_CTRLC) { #else if (G.disk_full > 1) { #endif if (fn_matched) free((zvoid *)fn_matched); if (xn_matched) free((zvoid *)xn_matched); return error_in_archive; /* (unless disk full) */ } } #ifdef DLL if ((G.statreportcb != NULL) && (*G.statreportcb)(__G__ UZ_ST_FINISH_MEMBER, G.zipfn, G.filename, (zvoid *)&G.lrec.ucsize)) { if (fn_matched) free((zvoid *)fn_matched); if (xn_matched) free((zvoid *)xn_matched); return IZ_CTRLC; /* cancel operation by user request */ } #endif #ifdef MACOS /* MacOS is no preemptive OS, thus call event-handling by hand */ UserStop(); #endif } /* end for-loop (i: files in current block) */ /* * Jump back to where we were in the central directory, then go and do * the next batch of files. */ #ifdef USE_STRM_INPUT fseek((FILE *)G.zipfd, (LONGINT)cd_bufstart, SEEK_SET); G.cur_zipfile_bufstart = ftell((FILE *)G.zipfd); #else /* !USE_STRM_INPUT */ G.cur_zipfile_bufstart = lseek(G.zipfd,(LONGINT)cd_bufstart,SEEK_SET); #endif /* ?USE_STRM_INPUT */ read(G.zipfd, (char *)G.inbuf, INBUFSIZ); /* been here before... */ G.inptr = cd_inptr; G.incnt = cd_incnt; ++blknum; #ifdef TEST printf("\ncd_bufstart = %ld (%.8lXh)\n", cd_bufstart, cd_bufstart); printf("cur_zipfile_bufstart = %ld (%.8lXh)\n", cur_zipfile_bufstart, cur_zipfile_bufstart); printf("inptr-inbuf = %d\n", G.inptr-G.inbuf); printf("incnt = %d\n\n", G.incnt); #endif } /* end while-loop (blocks of files in central directory) */ /*--------------------------------------------------------------------------- Go back through saved list of directories, sort and set times/perms/UIDs and GIDs from the deepest level on up. ---------------------------------------------------------------------------*/ #ifdef SET_DIR_ATTRIB if (num_dirs > 0) { sorted_dirlist = (dirtime **)malloc(num_dirs*sizeof(dirtime *)); if (sorted_dirlist == (dirtime **)NULL) { Info(slide, 0x401, ((char *)slide, LoadFarString(DirlistSortNoMem))); while (dirlist != (dirtime *)NULL) { dirtime *d = dirlist; dirlist = dirlist->next; free(d); } } else { if (num_dirs == 1) sorted_dirlist[0] = dirlist; else { for (i = 0; i < num_dirs; ++i) { sorted_dirlist[i] = dirlist; dirlist = dirlist->next; } qsort((char *)sorted_dirlist, num_dirs, sizeof(dirtime *), dircomp); } Trace((stderr, "setting directory times/perms/attributes\n")); for (i = 0; i < num_dirs; ++i) { dirtime *d = sorted_dirlist[i]; Trace((stderr, "dir = %s\n", d->fn)); if ((error = set_direc_attribs(__G__ d)) != PK_OK) { Info(slide, 0x201, ((char *)slide, LoadFarString(DirlistSetAttrFailed), d->fn)); if (!error_in_archive) error_in_archive = error; } free(d->fn); free(d); } free(sorted_dirlist); } } #endif /* SET_DIR_ATTRIB */ #if (defined(WIN32) && defined(NTSD_EAS)) process_defer_NT(__G); /* process any deferred items for this .zip file */ #endif /*--------------------------------------------------------------------------- Check for unmatched filespecs on command line and print warning if any found. Free allocated memory. ---------------------------------------------------------------------------*/ if (fn_matched) { for (i = 0; i < G.filespecs; ++i) if (!fn_matched[i]) { #ifdef DLL if (!G.redirect_data && !G.redirect_text) bԁ UNZIP.BCK  [UNZIP542]EXTRACT.C;1\U Info(slide, 0x401, ((char *)slide, LoadFarString(FilenameNotMatched), G.pfnames[i])); else setFileNotFound(__G); #else Info(slide, 1, ((char *)slide, LoadFarString(FilenameNotMatched), G.pfnames[i])); #endif if (error_in_archive <= PK_WARN) error_in_archive = PK_FIND; /* some files not found */ } free((zvoid *)fn_matched); } if (xn_matched) { for (i = 0; i < G.xfilespecs; ++i) if (!xn_matched[i]) Info(slide, 0x401, ((char *)slide, LoadFarString(ExclFilenameNotMatched), G.pxnames[i])); free((zvoid *)xn_matched); } /*--------------------------------------------------------------------------- Double-check that we're back at the end-of-central-directory record, and print quick summary of results, if we were just testing the archive. We send the summary to stdout so that people doing the testing in the back- ground and redirecting to a file can just do a "tail" on the output file. ---------------------------------------------------------------------------*/ #ifndef SFX if (no_endsig_found) { /* just to make sure */ Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg))); Info(slide, 0x401, ((char *)slide, LoadFarString(ReportMsg))); if (!error_in_archive) /* don't overwrite stronger error */ error_in_archive = PK_WARN; } #endif /* !SFX */ if (uO.tflag) { ulg num = filnum - num_bad_pwd; if (uO.qflag < 2) { /* GRR 930710: was (uO.qflag == 1) */ if (error_in_archive) Info(slide, 0, ((char *)slide, LoadFarString(ErrorInArchive), (error_in_archive == 1)? "warning-" : "", G.zipfn)); else if (num == 0L) Info(slide, 0, ((char *)slide, LoadFarString(ZeroFilesTested), G.zipfn)); else if (G.process_all_files && (num_skipped+num_bad_pwd == 0L)) Info(slide, 0, ((char *)slide, LoadFarString(NoErrInCompData), G.zipfn)); else Info(slide, 0, ((char *)slide, LoadFarString(NoErrInTestedFiles) , G.zipfn, num, (num==1L)? "":"s")); if (num_skipped > 0L) Info(slide, 0, ((char *)slide, LoadFarString(FilesSkipped), num_skipped, (num_skipped==1L)? "":"s")); #if CRYPT if (num_bad_pwd > 0L) Info(slide, 0, ((char *)slide, LoadFarString(FilesSkipBadPasswd) , num_bad_pwd, (num_bad_pwd==1L)? "":"s")); #endif /* CRYPT */ } else if ((uO.qflag == 0) && !error_in_archive && (num == 0)) Info(slide, 0, ((char *)slide, LoadFarString(ZeroFilesTested), G.zipfn)); } /* give warning if files not tested or extracted (first condition can still * happen if zipfile is empty and no files specified on command line) */ if ((filnum == 0) && error_in_archive <= PK_WARN) { if (num_skipped > 0L) error_in_archive = IZ_UNSUP; /* unsupport. compression/encryption */ else error_in_archive = PK_FIND; /* no files found at all */ } #if CRYPT else if ((filnum == num_bad_pwd) && error_in_archive <= PK_WARN) error_in_archive = IZ_BADPWD; /* bad passwd => all files skipped */ #endif else if ((num_skipped > 0L) && error_in_archive <= PK_WARN) error_in_archive = IZ_UNSUP; /* was PK_WARN; Jean-loup complained */ #if CRYPT else if ((num_bad_pwd > 0L) && !error_in_archive) error_in_archive = PK_WARN; #endif return error_in_archive; } /* end function extract_or_test_files() */ /***************************/ /* Function store_info() */ /***************************/ static int store_info(__G) /* return 0 if skipping, 1 if OK */ __GDEF { #ifdef SFX # ifdef USE_DEFLATE64 # define UNKN_COMPR \ (G.crec.compression_method!=STORED && G.crec.compression_methodENHDEFLATED) # else # define UNKN_COMPR \ (G.crec.compression_method!=STORED && G.crec.compression_method!=DEFLATED) # endif #else # ifdef COPYRIGHT_CLEAN /* no reduced files */ # define UNKN_RED (G.crec.compression_method >= REDUCED1 && \ G.crec.compression_method <= REDUCED4) # else # define UNKN_RED FALSE /* reducing not unknown */ # endif # ifdef LZW_CLEAN /* no shrunk files */ # define UNKN_SHR (G.crec.compression_method == SHRUNK) # else # define UNKN_SHR FALSE /* unshrinking not unknown */ # endif # ifdef USE_DEFLATE64 # define UNKN_COMPR (UNKN_RED || UNKN_SHR || \ G.crec.compression_method==TOKENIZED || \ G.crec.compression_method>ENHDEFLATED) # else # define UNKN_COMPR (UNKN_RED || UNKN_SHR || \ G.crec.compression_method==TOKENIZED || \ G.crec.compression_method>DEFLATED) # endif #endif /*--------------------------------------------------------------------------- Check central directory info for version/compatibility requirements. ---------------------------------------------------------------------------*/ G.pInfo->encrypted = G.crec.general_purpose_bit_flag & 1; /* bit field */ G.pInfo->ExtLocHdr = (G.crec.general_purpose_bit_flag & 8) == 8; /* bit */ G.pInfo->textfile = G.crec.internal_file_attributes & 1; /* bit field */ G.pInfo->crc = G.crec.crc32; G.pInfo->compr_size = G.crec.csize; G.pInfo->uncompr_size = G.crec.ucsize; switch (uO.aflag) { case 0: G.pInfo->textmode = FALSE; /* bit field */ break; case 1: G.pInfo->textmode = G.pInfo->textfile; /* auto-convert mode */ break; default: /* case 2: */ G.pInfo->textmode = TRUE; break; } if (G.crec.version_needed_to_extract[1] == VMS_) { if (G.crec.version_needed_to_extract[0] > VMS_UNZIP_VERSION) { if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))) Info(slide, 0x401, ((char *)slide, LoadFarString(VersionMsg), FnFilter1(G.filename), "VMS", G.crec.version_needed_to_extract[0] / 10, G.crec.version_needed_to_extract[0] % 10, VMS_UNZIP_VERSION / 10, VMS_UNZIP_VERSION % 10)); return 0; } #ifndef VMS /* won't be able to use extra field, but still have data */ else if (!uO.tflag && !IS_OVERWRT_ALL) { /* if -o, extract anyway */ Info(slide, 0x481, ((char *)slide, LoadFarString(VMSFormatQuery), FnFilter1(G.filename))); fgets(G.answerbuf, 9, stdin); if ((*G.answerbuf != 'y') && (*G.answerbuf != 'Y')) return 0; } #endif /* !VMS */ /* usual file type: don't need VMS to extract */ } else if (G.crec.version_needed_to_extract[0] > UNZIP_VERSION) { if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))) Info(slide, 0x401, ((char *)slide, LoadFarString(VersionMsg), FnFilter1(G.filename), "PK", G.crec.version_needed_to_extract[0] / 10, G.crec.version_needed_to_extract[0] % 10, UNZIP_VERSION / 10, UNZIP_VERSION % 10)); return 0; } if UNKN_COMPR { if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))) { #ifndef SFX if (G.crec.compression_method < NUM_METHODS) Info(slide, 0x401, ((char *)slide, LoadcNVY@EG2 0] Y#sQeFh%8Cjj4,@:qho@Q@v1va`{\\$wg^(:*Kp2(yd;=Y_P,|Vuf]_f T_TDXOk#> XOi\/ %U j3R 4G_i[t3/THJi&mDLgx.jonB.["w/:#"S kiu`Vx7FMT#{YJGUM1YLASNF3cj^PKB00X[X P;|+F+t[$6L'^D\Ci53t&FeP_.a3i::s"7(| 2 w^w) 5i k;yO& K/%fX;R \xWIMJ~BgJPb9z 97m;b*-,>^}7}#J!/[uh5RCFrR+Uh}Lzq<+-PPCi{+oB2UYJ 7rUILk]Mv_U _Ryi{gB][U|sRoR3$Rfr;0tg{pW mCAl`w?c f;2q)q*!q>|y&JD/tS_ !HT hNZJQO]>JmjTXMI-!^0q )OQC+,G;Y{m Y+VhvTR}c>w-ed| YM=XH_g_g)1m\ #zyInPmm:G&E&P1#dZ`]9i 8 IU s'QPz1]Ym6d4RFZ8&B&v+WxSs*S>~9:RhO5xxt"lkcgm \9dn"sRj}G)2*bi,gx}-NJ+YU^J~eZw B`mb^-K6p%{~kNL\"q{vO6 $-?KFmSbw2P'  YHW8J_C|?<, DWaEu270Ku Q NK*ERNBp jRMHYi?P1_ #I w4G9N7"Tv#6ZUi%W6R[~Wq :Nk4+O@B-J H= WcF6;I>He ;{ -n75Iwi|O4ntJeLDiGZ?Tc3 &YFgMi\ t^ nOM{N*z]TFFAF;{;x\^DXQ&iP"x ,I-vdeY`&;/ z`yuB H+[KnHm^ ]wQ ~?Fb*Pkf^vNG$>YS 8 Uu]s3v)t+J(::5)r|cAGCEtl/_1nUYcpGi (| ^ ?"X.X5f)\S}H'.Cv4AwL0`Y'euA 1-wGGj`~fVN^otZXVV?]0FKx*mD;{+ydMId{vD41[r_'mkWknS92L.< OAR/ODf-F@#8Xqw5^  xnZgF=.D\CYs@)&UX?z.9+ ~0dUx1 UUDal~`+ Bn> U5*}^T:(p0'lf%?$ ]lXT_)BH68P-| I_NaLNxUP'FG- $,9N@#t&p] W@+T ,g^>vtrybN)] o2 %4HXO~c3x)p8xw/ d-WF5(}VU!A\Vc-ppM9>0i(>*mZPL6JFfVW5STX0Sp/nsxO+ 747t@S_]1!Gh!SP?m<+YA;eN {?vN#b?OJ@T^11 ;K.k"SO~exa,c5paFm hR0MiM_AE 5SH@&e~d`FK1bM?\2?p%vv9# U,0>5P%7}G R-PS~gJE{|_ 0$G "4S)kpe6wI6tx6NJ[^+\UvS_B R K/rR~QV 6t'S]03F5kVGO=OIVc,fj|EU kg[zny~W0zWW.&J}d0&&x+6 0nx pL@Lo+F}:G.fs+f+@>j/SbG fJ#qxq>Dsx'h DyOTMPF*E`OY:`X}@abq~(bTd(WR?)1%_ 3o]Q$j3\ a8!#hPU&RY D [K(\V8 GM3X!/]Nr""@k ~tkoBs# #@u@C'@gx,!yS9i<7BJ- TE:w1R3DD8KmF%s@mg.K(/h!Al\GME}j u;TgO7/ 1TV~F4-Cqc/g2\AY326m>]m"'z%dA~x\v` :0J&eED;;X#Xbw{pGL|d!d{n:a"h-#l+gUJ>j^QT DY=>],mn_+J/#)YyS1(OrH2\xK{TQ1GYdnSh@)E #(lB6%|i\E o'R6]k"qu&F @-[[Bb)B[." R*E0s7A+Z&l h`y% M?F >FjyEdy WfQQ4^O AWy|RXH K!O Z'>nG$fR$vL#kg-61]G>@R+ mu&8COnv?:PTyLXEYS2]sIOCUGE7}bHX{,!}*Z:>j'^sbUQ OUU] RwGrq@r] x*@%'2*X$=I'7vA+T=*DR"}:Ek |:?51XD1SsLx~=O6r,U5akYhOn.(EVjh4 0F0uVH& 0NUJ FB nP2K~XBG#'VKH\|;!#zvI{(i/Qjob5+*#OwzWG_>QZP*jJw'!lZKv!#G m/Qs(911.6NvPP{(.o, _3!uoG6cJXr O#gkX_qlW>H`hp(t4g+b1UD ;>eJq8u:?N,r82BCfo:K@.4T$!*0Vj7"{ PP/NsJgkwuc`{)#AqOWiF_UU$2OzZJ9-~D{E\SRiSzEYg_v2 Y`A'}OH.8"K6WIRz5wmEhHmdOy.r{/T62 :?,hK%^GRUxYHL\L;VL <&0`j%Jv}TsF=eut{vo~CQT OqL e_PBI ]6V*R%WW"\4 ni[-ssH3N/QA\J gc4-hDZ.rh=9f.a\nF0$cSzUZk 40_P:zDMhUhQ: -{AT:{` U0(*}Wl<!2+I{=HWbA^#N8{Zh!b |-R[Bk[Lvht~SA hO/*dhZLiD~oTLeZ7!}[GF;Fc4sg+1L N)j~TzG,' "'C*Y}t 5(&A*V%K}Kr^0n$\uz?tqI '2 5:l6F>3)G6F{ [MZX'3v.GHe$$^q4KUk!x_O@8*ruD)kY|}# DdxE^^m8?_O%5,KWZKeSXt8nZ-/<#$f$R4h6,8v) (tsiMVawJU}mJ[\ 5&-.&wQ9h *IV4cG,M,I`L~s0)nq.PFUi!4&`W%}/L5%e0Mva-iq-M^Ss)Ad2|jPa/yU$]F%&MCt>s iYdA5hKU l.XNJL;M *ct_:2HH=BZ8gKb5j#:1-2>=(a]( [ d}d{c}' nv^JEr*MU2-'V-v>\^ rqKU:# ) o|[CY=y? IIzB ?WpE .`Eldr<]HK=X @ MFgT PF ,(7KKUYALYKrg8&KrSiCCYQ X<N'>EkN ,n%"4G T  S ik|)"}+TM$#]lMY9~ 8zxd+(:\Usd* 6'`bIg Mz'|F=$) &J/j}E{;Karr?ep5JAa&m  1z}o5kkqu=z=Wn3>0/jv0.Qls?.HcHl`J?]?7A mR)%[8\g2,F=C.O[B(u!-td'm!98=6BZJU#uuJ7YemY(]qS;er:dIZqD,tTn5J86CL]4\P  D-DRvB#+l~ NH_ePJ6O:XkwuT&P AXCm\_M=q &v+Q}h50.yY>y ]Wl%Kp%Kb8*%Zl2w7kvhhg{VQdLtY/3&n^0}qi[VA9b4A<+ L"c!G~z";Yqn: )ymoeqER" WIQ\%V8>.p8smd,{2UY38DS H\"I(3k#v1b&Sp:Y/g3uMC>Pc $?SKNip" u[6j x0oY^$BlN-TQV-H~"Xmn$U:Ankh6=+p#T\7ne0v&Gd5" \.|paB IwQ2 h=8|fqK0r9D o2Ego.8k 6f>?-m-4Amy7\iz$F|if_ D|4 7k1$|G ll j$rykyRIC>[[{u ]PuWA\7F|%3W0|_~fKv >BPX_Wvlja" )pTPQ+=,ybl2|+c]X&DHLH~i*.e9rtDXKSB FDO JP6|^ok h$v mK5Xe%*>7A6Vu"G I0\&=Qe% oRq?.7n*rl,Y.0y-NBY\A_P/[5>DfX6*+#PsNZ\[,|maz<;L{-c]M{8<:5Q9{ "{ y"iWQmBQOM W@G8QF4HHPl#=a27>+rP".`rEft!@ E DQ#`e#]Lm371r/ 2.zE#e$i''OE]f + Q^~~3k&iI$EocuEJt=O8']0fIuYY^Ln*)"/M`U_QKhwL^B1;?^!]pjLx$RZ !UYS |{ >IaOJy^xD& WDiILg'Gg*N<$zMhw)a87:48y'u(GGjGuKDCS,|lN`]@\rI@DGEL+7*dtWTj ?AZJ`aHxTnJxO%ULH03 ?U_\(7 I3WBi%j51j4{GZ6i`K)P~K:Y e2$hltNn|PZJ" .%1/\'kruswv^h`{egjRhzj J$Uj|MpEUQS9T,ikT@.6R~O].:mU *h% "S%5 ] Z?Aif< 'Jkr 9h!4Qy_d J_B]8\*FX=}U0z+~;pQJsHCD6~s,VB P#[ NcR16_]28F >HL|U*.~`( LK\Do9ibi :Mt9a;A'r WtR~/`EMYi5GZW:2zRlR8s`Dj$:=AA.&2:s+u>I+1([ @J6aKMhbM[=: ?)a0n=i#$wO]`vcy.{-s*?pmG lLd%(#>p)%+4g M38foarX,FT AMxP&S)P32;?#T-A hkR|vk7  t6fd U0n arj!#&Z{33p <[TGMB|&}zNu-]/+8d1Q<,/R^P9u6378v//,Jgmva6gid-tvdx$' %6t4Wy*u1P)d!Zsy{f~K%%mEj#td5, UNZIP.BCK  [UNZIP542]EXTRACT.C;1_dFarString(ComprMsgName), FnFilter1(G.filename), LoadFarStringSmall(ComprNames[G.crec.compression_method]))); else #endif Info(slide, 0x401, ((char *)slide, LoadFarString(ComprMsgNum), FnFilter1(G.filename), G.crec.compression_method)); } return 0; } #if (!CRYPT) if (G.pInfo->encrypted) { if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))) Info(slide, 0x401, ((char *)slide, LoadFarString(SkipEncrypted), FnFilter1(G.filename))); return 0; } #endif /* !CRYPT */ /* map whatever file attributes we have into the local format */ mapattr(__G); /* GRR: worry about return value later */ G.pInfo->offset = (long)G.crec.relative_offset_local_header; return 1; } /* end function store_info() */ /***************************************/ /* Function extract_or_test_member() */ /***************************************/ static int extract_or_test_member(__G) /* return PK-type error code */ __GDEF { char *nul="[empty] ", *txt="[text] ", *bin="[binary]"; #ifdef CMS_MVS char *ebc="[ebcdic]"; #endif register int b; int r, error=PK_COOL; #if (defined(DLL) && !defined(NO_SLIDE_REDIR)) ulg wsize; #else # define wsize WSIZE #endif /*--------------------------------------------------------------------------- Initialize variables, buffers, etc. ---------------------------------------------------------------------------*/ G.bits_left = 0; G.bitbuf = 0L; /* unreduce and unshrink only */ G.zipeof = 0; G.newfile = TRUE; G.crc32val = CRCVAL_INITIAL; #ifdef SYMLINKS /* if file came from Unix and is a symbolic link and we are extracting * to disk, prepare to restore the link */ if (S_ISLNK(G.pInfo->file_attr) && (G.pInfo->hostnum == UNIX_ || G.pInfo->hostnum == ATARI_ || G.pInfo->hostnum == BEOS_) && !uO.tflag && !uO.cflag && (G.lrec.ucsize > 0)) G.symlnk = TRUE; else G.symlnk = FALSE; #endif /* SYMLINKS */ if (uO.tflag) { if (!uO.qflag) Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), "test", FnFilter1(G.filename), "", "")); } else { #ifdef DLL if (uO.cflag && !G.redirect_data) #else if (uO.cflag) #endif { #if (defined(OS2) && defined(__IBMC__) && (__IBMC__ >= 200)) G.outfile = freopen("", "wb", stdout); /* VAC++ ignores setmode */ #else G.outfile = stdout; #endif #ifdef DOS_FLX_NLM_OS2_W32 #if (defined(__HIGHC__) && !defined(FLEXOS)) setmode(G.outfile, _BINARY); #else /* !(defined(__HIGHC__) && !defined(FLEXOS)) */ setmode(fileno(G.outfile), O_BINARY); #endif /* ?(defined(__HIGHC__) && !defined(FLEXOS)) */ # define NEWLINE "\r\n" #else /* !DOS_FLX_NLM_OS2_W32 */ # define NEWLINE "\n" #endif /* ?DOS_FLX_NLM_OS2_W32 */ #ifdef VMS if (open_outfile(__G)) /* VMS: required even for stdout! */ return PK_DISK; #endif } else if (open_outfile(__G)) return PK_DISK; } /*--------------------------------------------------------------------------- Unpack the file. ---------------------------------------------------------------------------*/ defer_leftover_input(__G); /* so NEXTBYTE bounds check will work */ switch (G.lrec.compression_method) { case STORED: if (!uO.tflag && QCOND2) { #ifdef SYMLINKS if (G.symlnk) /* can also be deflated, but rarer... */ Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), "link", FnFilter1(G.filename), "", "")); else #endif /* SYMLINKS */ Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), "extract", FnFilter1(G.filename), (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)? "" : (G.lrec.ucsize == 0L? nul : (G.pInfo->textfile? txt : bin)), uO.cflag? NEWLINE : "")); } #if (defined(DLL) && !defined(NO_SLIDE_REDIR)) if (G.redirect_slide) { wsize = G.redirect_size; redirSlide = G.redirect_buffer; } else { wsize = WSIZE; redirSlide = slide; } #endif G.outptr = redirSlide; G.outcnt = 0L; while ((b = NEXTBYTE) != EOF) { *G.outptr++ = (uch)b; if (++G.outcnt == wsize) { error = flush(__G__ redirSlide, G.outcnt, 0); G.outptr = redirSlide; G.outcnt = 0L; if (error != PK_COOL || G.disk_full) break; } } if (G.outcnt) /* flush final (partial) buffer */ flush(__G__ redirSlide, G.outcnt, 0); break; #ifndef SFX #ifndef LZW_CLEAN case SHRUNK: if (!uO.tflag && QCOND2) { Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), LoadFarStringSmall(Unshrink), FnFilter1(G.filename), (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)? "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : "")); } if ((r = unshrink(__G)) != PK_COOL) { if (r < PK_DISK) { if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)) Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(ErrUnzipFile), LoadFarString(NotEnoughMem), LoadFarStringSmall2(Unshrink), FnFilter1(G.filename))); else Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(ErrUnzipNoFile), LoadFarString(NotEnoughMem), LoadFarStringSmall2(Unshrink))); } error = r; } break; #endif /* !LZW_CLEAN */ #ifndef COPYRIGHT_CLEAN case REDUCED1: case REDUCED2: case REDUCED3: case REDUCED4: if (!uO.tflag && QCOND2) { Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), "unreduc", FnFilter1(G.filename), (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)? "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : "")); } if ((r = unreduce(__G)) != PK_COOL) { /* unreduce() returns only PK_COOL, PK_DISK, or IZ_CTRLC */ error = r; } break; #endif /* !COPYRIGHT_CLEAN */ case IMPLODED: if (!uO.tflag && QCOND2) { Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), "explod", FnFilter1(G.filename), (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)? "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : "")); } if (((r = explode(__G)) != 0) && (r != 5)) { /* treat 5 specially */ if (r < PK_DISK) { if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)) Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(ErrUnzipFile), r == 3? LoadFarString(NotEnoughMem) : LoadFarString(InvalidComprDae<% UNZIP.BCK  [UNZIP542]EXTRACT.C;1sta), LoadFarStringSmall2(Explode), FnFilter1(G.filename))); else Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(ErrUnzipNoFile), r == 3? LoadFarString(NotEnoughMem) : LoadFarString(InvalidComprData), LoadFarStringSmall2(Explode))); error = (r == 3)? PK_MEM3 : PK_ERR; } else { error = r; } } if (r == 5) { int warning = ((ulg)G.used_csize <= G.lrec.csize); if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)) Info(slide, 0x401, ((char *)slide, LoadFarString(LengthMsg), "", warning? "warning" : "error", G.used_csize, G.lrec.ucsize, warning? " " : "", G.lrec.csize, " [", FnFilter1(G.filename), "]")); else Info(slide, 0x401, ((char *)slide, LoadFarString(LengthMsg), "\n", warning? "warning" : "error", G.used_csize, G.lrec.ucsize, warning? " ":"", G.lrec.csize, "", "", ".")); error = warning? PK_WARN : PK_ERR; } break; #endif /* !SFX */ case DEFLATED: #ifdef USE_DEFLATE64 case ENHDEFLATED: #endif if (!uO.tflag && QCOND2) { Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), "inflat", FnFilter1(G.filename), (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)? "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : "")); } #ifndef USE_ZLIB /* zlib's function is called inflate(), too */ # define UZinflate inflate #endif if ((r = UZinflate(__G)) != 0) { if (r < PK_DISK) { if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)) Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(ErrUnzipFile), r == 3? LoadFarString(NotEnoughMem) : LoadFarString(InvalidComprData), LoadFarStringSmall2(Inflate), FnFilter1(G.filename))); else Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(ErrUnzipNoFile), r == 3? LoadFarString(NotEnoughMem) : LoadFarString(InvalidComprData), LoadFarStringSmall2(Inflate))); error = (r == 3)? PK_MEM3 : PK_ERR; } else { error = r; } } break; default: /* should never get to this point */ Info(slide, 0x401, ((char *)slide, LoadFarString(FileUnknownCompMethod), FnFilter1(G.filename))); /* close and delete file before return? */ undefer_input(__G); return PK_WARN; } /* end switch (compression method) */ /*--------------------------------------------------------------------------- Close the file and set its date and time (not necessarily in that order), and make sure the CRC checked out OK. Logical-AND the CRC for 64-bit machines (redundant on 32-bit machines). ---------------------------------------------------------------------------*/ #ifdef VMS /* VMS: required even for stdout! (final flush) */ if (!uO.tflag) /* don't close NULL file */ close_outfile(__G); #else #ifdef DLL if (!uO.tflag && (!uO.cflag || G.redirect_data)) { if (G.redirect_data) FINISH_REDIRECT(); else close_outfile(__G); } #else if (!uO.tflag && !uO.cflag) /* don't close NULL file or stdout */ close_outfile(__G); #endif #endif /* VMS */ /* GRR: CONVERT close_outfile() TO NON-VOID: CHECK FOR ERRORS! */ if (G.disk_full) { /* set by flush() */ if (G.disk_full > 1) { #if (defined(DELETE_IF_FULL) && defined(HAVE_UNLINK)) /* delete the incomplete file if we can */ if (unlink(G.filename) != 0) Trace((stderr, "extract.c: could not delete %s\n", FnFilter1(G.filename))); #else /* warn user about the incomplete file */ Info(slide, 0x421, ((char *)slide, LoadFarString(FileTruncated), FnFilter1(G.filename))); #endif error = PK_DISK; } else { error = PK_WARN; } } if (error > PK_WARN) {/* don't print redundant CRC error if error already */ undefer_input(__G); return error; } if (G.crc32val != G.lrec.crc32) { /* if quiet enough, we haven't output the filename yet: do it */ if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)) Info(slide, 0x401, ((char *)slide, "%-22s ", FnFilter1(G.filename))); Info(slide, 0x401, ((char *)slide, LoadFarString(BadCRC), G.crc32val, G.lrec.crc32)); #if CRYPT if (G.pInfo->encrypted) Info(slide, 0x401, ((char *)slide, LoadFarString(MaybeBadPasswd))); #endif error = PK_ERR; } else if (uO.tflag) { #ifndef SFX if (G.extra_field) { if ((r = TestExtraField(__G__ G.extra_field, G.lrec.extra_field_length)) > error) error = r; } else #endif /* !SFX */ if (!uO.qflag) Info(slide, 0, ((char *)slide, " OK\n")); } else { if (QCOND2 && !error) /* GRR: is stdout reset to text mode yet? */ Info(slide, 0, ((char *)slide, "\n")); } undefer_input(__G); return error; } /* end function extract_or_test_member() */ #ifndef SFX /*******************************/ /* Function TestExtraField() */ /*******************************/ static int TestExtraField(__G__ ef, ef_len) __GDEF uch *ef; unsigned ef_len; { ush ebID; unsigned ebLen; unsigned eb_cmpr_offs = 0; int r; /* we know the regular compressed file data tested out OK, or else we * wouldn't be here ==> print filename if any extra-field errors found */ while (ef_len >= EB_HEADSIZE) { ebID = makeword(ef); ebLen = (unsigned)makeword(ef+EB_LEN); if (ebLen > (ef_len - EB_HEADSIZE)) { /* Discovered some extra field inconsistency! */ if (uO.qflag) Info(slide, 1, ((char *)slide, "%-22s ", FnFilter1(G.filename))); Info(slide, 1, ((char *)slide, LoadFarString(InconsistEFlength), ebLen, (ef_len - EB_HEADSIZE))); return PK_ERR; } switch (ebID) { case EF_OS2: case EF_ACL: case EF_MAC3: case EF_BEOS: switch (ebID) { case EF_OS2: case EF_ACL: eb_cmpr_offs = EB_OS2_HLEN; break; case EF_MAC3: if (ebLen >= EB_MAC3_HLEN && (makeword(ef+(EB_HEADSIZE+EB_FLGS_OFFS)) & EB_M3_FL_UNCMPR) && (makelong(ef+EB_HEADSIZE) == ebLen - EB_MAC3_HLEN)) eb_cmpr_offs = 0; else eb_cmpr_offs = EB_MAC3_HLEN; f!i7X UNZIP.BCK  [UNZIP542]EXTRACT.C;1., break; case EF_BEOS: if (ebLen >= EB_BEOS_HLEN && (*(ef+(EB_HEADSIZE+EB_FLGS_OFFS)) & EB_BE_FL_UNCMPR) && (makelong(ef+EB_HEADSIZE) == ebLen - EB_BEOS_HLEN)) eb_cmpr_offs = 0; else eb_cmpr_offs = EB_BEOS_HLEN; break; } if ((r = test_compr_eb(__G__ ef, ebLen, eb_cmpr_offs, NULL)) != PK_OK) { if (uO.qflag) Info(slide, 1, ((char *)slide, "%-22s ", FnFilter1(G.filename))); switch (r) { case IZ_EF_TRUNC: Info(slide, 1, ((char *)slide, LoadFarString(TruncEAs), ebLen-(eb_cmpr_offs+EB_CMPRHEADLEN), "\n")); break; case PK_ERR: Info(slide, 1, ((char *)slide, LoadFarString(InvalidComprDataEAs))); break; case PK_MEM3: case PK_MEM4: Info(slide, 1, ((char *)slide, LoadFarString(NotEnoughMemEAs))); break; default: if ((r & 0xff) != PK_ERR) Info(slide, 1, ((char *)slide, LoadFarString(UnknErrorEAs))); else { ush m = (ush)(r >> 8); if (m == DEFLATED) /* GRR KLUDGE! */ Info(slide, 1, ((char *)slide, LoadFarString(BadCRC_EAs))); else Info(slide, 1, ((char *)slide, LoadFarString(UnknComprMethodEAs), m)); } break; } return r; } break; case EF_NTSD: Trace((stderr, "ebID: %i / ebLen: %u\n", ebID, ebLen)); r = ebLen < EB_NTSD_L_LEN ? IZ_EF_TRUNC : ((ef[EB_HEADSIZE+EB_NTSD_VERSION] > EB_NTSD_MAX_VER) ? (PK_WARN | 0x4000) : test_compr_eb(__G__ ef, ebLen, EB_NTSD_L_LEN, TEST_NTSD)); if (r != PK_OK) { if (uO.qflag) Info(slide, 1, ((char *)slide, "%-22s ", FnFilter1(G.filename))); switch (r) { case IZ_EF_TRUNC: Info(slide, 1, ((char *)slide, LoadFarString(TruncNTSD), ebLen-(EB_NTSD_L_LEN+EB_CMPRHEADLEN), "\n")); break; #if (defined(WIN32) && defined(NTSD_EAS)) case PK_WARN: Info(slide, 1, ((char *)slide, LoadFarString(InvalidSecurityEAs))); break; #endif case PK_ERR: Info(slide, 1, ((char *)slide, LoadFarString(InvalidComprDataEAs))); break; case PK_MEM3: case PK_MEM4: Info(slide, 1, ((char *)slide, LoadFarString(NotEnoughMemEAs))); break; case (PK_WARN | 0x4000): Info(slide, 1, ((char *)slide, LoadFarString(UnsuppNTSDVersEAs), (int)ef[EB_HEADSIZE+EB_NTSD_VERSION])); r = PK_WARN; break; default: if ((r & 0xff) != PK_ERR) Info(slide, 1, ((char *)slide, LoadFarString(UnknErrorEAs))); else { ush m = (ush)(r >> 8); if (m == DEFLATED) /* GRR KLUDGE! */ Info(slide, 1, ((char *)slide, LoadFarString(BadCRC_EAs))); else Info(slide, 1, ((char *)slide, LoadFarString(UnknComprMethodEAs), m)); } break; } return r; } break; case EF_PKVMS: case EF_PKW32: case EF_PKUNIX: case EF_ASIUNIX: case EF_IZVMS: case EF_IZUNIX: case EF_VMCMS: case EF_MVS: case EF_SPARK: case EF_TANDEM: case EF_THEOS: case EF_AV: default: break; } ef_len -= (ebLen + EB_HEADSIZE); ef += (ebLen + EB_HEADSIZE); } if (!uO.qflag) Info(slide, 0, ((char *)slide, " OK\n")); return PK_COOL; } /* end function TestExtraField() */ /******************************/ /* Function test_compr_eb() */ /******************************/ #ifdef PROTO static int test_compr_eb( __GPRO__ uch *eb, unsigned eb_size, unsigned compr_offset, int (*test_uc_ebdata)(__GPRO__ uch *eb, unsigned eb_size, uch *eb_ucptr, ulg eb_ucsize)) #else /* !PROTO */ static int test_compr_eb(__G__ eb, eb_size, compr_offset, test_uc_ebdata) __GDEF uch *eb; unsigned eb_size; unsigned compr_offset; int (*test_uc_ebdata)(); #endif /* ?PROTO */ { ulg eb_ucsize; uch *eb_ucptr; int r; if (compr_offset < 4) /* field is not compressed: */ return PK_OK; /* do nothing and signal OK */ if ((eb_size < (EB_UCSIZE_P + 4)) || ((eb_ucsize = makelong(eb+(EB_HEADSIZE+EB_UCSIZE_P))) > 0L && eb_size <= (compr_offset + EB_CMPRHEADLEN))) return IZ_EF_TRUNC; /* no compressed data! */ if ((eb_ucptr = (uch *)malloc((extent)eb_ucsize)) == (uch *)NULL) return PK_MEM4; r = memextract(__G__ eb_ucptr, eb_ucsize, eb + (EB_HEADSIZE + compr_offset), (ulg)(eb_size - compr_offset)); if (r == PK_OK && test_uc_ebdata != NULL) r = (*test_uc_ebdata)(__G__ eb, eb_size, eb_ucptr, eb_ucsize); free(eb_ucptr); return r; } /* end function test_compr_eb() */ #endif /* !SFX */ /***************************/ /* Function memextract() */ /***************************/ int memextract(__G__ tgt, tgtsize, src, srcsize) /* extract compressed */ __GDEF /* extra field block; */ uch *tgt, *src; /* return PK-type error */ ulg tgtsize, srcsize; /* level */ { long old_csize=G.csize; uch *old_inptr=G.inptr; int old_incnt=G.incnt; int r, error=PK_OK; ush method; ulg extra_field_crc; method = makeword(src); extra_field_crc = makelong(src+2); /* compressed extra field exists completely in memory at thigJYT UNZIP.BCK  [UNZIP542]EXTRACT.C;1s location: */ G.inptr = src + 2 + 4; /* method and extra_field_crc */ G.incnt = (int)(G.csize = (long)(srcsize - (2 + 4))); G.mem_mode = TRUE; G.outbufptr = tgt; G.outsize = tgtsize; switch (method) { case STORED: memcpy((char *)tgt, (char *)G.inptr, (extent)G.incnt); G.outcnt = G.csize; /* for CRC calculation */ break; case DEFLATED: G.outcnt = 0L; if ((r = UZinflate(__G)) != 0) { if (!uO.tflag) Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(ErrUnzipNoFile), r == 3? LoadFarString(NotEnoughMem) : LoadFarString(InvalidComprData), LoadFarStringSmall2(Inflate))); error = (r == 3)? PK_MEM3 : PK_ERR; } if (G.outcnt == 0L) /* inflate's final FLUSH sets outcnt */ break; break; default: if (uO.tflag) error = PK_ERR | ((int)method << 8); else { Info(slide, 0x401, ((char *)slide, LoadFarString(UnsupportedExtraField), method)); error = PK_ERR; /* GRR: should be passed on up via SetEAs() */ } break; } G.inptr = old_inptr; G.incnt = old_incnt; G.csize = old_csize; G.mem_mode = FALSE; if (!error) { register ulg crcval = crc32(CRCVAL_INITIAL, tgt, (extent)G.outcnt); if (crcval != extra_field_crc) { if (uO.tflag) error = PK_ERR | (DEFLATED << 8); /* kludge for now */ else { Info(slide, 0x401, ((char *)slide, LoadFarString(BadExtraFieldCRC), G.zipfn, crcval, extra_field_crc)); error = PK_ERR; } } } return error; } /* end function memextract() */ /*************************/ /* Function memflush() */ /*************************/ int memflush(__G__ rawbuf, size) __GDEF uch *rawbuf; ulg size; { if (size > G.outsize) /* Here, PK_DISK is a bit off-topic, but in the sense of marking "overflow of output space", its use may be tolerated. */ return PK_DISK; /* more data than output buffer can hold */ memcpy((char *)G.outbufptr, (char *)rawbuf, (extent)size); G.outbufptr += (unsigned int)size; G.outsize -= size; G.outcnt += size; return 0; } /* end function memflush() */ /*************************/ /* Function fnfilter() */ /* here instead of in list.c for SFX */ /*************************/ char *fnfilter(raw, space) /* convert name to safely printable form */ ZCONST char *raw; uch *space; { #ifndef NATIVE /* ASCII: filter ANSI escape codes, etc. */ uch *r=(uch *)raw, *s=space; while (*r) { #ifdef QDOS if (qlflag & 2) { if (*r == '/' || *r == '.') { ++r; *s++ = '_'; continue; } } else #endif if (*r < 32) { *s++ = '^', *s++ = (uch)(64 + *r++); } else { #ifdef _MBCS unsigned i; for (i = CLEN(r); i > 0; i--) *s++ = *r++; #else *s++ = *r++; #endif } } *s = 0; #ifdef WINDLL INTERN_TO_ISO((char *)space, (char *)space); /* translate to ANSI */ #else #ifdef WIN32 /* Win9x console always uses OEM character coding, and WinNT console is set to OEM charset by default, too */ INTERN_TO_OEM((char *)space, (char *)space); #endif /* WIN32 */ #endif /* ?WINDLL */ return (char *)space; #else /* NATIVE: EBCDIC or whatever */ return (char *)raw; #endif } /* end function fnfilter() */ #ifdef SET_DIR_ATTRIB /* must sort saved directories so can set perms from bottom up */ /************************/ /* Function dircomp() */ /************************/ static int dircomp(a, b) /* used by qsort(); swiped from Zip */ ZCONST zvoid *a, *b; { /* order is significant: this sorts in reverse order (deepest first) */ return strcmp((*(dirtime **)b)->fn, (*(dirtime **)a)->fn); /* return namecmp((*(dirtime **)b)->fn, (*(dirtime **)a)->fn); */ } #if 0 /* not used in Unix, but maybe for future OSes? */ /************************/ /* Function namecmp() */ /************************/ static int namecmp(s1, s2) /* [not] used by dircomp(); swiped from Zip */ ZCONST char *s1, *s2; { int d; for (;;) { d = (int)(uch)case_map(*s1) - (int)(uch)case_map(*s2); if (d || *s1 == 0 || *s2 == 0) return d; s1++; s2++; } } #endif /* 0 */ #endif /* SET_DIR_ATTRIB */ *[UNZIP542]FILEIO.C;1+, ./ 4u- 0@123KPWO56n@:a7n@:a89GHJ/* Copyright (c) 1990-2001 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*--------------------------------------------------------------------------- fileio.c This file contains routines for doing direct but relatively generic input/ output, file-related sorts of things, plus some miscellaneous stuff. Most of the stuff has to do with opening, closing, reading and/or writing files. Contains: open_input_file() open_outfile() (non-VMS, non-AOS/VS, non-CMS_MVS) undefer_input() defer_leftover_input() readbuf() readbyte() fillinbuf() flush() (non-VMS) disk_error() (non-VMS) UzpMessagePrnt() UzpMessageNull() (DLL only) UzpInput() UzpMorePause() UzpPassword() (non-WINDLL) handler() dos_to_unix_time() (non-VMS, non-VM/CMS, non-MVS) check_for_newer() (non-VMS, non-OS/2, non-VM/CMS, non-MVS) do_string() makeword() makelong() str2iso() (CRYPT && NEED_STR2ISO, only) str2oem() (CRYPT && NEED_STR2OEM, only) memset() (ZMEM only) memcpy() (ZMEM only) zstrnicmp() (NO_STRNICMP only) zstat() (REGULUS only) plastchar() (_MBCS only) uzmbschr() (_MBCS && NEED_UZMBSCHR, only) uzmbsrchr() (_MBCS && NEED_UZMBSRCHR, only) fLoadFarString() (SMALL_MEM only) fLoadFahl UNZIP.BCK  [UNZIP542]FILEIO.C;1rStringSmall() (SMALL_MEM only) fLoadFarStringSmall2() (SMALL_MEM only) zfstrcpy() (SMALL_MEM only) ---------------------------------------------------------------------------*/ #define __FILEIO_C /* identifies this source module */ #define UNZIP_INTERNAL #include "unzip.h" #ifdef WINDLL # include "windll/windll.h" # include #endif #include "crypt.h" #include "ttyio.h" /* setup of codepage conversion for decryption passwords */ #if CRYPT # if (defined(CRYP_USES_ISO2OEM) && !defined(IZ_ISO2OEM_ARRAY)) # define IZ_ISO2OEM_ARRAY /* pull in iso2oem[] table */ # endif # if (defined(CRYP_USES_OEM2ISO) && !defined(IZ_OEM2ISO_ARRAY)) # define IZ_OEM2ISO_ARRAY /* pull in oem2iso[] table */ # endif #endif #include "ebcdic.h" /* definition/initialization of ebcdic[] */ /* Note: Under Windows, the maximum size of the buffer that can be used with any of the *printf calls is 16,384, so win_fprintf was used to feed the fprintf clone no more than 16K chunks at a time. This should be valid for anything up to 64K (and probably beyond, assuming your buffers are that big). */ #ifdef WINDLL # define WriteError(buf,len,strm) \ (win_fprintf(pG, strm, (extent)len, (char far *)buf) != (int)(len)) #else /* !WINDLL */ # ifdef USE_FWRITE # define WriteError(buf,len,strm) \ ((extent)fwrite((char *)(buf),1,(extent)(len),strm) != (extent)(len)) # else # define WriteError(buf,len,strm) \ ((extent)write(fileno(strm),(char *)(buf),(extent)(len)) != (extent)(len)) # endif #endif /* ?WINDLL */ static int disk_error OF((__GPRO)); /****************************/ /* Strings used in fileio.c */ /****************************/ #if (defined(BEO_THS_UNX) || defined(DOS_FLX_NLM_OS2_W32)) static ZCONST char Far CannotDeleteOldFile[] = "error: cannot delete old %s\n"; #ifdef UNIXBACKUP static ZCONST char Far CannotRenameOldFile[] = "error: cannot rename old %s\n"; static ZCONST char Far BackupSuffix[] = "~"; #endif #endif /* BEO_THS_UNX || DOS_FLX_NLM_OS2_W32 */ static ZCONST char Far CannotOpenZipfile[] = "error: cannot open zipfile [ %s ]\n"; #if (!defined(VMS) && !defined(AOS_VS) && !defined(CMS_MVS) && !defined(MACOS)) static ZCONST char Far CannotCreateFile[] = "error: cannot create %s\n"; #endif #ifdef NOVELL_BUG_FAILSAFE static ZCONST char Far NovellBug[] = "error: %s: stat() says does not exist, but fopen() found anyway\n"; #endif static ZCONST char Far ReadError[] = "error: zipfile read error\n"; static ZCONST char Far FilenameTooLongTrunc[] = "warning: filename too long--truncating.\n"; static ZCONST char Far ExtraFieldTooLong[] = "warning: extra field too long (%d). Ignoring...\n"; #ifdef WINDLL static ZCONST char Far DiskFullQuery[] = "%s: write error (disk full?).\n"; #else static ZCONST char Far DiskFullQuery[] = "%s: write error (disk full?). Continue? (y/n/^C) "; static ZCONST char Far ZipfileCorrupt[] = "error: zipfile probably corrupt (%s)\n"; # ifdef SYMLINKS static ZCONST char Far FileIsSymLink[] = "%s exists and is a symbolic link%s.\n"; # endif # ifdef MORE static ZCONST char Far MorePrompt[] = "--More--(%lu)"; # endif static ZCONST char Far QuitPrompt[] = "--- Press `Q' to quit, or any other key to continue ---"; static ZCONST char Far HidePrompt[] = /* "\r \r"; */ "\r \r"; # if CRYPT # ifdef MACOS /* SPC: are names on MacOS REALLY so much longer than elsewhere ??? */ static ZCONST char Far PasswPrompt[] = "[%s]\n %s password: "; # else static ZCONST char Far PasswPrompt[] = "[%s] %s password: "; # endif static ZCONST char Far PasswPrompt2[] = "Enter password: "; static ZCONST char Far PasswRetry[] = "password incorrect--reenter: "; # endif /* CRYPT */ #endif /* !WINDLL */ /******************************/ /* Function open_input_file() */ /******************************/ int open_input_file(__G) /* return 1 if open failed */ __GDEF { /* * open the zipfile for reading and in BINARY mode to prevent cr/lf * translation, which would corrupt the bitstreams */ #ifdef VMS G.zipfd = open(G.zipfn, O_RDONLY, 0, "ctx=stm"); #else /* !VMS */ #ifdef MACOS G.zipfd = open(G.zipfn, 0); #else /* !MACOS */ #ifdef CMS_MVS G.zipfd = vmmvs_open_infile(__G); #else /* !CMS_MVS */ #ifdef USE_STRM_INPUT G.zipfd = fopen(G.zipfn, FOPR); #else /* !USE_STRM_INPUT */ # ifdef O_BINARY G.zipfd = open(G.zipfn, O_RDONLY | O_BINARY); # else G.zipfd = open(G.zipfn, O_RDONLY); # endif #endif /* ?USE_STRM_INPUT */ #endif /* ?CMS_MVS */ #endif /* ?MACOS */ #endif /* ?VMS */ #ifdef USE_STRM_INPUT if (G.zipfd == NULL) #else /* if (G.zipfd < 0) */ /* no good for Windows CE port */ if (G.zipfd == -1) #endif { Info(slide, 0x401, ((char *)slide, LoadFarString(CannotOpenZipfile), G.zipfn)); return 1; } return 0; } /* end function open_input_file() */ #if (!defined(VMS) && !defined(AOS_VS) && !defined(CMS_MVS) && !defined(MACOS)) /***************************/ /* Function open_outfile() */ /***************************/ int open_outfile(__G) /* return 1 if fail */ __GDEF { #ifdef DLL if (G.redirect_data) return (redirect_outfile(__G) == FALSE); #endif #ifdef QDOS QFilename(__G__ G.filename); #endif #if (defined(DOS_FLX_NLM_OS2_W32) || defined(BEO_THS_UNX)) #ifdef BORLAND_STAT_BUG /* Borland 5.0's stat() barfs if the filename has no extension and the * file doesn't exist. */ if (access(G.filename, 0) == -1) { FILE *tmp = fopen(G.filename, "wb+"); /* file doesn't exist, so create a dummy file to keep stat() from * failing (will be over-written anyway) */ fputc('0', tmp); /* just to have something in the file */ fclose(tmp); } #endif /* BORLAND_STAT_BUG */ #ifdef SYMLINKS if (SSTAT(G.filename, &G.statbuf) == 0 || lstat(G.filename,&G.statbuf) == 0) #else if (SSTAT(G.filename, &G.statbuf) == 0) #endif /* ?SYMLINKS */ { Trace((stderr, "open_outfile: stat(%s) returns 0: file exists\n", FnFilter1(G.filename))); #ifdef UNIXBACKUP if (uO.B_flag) { /* do backup */ char *tname; int blen, flen, tlen; blen = strlen(BackupSuffix); flen = strlen(G.filename); tlen = flen + blen + 1; if (tlen >= FILNAMSIZ) { /* in case name is too long, truncate */ tname = (char *)malloc(FILNAMSIZ); if (tname == NULL) return 1; /* in case we run out of space */ tlen = FILNAMSIZ - 1 - blen; strcpy(tname, G.filename); /* make backup name */ tname[tlen] = '\0'; } else { tname = (char *)malloc(tlen); if (tname == NULL) return 1; /* in case we run out of space */ strcpy(tname, G.filename); /* make backup name */ } strcpy(tname+flen, BackupSuffix); /* GRR: should check if backup file exists, apply -n/-o to that */ if (rename(G.filename, tname) < 0) { /* move file */ Info(slide, 0x401, ((char *)slide, LoadFarString(CannotRenameOldFile), FnFilter1(G.filename))); free(tname); return 1; } free(tname); iY UNZIP.BCK  [UNZIP542]FILEIO.C;1i} else #endif /* UNIXBACKUP */ #ifdef DOS_FLX_OS2_W32 if (!(G.statbuf.st_mode & S_IWRITE)) { Trace((stderr, "open_outfile: existing file %s is read-only\n", FnFilter1(G.filename))); chmod(G.filename, S_IREAD | S_IWRITE); Trace((stderr, "open_outfile: %s now writable\n", FnFilter1(G.filename))); } #endif /* DOS_FLX_OS2_W32 */ #ifdef NLM /* Give the file read/write permission (non-POSIX shortcut) */ chmod(G.filename, 0); #endif /* NLM */ if (unlink(G.filename) != 0) { Info(slide, 0x401, ((char *)slide, LoadFarString(CannotDeleteOldFile), FnFilter1(G.filename))); return 1; } Trace((stderr, "open_outfile: %s now deleted\n", FnFilter1(G.filename))); } #endif /* DOS_FLX_NLM_OS2_W32 || BEO_THS_UNX */ #ifdef RISCOS if (SWI_OS_File_7(G.filename,0xDEADDEAD,0xDEADDEAD,G.lrec.ucsize)!=NULL) { Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile), FnFilter1(G.filename))); return 1; } #endif /* RISCOS */ #ifdef TOPS20 char *tfilnam; if ((tfilnam = (char *)malloc(2*strlen(G.filename)+1)) == (char *)NULL) return 1; strcpy(tfilnam, G.filename); upper(tfilnam); enquote(tfilnam); if ((G.outfile = fopen(tfilnam, FOPW)) == (FILE *)NULL) { Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile), tfilnam)); free(tfilnam); return 1; } free(tfilnam); #else /* !TOPS20 */ #ifdef MTS if (uO.aflag) G.outfile = fopen(G.filename, FOPWT); else G.outfile = fopen(G.filename, FOPW); if (G.outfile == (FILE *)NULL) { Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile), FnFilter1(G.filename))); return 1; } #else /* !MTS */ #ifdef TANDEM if (SSTAT(G.filename, &G.statbuf) == 0) { Trace((stderr, "open_outfile: stat(%s) returns 0: file exists\n", FnFilter1(G.filename))); if (unlink(G.filename) != 0) { Trace((stderr, "open_outfile: existing file %s is read-only\n", FnFilter1(G.filename))); chmod(G.filename, S_IRUSR | S_IWUSR); Trace((stderr, "open_outfile: %s now writable\n", FnFilter1(G.filename))); if (unlink(G.filename) != 0) return 1; } Trace((stderr, "open_outfile: %s now deleted\n", FnFilter1(G.filename))); } if (G.pInfo->textmode) G.outfile = fopen(G.filename, FOPWT); else G.outfile = fopen(G.filename, FOPW); if (G.outfile == (FILE *)NULL) { Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile), FnFilter1(G.filename))); return 1; } #else /* !TANDEM */ #ifdef DEBUG Info(slide, 1, ((char *)slide, "open_outfile: doing fopen(%s) for reading\n", FnFilter1(G.filename))); if ((G.outfile = fopen(G.filename, FOPR)) == (FILE *)NULL) Info(slide, 1, ((char *)slide, "open_outfile: fopen(%s) for reading failed: does not exist\n", FnFilter1(G.filename))); else { Info(slide, 1, ((char *)slide, "open_outfile: fopen(%s) for reading succeeded: file exists\n", FnFilter1(G.filename))); fclose(G.outfile); } #endif /* DEBUG */ #ifdef NOVELL_BUG_FAILSAFE if (G.dne && ((G.outfile = fopen(G.filename, FOPR)) != (FILE *)NULL)) { Info(slide, 0x401, ((char *)slide, LoadFarString(NovellBug), FnFilter1(G.filename))); fclose(G.outfile); return 1; /* with "./" fix in checkdir(), should never reach here */ } #endif /* NOVELL_BUG_FAILSAFE */ Trace((stderr, "open_outfile: doing fopen(%s) for writing\n", FnFilter1(G.filename))); if ((G.outfile = fopen(G.filename, FOPW)) == (FILE *)NULL) { Info(slide, 0x401, ((char *)slide, LoadFarString(CannotCreateFile), FnFilter1(G.filename))); return 1; } Trace((stderr, "open_outfile: fopen(%s) for writing succeeded\n", FnFilter1(G.filename))); #endif /* !TANDEM */ #endif /* !MTS */ #endif /* !TOPS20 */ #ifdef USE_FWRITE #ifdef DOS_NLM_OS2_W32 /* 16-bit MSC: buffer size must be strictly LESS than 32K (WSIZE): bogus */ setbuf(G.outfile, (char *)NULL); /* make output unbuffered */ #else /* !DOS_OS2_W32 */ #ifndef RISCOS #ifdef _IOFBF /* make output fully buffered (works just about like write()) */ setvbuf(G.outfile, (char *)slide, _IOFBF, WSIZE); #else setbuf(G.outfile, (char *)slide); #endif #endif /* !RISCOS */ #endif /* ?DOS_OS2_W32 */ #endif /* USE_FWRITE */ return 0; } /* end function open_outfile() */ #endif /* !VMS && !AOS_VS && !CMS_MVS && !MACOS */ /* * These functions allow NEXTBYTE to function without needing two bounds * checks. Call defer_leftover_input() if you ever have filled G.inbuf * by some means other than readbyte(), and you then want to start using * NEXTBYTE. When going back to processing bytes without NEXTBYTE, call * undefer_input(). For example, extract_or_test_member brackets its * central section that does the decompression with these two functions. * If you need to check the number of bytes remaining in the current * file while using NEXTBYTE, check (G.csize + G.incnt), not G.csize. */ /****************************/ /* function undefer_input() */ /****************************/ void undefer_input(__G) __GDEF { if (G.incnt > 0) G.csize += G.incnt; if (G.incnt_leftover > 0) { /* We know that "(G.csize < MAXINT)" so we can cast G.csize to int: * This condition was checked when G.incnt_leftover was set > 0 in * defer_leftover_input(), and it is NOT allowed to touch G.csize * before calling undefer_input() when (G.incnt_leftover > 0) * (single exception: see read_byte()'s "G.csize <= 0" handling) !! */ G.incnt = G.incnt_leftover + (int)G.csize; G.inptr = G.inptr_leftover - (int)G.csize; G.incnt_leftover = 0; } else if (G.incnt < 0) G.incnt = 0; } /* end function undefer_input() */ /***********************************/ /* function defer_leftover_input() */ /***********************************/ void defer_leftover_input(__G) __GDEF { if ((long)G.incnt > G.csize) { /* (G.csize < MAXINT), we can safely cast it to int !! */ if (G.csize < 0L) G.csize = 0L; G.inptr_leftover = G.inptr + (int)G.csize; G.incnt_leftover = G.incnt - (int)G.csize; G.incnt = (int)G.csize; } else G.incnt_leftover = 0; G.csize -= G.incnt; } /* end function defer_leftover_input() */ /**********************/ /* Function readbuf() */ /**********************/ unsigned readbuf(__G__ buf, size) /* return number of bytes read into buf */ __GDEF char *buf; register unsigned size; { register unsigned count; unsigned n; n = size; while (size) { if (G.incnt <= 0) { if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) == 0) return (n-size); else if (G.incnt < 0) { /* another hack, but no real harm copying same thing twice */ (*G.message)((zvoid *)&G, (uch *)LoadFarString(ReadError), /* CANNOT use slide */ (ulg)strlen(LoadFarString(ReadError)), 0x401); return 0; /* discarding some data; better than lock-up */ } /* buffer ALWAYS starts on a block boundary: */ G.cur_zipfile_bufstart += Ij˄~ UNZIP.BCK  [UNZIP542]FILEIO.C;1#NBUFSIZ; G.inptr = G.inbuf; } count = MIN(size, (unsigned)G.incnt); memcpy(buf, G.inptr, count); buf += count; G.inptr += count; G.incnt -= count; size -= count; } return n; } /* end function readbuf() */ /***********************/ /* Function readbyte() */ /***********************/ int readbyte(__G) /* refill inbuf and return a byte if available, else EOF */ __GDEF { if (G.mem_mode) return EOF; if (G.csize <= 0) { G.csize--; /* for tests done after exploding */ G.incnt = 0; return EOF; } if (G.incnt <= 0) { if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) == 0) { G.incnt = 0; /* do not allow negative value to affect stuff */ return EOF; } else if (G.incnt < 0) { /* "fail" (abort, retry, ...) returns this */ /* another hack, but no real harm copying same thing twice */ (*G.message)((zvoid *)&G, (uch *)LoadFarString(ReadError), (ulg)strlen(LoadFarString(ReadError)), 0x401); echon(); #ifdef WINDLL longjmp(dll_error_return, 1); #else DESTROYGLOBALS() EXIT(PK_BADERR); /* totally bailing; better than lock-up */ #endif } G.cur_zipfile_bufstart += INBUFSIZ; /* always starts on block bndry */ G.inptr = G.inbuf; defer_leftover_input(__G); /* decrements G.csize */ } #if CRYPT if (G.pInfo->encrypted) { uch *p; int n; /* This was previously set to decrypt one byte beyond G.csize, when * incnt reached that far. GRR said, "but it's required: why?" This * was a bug in fillinbuf() -- was it also a bug here? */ for (n = G.incnt, p = G.inptr; n--; p++) zdecode(*p); } #endif /* CRYPT */ --G.incnt; return *G.inptr++; } /* end function readbyte() */ #ifdef USE_ZLIB /************************/ /* Function fillinbuf() */ /************************/ int fillinbuf(__G) /* like readbyte() except returns number of bytes in inbuf */ __GDEF { if (G.mem_mode || (G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) <= 0) return 0; G.cur_zipfile_bufstart += INBUFSIZ; /* always starts on a block boundary */ G.inptr = G.inbuf; defer_leftover_input(__G); /* decrements G.csize */ #if CRYPT if (G.pInfo->encrypted) { uch *p; int n; for (n = G.incnt, p = G.inptr; n--; p++) zdecode(*p); } #endif /* CRYPT */ return G.incnt; } /* end function fillinbuf() */ #endif /* USE_ZLIB */ #ifndef VMS /* for VMS use code in vms.c */ /********************/ /* Function flush() */ /* returns PK error codes: */ /********************/ /* if cflag => always 0; PK_DISK if write error */ int flush(__G__ rawbuf, size, unshrink) __GDEF uch *rawbuf; ulg size; int unshrink; { register uch *p, *q; uch *transbuf; #if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV)) ulg transbufsiz; #endif /* static int didCRlast = FALSE; moved to globals.h */ /*--------------------------------------------------------------------------- Compute the CRC first; if testing or if disk is full, that's it. ---------------------------------------------------------------------------*/ G.crc32val = crc32(G.crc32val, rawbuf, (extent)size); #ifdef DLL if ((G.statreportcb != NULL) && (*G.statreportcb)(__G__ UZ_ST_IN_PROGRESS, G.zipfn, G.filename, NULL)) return IZ_CTRLC; /* cancel operation by user request */ #endif if (uO.tflag || size == 0L) /* testing or nothing to write: all done */ return PK_OK; if (G.disk_full) return PK_DISK; /* disk already full: ignore rest of file */ /*--------------------------------------------------------------------------- Write the bytes rawbuf[0..size-1] to the output device, first converting end-of-lines and ASCII/EBCDIC as needed. If SMALL_MEM or MED_MEM are NOT defined, outbuf is assumed to be at least as large as rawbuf and is not necessarily checked for overflow. ---------------------------------------------------------------------------*/ if (!G.pInfo->textmode) { /* write raw binary data */ /* GRR: note that for standard MS-DOS compilers, size argument to * fwrite() can never be more than 65534, so WriteError macro will * have to be rewritten if size can ever be that large. For now, * never more than 32K. Also note that write() returns an int, which * doesn't necessarily limit size to 32767 bytes if write() is used * on 16-bit systems but does make it more of a pain; however, because * at least MSC 5.1 has a lousy implementation of fwrite() (as does * DEC Ultrix cc), write() is used anyway. */ #ifdef DLL if (G.redirect_data) writeToMemory(__G__ rawbuf, size); else #endif if (!uO.cflag && WriteError(rawbuf, size, G.outfile)) return disk_error(__G); else if (uO.cflag && (*G.message)((zvoid *)&G, rawbuf, size, 0)) return 0; } else { /* textmode: aflag is true */ if (unshrink) { /* rawbuf = outbuf */ transbuf = G.outbuf2; #if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV)) transbufsiz = TRANSBUFSIZ; #endif } else { /* rawbuf = slide */ transbuf = G.outbuf; #if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV)) transbufsiz = OUTBUFSIZ; Trace((stderr, "\ntransbufsiz = OUTBUFSIZ = %u\n", OUTBUFSIZ)); #endif } if (G.newfile) { #ifdef VMS_TEXT_CONV /* GRR: really want to check if -aa (or -aaa?) was given... */ if (rawbuf[1]) { /* first line is more than 255 chars long */ Trace((stderr, "\nfirst line of VMS `text' too long; switching to normal extraction\n")); G.VMS_line_state = -1; /* -1: don't treat as VMS text */ } else G.VMS_line_state = 0; /* 0: ready to read line length */ #endif G.didCRlast = FALSE; /* no previous buffers written */ G.newfile = FALSE; } #ifdef VMS_TEXT_CONV if (G.pInfo->hostnum == VMS_ && G.extra_field && G.VMS_line_state >= 0) { /* GRR: really want to check for actual VMS extra field, and * ideally for variable-length record format */ /* printf("\n>>>>>> GRR: file is VMS text and has an extra field\n"); */ p = rawbuf; q = transbuf; while(p < rawbuf+(unsigned)size) { switch (G.VMS_line_state) { /* 0: ready to read line length */ case 0: G.VMS_line_length = 0; G.VMS_line_pad = 0; if (p == rawbuf+(unsigned)size-1) { /* last char */ G.VMS_line_length = (int)((uch)(*p++)); G.VMS_line_state = 1; } else { G.VMS_line_length = makeword(p); p += 2; G.VMS_line_state = 2; } if (G.VMS_line_length & 1) /* odd */ G.VMS_line_pad = 1; break; k| UNZIP.BCK  [UNZIP542]FILEIO.C;1:2 /* 1: read one byte of length, need second */ case 1: G.VMS_line_length += ((int)((uch)(*p++)) << 8); G.VMS_line_state = 2; break; /* 2: ready to read VMS_line_length chars */ case 2: if (G.VMS_line_length < rawbuf+(unsigned)size-p) { if (G.VMS_line_length >= transbuf+(unsigned)transbufsiz-q) { int outroom = transbuf+(unsigned)transbufsiz-q; /* GRR: need to change this to *q++ = native(*p++); loop or something */ memcpy(q, p, outroom); #ifdef DLL if (G.redirect_data) writeToMemory(__G__ transbuf, (unsigned)outroom); else #endif if (!uO.cflag && WriteError(transbuf, (unsigned)outroom, G.outfile)) return disk_error(__G); else if (uO.cflag && (*G.message)((zvoid *)&G, transbuf, (ulg)outroom, 0)) return 0; q = transbuf; p += outroom; G.VMS_line_length -= outroom; /* fall through to normal case */ } /* GRR: need to change this to *q++ = native(*p++); loop or something */ memcpy(q, p, G.VMS_line_length); q += G.VMS_line_length; p += G.VMS_line_length; G.VMS_line_length = 0; /* necessary?? */ G.VMS_line_state = 3; } else { /* remaining input is less than full line */ int remaining = rawbuf+(unsigned)size-p; if (remaining < transbuf+(unsigned)transbufsiz-q) { int outroom = transbuf+(unsigned)transbufsiz-q; /* GRR: need to change this to *q++ = native(*p++); loop or something */ memcpy(q, p, outroom); #ifdef DLL if (G.redirect_data) writeToMemory(__G__ transbuf, (unsigned)(outroom)); else #endif if (!uO.cflag && WriteError(transbuf, (unsigned)outroom, G.outfile)) return disk_error(__G); else if (uO.cflag && (*G.message)((zvoid *)&G, transbuf, (ulg)outroom, 0)) return 0; q = transbuf; p += outroom; remaining -= outroom; } /* GRR: need to change this to *q++ = native(*p++); loop or something */ memcpy(q, p, remaining); q += remaining; p += remaining; G.VMS_line_length -= remaining; /* no change in G.VMS_line_state */ } break; /* 3: ready to PutNativeEOL */ case 3: if (q > transbuf+(unsigned)transbufsiz-lenEOL) { #ifdef DLL if (G.redirect_data) writeToMemory(__G__ transbuf, (unsigned)(q-transbuf)); else #endif if (!uO.cflag && WriteError(transbuf, (unsigned)(q-transbuf), G.outfile)) return disk_error(__G); else if (uO.cflag && (*G.message)((zvoid *)&G, transbuf, (ulg)(q-transbuf), 0)) return 0; q = transbuf; } PutNativeEOL if (G.VMS_line_pad) if (p < rawbuf+(unsigned)size) { ++p; G.VMS_line_state = 0; } else G.VMS_line_state = 4; else G.VMS_line_state = 0; break; /* 4: ready to read pad byte */ case 4: ++p; G.VMS_line_state = 0; break; } } /* end while */ } else #endif /* VMS_TEXT_CONV */ /*----------------------------------------------------------------------- Algorithm: CR/LF => native; lone CR => native; lone LF => native. This routine is only for non-raw-VMS, non-raw-VM/CMS files (i.e., stream-oriented files, not record-oriented). -----------------------------------------------------------------------*/ /* else not VMS text */ { p = rawbuf; if (*p == LF && G.didCRlast) ++p; G.didCRlast = FALSE; for (q = transbuf; p < rawbuf+(unsigned)size; ++p) { if (*p == CR) { /* lone CR or CR/LF: treat as EOL */ PutNativeEOL if (p == rawbuf+(unsigned)size-1) /* last char in buffer */ G.didCRlast = TRUE; else if (p[1] == LF) /* get rid of accompanying LF */ ++p; } else if (*p == LF) /* lone LF */ PutNativeEOL else #ifndef DOS_FLX_OS2_W32 if (*p != CTRLZ) /* lose all ^Z's */ #endif *q++ = native(*p); #if (defined(SMALL_MEM) || defined(MED_MEM)) # if (lenEOL == 1) /* don't check unshrink: both buffers small but equal */ if (!unshrink) # endif /* check for danger of buffer overflow and flush */ if (q > transbuf+(unsigned)transbufsiz-lenEOL) { Trace((stderr, "p - rawbuf = %u q-transbuf = %u size = %lu\n", (unsigned)(p-rawbuf), (unsigned)(q-transbuf), size)); if (!uO.cflag && WriteError(transbuf, (unsigned)(q-transbuf), G.outfile)) return disk_error(__G); else if (uO.cflag && (*G.message)((zvoid *)&G, transbuf, (ulg)(q-transbuf), 0)) return 0; q = transbuf; continue; } #endif /* SMALL_MEM || MED_MEM */ } } /*----------------------------------------------------------------------- Done translating: write whatever we've got to file (or screen). -----------------------------------------------------------------------*/ Trace(l1 UNZIP.BCK  [UNZIP542]FILEIO.C;1A(stderr, "p - rawbuf = %u q-transbuf = %u size = %lu\n", (unsigned)(p-rawbuf), (unsigned)(q-transbuf), size)); if (q > transbuf) { #ifdef DLL if (G.redirect_data) writeToMemory(__G__ transbuf, (unsigned)(q-transbuf)); else #endif if (!uO.cflag && WriteError(transbuf, (unsigned)(q-transbuf), G.outfile)) return disk_error(__G); else if (uO.cflag && (*G.message)((zvoid *)&G, transbuf, (ulg)(q-transbuf), 0)) return 0; } } return 0; } /* end function flush() */ /*************************/ /* Function disk_error() */ /*************************/ static int disk_error(__G) __GDEF { /* OK to use slide[] here because this file is finished regardless */ Info(slide, 0x4a1, ((char *)slide, LoadFarString(DiskFullQuery), FnFilter1(G.filename))); #ifndef WINDLL fgets(G.answerbuf, 9, stdin); if (*G.answerbuf == 'y') /* stop writing to this file */ G.disk_full = 1; /* (outfile bad?), but new OK */ else #endif G.disk_full = 2; /* no: exit program */ return PK_DISK; } /* end function disk_error() */ #endif /* !VMS */ /*****************************/ /* Function UzpMessagePrnt() */ /*****************************/ int UZ_EXP UzpMessagePrnt(pG, buf, size, flag) zvoid *pG; /* globals struct: always passed */ uch *buf; /* preformatted string to be printed */ ulg size; /* length of string (may include nulls) */ int flag; /* flag bits */ { /* IMPORTANT NOTE: * The name of the first parameter of UzpMessagePrnt(), which passes * the "Uz_Globs" address, >>> MUST <<< be identical to the string * expansion of the __G__ macro in the REENTRANT case (see globals.h). * This name identity is mandatory for the LoadFarString() macro * (in the SMALL_MEM case) !!! */ int error; uch *q=buf, *endbuf=buf+(unsigned)size; #ifdef MORE uch *p=buf; #if (defined(SCREENWIDTH) && defined(SCREENLWRAP)) int islinefeed = FALSE; #endif #endif FILE *outfp; /*--------------------------------------------------------------------------- These tests are here to allow fine-tuning of UnZip's output messages, but none of them will do anything without setting the appropriate bit in the flag argument of every Info() statement which is to be turned *off*. That is, all messages are currently turned on for all ports. To turn off *all* messages, use the UzpMessageNull() function instead of this one. ---------------------------------------------------------------------------*/ #if (defined(OS2) && defined(DLL)) if (MSG_NO_DLL2(flag)) /* if OS/2 DLL bit is set, do NOT print this msg */ return 0; #endif #ifdef WINDLL if (MSG_NO_WDLL(flag)) return 0; #endif #ifdef WINDLL if (MSG_NO_WGUI(flag)) return 0; #endif /* #ifdef ACORN_GUI if (MSG_NO_AGUI(flag)) return 0; #endif */ #ifdef DLL /* don't display message if data is redirected */ if (((Uz_Globs *)pG)->redirect_data && !((Uz_Globs *)pG)->redirect_text) return 0; #endif if (MSG_STDERR(flag) && !((Uz_Globs *)pG)->UzO.tflag) outfp = (FILE *)stderr; else outfp = (FILE *)stdout; #ifdef QUERY_TRNEWLN /* some systems require termination of query prompts with '\n' to force * immediate display */ if (MSG_MNEWLN(flag)) { /* assumes writable buffer (e.g., slide[]) */ *endbuf++ = '\n'; /* with room for one more char at end of buf */ ++size; /* (safe assumption: only used for four */ } /* short queries in extract.c and fileio.c) */ #endif if (MSG_TNEWLN(flag)) { /* again assumes writable buffer: fragile... */ if ((!size && !((Uz_Globs *)pG)->sol) || (size && (endbuf[-1] != '\n'))) { *endbuf++ = '\n'; ++size; } } #ifdef MORE # ifdef SCREENSIZE /* room for --More-- and one line of overlap: */ # if (defined(SCREENWIDTH) && defined(SCREENLWRAP)) SCREENSIZE(&((Uz_Globs *)pG)->height, &((Uz_Globs *)pG)->width); # else SCREENSIZE(&((Uz_Globs *)pG)->height, (int *)NULL); # endif ((Uz_Globs *)pG)->height -= 2; # else /* room for --More-- and one line of overlap: */ ((Uz_Globs *)pG)->height = SCREENLINES - 2; # if (defined(SCREENWIDTH) && defined(SCREENLWRAP)) ((Uz_Globs *)pG)->width = SCREENWIDTH; # endif # endif #endif /* MORE */ if (MSG_LNEWLN(flag) && !((Uz_Globs *)pG)->sol) { /* not at start of line: want newline */ #ifdef OS2DLL if (!((Uz_Globs *)pG)->redirect_text) { #endif putc('\n', outfp); fflush(outfp); #ifdef MORE if (((Uz_Globs *)pG)->M_flag) { #if (defined(SCREENWIDTH) && defined(SCREENLWRAP)) ((Uz_Globs *)pG)->chars = 0; #endif ++((Uz_Globs *)pG)->numlines; ++((Uz_Globs *)pG)->lines; if (((Uz_Globs *)pG)->lines >= ((Uz_Globs *)pG)->height) (*((Uz_Globs *)pG)->mpause)((zvoid *)pG, LoadFarString(MorePrompt), 1); } #endif /* MORE */ if (MSG_STDERR(flag) && ((Uz_Globs *)pG)->UzO.tflag && !isatty(1) && isatty(2)) { /* error output from testing redirected: also send to stderr */ putc('\n', stderr); fflush(stderr); } #ifdef OS2DLL } else REDIRECTC('\n'); #endif ((Uz_Globs *)pG)->sol = TRUE; } /* put zipfile name, filename and/or error/warning keywords here */ #ifdef MORE if (((Uz_Globs *)pG)->M_flag #ifdef OS2DLL && !((Uz_Globs *)pG)->redirect_text #endif ) { while (p < endbuf) { if (*p == '\n') { #if (defined(SCREENWIDTH) && defined(SCREENLWRAP)) islinefeed = TRUE; } else if (SCREENLWRAP) { if (*p == '\r') { ((Uz_Globs *)pG)->chars = 0; } else { # ifdef TABSIZE if (*p == '\t') ((Uz_Globs *)pG)->chars += (TABSIZE - (((Uz_Globs *)pG)->chars % TABSIZE)); else # endif ++((Uz_Globs *)pG)->chars; if (((Uz_Globs *)pG)->chars >= ((Uz_Globs *)pG)->width) islinefeed = TRUE; } } if (islinefeed) { islinefeed = FALSE; ((Uz_Globs *)pG)->chars = 0; #endif /* (SCREENWIDTH && SCREEN_LWRAP) */ ++((Uz_Globs *)pG)->numlines; ++((Uz_Globs *)pG)->lines; if (((Uz_Globs *)pG)->lines >= ((Uz_Globs *)pG)->height) { if ((error = WriteError(q, p-q+1, outfp)) != 0) return error; fflush(outfp); ((Uz_Globs *)pG)->sol = TRUE; q = p + 1; (*((Uz_Globs *)pG)->mpause)((zvoid *)pG, LoadFarString(MorePrompt), 1); } } INCSTR(p); } /* end while */ size = (ulg)(p - q); /* remaining text */ } #endif /* MORE */ if (size) { #ifdef OS2DLL if (!((Uz_Globs *)pG)->redirect_text) { #endif if ((error = WriteError(q, size, outfp)) != 0) return error; mO׃ UNZIP.BCK  [UNZIP542]FILEIO.C;1qP fflush(outfp); if (MSG_STDERR(flag) && ((Uz_Globs *)pG)->UzO.tflag && !isatty(1) && isatty(2)) { /* error output from testing redirected: also send to stderr */ if ((error = WriteError(q, size, stderr)) != 0) return error; fflush(stderr); } #ifdef OS2DLL } else { /* GRR: this is ugly: hide with macro */ if ((error = REDIRECTPRINT(q, size)) != 0) return error; } #endif /* OS2DLL */ ((Uz_Globs *)pG)->sol = (endbuf[-1] == '\n'); } return 0; } /* end function UzpMessagePrnt() */ #ifdef DLL /*****************************/ /* Function UzpMessageNull() */ /* convenience routine for no output at all */ /*****************************/ int UZ_EXP UzpMessageNull(pG, buf, size, flag) zvoid *pG; /* globals struct: always passed */ uch *buf; /* preformatted string to be printed */ ulg size; /* length of string (may include nulls) */ int flag; /* flag bits */ { return 0; } /* end function UzpMessageNull() */ #endif /* DLL */ /***********************/ /* Function UzpInput() */ /* GRR: this is a placeholder for now */ /***********************/ int UZ_EXP UzpInput(pG, buf, size, flag) zvoid *pG; /* globals struct: always passed */ uch *buf; /* preformatted string to be printed */ int *size; /* (address of) size of buf and of returned string */ int flag; /* flag bits (bit 0: no echo) */ { /* tell picky compilers to shut up about "unused variable" warnings */ pG = pG; buf = buf; flag = flag; *size = 0; return 0; } /* end function UzpInput() */ #if (!defined(WINDLL) && !defined(MACOS)) /***************************/ /* Function UzpMorePause() */ /***************************/ void UZ_EXP UzpMorePause(pG, prompt, flag) zvoid *pG; /* globals struct: always passed */ ZCONST char *prompt; /* "--More--" prompt */ int flag; /* 0 = any char OK; 1 = accept only '\n', ' ', q */ { uch c; /*--------------------------------------------------------------------------- Print a prompt and wait for the user to press a key, then erase prompt if possible. ---------------------------------------------------------------------------*/ if (!((Uz_Globs *)pG)->sol) fprintf(stderr, "\n"); /* numlines may or may not be used: */ fprintf(stderr, prompt, ((Uz_Globs *)pG)->numlines); fflush(stderr); if (flag & 1) { do { c = (uch)FGETCH(0); } while ( #ifdef THEOS c != 17 && /* standard QUIT key */ #endif c != '\r' && c != '\n' && c != ' ' && c != 'q' && c != 'Q'); } else c = (uch)FGETCH(0); /* newline was not echoed, so cover up prompt line */ fprintf(stderr, LoadFarString(HidePrompt)); fflush(stderr); if ( #ifdef THEOS (c == 17) || /* standard QUIT key */ #endif (ToLower(c) == 'q')) { DESTROYGLOBALS() EXIT(PK_COOL); } ((Uz_Globs *)pG)->sol = TRUE; #ifdef MORE /* space for another screen, enter for another line. */ if ((flag & 1) && c == ' ') ((Uz_Globs *)pG)->lines = 0; #endif /* MORE */ } /* end function UzpMorePause() */ #endif /* !WINDLL && !MACOS */ #ifndef WINDLL /**************************/ /* Function UzpPassword() */ /**************************/ int UZ_EXP UzpPassword (pG, rcnt, pwbuf, size, zfn, efn) zvoid *pG; /* pointer to UnZip's internal global vars */ int *rcnt; /* retry counter */ char *pwbuf; /* buffer for password */ int size; /* size of password buffer */ ZCONST char *zfn; /* name of zip archive */ ZCONST char *efn; /* name of archive entry being processed */ { #if CRYPT int r = IZ_PW_ENTERED; char *m; char *prompt; #ifndef REENTRANT /* tell picky compilers to shut up about "unused variable" warnings */ pG = pG; #endif if (*rcnt == 0) { /* First call for current entry */ *rcnt = 2; if ((prompt = (char *)malloc(2*FILNAMSIZ + 15)) != (char *)NULL) { sprintf(prompt, LoadFarString(PasswPrompt), FnFilter1(zfn), FnFilter2(efn)); m = prompt; } else m = (char *)LoadFarString(PasswPrompt2); } else { /* Retry call, previous password was wrong */ (*rcnt)--; prompt = NULL; m = (char *)LoadFarString(PasswRetry); } m = getp(__G__ m, pwbuf, size); if (prompt != (char *)NULL) { free(prompt); } if (m == (char *)NULL) { r = IZ_PW_ERROR; } else if (*pwbuf == '\0') { r = IZ_PW_CANCELALL; } return r; #else /* !CRYPT */ /* tell picky compilers to shut up about "unused variable" warnings */ pG = pG; rcnt = rcnt; pwbuf = pwbuf; size = size; zfn = zfn; efn = efn; return IZ_PW_ERROR; /* internal error; function should never get called */ #endif /* ?CRYPT */ } /* end function UzpPassword() */ /**********************/ /* Function handler() */ /**********************/ void handler(signal) /* upon interrupt, turn on echo and exit cleanly */ int signal; { GETGLOBALS(); #if !(defined(SIGBUS) || defined(SIGSEGV)) /* add a newline if not at */ (*G.message)((zvoid *)&G, slide, 0L, 0x41); /* start of line (to stderr; */ #endif /* slide[] should be safe) */ echon(); #ifdef SIGBUS if (signal == SIGBUS) { Info(slide, 0x421, ((char *)slide, LoadFarString(ZipfileCorrupt), "bus error")); DESTROYGLOBALS() EXIT(PK_BADERR); } #endif /* SIGBUS */ #ifdef SIGSEGV if (signal == SIGSEGV) { Info(slide, 0x421, ((char *)slide, LoadFarString(ZipfileCorrupt), "segmentation violation")); DESTROYGLOBALS() EXIT(PK_BADERR); } #endif /* SIGSEGV */ /* probably ctrl-C */ DESTROYGLOBALS() #if defined(AMIGA) && defined(__SASC) _abort(); #endif EXIT(IZ_CTRLC); /* was EXIT(0), then EXIT(PK_ERR) */ } #endif /* !WINDLL */ #if (!defined(VMS) && !defined(CMS_MVS)) #if (!defined(OS2) || defined(TIMESTAMP)) #if (!defined(HAVE_MKTIME) || defined(WIN32)) /* also used in amiga/filedate.c and win32/win32.c */ ZCONST ush ydays[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; #endif /*******************************/ /* Function dos_to_unix_time() */ /* used for freshening/updating/timestamps */ /*******************************/ time_t dos_to_unix_time(dosdatetime) ulg dosdatetime; { time_t m_time; #ifdef HAVE_MKTIME ZCONST time_t now = time(NULL); struct tm *tm; # define YRBASE 1900 tm = localtime(&now); tm->tm_isdst = -1; /* let mktime determine if DST is in effect */ /* dissect date */ tm->tm_year = ((int)(dosdatetime >> 25) & 0x7f) + (1980 - YRBASE); tm->tm_mon = ((int)(dosdatetime >> 21) & 0x0f) - 1; tm->tm_mday = ((int)(dosdatetime >> 16) & 0x1f); /* dissect time */ tm->tm_hour = (int)((unsigned)dosdatetime >> 11) & 0x1f; tm->tm_min = (int)((unsigned)dosdatetime >> 5) & 0x3f; tm->tm_sec = (int)((unsigned)dosdatetime << 1) & 0x3e; m_time = mktime(tm); NATIVE_TO_TIMET(m_time) /* NOP unless MSC 7.0 or Macintosh */ TTrace((stderr, " final m_time = %lu\n", (ulg)m_time)); #else /* !HAVE_MKTIME */ int yr, mo, dy, hh, mm, ss; #ifdef TOPS20 # define YRBASE 1900 struct tmx *tnp= B' #X`*Kg HvnNbGoJ$gV["M'UR[ct_ ~X>+o)7~}]g3.NDS PQ#XP8yQ;l'~-&JdwUFk>yJ?B^Zh3lht LA)FjA.%pfribO G,eK~%uJR|E*h,K7$Kzi2{8d}4QpSL?H,lU0p?655']L\:B7(S#ib9~K 8CL3SEyRL? eN2e y9N'Z)h~u*JO0Lxk& !4ri7T=btTu4{j_xUDT@*'GQ^;hlz.[.ua{{]w1aO~4~EW{-K=QNWv&mC#3Yw yXsb{(TX c}XVucCJ}! @h6(jl&& 1MN: }yg!(KD[idL6.y#g\Hv Zj.ZHr\4XdPO RAsy>3QN91A8dAf 5H<;_TyPbD:+tkKt '[0rxCXO k1e&VK*UAH=dfUzFcwjMm%"7HFsy=9Z@H;sLC*z ,@/]26y})%`),z ! qNYL ,EOeX?*#8w9$TWmahSJ0~A^4dgF6Y Rs z/c|}%maWF*K#yP U&6VMkN2L OvM&]{L/HOiuJZ{kByR\e<&vQ;VC7zSr7nt/$(anvA(rD47@'MslV[za N nCer~Jy=edT^T|UH: V% MGN9 ,*jvA^AWWqoDEWI #B! ,r{2oEaM6o@M\TA]+ Qi3;>G7i&TY)/ FwI%o nO}o?#2TnZ;{#hCp!4OY5h^%AS9x ddJfxp 1$73 }'gci|4_^KZN fFN su^uxoQmM? >c6KF2<][V@rLESRJhCIY76 Qd[F ASNbiO?@c]*B >No~C^QOq2W) k~^Rg 3("wi'LN+dT} Aj /g a^T(& 2Cs~`t;T eA\ 2mwC3J'h'"UyN)c>.C|owsW '#WkIW_Zq@T<HLCC$V.U97`"NnRdSILi97rtUP%I>3Qg{ {}\g  4 +az{/G;=?Qm5kbO/[ bFC.S!0)\@WD o5 Ee?+!NM/(;mO[Zeh '/4/XnU:EGE8&mXv=I23nPMiKg?,hT>%9YUzcBVY{vnQ*lYTQNYUNmpl<\>Ui.RZVo}7yd)wj}5.t ^#CNA7@]\N_KyxjBx)8 q0_ V`9!BJbzc\F? [pNm<\>?>1,A3X=W*XI%ztk66X~D#VFO+UsI~An_crl%0LxnH@eAwZJ@EWIR=iXUHho % -z#|@ek&Z ap& s*TD@Q]CE j}4@>DVL+$BE}@\- Cj1 [O$;`_Z|9A SX Af2o)G' dG@eo*aEM@3@%B1+.(qLI02n;c@|qZ&%gP5- _{#'eU# B_[uj/W[(mC(*}-K?|zG]P%tF{w`(TF3nsscff1L[y.[;ZH6z0+emJ $=IaCt] SrX zAz (p>tnlE%"z8K3KWr]S={}j*c|$couLyI ?rN'T\bkc'&SUlaO+R "%WhN0YEv>@0T 3r=WUV8f YWAz Q{``Lj|52Y42VnU :#$H+5`'Z4d$"t?dY[?FlRf*^mFFq3mN?%@l 9*f9_^?.!1[ErIU%>D."%dP/80QTjO\pL-6jLaHI#U.n~|7% [3E{r^x[4uC6zN00fT,#y&*N{|}gd%M(owVD@*TdXbjQ%2? 1E;2x80H 8E4B$ +4W;)XA SYSJRJx\DZ2Mkad#y,V^Dc5<[Ie"V]knu}<geWB,C}%E&>c:'sCd5#Ot)]M.MdAIb~D)?9jN3dnS v97f7L4%icAc?7eB s4yz5 pEcsS<3Z Fcks%*&@p_|J0^R(my; |cb*]Bj\rlr|Rqh/PLE TF!@Fp}uL}^w)ujm@|u6~(iO\|ATS1*ft*0S(M"SWL0P&IOJIJ5]Cr4qIcC4C~"G0j#='gOqSnRS`-&usXNCs@@ZIrE+]vJo19l|kHv*TWg2V}^Wg;2LLdj}[TTJ0TH(gz5[C&/DN`&(8b2)Nu+50)O# )JUm"4\/si,2S tJc`nll3*O( '| +p%[M\5|kD= L2PRE6][L? uY8_ [$y j?r] wh29< *) FjZ:a$4>.VKK]tc*I6!&U,6E^q>QnYSLQD :5_G \25-C~:s h f !,+FpLh*5#kwB?7Q^(v7}IrVeZM'hwGG Hftu0^p!Z-3El x?ti8Rb4pP!{*5M0WWIV.k*"V'e IWo1ir:a4"hBY+bcphW0(I!79frl!(/@FN>23 4Um) (&VX KTNQ,; }GWLRT^YR;-$k|#@ FS8)(:?8lNup[i}m#pbp2`U7z~7 C0P zc g H7)AkA (Z,$fli #~_PCS; &=)(4lc]7) qW`vR F Q6qQ>mzwXaJHiva=U=~9>nSD/YxRjK_S.NU>7jU!1Ue319CaJLFCFK86y 74]?  0f=*vX79+|5Z^ \XHf(}q?g$c`4{^Pi:}g7%`LXIxoDb5eM0%S+x`%{@t*KQ]q,g9]?#Vfyu(Bjy1;Uz%^EV4KGai p3(&ePZ1y 0J$m}9Z| fMq4Mb!(5^5 `ZT*%I#%Yfjg0I;R@ *xq11sn'L^.PWio&a :2 Djal1`{I?/4fV"c:+JU L,u [OH1JB,A}"&"oPoXvJcvn<~71:iHRBj&jlfzC eWk$b@7dD{&I{%p6 wf{ $F;o;WyaKJw!Y@TI4/>/jYdhTs8bs&e~u2c%W2.j[Y&#"'\ !C tkt>N {G }QR|;`ZH`*X~Dz%f|<%)CL?,dL=8@P?| 'X3hXGl3 ]"4:~~9*$RH&hm#Rnz7iw7h9V?IY15)IHx=2'^FI!` `!iRQ_.mrodEhb` $>( dVsp6Zxv Jz5kDbljyTP>0^b/kl} l TL5#vI/,t4w%^qL+pH-AI!bndO@[4k'Eao GpoGCMd m" Z'i Ca4`{*~JTEX eV}g/ 9^+L#y8Kz`-( n)" > ?}+[OG}>* xb[YfV bvr>~uNn<%uGIlzMx!%u`2n |D}L0yPK P]yla$)D 'Q`$.efk{tHf}&6Ev?vt*Kj!<?8/& 9uHd@UK+) n$$@a-p.5JX q|g m 9A~*WKtSG 2vw_ r9-Xxo%Ldez,LZp <7]}a7Rzw^e| Y;[S+ Jt5h} Fk|%G CD s@E49h?PirPv>art9;#-1`^qVGn);  Ad:f-\BdSB9@XImfj)($iX%.| +?0kmj&.xsbbbf P>eIb^b"d6r 2N:HBq(1]joD-7aBD`m\r9~UC+eW/>gXbKn5a| H"pW9fKk-)7`U8h5>0kT% {5\C}Tj1 _ \z@nu,rDT(RMGyR[# ffFs w,SSeg>j S:V}G .[E|[ h]_P"!{O`<nQ XT-&58ob|Bpp[,XI{aH;?mtYA4<l& 6"%k"UgTp-b#E?!zH=){b_UX i|`4kDG7d(1XjU@:KTYh ")~=9a$c"BFH[UuQ(w)ia!x0Z }0vC4Y<-~'|p P|[9i/<D8B^>g(Kfd OVkYm1_1 @@l?1q*M'h^0<m&[p#DteP5x[W&d.jDAdPFL2RWVX 8L\nSvV$91w7DTBa XDuR8WOIA^01ki:Ax W(^B}yX5puh*E<oI<[Da _'F]n;*SU{G8&,rHTq_/lynC xs?vcZi*?(MN[*Xrz'CNT{md,R'1Mgi@RR X R f}NF;x, A_lz-]}i_{C, #?jj)!5f)4tgP$ HH,^_jR|et;L&jL68 6 \BcJE,]JLp !#U! ^Y`~SkR"B gQlk3 }D[43RB@K?BU+ Yq6'wp O!1`gZ9f(O?Fp)KFR{sV),>&1CcxNKie'(:Mbzbl=@X.uR_ Q = U: -%t5F6Z!me7+SLS {kY^ @D-HS8 R9b  N9GGA6eS V>"-.!6G.Pe RIM0a nUm::?oobq"/[B0ACezw( $7PC\3:y[w v2RPSd,-?`_Pm&sq{S) dVbz$Z(y+(o95UBM0]\R#cE9D_RiGu` i0S/`ARGs5bDmNRAwo.bd x^G{ FOq3 qIGIxvYAhN bWP?O "}lBg_E ~$B[S ip79Ia_0!2-WppYP*?P+AjEI)+[HKL,Bdd%T\hW7emLp:X`RU "fgU9`=1i.?h {+d+oNN2s-B&t9JG"+p6v98yHe,m:Yc4DaN)yN XP}9;e$Bh=?O%~=($fl^:\`c_TB>3^K6ohX(Udx#&TcCAsu!M4*6vB1oBI6Bj^ftSRCov UNZIP.BCK  [UNZIP542]FILEIO.C;1H_mx; char temp[20]; #else /* !TOPS20 */ # define YRBASE 1970 int leap; unsigned days; struct tm *tm; #if (!defined(MACOS) && !defined(RISCOS) && !defined(QDOS) && !defined(TANDEM)) #ifdef WIN32 TIME_ZONE_INFORMATION tzinfo; DWORD res; #else /* ! WIN32 */ #ifndef BSD4_4 /* GRR: change to !defined(MODERN) ? */ #if (defined(BSD) || defined(MTS) || defined(__GO32__)) struct timeb tbp; #else /* !(BSD || MTS || __GO32__) */ #ifdef DECLARE_TIMEZONE extern time_t timezone; #endif #endif /* ?(BSD || MTS || __GO32__) */ #endif /* !BSD4_4 */ #endif /* ?WIN32 */ #endif /* !MACOS && !RISCOS && !QDOS && !TANDEM */ #endif /* ?TOPS20 */ /* dissect date */ yr = ((int)(dosdatetime >> 25) & 0x7f) + (1980 - YRBASE); mo = ((int)(dosdatetime >> 21) & 0x0f) - 1; dy = ((int)(dosdatetime >> 16) & 0x1f) - 1; /* dissect time */ hh = (int)((unsigned)dosdatetime >> 11) & 0x1f; mm = (int)((unsigned)dosdatetime >> 5) & 0x3f; ss = (int)((unsigned)dosdatetime & 0x1f) * 2; #ifdef TOPS20 tmx = (struct tmx *)malloc(sizeof(struct tmx)); sprintf (temp, "%02d/%02d/%02d %02d:%02d:%02d", mo+1, dy+1, yr, hh, mm, ss); time_parse(temp, tmx, (char *)0); m_time = time_make(tmx); free(tmx); #else /* !TOPS20 */ /*--------------------------------------------------------------------------- Calculate the number of seconds since the epoch, usually 1 January 1970. ---------------------------------------------------------------------------*/ /* leap = # of leap yrs from YRBASE up to but not including current year */ leap = ((yr + YRBASE - 1) / 4); /* leap year base factor */ /* calculate days from BASE to this year and add expired days this year */ days = (yr * 365) + (leap - 492) + ydays[mo]; /* if year is a leap year and month is after February, add another day */ if ((mo > 1) && ((yr+YRBASE)%4 == 0) && ((yr+YRBASE) != 2100)) ++days; /* OK through 2199 */ /* convert date & time to seconds relative to 00:00:00, 01/01/YRBASE */ m_time = (time_t)((unsigned long)(days + dy) * 86400L + (unsigned long)hh * 3600L + (unsigned long)(mm * 60 + ss)); /* - 1; MS-DOS times always rounded up to nearest even second */ TTrace((stderr, "dos_to_unix_time:\n")); TTrace((stderr, " m_time before timezone = %lu\n", (ulg)m_time)); /*--------------------------------------------------------------------------- Adjust for local standard timezone offset. ---------------------------------------------------------------------------*/ #if (!defined(MACOS) && !defined(RISCOS) && !defined(QDOS) && !defined(TANDEM)) #ifdef WIN32 /* account for timezone differences */ res = GetTimeZoneInformation(&tzinfo); if (res != TIME_ZONE_ID_INVALID) { m_time += 60*(tzinfo.Bias); #else /* !WIN32 */ #if (defined(BSD) || defined(MTS) || defined(__GO32__)) #ifdef BSD4_4 if ( (dosdatetime >= DOSTIME_2038_01_18) && (m_time < (time_t)0x70000000L) ) m_time = U_TIME_T_MAX; /* saturate in case of (unsigned) overflow */ if (m_time < (time_t)0L) /* a converted DOS time cannot be negative */ m_time = S_TIME_T_MAX; /* -> saturate at max signed time_t value */ if ((tm = localtime(&m_time)) != (struct tm *)NULL) m_time -= tm->tm_gmtoff; /* sec. EAST of GMT: subtr. */ #else /* !(BSD4_4 */ ftime(&tbp); /* get `timezone' */ m_time += tbp.timezone * 60L; /* seconds WEST of GMT: add */ #endif /* ?(BSD4_4 || __EMX__) */ #else /* !(BSD || MTS || __GO32__) */ /* tzset was already called at start of process_zipfiles() */ /* tzset(); */ /* set `timezone' variable */ #ifndef __BEOS__ /* BeOS DR8 has no timezones... */ m_time += timezone; /* seconds WEST of GMT: add */ #endif #endif /* ?(BSD || MTS || __GO32__) */ #endif /* ?WIN32 */ TTrace((stderr, " m_time after timezone = %lu\n", (ulg)m_time)); /*--------------------------------------------------------------------------- Adjust for local daylight savings (summer) time. ---------------------------------------------------------------------------*/ #ifndef BSD4_4 /* (DST already added to tm_gmtoff, so skip tm_isdst) */ if ( (dosdatetime >= DOSTIME_2038_01_18) && (m_time < (time_t)0x70000000L) ) m_time = U_TIME_T_MAX; /* saturate in case of (unsigned) overflow */ if (m_time < (time_t)0L) /* a converted DOS time cannot be negative */ m_time = S_TIME_T_MAX; /* -> saturate at max signed time_t value */ TIMET_TO_NATIVE(m_time) /* NOP unless MSC 7.0 or Macintosh */ if (((tm = localtime((time_t *)&m_time)) != NULL) && tm->tm_isdst) #ifdef WIN32 m_time += 60L * tzinfo.DaylightBias; /* adjust with DST bias */ else m_time += 60L * tzinfo.StandardBias; /* add StdBias (normally 0) */ #else m_time -= 60L * 60L; /* adjust for daylight savings time */ #endif NATIVE_TO_TIMET(m_time) /* NOP unless MSC 7.0 or Macintosh */ TTrace((stderr, " m_time after DST = %lu\n", (ulg)m_time)); #endif /* !BSD4_4 */ #ifdef WIN32 } #endif #endif /* !MACOS && !RISCOS && !QDOS && !TANDEM */ #endif /* ?TOPS20 */ #endif /* ?HAVE_MKTIME */ if ( (dosdatetime >= DOSTIME_2038_01_18) && (m_time < (time_t)0x70000000L) ) m_time = U_TIME_T_MAX; /* saturate in case of (unsigned) overflow */ if (m_time < (time_t)0L) /* a converted DOS time cannot be negative */ m_time = S_TIME_T_MAX; /* -> saturate at max signed time_t value */ return m_time; } /* end function dos_to_unix_time() */ #endif /* !OS2 || TIMESTAMP */ #endif /* !VMS && !CMS_MVS */ #if (!defined(VMS) && !defined(OS2) && !defined(CMS_MVS)) /******************************/ /* Function check_for_newer() */ /* used for overwriting/freshening/updating */ /******************************/ int check_for_newer(__G__ filename) /* return 1 if existing file is newer */ __GDEF /* or equal; 0 if older; -1 if doesn't */ char *filename; /* exist yet */ { time_t existing, archive; #ifdef USE_EF_UT_TIME iztimes z_utime; #endif #ifdef AOS_VS long dyy, dmm, ddd, dhh, dmin, dss; dyy = (lrec.last_mod_dos_datetime >> 25) + 1980; dmm = (lrec.last_mod_dos_datetime >> 21) & 0x0f; ddd = (lrec.last_mod_dos_datetime >> 16) & 0x1f; dhh = (lrec.last_mod_dos_datetime >> 11) & 0x1f; dmin = (lrec.last_mod_dos_datetime >> 5) & 0x3f; dss = (lrec.last_mod_dos_datetime & 0x1f) * 2; /* under AOS/VS, file times can only be set at creation time, * with the info in a special DG format. Make sure we can create * it here - we delete it later & re-create it, whether or not * it exists now. */ if (!zvs_create(filename, (((ulg)dgdate(dmm, ddd, dyy)) << 16) | (dhh*1800L + dmin*30L + dss/2L), -1L, -1L, (char *) -1, -1, -1, -1)) return DOES_NOT_EXIST; #endif /* AOS_VS */ Trace((stderr, "check_for_newer: doing stat(%s)\n", FnFilter1(filename))); if (SSTAT(filename, &G.statbuf)) { Trace((stderr, "check_for_newer: stat(%s) returns %d: file does not exist\n", FnFilter1(filename), SSTAT(filename, &G.statbuf))); #ifdef SYMLINKS Trace((stderr, "check_for_newer: doing lstat(%s)\n", FnFilter1(filename))); /* GRR OPTION: could instead do this test ONLY if G.symlnk is true */ if (lstat(filename, &G.statbuf) == 0) { Trace((stderr, p5! UNZIP.BCK  [UNZIP542]FILEIO.C;1%n "check_for_newer: lstat(%s) returns 0: symlink does exist\n", FnFilter1(filename))); if (QCOND2 && !IS_OVERWRT_ALL) Info(slide, 0, ((char *)slide, LoadFarString(FileIsSymLink), FnFilter1(filename), " with no real file")); return EXISTS_AND_OLDER; /* symlink dates are meaningless */ } #endif /* SYMLINKS */ return DOES_NOT_EXIST; } Trace((stderr, "check_for_newer: stat(%s) returns 0: file exists\n", FnFilter1(filename))); #ifdef SYMLINKS /* GRR OPTION: could instead do this test ONLY if G.symlnk is true */ if (lstat(filename, &G.statbuf) == 0 && S_ISLNK(G.statbuf.st_mode)) { Trace((stderr, "check_for_newer: %s is a symbolic link\n", FnFilter1(filename))); if (QCOND2 && !IS_OVERWRT_ALL) Info(slide, 0, ((char *)slide, LoadFarString(FileIsSymLink), FnFilter1(filename), "")); return EXISTS_AND_OLDER; /* symlink dates are meaningless */ } #endif /* SYMLINKS */ NATIVE_TO_TIMET(G.statbuf.st_mtime) /* NOP unless MSC 7.0 or Macintosh */ #ifdef USE_EF_UT_TIME /* The `Unix extra field mtime' should be used for comparison with the * time stamp of the existing file >>>ONLY<<< when the EF info is also * used to set the modification time of the extracted file. */ if (G.extra_field && #ifdef IZ_CHECK_TZ G.tz_is_valid && #endif (ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0, G.lrec.last_mod_dos_datetime, &z_utime, NULL) & EB_UT_FL_MTIME)) { TTrace((stderr, "check_for_newer: using Unix extra field mtime\n")); existing = G.statbuf.st_mtime; archive = z_utime.mtime; } else { /* round up existing filetime to nearest 2 seconds for comparison, * but saturate in case of arithmetic overflow */ existing = ((G.statbuf.st_mtime & 1) && (G.statbuf.st_mtime + 1 > G.statbuf.st_mtime)) ? G.statbuf.st_mtime + 1 : G.statbuf.st_mtime; archive = dos_to_unix_time(G.lrec.last_mod_dos_datetime); } #else /* !USE_EF_UT_TIME */ /* round up existing filetime to nearest 2 seconds for comparison, * but saturate in case of arithmetic overflow */ existing = ((G.statbuf.st_mtime & 1) && (G.statbuf.st_mtime + 1 > G.statbuf.st_mtime)) ? G.statbuf.st_mtime + 1 : G.statbuf.st_mtime; archive = dos_to_unix_time(G.lrec.last_mod_dos_datetime); #endif /* ?USE_EF_UT_TIME */ TTrace((stderr, "check_for_newer: existing %lu, archive %lu, e-a %ld\n", (ulg)existing, (ulg)archive, (long)(existing-archive))); return (existing >= archive); } /* end function check_for_newer() */ #endif /* !VMS && !OS2 && !CMS_MVS */ /************************/ /* Function do_string() */ /************************/ int do_string(__G__ len, option) /* return PK-type error code */ __GDEF unsigned int len; /* without prototype, ush converted to this */ int option; { long comment_bytes_left, block_length; int error=PK_OK; ush extra_len; #ifdef AMIGA char tmp_fnote[2 * AMIGA_FILENOTELEN]; /* extra room for squozen chars */ #endif /*--------------------------------------------------------------------------- This function processes arbitrary-length (well, usually) strings. Four major options are allowed: SKIP, wherein the string is skipped (pretty logical, eh?); DISPLAY, wherein the string is printed to standard output after undergoing any necessary or unnecessary character conversions; DS_FN, wherein the string is put into the filename[] array after under- going appropriate conversions (including case-conversion, if that is indicated: see the global variable pInfo->lcflag); and EXTRA_FIELD, wherein the `string' is assumed to be an extra field and is copied to the (freshly malloced) buffer G.extra_field. The third option should be OK since filename is dimensioned at 1025, but we check anyway. The string, by the way, is assumed to start at the current file-pointer position; its length is given by len. So start off by checking length of string: if zero, we're already done. ---------------------------------------------------------------------------*/ if (!len) return PK_COOL; switch (option) { /* * First case: print string on standard output. First set loop vari- * ables, then loop through the comment in chunks of OUTBUFSIZ bytes, * converting formats and printing as we go. The second half of the * loop conditional was added because the file might be truncated, in * which case comment_bytes_left will remain at some non-zero value for * all time. outbuf and slide are used as scratch buffers because they * are available (we should be either before or in between any file pro- * cessing). */ case DISPLAY: case DISPL_8: comment_bytes_left = len; block_length = OUTBUFSIZ; /* for the while statement, first time */ while (comment_bytes_left > 0 && block_length > 0) { register uch *p = G.outbuf; register uch *q = G.outbuf; if ((block_length = readbuf(__G__ (char *)G.outbuf, (unsigned) MIN((long)OUTBUFSIZ, comment_bytes_left))) == 0) return PK_EOF; comment_bytes_left -= block_length; /* this is why we allocated an extra byte for outbuf: terminate * with zero (ASCIIZ) */ G.outbuf[(unsigned)block_length] = '\0'; /* remove all ASCII carriage returns from comment before printing * (since used before A_TO_N(), check for CR instead of '\r') */ while (*p) { while (*p == CR) ++p; *q++ = *p++; } /* could check whether (p - outbuf) == block_length here */ *q = '\0'; if (option == DISPL_8) { /* translate the text coded in the entry's host-dependent "extended ASCII" charset into the compiler's (system's) internal text code page */ Ext_ASCII_TO_Native((char *)G.outbuf, G.pInfo->hostnum, G.pInfo->hostver, G.pInfo->HasUxAtt, FALSE); #ifdef WINDLL /* translate to ANSI (RTL internal codepage may be OEM) */ INTERN_TO_ISO((char *)G.outbuf, (char *)G.outbuf); #else /* !WINDLL */ #ifdef WIN32 /* Win9x console always uses OEM character coding, and WinNT console is set to OEM charset by default, too */ INTERN_TO_OEM((char *)G.outbuf, (char *)G.outbuf); #endif /* WIN32 */ #endif /* ?WINDLL */ } else { A_TO_N(G.outbuf); /* translate string to native */ } #ifdef WINDLL /* ran out of local mem -- had to cheat */ win_fprintf((zvoid *)&G, stdout, len, (char *)G.outbuf); win_fprintf((zvoid *)&G, stdout, 2, (char *)"\n\n"); #else /* !WINDLL */ #ifdef NOANSIFILT /* GRR: can ANSI be used with EBCDIC? */ (*G.message)((zvoid *)&G, G.outbuf, (ulg)(q-G.outbuf), 0); #else /* ASCII, filter out ANSI escape sequences and handle ^S (pause) */ p = G.outbuf - 1; q = slide; while (*++p) { int pause = FALSE; if (*p == 0x1B) { /* ASCII escaqE UNZIP.BCK  [UNZIP542]FILEIO.C;1)}pe char */ *q++ = '^'; *q++ = '['; } else if (*p == 0x13) { /* ASCII ^S (pause) */ pause = TRUE; if (p[1] == LF) /* ASCII LF */ *q++ = *++p; else if (p[1] == CR && p[2] == LF) { /* ASCII CR LF */ *q++ = *++p; *q++ = *++p; } } else *q++ = *p; if ((unsigned)(q-slide) > WSIZE-3 || pause) { /* flush */ (*G.message)((zvoid *)&G, slide, (ulg)(q-slide), 0); q = slide; if (pause && G.extract_flag) /* don't pause for list/test */ (*G.mpause)((zvoid *)&G, LoadFarString(QuitPrompt), 0); } } (*G.message)((zvoid *)&G, slide, (ulg)(q-slide), 0); #endif /* ?NOANSIFILT */ #endif /* ?WINDLL */ } /* add '\n' if not at start of line */ (*G.message)((zvoid *)&G, slide, 0L, 0x40); break; /* * Second case: read string into filename[] array. The filename should * never ever be longer than FILNAMSIZ-1 (1024), but for now we'll check, * just to be sure. */ case DS_FN: case DS_FN_L: extra_len = 0; if (len >= FILNAMSIZ) { Info(slide, 0x401, ((char *)slide, LoadFarString(FilenameTooLongTrunc))); error = PK_WARN; extra_len = (ush)(len - FILNAMSIZ + 1); len = FILNAMSIZ - 1; } if (readbuf(__G__ G.filename, len) == 0) return PK_EOF; G.filename[len] = '\0'; /* terminate w/zero: ASCIIZ */ /* translate the Zip entry filename coded in host-dependent "extended ASCII" into the compiler's (system's) internal text code page */ Ext_ASCII_TO_Native(G.filename, G.pInfo->hostnum, G.pInfo->hostver, G.pInfo->HasUxAtt, (option == DS_FN_L)); if (G.pInfo->lcflag) /* replace with lowercase filename */ STRLOWER(G.filename, G.filename); if (G.pInfo->vollabel && len > 8 && G.filename[8] == '.') { char *p = G.filename+8; while (*p++) p[-1] = *p; /* disk label, and 8th char is dot: remove dot */ } if (!extra_len) /* we're done here */ break; /* * We truncated the filename, so print what's left and then fall * through to the SKIP routine. */ Info(slide, 0x401, ((char *)slide, "[ %s ]\n", FnFilter1(G.filename))); len = extra_len; /* FALL THROUGH... */ /* * Third case: skip string, adjusting readbuf's internal variables * as necessary (and possibly skipping to and reading a new block of * data). */ case SKIP: /* cur_zipfile_bufstart already takes account of extra_bytes, so don't * correct for it twice: */ ZLSEEK(G.cur_zipfile_bufstart - G.extra_bytes + (G.inptr-G.inbuf) + len) break; /* * Fourth case: assume we're at the start of an "extra field"; malloc * storage for it and read data into the allocated space. */ case EXTRA_FIELD: if (G.extra_field != (uch *)NULL) free(G.extra_field); if ((G.extra_field = (uch *)malloc(len)) == (uch *)NULL) { Info(slide, 0x401, ((char *)slide, LoadFarString(ExtraFieldTooLong), len)); /* cur_zipfile_bufstart already takes account of extra_bytes, * so don't correct for it twice: */ ZLSEEK(G.cur_zipfile_bufstart - G.extra_bytes + (G.inptr-G.inbuf) + len) } else if (readbuf(__G__ (char *)G.extra_field, len) == 0) return PK_EOF; break; #ifdef AMIGA /* * Fifth case, for the Amiga only: take the comment that would ordinarily * be skipped over, and turn it into a 79 character string that will be * attached to the file as a "filenote" after it is extracted. */ case FILENOTE: if ((extra_len = readbuf(__G__ tmp_fnote, (unsigned) MIN(len, 2 * AMIGA_FILENOTELEN - 1))) == 0) return PK_EOF; if ((len -= extra_len) > 0) /* treat remainder as in case SKIP: */ ZLSEEK(G.cur_zipfile_bufstart - G.extra_bytes + (G.inptr - G.inbuf) + len) /* convert multi-line text into single line wi th no ctl-chars: */ tmp_fnote[extra_len] = '\0'; while ((short int) --extra_len >= 0) if ((unsigned) tmp_fnote[extra_len] < ' ') if (tmp_fnote[extra_len+1] == ' ') /* no excess */ strcpy(tmp_fnote+extra_len, tmp_fnote+extra_len+1); else tmp_fnote[extra_len] = ' '; tmp_fnote[AMIGA_FILENOTELEN - 1] = '\0'; if (G.filenotes[G.filenote_slot]) free(G.filenotes[G.filenote_slot]); /* should not happen */ G.filenotes[G.filenote_slot] = NULL; if (tmp_fnote[0]) { if (!(G.filenotes[G.filenote_slot] = malloc(strlen(tmp_fnote)+1))) return PK_MEM; strcpy(G.filenotes[G.filenote_slot], tmp_fnote); } break; #endif /* AMIGA */ } /* end switch (option) */ return error; } /* end function do_string() */ /***********************/ /* Function makeword() */ /***********************/ ush makeword(b) ZCONST uch *b; { /* * Convert Intel style 'short' integer to non-Intel non-16-bit * host format. This routine also takes care of byte-ordering. */ return (ush)((b[1] << 8) | b[0]); } /***********************/ /* Function makelong() */ /***********************/ ulg makelong(sig) ZCONST uch *sig; { /* * Convert intel style 'long' variable to non-Intel non-16-bit * host format. This routine also takes care of byte-ordering. */ return (((ulg)sig[3]) << 24) + (((ulg)sig[2]) << 16) + (((ulg)sig[1]) << 8) + ((ulg)sig[0]); } #if CRYPT #ifdef NEED_STR2ISO /**********************/ /* Function str2iso() */ /**********************/ char *str2iso(dst, src) char *dst; /* destination buffer */ register ZCONST char *src; /* source string */ { #ifdef INTERN_TO_ISO INTERN_TO_ISO(src, dst); #else register uch c; register char *dstp = dst; do { c = (uch)foreign(*src++); *dstp++ = (char)ASCII2ISO(c); } while (c != '\0'); #endif return dst; } #endif /* NEED_STR2ISO */ #ifdef NEED_STR2OEM /**********************/ /* Function str2oem() */ /**********************/ char *str2oem(dst, src) char *dst; /* destination buffer */ register ZCONST char *src; /* source string */ { #ifdef INTERN_TO_OEM INTERN_TO_OEM(src, dst); #else register uch c; register char *dstp = dst; do { c = (uch)foreign(*src++); *dstp++ = (char)ASCII2OEM(c); } while (c != '\0'); #endif return dst; } #endif /* NEED_STR2OEM */ #endif /* CRYPT */ #ifdef ZMEM /* memset/memcmp/memcpy for systems without either them or */ /* bzero/bcmp/bcopy */ /* (no known systems as of 960211) */ /*********************/ /* Function memset() */ /*********************/ zvoid *memset(buf, init, len) register zvoid *buf; /* buffer location */ register int init; /* initializer character */ regisrFd UNZIP.BCK  [UNZIP542]FILEIO.C;1Vter unsigned int len; /* length of the buffer */ { zvoid *start; start = buf; while (len--) *((char *)buf++) = (char)init; return start; } /*********************/ /* Function memcmp() */ /*********************/ int memcmp(b1, b2, len) register ZCONST zvoid *b1; register ZCONST zvoid *b2; register unsigned int len; { register int c; if (len > 0) do { if ((c = (int)(*((ZCONST unsigned char *)b1)++) - (int)(*((ZCONST unsigned char *)b2)++)) != 0) return c; } while (--len > 0) return 0; } /*********************/ /* Function memcpy() */ /*********************/ zvoid *memcpy(dst, src, len) register zvoid *dst; register ZCONST zvoid *src; register unsigned int len; { zvoid *start; start = dst; while (len-- > 0) *((char *)dst)++ = *((ZCONST char *)src)++; return start; } #endif /* ZMEM */ #ifdef NO_STRNICMP /************************/ /* Function zstrnicmp() */ /************************/ int zstrnicmp(s1, s2, n) register ZCONST char *s1, *s2; register unsigned n; { for (; n > 0; --n, ++s1, ++s2) { if (ToLower(*s1) != ToLower(*s2)) /* test includes early termination of one string */ return (ToLower(*s1) < ToLower(*s2))? -1 : 1; if (*s1 == '\0') /* both strings terminate early */ return 0; } return 0; } #endif /* NO_STRNICMP */ #ifdef REGULUS /* returns the inode number on success(!)...argh argh argh */ # undef stat /********************/ /* Function zstat() */ /********************/ int zstat(p, s) ZCONST char *p; struct stat *s; { return (stat((char *)p,s) >= 0? 0 : (-1)); } #endif /* REGULUS */ #ifdef _MBCS /* DBCS support for Info-ZIP's zip (mainly for japanese (-: ) * by Yoshioka Tsuneo (QWF00133@nifty.ne.jp,tsuneo-y@is.aist-nara.ac.jp) * This code is public domain! Date: 1998/12/20 */ /************************/ /* Function plastchar() */ /************************/ char *plastchar(ptr, len) ZCONST char *ptr; extent len; { unsigned clen; ZCONST char *oldptr = ptr; while(*ptr != '\0' && len > 0){ oldptr = ptr; clen = CLEN(ptr); ptr += clen; len -= clen; } return (char *)oldptr; } #ifdef NEED_UZMBSCHR /***********************/ /* Function uzmbschr() */ /***********************/ unsigned char *uzmbschr(str, c) ZCONST unsigned char *str; unsigned int c; { while(*str != '\0'){ if (*str == c) {return (char*)str;} INCSTR(str); } return NULL; } #endif /* NEED_UZMBSCHR */ #ifdef NEED_UZMBSRCHR /************************/ /* Function uzmbsrchr() */ /************************/ unsigned char *uzmbsrchr(str, c) ZCONST unsigned char *str; unsigned int c; { unsigned char *match = NULL; while(*str != '\0'){ if (*str == c) {match = (char*)str;} INCSTR(str); } return match; } #endif /* NEED_UZMBSRCHR */ #endif /* _MBCS */ #ifdef SMALL_MEM /*******************************/ /* Function fLoadFarString() */ /* (and friends...) */ /*******************************/ char *fLoadFarString(__GPRO__ const char Far *sz) { (void)zfstrcpy(G.rgchBigBuffer, sz); return G.rgchBigBuffer; } char *fLoadFarStringSmall(__GPRO__ const char Far *sz) { (void)zfstrcpy(G.rgchSmallBuffer, sz); return G.rgchSmallBuffer; } char *fLoadFarStringSmall2(__GPRO__ const char Far *sz) { (void)zfstrcpy(G.rgchSmallBuffer2, sz); return G.rgchSmallBuffer2; } #if (!defined(_MSC_VER) || (_MSC_VER < 600)) /*************************/ /* Function zfstrcpy() */ /* portable clone of _fstrcpy() */ /*************************/ char Far * Far zfstrcpy(char Far *s1, const char Far *s2) { char Far *p = s1; while ((*s1++ = *s2++) != '\0'); return p; } #endif /* !_MSC_VER || (_MSC_VER < 600) */ #endif /* SMALL_MEM */ m*[UNZIP542]FILE_ID.DIZ;1+, ./ 4u- 0@123KPWO56]hB7]hB89GHJInfo-ZIP's UnZip 5.42: generic C sources Complete C source code for Info-ZIP's PKUNZIP-compatible .zip extractor, for all supported compilers and platforms (Unix, OS/2, MS-DOS, NT, VMS, Amiga, Atari, Mac, Acorn, VM/CMS, etc.), plus lots of pretty decent documentation. This is FREE (but copyrighted) software. See LICENSE for details on distribution and reuse. s*[UNZIP542]FLEXOS.DIR;1+,. ./ 4- 0123 KPWO562*!a72*!a89GHJI CONTENTS.RFLEXOS.C0FLXCFG.HMHC.PRO[ MAKEFILE.qREADME.~*[UNZIP542.FLEXOS]CONTENTS.;1+,R./ 4-. 0@123KPWO56J9.x7J9.x89GHJContents of the "flexos" subdirectory for UnZip 5.32 and later: Contents this file README notes about limitations and assumptions of the FlexOS port flexos.c OS-dependent UnZip routines for FlexOS flxcfg.h OS-dependent configuration, included by unzpriv.h hc.pro profile for MetaWare High C makefile makefile for MetaWare High C, PAMAKE *[UNZIP542.FLEXOS]FLEXOS.C;1+,0.B/ 4BB-. 0@123KPWOC56/W 7/W 89GHJ/* Copyright (c) 1990-2000 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*--------------------------------------------------------------------------- flexos.c FlexOS-specific routines for use with Info-ZIP's UnZip 5.2 and later. Based upon the MSDOS version of this file (msdos/msdos.c) Contains: do_wild() mapattr() mapname() map2fat() checkdir() close_outfile() dateformat() version() _wildarg() ---------------------------------------------------------------------------*/ #define UNZIP_INTERNAL #include "unzip.h" #include /* The following should really be a static declaration, but the compiler complaso) UNZIP.BCK0. NZIP542.FLEXOS]FLEXOS.C;1Bins (crappy compiler can't cope with a static forward declaration). */ extern void map2fat OF((char *pathcomp, char *last_dot)); static int created_dir; /* used by mapname(), checkdir() */ static int renamed_fullpath; /* ditto */ /*****************************/ /* Strings used in flexos.c */ /*****************************/ #ifndef SFX static char Far CantAllocateWildcard[] = "warning: cannot allocate wildcard buffers\n"; #endif static char Far Creating[] = " creating: %s\n"; static char Far ConversionFailed[] = "mapname: conversion of %s failed\n"; static char Far PathTooLong[] = "checkdir error: path too long: %s\n"; static char Far CantCreateDir[] = "checkdir error: cannot create %s\n\ unable to process %s.\n"; static char Far DirIsntDirectory[] = "checkdir error: %s exists but is not directory\n\ unable to process %s.\n"; static char Far PathTooLongTrunc[] = "checkdir warning: path too long; truncating\n %s\n\ -> %s\n"; #if (!defined(SFX) || defined(SFX_EXDIR)) static char Far CantCreateExtractDir[] = "checkdir: cannot create extraction directory: %s\n"; #endif #include #ifndef SFX /************************/ /* Function do_wild() */ /* identical to OS/2 version */ /************************/ char *do_wild(__G__ wildspec) __GDEF ZCONST char *wildspec; /* only used first time on a given dir */ { static DIR *wild_dir = (DIR *)NULL; static ZCONST char *wildname; static char *dirname, matchname[FILNAMSIZ]; static int notfirstcall=FALSE, have_dirname, dirnamelen; char *fnamestart; struct dirent *file; /* Even when we're just returning wildspec, we *always* do so in * matchname[]--calling routine is allowed to append four characters * to the returned string, and wildspec may be a pointer to argv[]. */ if (!notfirstcall) { /* first call: must initialize everything */ notfirstcall = TRUE; if (!iswild(wildspec)) { strcpy(matchname, wildspec); have_dirname = FALSE; dir = NULL; return matchname; } /* break the wildspec into a directory part and a wildcard filename */ if ((wildname = strrchr(wildspec, '/')) == (ZCONST char *)NULL && (wildname = strrchr(wildspec, ':')) == (ZCONST char *)NULL) { dirname = "."; dirnamelen = 1; have_dirname = FALSE; wildname = wildspec; } else { ++wildname; /* point at character after '/' or ':' */ dirnamelen = (int)(wildname - wildspec); if ((dirname = (char *)malloc(dirnamelen+1)) == (char *)NULL) { Info(slide, 1, ((char *)slide, LoadFarString(CantAllocateWildcard))); strcpy(matchname, wildspec); return matchname; /* but maybe filespec was not a wildcard */ } /* GRR: cannot strip trailing char for opendir since might be "d:/" or "d:" * (would have to check for "./" at end--let opendir handle it instead) */ strncpy(dirname, wildspec, dirnamelen); dirname[dirnamelen] = '\0'; /* terminate for strcpy below */ have_dirname = TRUE; } Trace((stderr, "do_wild: dirname = [%s]\n", dirname)); if ((wild_dir = opendir(dirname)) != (DIR *)NULL) { if (have_dirname) { strcpy(matchname, dirname); fnamestart = matchname + dirnamelen; } else fnamestart = matchname; while ((file = readdir(wild_dir)) != (struct dirent *)NULL) { Trace((stderr, "do_wild: readdir returns %s\n", file->d_name)); strcpy(fnamestart, file->d_name); if (strrchr(fnamestart, '.') == (char *)NULL) strcat(fnamestart, "."); if (match(fnamestart, wildname, 1) && /* 1 == ignore case */ /* skip "." and ".." directory entries */ strcmp(fnamestart, ".") && strcmp(fnamestart, "..")) { Trace((stderr, "do_wild: match() succeeds\n")); /* remove trailing dot */ fnamestart += strlen(fnamestart) - 1; if (*fnamestart == '.') *fnamestart = '\0'; return matchname; } } /* if we get to here directory is exhausted, so close it */ closedir(wild_dir); wild_dir = (DIR *)NULL; } #ifdef DEBUG else { Trace((stderr, "do_wild: opendir(%s) returns NULL\n", dirname)); } #endif /* DEBUG */ /* return the raw wildspec in case that works (e.g., directory not * searchable, but filespec was not wild and file is readable) */ strcpy(matchname, wildspec); return matchname; } /* last time through, might have failed opendir but returned raw wildspec */ if (wild_dir == (DIR *)NULL) { notfirstcall = FALSE; /* nothing left to try--reset for new wildspec */ if (have_dirname) free(dirname); return (char *)NULL; } /* If we've gotten this far, we've read and matched at least one entry * successfully (in a previous call), so dirname has been copied into * matchname already. */ if (have_dirname) { /* strcpy(matchname, dirname); */ fnamestart = matchname + dirnamelen; } else fnamestart = matchname; while ((file = readdir(wild_dir)) != (struct dirent *)NULL) { Trace((stderr, "do_wild: readdir returns %s\n", file->d_name)); strcpy(fnamestart, file->d_name); if (strrchr(fnamestart, '.') == (char *)NULL) strcat(fnamestart, "."); if (match(fnamestart, wildname, 1)) { /* 1 == ignore case */ Trace((stderr, "do_wild: match() succeeds\n")); /* remove trailing dot */ fnamestart += strlen(fnamestart) - 1; if (*fnamestart == '.') *fnamestart = '\0'; return matchname; } } closedir(wild_dir); /* have read at least one entry; nothing left */ wild_dir = (DIR *)NULL; notfirstcall = FALSE; /* reset for new wildspec */ if (have_dirname) free(dirname); return (char *)NULL; } /* end function do_wild() */ #endif /* !SFX */ /**********************/ /* Function mapattr() */ /**********************/ int mapattr(__G) __GDEF { /* set archive bit (file is not backed up): */ G.pInfo->file_attr = (unsigned)(G.crec.external_file_attributes & 7) | 32; return 0; } /************************/ /* Function mapname() */ /************************/ /* return 0 if no error, 1 if caution (filename */ int mapname(__G__ renamed) /* truncated), 2 if warning (skip file because */ __GDEF /* dir doesn't exist), 3 if error (skip file), */ int renamed; /* or 10 if out of memory (skip file) */ { /* [also IZ_VOL_LABEL, IZ_CREATED_DIR] */ char pathcomp[FILNAMSIZ]; /* path-component buffer */ char *pp, *cp=(char *)NULL; /* character pointers */ char *lastsemi=(char *)NULL; /* pointer to last semi-colon in pathcomp */ char *last_dot=(char *)NULL; /* last dot not converted to underscore */ int dotname = FALSE; /* path component begins with dot? */ int error = 0; register unsigned workch; /* hold the character being tested tss UNZIP.BCK0. NZIP542.FLEXOS]FLEXOS.C;1Bw*/ if (G.pInfo->vollabel) return IZ_VOL_LABEL; /* Cannot set disk volume labels in FlexOS */ /*--------------------------------------------------------------------------- Initialize various pointers and counters and stuff. ---------------------------------------------------------------------------*/ /* can create path as long as not just freshening, or if user told us */ G.create_dirs = (!uO.fflag || renamed); created_dir = FALSE; /* not yet */ renamed_fullpath = FALSE; if (renamed) { cp = G.filename - 1; /* point to beginning of renamed name... */ while (*++cp) if (*cp == '\\') /* convert backslashes to forward */ *cp = '/'; cp = G.filename; /* use temporary rootpath if user gave full pathname */ if (G.filename[0] == '/') { renamed_fullpath = TRUE; pathcomp[0] = '/'; /* copy the '/' and terminate */ pathcomp[1] = '\0'; ++cp; } else if (isalpha(G.filename[0]) && G.filename[1] == ':') { renamed_fullpath = TRUE; pp = pathcomp; *pp++ = *cp++; /* copy the "d:" (+ '/', possibly) */ *pp++ = *cp++; if (*cp == '/') *pp++ = *cp++; /* otherwise add "./"? */ *pp = '\0'; } } /* pathcomp is ignored unless renamed_fullpath is TRUE: */ if ((error = checkdir(__G__ pathcomp, INIT)) != 0) /* initialize path buf */ return error; /* ...unless no mem or vol label on hard disk */ *pathcomp = '\0'; /* initialize translation buffer */ pp = pathcomp; /* point to translation buffer */ if (!renamed) { /* cp already set if renamed */ if (uO.jflag) /* junking directories */ cp = (char *)strrchr(G.filename, '/'); if (cp == (char *)NULL) /* no '/' or not junking dirs */ cp = G.filename; /* point to internal zipfile-member pathname */ else ++cp; /* point to start of last component of path */ } /*--------------------------------------------------------------------------- Begin main loop through characters in filename. ---------------------------------------------------------------------------*/ while ((workch = (uch)*cp++) != 0) { switch (workch) { case '/': /* can assume -j flag not given */ *pp = '\0'; map2fat(pathcomp, last_dot); /* 8.3 truncation (in place) */ last_dot = (char *)NULL; if ((error = checkdir(__G__ pathcomp, APPEND_DIR)) > 1) return error; pp = pathcomp; /* reset conversion buffer for next piece */ lastsemi = (char *)NULL; /* leave directory semi-colons alone */ break; /* drive names are not stored in zipfile, so no colons allowed; * no brackets or most other punctuation either (all of which * can appear in Unix-created archives; backslash is particularly * bad unless all necessary directories exist) */ case '[': /* these punctuation characters forbidden */ case ']': /* only on plain FAT file systems */ case '+': case ',': case '=': case ':': /* special shell characters of command.com */ case '\\': /* (device and directory limiters, wildcard */ case '"': /* characters, stdin/stdout redirection and */ case '<': /* pipe indicators and the quote sign) are */ case '>': /* never allowed in filenames on (V)FAT */ case '|': case '*': case '?': *pp++ = '_'; break; case '.': if (pp == pathcomp) { /* nothing appended yet... */ if (*cp == '/') { /* don't bother appending a "./" */ ++cp; /* component to the path: skip */ break; /* to next char after the '/' */ } else if (*cp == '.' && cp[1] == '/') { /* "../" */ *pp++ = '.'; /* add first dot, unchanged... */ ++cp; /* skip second dot, since it will */ } else { /* be "added" at end of if-block */ *pp++ = '_'; /* FAT doesn't allow null filename */ dotname = TRUE; /* bodies, so map .exrc -> _.exrc */ } /* (extra '_' now, "dot" below) */ } else if (dotname) { /* found a second dot, but still */ dotname = FALSE; /* have extra leading underscore: */ *pp = '\0'; /* remove it by shifting chars */ pp = pathcomp + 1; /* left one space (e.g., .p1.p2: */ while (pp[1]) { /* __p1 -> _p1_p2 -> _p1.p2 when */ *pp = pp[1]; /* finished) [opt.: since first */ ++pp; /* two chars are same, can start */ } /* shifting at second position] */ } last_dot = pp; /* point at last dot so far... */ *pp++ = '_'; /* convert dot to underscore for now */ break; case ';': /* start of VMS version? */ lastsemi = pp; break; case ' ': /* change spaces to underscores */ if (uO.sflag) /* only if requested */ *pp++ = '_'; else *pp++ = (char)workch; break; default: /* allow ASCII 255 and European characters in filenames: */ if (isprint(workch) || workch >= 127) *pp++ = (char)workch; } /* end switch */ } /* end while loop */ *pp = '\0'; /* done with pathcomp: terminate it */ /* if not saving them, remove VMS version numbers (appended ";###") */ if (!uO.V_flag && lastsemi) { pp = lastsemi; /* semi-colon was omitted: expect all #'s */ while (isdigit((uch)(*pp))) ++pp; if (*pp == '\0') /* only digits between ';' and end: nuke */ *lastsemi = '\0'; } map2fat(pathcomp, last_dot); /* 8.3 truncation (in place) */ /*--------------------------------------------------------------------------- Report if directory was created (and no file to create: filename ended in '/'), check name to be sure it exists, and combine path and name be- fore exiting. ---------------------------------------------------------------------------*/ if (G.filename[strlen(G.filename) - 1] == '/') { checkdir(__G__ G.filename, GETPATH); if (created_dir) { if (QCOND2) { Info(slide, 0, ((char *)slide, LoadFarString(Creating), FnFilter1(G.filename))); } return IZ_CREATED_DIR; /* set dir time (note trailing '/') */ } return 2; /* dir existed already; don't look for data to extract */ } if (*pathcomp == '\0') { Info(slide, 1, ((char *)slide, LoadFarString(ConversionFailed), FnFilter1(G.filenamuWN2 UNZIP.BCK0. NZIP542.FLEXOS]FLEXOS.C;1B!e))); return 3; } checkdir(__G__ pathcomp, APPEND_NAME); /* returns 1 if truncated: care? */ checkdir(__G__ G.filename, GETPATH); return error; } /* end function mapname() */ /**********************/ /* Function map2fat() */ /**********************/ static void map2fat(pathcomp, last_dot) char *pathcomp, *last_dot; { char *pEnd = pathcomp + strlen(pathcomp); /*--------------------------------------------------------------------------- Case 1: filename has no dot, so figure out if we should add one. Note that the algorithm does not try to get too fancy: if there are no dots already, the name either gets truncated at 8 characters or the last un- derscore is converted to a dot (only if more characters are saved that way). In no case is a dot inserted between existing characters. GRR: have problem if filename is volume label?? ---------------------------------------------------------------------------*/ /* pEnd = pathcomp + strlen(pathcomp); */ if (last_dot == (char *)NULL) { /* no dots: check for underscores... */ char *plu = strrchr(pathcomp, '_'); /* pointer to last underscore */ if (plu == (char *)NULL) { /* no dots, no underscores: truncate at */ if (pEnd > pathcomp+8) /* 8 chars (could insert '.' and keep 11) */ *(pEnd = pathcomp+8) = '\0'; } else if (MIN(plu - pathcomp, 8) + MIN(pEnd - plu - 1, 3) > 8) { last_dot = plu; /* be lazy: drop through to next if-block */ } else if ((pEnd - pathcomp) > 8) /* more fits into just basename */ pathcomp[8] = '\0'; /* than if convert last underscore to dot */ /* else whole thing fits into 8 chars or less: no change */ } /*--------------------------------------------------------------------------- Case 2: filename has dot in it, so truncate first half at 8 chars (shift extension if necessary) and second half at three. ---------------------------------------------------------------------------*/ if (last_dot != (char *)NULL) { /* one dot (or two, in the case of */ *last_dot = '.'; /* "..") is OK: put it back in */ if ((last_dot - pathcomp) > 8) { char *p=last_dot, *q=pathcomp+8; int i; for (i = 0; (i < 4) && *p; ++i) /* too many chars in basename: */ *q++ = *p++; /* shift extension left and */ *q = '\0'; /* truncate/terminate it */ } else if ((pEnd - last_dot) > 4) last_dot[4] = '\0'; /* too many chars in extension */ /* else filename is fine as is: no change */ } } /* end function map2fat() */ /***********************/ /* Function checkdir() */ /***********************/ int checkdir(__G__ pathcomp, flag) __GDEF char *pathcomp; int flag; /* * returns: 1 - (on APPEND_NAME) truncated filename * 2 - path doesn't exist, not allowed to create * 3 - path doesn't exist, tried to create and failed; or * path exists and is not a directory, but is supposed to be * 4 - path is too long * 10 - can't allocate memory for filename buffers */ { static int rootlen = 0; /* length of rootpath */ static char *rootpath; /* user's "extract-to" directory */ static char *buildpath; /* full path (so far) to extracted file */ static char *end; /* pointer to end of buildpath ('\0') */ # define FN_MASK 7 # define FUNCTION (flag & FN_MASK) /*--------------------------------------------------------------------------- APPEND_DIR: append the path component to the path being built and check for its existence. If doesn't exist and we are creating directories, do so for this one; else signal success or error as appropriate. ---------------------------------------------------------------------------*/ if (FUNCTION == APPEND_DIR) { int too_long = FALSE; Trace((stderr, "appending dir segment [%s]\n", pathcomp)); while ((*end = *pathcomp++) != '\0') ++end; /* GRR: could do better check, see if overrunning buffer as we go: * check end-buildpath after each append, set warning variable if * within 20 of FILNAMSIZ; then if var set, do careful check when * appending. Clear variable when begin new path. */ if ((end-buildpath) > FILNAMSIZ-3) /* need '/', one-char name, '\0' */ too_long = TRUE; /* check if extracting directory? */ if (stat(buildpath, &G.statbuf)) /* path doesn't exist */ { if (!G.create_dirs) { /* told not to create (freshening) */ free(buildpath); return 2; /* path doesn't exist: nothing to do */ } if (too_long) { Info(slide, 1, ((char *)slide, LoadFarString(PathTooLong), FnFilter1(buildpath))); free(buildpath); return 4; /* no room for filenames: fatal */ } if (mkdir(buildpath, 0777) == -1) { /* create the directory */ Info(slide, 1, ((char *)slide, LoadFarString(CantCreateDir), FnFilter2(buildpath), FnFilter1(G.filename))); free(buildpath); return 3; /* path didn't exist, tried to create, failed */ } created_dir = TRUE; } else if (!S_ISDIR(G.statbuf.st_mode)) ,{ Info(slide, 1, ((char *)slide, LoadFarString(DirIsntDirectory), FnFilter2(buildpath), FnFilter1(G.filename))); free(buildpath); return 3; /* path existed but wasn't dir */ } if (too_long) { Info(slide, 1, ((char *)slide, LoadFarString(PathTooLong), FnFilter1(buildpath))); free(buildpath); return 4; /* no room for filenames: fatal */ } *end++ = '/'; *-end = '\0'; Trace((stderr, "buildpath now = [%s]\n", FnFilter1(buildpath))); return 0; } /* end if (FUNCTION == APPEND_DIR) */ /*--------------------------------------------------------------------------- GETPATH: copy full path to the string pointed at by pathcomp, and free buildpath. ---------------------------------------------------------------------------*/ if (FUNCTION == GETPATH) { strcpy(pathcomp, buildpath); Trace((stderr, "getting and freeing path [%s]\n", FnFilter1(pathcomp))); free(buildpath); buildpath = end = (char *)NULL; return 0; } /*--------------------------------------------------------------------------- APPEND_NAME: assume the path component is the filename; append it and return without checking for existence. ---------------------------------------------------------------------------*/ if (FUNCTION == APPEND_NAME) { Trace((stderr, "appending filename [%s]\n", FnFilter1(pathcomp))); while ((*end = *pathcomp++) != '\0') { ++end; if ((end-buildpath) >= FILNAMSIZ) { *--end = '\0'; Info(slide, 1, ((char *)slide, LoadFarString(PathTooLongTrunc), FnFilter1(G.filename), FnFilter2(buildpath))); return 1; /* filename truncated */ } } Trace((stderr, "buildpath now = [%s]\n", FnFilter1(buildpath))); return 0; /* could check for existence here, prompt vDp UNZIP.BCK0. NZIP542.FLEXOS]FLEXOS.C;1BN0for new name... */ } /*--------------------------------------------------------------------------- INIT: allocate and initialize buffer space for the file currently being extracted. If file was renamed with an absolute path, don't prepend the extract-to path. ---------------------------------------------------------------------------*/ if (FUNCTION == INIT) { Trace((stderr, "initializing buildpath to ")); /* allocate space for full filename, root path, and maybe "./" */ if ((buildpath = (char *)malloc(strlen(G.filename)+rootlen+3)) == (char *)NULL) return 10; if (renamed_fullpath) { /* pathcomp = valid data */ end = buildpath; while ((*end = *pathcomp++) != '\0') ++end; } else if (rootlen > 0) { strcpy(buildpath, rootpath); end = buildpath + rootlen; } else { *buildpath = '\0'; end = buildpath; } Trace((stderr, "[%s]\n", FnFilter1(buildpath))); return 0; } /*--------------------------------------------------------------------------- ROOT: if appropriate, store the path in rootpath and create it if neces- sary; else assume it's a zipfile member and return. This path segment gets used in extracting all members from every zipfile specified on the command line. Note that under FlexOS, if a candidate extract-to directory specification includes a drive letter (leading "x:"), it is treated just as if it had a trailing '/'--that is, one directory level will be created if the path doesn't exist, unless this is otherwise pro- hibited (e.g., freshening). ---------------------------------------------------------------------------*/ #if (!defined(SFX) || defined(SFX_EXDIR)) if (FUNCTION == ROOT) { Trace((stderr, "initializing root path to [%s]\n", FnFilter1(pathcomp))); if (pathcomp == (char *)NULL) { rootlen = 0; return 0; } if (rootlen > 0) /* rootpath was already set, nothing to do */ return 0; if ((rootlen = strlen(pathcomp)) > 0) { int had_trailing_pathsep=FALSE, add_dot=FALSE; char *tmproot; if ((tmproot = (char *)malloc(rootlen+3)) == (char *)NULL) { rootlen = 0; return 10; } strcpy(tmproot, pathcomp); if (tmproot[rootlen-1] == '/' || tmproot[rootlen-1] == '\\') { tmproot[--rootlen] = '\0'; had_trailing_pathsep = TRUE; } if (tmproot[rootlen-1] == ':') { if (!had_trailing_pathsep) /* i.e., original wasn't "xxx:/" */ add_dot = TRUE; /* relative path: add '.' before '/' */ } else if (rootlen > 0) { /* need not check "xxx:." and "xxx:/" */ if (SSTAT(tmproot, &G.statbuf) || !S_ISDIR(G.statbuf.st_mode)) { /* path does not exist */ if (!G.create_dirs /* || iswild(tmproot) */ ) { free(tmproot); rootlen = 0; return 2; /* treat as stored file */ } /* GRR: scan for wildcard characters? OS-dependent... if find any, return 2: * treat as stored file(s) */ /* create directory (could add loop here scanning tmproot * to create more than one level, but really necessary?) */ if (mkdir(tmproot, 0777) == -1) { Info(slide, 1, ((char *)slide, LoadFarString(CantCreateExtractDir), FnFilter1(tmproot))); free(tmproot); rootlen = 0; /* path didn't exist, tried to create, */ return 3; /* failed: file exists, or need 2+ levels */ } } } if (add_dot) /* had just "x:", make "x:." */ tmproot[rootlen++] = '.'; tmproot[rootlen++] = '/'; tmproot[rootlen] = '\0'; if ((rootpath = (char *)realloc(tmproot, rootlen+1)) == NULL) { free(tmproot); rootlen = 0; return 10; } Trace((stderr, "rootpath now = [%s]\n", FnFilter1(rootpath))); } return 0; } #endif /* !SFX || SFX_EXDIR */ /*--------------------------------------------------------------------------- END: free rootpath, immediately prior to program exit. ---------------------------------------------------------------------------*/ if (FUNCTION == END) { Trace((stderr, "freeing rootpath\n")); if (rootlen > 0) { free(rootpath); rootlen = 0; } return 0; } return 99; /* should never reach */ } /* end function checkdir() */ /****************************/ /* Function close_outfile() */ /****************************/ void close_outfile(__G) __GDEF /* * FlexOS VERSION * * Set the output file date/time stamp according to information from the * zipfile directory record for this member, then close the file and set * its permissions (archive, hidden, read-only, system). Aside from closing * the file, this routine is optional (but most compilers support it). */ { DISKFILE df; LONG fnum; struct { /* date and time words */ union { /* DOS file modification time word */ ush ztime; struct { unsigned zt_se : 5; unsigned zt_mi : 6; unsigned zt_hr : 5; } _tf; } _t; union { /* DOS file modification date word */ ush zdate; struct { unsigned zd_dy : 5; unsigned zd_mo : 4; unsigned zd_yr : 7; } _df; } _d; } zt; #ifdef USE_EF_UT_TIME iztimes z_utime; struct tm *t; #endif /* ?USE_EF_UT_TIME */ fclose(G.outfile); if ((fnum = s_open(A_SET, G.filename)) < 0) { Info(slide, 0x201, ((char *)slide, "warning: cannot open %s to set the time\n", G.filename)); return; } if (s_get(T_FILE, fnum, &df, DSKFSIZE) < 0) { s_close(0, fnum); Info(slide, 0x201, ((char *)slide, "warning: cannot get info on %s\n", G.filename)); return; } /*--------------------------------------------------------------------------- Copy and/or convert time and date variables, if necessary; then fill in the file time/date. ---------------------------------------------------------------------------*/ #ifdef USE_EF_UT_TIME if (G.extra_field && #ifdef IZ_CHECK_TZ G.tz_is_valid && #endif (ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0, G.lrec.last_mod_dos_datetime, &z_utime, NULL) & EB_UT_FL_MTIME)) { TTrace((stderr, "close_outfile: Unix e.f. modif. time = %ld\n", z_utime.mtime)); t = localtime(&(z_utime.mtime)); } else t = (struct tm *)NULL; if (t != (struct tm *)NULL) { if (t->tm_year < 80) { df.df_modyear = 1980; df.df_modmonth = 1; df.df_modday = 1; df.df_modhr = 0; df.df_modmin = 0; df.df_modsec = 0; } else { df.df_modyear = t->tm_year + 1900; df.df_modmonth = t->tm_mon + 1; wٔ UNZIP.BCK0. NZIP542.FLEXOS]FLEXOS.C;1Bo? df.df_modday = t->tm_mday; df.df_modhr = t->tm_hour; df.df_modmin = t->tm_min; df.df_modsec = t->tm_sec; } } else #endif /* ?USE_EF_UX_TIME */ { zt._t.ztime = (ush)(G.lrec.last_mod_dos_datetime) & 0xffff; zt._d.zdate = (ush)(G.lrec.last_mod_dos_datetime >> 16); df.df_modyear = 1980 + zt._d._df.zd_yr; df.df_modmonth = zt._d._df.zd_mo; df.df_modday = zt._d._df.zd_dy; df.df_modhr = zt._t._tf.zt_hr; df.df_modmin = zt._t._tf.zt_mi; df.df_modsec = zt._t._tf.zt_se << 1; } /*--------------------------------------------------------------------------- Fill in the file attributes. ---------------------------------------------------------------------------*/ df.df_attr1 = (UBYTE)G.pInfo->file_attr; /*--------------------------------------------------------------------------- Now we try to set the attributes & date/time. ---------------------------------------------------------------------------*/ if (s_set(T_FILE, fnum, &df, DSKFSIZE) < 0) Info(slide, 0x201, ((char *)slide, "warning: cannot set info for %s\n", G.filename)); s_close(0, fnum); } #ifndef SFX /*************************/ /* Function dateformat() */ /*************************/ int dateformat() { return DF_DMY; /* default for systems without locale info */ } /************************/ /* Function version() */ /************************/ void version(__G) __GDEF { int len; len = sprintf((char *)slide, LoadFarString(CompiledWith), "MetaWare High C", "", "FlexOS", " (16-bit, big)", #ifdef __DATE__ " on ", __DATE__ #else "", "" #endif ); (*G.message)((zvoid *)&G, slide, (ulg)len, 0); } #endif /* !SFX */ /************************/ /* Function _wildarg() */ /************************/ /* This prevents the PORTLIB startup code from preforming argument globbing */ _wildarg() {} *[UNZIP542.FLEXOS]FLXCFG.H;1+,M./ 4)-. 0@123KPWO56M" 7M" 89GHJ/* Copyright (c) 1990-2000 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*--------------------------------------------------------------------------- FlexOS specific configuration section: ---------------------------------------------------------------------------*/ #ifndef __flxcfg_h #define __flxcfg_h #define __16BIT__ #define MED_MEM #define EXE_EXTENSION ".286" #ifndef nearmalloc # define nearmalloc malloc # define nearfree free #endif #define CRTL_CP_IS_OEM #define near #define far #endif /* !__flxcfg_h */ -*[UNZIP542.FLEXOS]HC.PRO;1+,[./ 4-. 0@123KPWO56ȳkv7ȳkv89GHJpragma Off(Floating_point); pragma On(286); pragma On(Literals_in_code); pragma On(Warn); pragma On(pointers_compatible); pragma On(Callee_pops_when_possible); pragma On(Auto_reg_alloc); pragma On(Const_in_Code); pragma On(Read_only_strings); pragma On(Optimize_for_space); pragma Off(Prototype_override_warnings); pragma Off(Quiet); pragma Off(Asm); pragma Off(flexview); #define PORTLIB #define FLEXOS 1 -*[UNZIP542.FLEXOS]MAKEFILE.;1+,q. / 4 -. 0@123KPWO 56kv7kv89GHJ#------------------------------------------------------------------------------ # Makefile for UnZip 5.2 and later Derek Fawcus # Version: MetaWare High C with PAMAKE 3 Jun 96 # ########################################################################### # # Alter the first two macros to change the model # MODEL = big M = b # ########################################################################### # # These two sets of prefixes are changed when swapping between the master # and my machine. # FL_PREFIX = d:/flexos # Where FlexOS is rooted #FL_PREFIX = c:/. # ########################################################################### # # The following should not have to be changed - they should be automatic # given correct values for the above. # HC_LIB = $(FL_PREFIX)/highc/$(MODEL)/hc$(M)e.l86 PORT_LIB = $(FL_PREFIX)/usr/portlib/$(MODEL)/prtlbhc$(M).l86 PORT_OBJ = $(FL_PREFIX)/usr/portlib/$(MODEL)/prtlbhc$(M).obj HC_INC = $(FL_PREFIX)/highc/inc PORT_INC = $(FL_PREFIX)/usr/portlib/inc FLEX_INC = $(FL_PREFIX)/usr/inc +IPATH = $(PORT_INC)/;$(FLEX_INC)/; #+IPATH = $(PORT_INC)/;$(HC_INC)/;$(FLEX_INC)/; # ########################################################################### # # The programs to do the work. # CC = hc AS = rasm86 LD = link86 #HCOPTS=-mm $(MODEL) -debug -pr flexos/hc.pro HCOPTS=-mm $(MODEL) -pr flexos/hc.pro # ########################################################################### # # The file extensions to build from # .SUFFIXES: .SUFFIXES: .c .h .a86 # ########################################################################### # # Type for CPU required: 0: 8086, 1: 80186, 2: 80286, 3: 80386, etc. CPU_TYP = 2 # Uncomment the following three macros to use the optimized CRC32 assembler # routine in UnZip and UnZipSFX: #ASMFLG = -DASM_CRC #ASMOBJS = crc_i86.obj #ASMOBJF = crc_i86_.obj ASCPUFLAG = __$(CPU_TYP)86 UNZIP_H = unzip.h unzpriv.h globals.h flexos/flxcfg.h default: unzip.286 #default: unzip.286 funzip.286 unzipsfx.286 clean: del *.ob? del unzip.286 del funzip.286 del unzipsfx.* del *.map del *.lin del *.sym del *.dbg # ########################################################################### # .asm.obj: $(AS) $(ASFLAGS) -D$(ASUNMODEL) $*.asm .c.obj: $(CC) $< $(HCOPTS) -ob $@ .c.obf: $(CC) $< $(HCOPTS) -def FUNZIP -ob $@ .c.obs: $(CC) $< $(HCOPTS) -def SFX -ob $@ # ########################################################################### # crc_i86.obj: flexos/crc_i86.a86 $(AS) $(ASFLAGS) -D$(ASUNMODEL) flexos/crc_i86.a86, $*.obj ; # ######################################################################### # # The objects to build from # UNZIP_OBJS = unzip.obj crc32.obj crctab.obj crypt.obj envargs.obj \ explode.obj extract.obj fileio.obj globals.obj inflate.obj \ list.obj match.obj process.obj ttyio.obj unreduce.obj \ unshrink.obj zipinfo.obj flexos.obj $(ASMOBJS) unzip.286: $(UNZIP_OBJS) $(LD) $@[st[add[17e]]] = $-[input] $(PORT_OBJ), $+(${UNZIP_OBJS}), $(Px UNZIP.BCKq. [UNZIP542.FLEXOS]MAKEFILE.;1 7ORT_LIB), $(HC_LIB) < UNZIPSFX_OBJS = unzip.obs crc32.obj crctab.obj crypt.obj extract.obs \ fileio.obj globals.obj inflate.obj match.obj process.obs \ ttyio.obj flexos.obs $(ASMOBJS) unzipsfx.286: $(UNZIPSFX_OBJS) $(LD) $@[dbi,map[all],st[add[17e]]] = $-[input] $(PORT_OBJ), $+(${UNZIPSFX_OBJS}), $(PORT_LIB), $(HC_LIB) < FUNZIP_OBJS = funzip.obj crc32.obf crypt.obf globals.obf inflate.obf \ ttyio.obf $(ASMOBJF) funzip.286: $(FUNZIP_OBJS) $(LD) $@[dbi,map[all],st[add[17e]]] = $-[input] $(PORT_OBJ), $+(${FUNZIP_OBJS}), $(PORT_LIB), $(HC_LIB) < # ########################################################################### # unreduce.obj: unreduce.c $(UNZIP_H) unshrink.obj: unshrink.c $(UNZIP_H) unzip.obj: unzip.c $(UNZIP_H) crypt.h version.h consts.h zipinfo.obj: zipinfo.c $(UNZIP_H) process.obj: process.c $(UNZIP_H) list.obj: list.c $(UNZIP_H) match.obj: match.c $(UNZIP_H) fileio.obj: fileio.c $(UNZIP_H) crypt.h ttyio.h ebcdic.h envargs.obj: envargs.c $(UNZIP_H) explode.obj: explode.c $(UNZIP_H) extract.obj: extract.c $(UNZIP_H) crypt.h crctab.obj: crctab.c $(UNZIP_H) zip.h flexos.obj: flexos/flexos.c $(UNZIP_H) crc32.obj: crc32.c $(UNZIP_H) zip.h crypt.obj: crypt.c $(UNZIP_H) crypt.h ttyio.h zip.h globals.obj: globals.c $(UNZIP_H) inflate.obj: inflate.c inflate.h $(UNZIP_H) ttyio.obj: ttyio.c $(UNZIP_H) crypt.h ttyio.h zip.h funzip.obj: funzip.c $(UNZIP_H) crypt.h ttyio.h tables.h crc32.obf: crc32.c $(UNZIP_H) zip.h crypt.obf: crypt.c $(UNZIP_H) crypt.h ttyio.h zip.h globals.obf: globals.c $(UNZIP_H) inflate.obf: inflate.c inflate.h $(UNZIP_H) crypt.h ttyio.obf: ttyio.c $(UNZIP_H) crypt.h ttyio.h zip.h flexos.obs: flexos/flexos.c $(UNZIP_H) extract.obs: extract.c $(UNZIP_H) crypt.h process.obs: process.c $(UNZIP_H) unzip.obs: unzip.c $(UNZIP_H) crypt.h version.h consts.h h*[UNZIP542.FLEXOS]README.;1+,~./ 4-. 0@123KPWO56^3.x7^3.x89GHJThis should be considered an initial port - there will probably be some bugs and non-functioning features. The only functionality that has had any real testing is "unzip filename", anything else is basically untested. This has been cross-compiled from DOS using Metaware's High C compiler and the DOS version of pamake (v3.0). It should compile with the FlexOS hosted version of HighC, and the makefile could be converted to work with the native FlexOS make. The following considerations apply: )Compiled against and linked with portlib. )Used on FlexOS 286 v2.32 )Volume labels are not supported - this is due to the way FlexOS decides if a drive has case-sensitive filenames based upon the contents of the volume label. )No special handling for case-sensitive media (see above). )Not using the PORTLIB wildarg routine (i.e., UnZip does its own globbing). )Based upon the MSDOS port. )Filenames are in FAT format. )The current version of getch is a cheat (simply using getchar()). I should interrogate stdin and if it's a FlexOS console use special code to turn off echo and just read one char. )Only the basic MSDOS FAT file attributes are saved/restored. There is currently no support for the FlexOS extended file attributes. )There is some code that should attempt to do the correct thing when a pathspec with a logical name definition is used (e.g., "system:path/to/it"); however it again has not been stress-tested. )There is no special handling for floppy drives, there probably should be. )The dateformat is compiled in as DMY (shoot me I'm British), I'm not sure if there is actually a way to get locale info. )The assembler speedups haven't yet been ported to ASM86 (should simply be a change of syntax) -- D.Fawcus 17 July 1997 b y^V A  b 1H,d f-vNa myqvYj#C?:wgREUO3p]S BDW15.T[P_q(dU_') ^LY,bai\i3mJt_SLQ)B 1/J Po#@ zj 5<]LX6}[H(4mxTSL!~vbO U-hPJV Tv `TaHfdRI =5x !E$S-\B_yZO H'/E#C!qQ,{s_TI b 30vi;JZDE/j|F(c8WM1BU2cw_mbCr{a]Hr,q3I(zh@'IkNKs| m@7p F({hB2O-VP7Ed,6Z<}caj23Ui/+{1~ LfZ)>[EE |WaBx   8y2+(mNlMOl~z^RC@MJ|(p`Ey7WZ.M]nNb ;Sf UY!f U({m%'s 3EO5LN#/#V22spN\ Ak^8Im|5auS$Ryl/\>h?T@#\ ddKzIQ*FIL&o'eDAMdi_IwG:bz  :r( & 0#T"W r=3E7h"gA(GdX #]7gw>A 'H;\Ph5;ncHeAEFdvTQP` @Jj""~z&AC f TvhG! Gm'N:m4ARLv'@[^^`=XAL+}=G2%*QO^-M9=<=EWoO v5Kn$T#k!C}}$0!syEOxW]A & XmaR7jTtz"dN*!\mBh4~ZCJr[o_#+Rc[8A[eX+frd~)T"T;M sK+K/]P^4,_ 8XIK^TUY|1g5/dYo=ZfelD-5I*LUYD@[DEs_@]j{Xws?D(g@Kf0eW:" tjc%qV{AV0 ~`\aj\p10Z>ua+:]Gx Vpf ?g\E $yU[#pS!_ 8DBjN$9*-YTE /{ UgH t:@,9Q/\[j'H$,:|P|w,j6Z+[W]Y\YWs3}pV1x{p(ozuz=4lrgY2 C'BDxb5\[*aL9$ATA6>4D] 'xEH[9h(wfp^)CM^GE4\ B[UY#))3z*>\ c+tI^ ;" MB\D %_D tc")U};Um(c{ 1lpGO]1 [52e'NEXcW"2}mU>i%k 6d^tC!rIG<@otd?c ?(\?"XN /9W@]3vKRrDq8 yeSV \hB ^(SPIKA_vhMx Q"P oHI_ i +d%pL08XVaT5Jo?(%ZH#33hG/w!_1c,?}]ZZ?P>? yq\tF :q*6b z2s-Bu*+Z] adzpKckY)uJ&KYn,)AyJ'NUbkB17`QbRuQ]i(*8+e[ DIP8v?r39>(`pzv0)9S>dz42$c#7,$3~_\@?~8iQ]@L2"RS^ n?T|mt?^gjS?}bb`@4JVb,U7+`!'M',rut$B03s&Z QCeKIc@3qazN0BbA_/w?u5I &P`pxcG~OqBF[iZcqGbJIloE_mYwXWA%q(w*o9LccWc&P9Id ~\_9y2y l4}NRK 8Mpi;vuNt2`@p< ~$8!LN]XBW\\X wEN[X,@qt*z&i/H ,M|k V Kb1iJf YGx[c\ O(E)$ J ,x)1cJ(wq=zltywy>/xl8dEq'(v=>V:jV4H+o*+s7YhEs4<S*j 0 ?AOOg]9 >}*}|kRT4CYJ!x^dY:,}-h%a2&4panm9w9|nq'sQANo8q 3 YPi|/O|pilZ\tPQz Q"Hu@P$IU8I`GCETXVJO` Vxpp*q(YUbk+]~3D@gC3} a>fE3Uf[1\cIznAXAl[$=Y/Ab(osF4giBk*;:GTlPexM1I W"ɭB=@9nj"-a2>_tTw6O\7J1G [ G^%l@ME9:~j"],\rF.2xC(M,=ZKNZX@P2vWcI  hYXuf|jHkkOhyoX R_/-Y^cG rt\,XZmW2``R?!g0M"QTDC%]edIqx h:7 @ D)XI%{ _Fe}3 CD }~`z(\n]6x7I66=SrABVuYkT{6-*,_T ^JD:DN2q/k6}JmwmG Z.CiJZ1'Y4 dn D^LmM !k<3N[%^I@FD`nr".vI Yq{ BCy UP{1%@'0; d!JP^FqB j,cGArT'uHj '!#K]>PdI{o\]aHmYR\xKcQQ@)h}X*mk +^/n]z] :aq}(9 )>-1t/d:]hq`V:1rg}EQSVtd8"ZA"*i'C=X}_A0a+,U-`Pk:9%wX03-v%JfyB#9f%Ld-U;u.9"x(lsh0X?{n+ f9m  gA#H1qN R\gwJtq9^dCJ|o5qBCA+1Zx -l \}<X+@mp & %=M> +|#;yo;Rb?< /%'/,x)T5F.3cb_` w%)iXsW:dYJ/lQ3wH_]VL-_DXq\} +FrFTw&TBFN E8@JcNZEY$3[)9945pQ-y}Ig2X"w"&0Gy0 PUF4H851q@{  1D !Tu+ASxDo($t];8 *Ve+EI8\CnTKH*z?w^]I F{ *$!Vy=0J2AU 8fN;]&|G|M3YO!L3Gs1^{#qH1=^/ \S<P-3_Vi'i$Jhn6?CCz@^kQGhd~oS;!0u="7l@fO H2D?i LZcWZd?td?96!q(.$JRG-m)&U` d}|$\Wf]16ll(agFp|v] 77m"Q*_057:y.?%a3a~B? vs^& Kk%.z$t K| b@B D`xN,>2+4}(7/6*%o90~c3zjV0U(mJ6wC3[2_82%TiS?q"h%?&e>'&x;q@Xz 0fS}ZIz}: Bt ;7&b0C94-7P -jo~E$gF&0vV{e{z0pDvvx:sqx*bN xXu-': vuv&KGE*}fGuj!W$PT`8dt8nq{FJ/Xklxrl!x|eE!wru2-3ODjl*{uEBiB$aBky @zsNXBrGI ,"4!~ Ru{z@i;XdvUA wNP]TE23=cz[Q.[vc$9CTWx 4IS)]MYGa-bM `xLBgNQH@I5L ]X Qg@BW7V<DE4 \Y#@a[C X NZD\R!?MG`6UfKhEe!+uxD!OB+ qZw. 2)cB[1>bZo^cMM*T%L*K dmdNE<*gn^:/x;[o/ RH)C]vr"; VV VMz8s}|Q{yZ1p>8]'FZg:f6Yt2%ES7lZBbL %wmB} "dQ/L4&B[  LHe|yDQG#?i Vgwty\EYc-yfu~E6xBIF(pW3#`Gp7U`0Gd[KM8@A=cJnP/&n5R*/8gP1e/tM>g>E`LXPHfx&Jtvx([C5G#sVck-or @2%qI.gJ{*RXCO*>{/up17y-lb.6S,JFWVM)+vH,yCN zPSQ'8k&'Nae~'.e#c!w=?aW0GFGO_-UC->SW9"rV"fg 8k1 'cVCHate||axES ?"f\-$dTF O:FpHlUKZpL  ]O ALD[Avd8nej6O.# (hRYQ'xDdw MB|-c-,NKs0/{Zb!+|5a}0'b7[LNGuD!X~.uRf0u2q}T R]&leGGr=QL>W7_+({`gvdL(#iw>zfuI- ZEW'bCt5t,QPb]6GI#NP1B9H0AUG_4;R.R=iXVt>;;df@%d$)  C1[\E +'Q6DS)`=R7C iE:7Ln@EK3} L9.Rv'FFPf)w=/3+$ L!R4qK iQ|Z"`<4ZU!``6xW~Ci <5G FXZRZB> {jf + kvZdA).G'E1lL%dyVYVB,pFJ_-d0P9VA[Y?CX+",!4QtHxmLDDS'c^>D' eAuee/`[o*)V {c6q@S\ Z;n%m_-t?5`r w[\wzk~0l&c0:,5[nDI@:uD  .qtl F Go)&Vy@&]|Ep~d`jknc&_5{5kX $TXqoZT9]\JS5Ac[]^8?g 413wcf$' Y#< /u YMp$vvT4<}{3( L=tJ%ZO~3&>=&Bk4aD? J Zptk}6%ziW6Po@Ig;qQJVgZINbfI ,8? z)M#\߁jf{>m:S]cD2V0;JfYMmI5Wa3jQqCc1Vd'8F|k?E*iBa#mtNul&iy~IMBSo%55n?WS~m#Bx5WcX };k1h%w2kX^w=Z QG^~TbEA@=mVTFDBHQ~CX_q`}{ k :&/m:<`h#:/Er sd2WKm8"?QaL;UMxjA($HoV1SR"bb2~`|_IdYx m?td %#dzdhR fhSx.9V fU&OaKl%N._:IL9jld_diiEogAFlg~'&!mN^ElPA[ *?f.bxqU2 : 9y1  ^ fdA!B"T[Iu6?'?h,U"i]xc{)%GvP U[y|tYWcOA=ZQWUAZC.[3FS8u<=v+F\2T$lCqZ s3  .yxW'&C0+h&oTA3 2Vw>!rpzR& 'i'oNU9#r-F] YTGf7puQpRY(BBapID3UMO<8DrG(}v{E VNSz\4KTN2>qn M#<=lK1+bwEA(GV{mo \eB-S?T:Mh{Yt{Byrm"y__U \d_PU^@d$ ;v{7tud[9q-'9p|'aJF,2O g|1 R D5}2^zaNoGe)=OY0{MIsk!rZD WR :K9.kXosN zH~{u$/m(U)] &wuD'M(Z= HUlLBHJ^<,{ncNq&e(dw1uN1~8+\OVcn[PKHXU >B @,k jXPSj*QF1 5Nctwba9R[gB$'n`Y%=(r(=/^*p\=;"rYQVJQeq*Kh  > ^T S^ji6 &R 6U>AkE LNTDu}/*;3l)!;tv,|T  D Ton, but the compiler complazmS! UNZIP.BCK  [UNZIP542]FUNZIP.C;1#i*[UNZIP542]FUNZIP.C;1+, .#/ 4##- 0@123KPWO$56-Na7-Na89GHJ/* Copyright (c) 1990-2001 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /* funzip.c -- by Mark Adler */ #define VERSION "3.93 of 14 January 2001" /* Copyright history: - Starting with UnZip 5.41 of 16-April-2000, this source file is covered by the Info-Zip LICENSE cited above. - Prior versions of this source file, found in UnZip source packages up to UnZip 5.40, were put in the public domain. The original copyright note by Mark Adler was: "You can do whatever you like with this source file, though I would prefer that if you modify it and redistribute it that you include comments to that effect with your name and the date. Thank you." History: vers date who what ---- --------- -------------- ------------------------------------ 1.0 13 Aug 92 M. Adler really simple unzip filter. 1.1 13 Aug 92 M. Adler cleaned up somewhat, give help if stdin not redirected, warn if more zip file entries after the first. 1.2 15 Aug 92 M. Adler added check of lengths for stored entries, added more help. 1.3 16 Aug 92 M. Adler removed redundant #define's, added decryption. 1.4 27 Aug 92 G. Roelofs added exit(0). 1.5 1 Sep 92 K. U. Rommel changed read/write modes for OS/2. 1.6 6 Sep 92 G. Roelofs modified to use dummy crypt.c and crypt.h instead of -DCRYPT. 1.7 23 Sep 92 G. Roelofs changed to use DOS_OS2; included crypt.c under MS-DOS. 1.8 9 Oct 92 M. Adler improved inflation error msgs. 1.9 17 Oct 92 G. Roelofs changed ULONG/UWORD/byte to ulg/ush/uch; renamed inflate_entry() to inflate(); adapted to use new, in-place zdecode. 2.0 22 Oct 92 M. Adler allow filename argument, prompt for passwords and don't echo, still allow command-line password entry, but as an option. 2.1 23 Oct 92 J-l. Gailly fixed crypt/store bug, G. Roelofs removed crypt.c under MS-DOS, fixed decryption check to compare single byte. 2.2 28 Oct 92 G. Roelofs removed declaration of key. 2.3 14 Dec 92 M. Adler replaced fseek (fails on stdin for SCO Unix V.3.2.4). added quietflg for inflate.c. 3.0 11 May 93 M. Adler added gzip support 3.1 9 Jul 93 K. U. Rommel fixed OS/2 pipe bug (PIPE_ERROR) 3.2 4 Sep 93 G. Roelofs moved crc_32_tab[] to tables.h; used FOPx from unzip.h; nuked OUTB macro and outbuf; replaced flush(); inlined FlushOutput(); renamed decrypt to encrypted 3.3 29 Sep 93 G. Roelofs replaced ReadByte() with NEXTBYTE macro; revised (restored?) flush(); added FUNZIP 3.4 21 Oct 93 G. Roelofs renamed quietflg to qflag; changed outcnt, H. Gessau second updcrc() arg and flush() arg to ulg; added inflate_free(); added "g =" to null getc(in) to avoid compiler warnings 3.5 31 Oct 93 H. Gessau changed DOS_OS2 to DOS_NT_OS2 3.6 6 Dec 93 H. Gessau added "near" to mask_bits[] 3.7 9 Dec 93 G. Roelofs added extent typecasts to fwrite() checks 3.8 28 Jan 94 GRR/JlG initialized g variable in main() for gcc 3.81 22 Feb 94 M. Hanning-Lee corrected usage message 3.82 27 Feb 94 G. Roelofs added some typecasts to avoid warnings 3.83 22 Jul 94 G. Roelofs changed fprintf to macro for DLLs - 2 Aug 94 - public release with UnZip 5.11 - 28 Aug 94 - public release with UnZip 5.12 3.84 1 Oct 94 K. U. Rommel changes for Metaware High C 3.85 29 Oct 94 G. Roelofs changed fprintf macro to Info 3.86 7 May 95 K. Davis RISCOS patches; P. Kienitz Amiga patches 3.87 12 Aug 95 G. Roelofs inflate_free(), DESTROYGLOBALS fixes 3.88 4 Sep 95 C. Spieler reordered macro to work around MSC 5.1 bug 3.89 22 Nov 95 PK/CS ifdef'd out updcrc() for ASM_CRC 3.9 17 Dec 95 G. Roelofs modified for USE_ZLIB (new fillinbuf()) - 30 Apr 96 - public release with UnZip 5.2 3.91 17 Aug 96 G. Roelofs main() -> return int (Peter Seebach) 3.92 13 Apr 97 G. Roelofs minor cosmetic fixes to messages - 22 Apr 97 - public release with UnZip 5.3 - 31 May 97 - public release with UnZip 5.31 3.93 20 Sep 97 G. Roelofs minor cosmetic fixes to messages - 3 Nov 97 - public release with UnZip 5.32 - 28 Nov 98 - public release with UnZip 5.4 - 16 Apr 00 - public release with UnZip 5.41 - 14 Jan 01 - public release with UnZip 5.42 */ /* All funzip does is take a zipfile from stdin and decompress the first entry to stdout. The entry has to be either deflated or stored. If the entry is encrypted, then the decryption password must be supplied on the command line as the first argument. funzip needs to be linked with inflate.o and crypt.o compiled from the unzip source. If decryption is desired, the full version of crypt.c (and crypt.h) from zcrypt28.zip or later must be used. */ #define FUNZIP #define UNZIP_INTERNAL #include "unzip.h" #include "crypt.h" #include "ttyio.h" #ifdef EBCDIC # undef EBCDIC /* don't need ebcdic[] */ #endif #include "tables.h" /* crc_32_tab[] */ #ifndef USE_ZLIB /* zlib's function is called inflate(), too */ # define UZinflate inflate #endif /* PKZIP header definitions */ #define ZIPMAG 0x4b50 /* two-byte zip lead-in */ #define LOCREM 0x0403 /* remaining two bytes in zip signature */ #define LOCSIG 0x04034b50L /* full signature */ #define LOCFLG 4 /* offset of bit flag */ #define CRPFLG 1 /* bit for encrypted entry */ #define EXTFLG 8 /* bit for extended local header */ #define LOCHOW 6 /* offset of compression method */ #define LOCTIM 8 /* file mod time (fo{2 UNZIP.BCK  [UNZIP542]FUNZIP.C;1#Br decryption) */ #define LOCCRC 12 /* offset of crc */ #define LOCSIZ 16 /* offset of compressed size */ #define LOCLEN 20 /* offset of uncompressed length */ #define LOCFIL 24 /* offset of file name field length */ #define LOCEXT 26 /* offset of extra field length */ #define LOCHDR 28 /* size of local header, including LOCREM */ #define EXTHDR 16 /* size of extended local header, inc sig */ /* GZIP header definitions */ #define GZPMAG 0x8b1f /* two-byte gzip lead-in */ #define GZPHOW 0 /* offset of method number */ #define GZPFLG 1 /* offset of gzip flags */ #define GZPMUL 2 /* bit for multiple-part gzip file */ #define GZPISX 4 /* bit for extra field present */ #define GZPISF 8 /* bit for filename present */ #define GZPISC 16 /* bit for comment present */ #define GZPISE 32 /* bit for encryption */ #define GZPTIM 2 /* offset of Unix file modification time */ #define GZPEXF 6 /* offset of extra flags */ #define GZPCOS 7 /* offset of operating system compressed on */ #define GZPHDR 8 /* length of minimal gzip header */ #ifdef THEOS /* Macros cause stack overflow in compiler */ ush SH(uch* p) { return ((ush)(uch)((p)[0]) | ((ush)(uch)((p)[1]) << 8)); } ulg LG(uch* p) { return ((ulg)(SH(p)) | ((ulg)(SH((p)+2)) << 16)); } #else /* !THEOS */ /* Macros for getting two-byte and four-byte header values */ #define SH(p) ((ush)(uch)((p)[0]) | ((ush)(uch)((p)[1]) << 8)) #define LG(p) ((ulg)(SH(p)) | ((ulg)(SH((p)+2)) << 16)) #endif /* ?THEOS */ /* Function prototypes */ void err OF((int, char *)); int main OF((int, char **)); /* Globals */ FILE *out; /* output file (*in moved to G struct) */ ulg outsiz; /* total bytes written to out */ int encrypted; /* flag to turn on decryption */ /* Masks for inflate.c */ ZCONST ush near mask_bits[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff }; #ifdef USE_ZLIB int fillinbuf(__G) __GDEF /* Fill input buffer for pull-model inflate() in zlib. Return the number of * bytes in inbuf. */ { /* GRR: check return value from fread(): same as read()? check errno? */ if ((G.incnt = fread((char *)G.inbuf, 1, INBUFSIZ, G.in)) <= 0) return 0; G.inptr = G.inbuf; #if CRYPT if (encrypted) { uch *p; int n; for (n = G.incnt, p = G.inptr; n--; p++) zdecode(*p); } #endif /* CRYPT */ return G.incnt; } #endif /* USE_ZLIB */ #if (!defined(USE_ZLIB) || defined(USE_OWN_CRCTAB)) #ifdef USE_ZLIB ZCONST uLongf *get_crc_table() { return (ZCONST uLongf *)crc_32_tab; } #else /* !USE_ZLIB */ ZCONST ulg near *get_crc_table() { return crc_32_tab; } #endif /* ?USE_ZLIB */ #endif /* !USE_ZLIB || USE_OWN_CRCTAB */ void err(n, m) int n; char *m; /* Exit on error with a message and a code */ { Info(slide, 1, ((char *)slide, "funzip error: %s\n", m)); DESTROYGLOBALS() EXIT(n); } int flush(w) /* used by inflate.c (FLUSH macro) */ ulg w; /* number of bytes to flush */ { G.crc32val = crc32(G.crc32val, slide, (extent)w); if (fwrite((char *)slide,1,(extent)w,out) != (extent)w && !PIPE_ERROR) err(9, "out of space on stdout"); outsiz += w; return 0; } int main(argc, argv) int argc; char **argv; /* Given a zipfile on stdin, decompress the first entry to stdout. */ { ush n; uch h[LOCHDR]; /* first local header (GZPHDR < LOCHDR) */ int g = 0; /* true if gzip format */ #if CRYPT char *s = " [-password]"; char *p; /* password */ #else /* !CRYPT */ char *s = ""; #endif /* ?CRYPT */ CONSTRUCTGLOBALS(); /* skip executable name */ argc--; argv++; #if CRYPT /* get the command line password, if any */ p = (char *)NULL; if (argc && **argv == '-') { argc--; p = 1 + *argv++; } #endif /* CRYPT */ #ifdef MALLOC_WORK G.area.Slide = (uch *)calloc(8193, sizeof(short)+sizeof(char)+sizeof(char)); #endif /* if no file argument and stdin not redirected, give the user help */ if (argc == 0 && isatty(0)) { Info(slide, 1, ((char *)slide, "fUnZip (filter UnZip), version %s\n", VERSION)); Info(slide, 1, ((char *)slide, "usage: ... | funzip%s | ...\n", s)); Info(slide, 1, ((char *)slide, " ... | funzip%s > outfile\n", s)); Info(slide, 1, ((char *)slide, " funzip%s infile.zip > outfile\n",s)); Info(slide, 1, ((char *)slide, " funzip%s infile.gz > outfile\n", s)); Info(slide, 1, ((char *)slide, "Extracts to stdout the gzip file or first\ zip entry of stdin or the given file.\n")); DESTROYGLOBALS() EXIT(3); } /* prepare to be a binary filter */ if (argc) { if ((G.in = fopen(*argv, FOPR)) == (FILE *)NULL) err(2, "cannot find input file"); } else { #ifdef DOS_FLX_NLM_OS2_W32 #if (defined(__HIGHC__) && !defined(FLEXOS)) setmode(stdin, _BINARY); #else setmode(0, O_BINARY); /* some buggy C libraries require BOTH setmode() */ #endif /* call AND the fdopen() in binary mode :-( */ #endif /* DOS_FLX_NLM_OS2_W32 */ #ifdef RISCOS G.in = stdin; #else if ((G.in = fdopen(0, FOPR)) == (FILE *)NULL) err(2, "cannot find stdin"); #endif } #ifdef DOS_FLX_H68_NLM_OS2_W32 #if (defined(__HIGHC__) && !defined(FLEXOS)) setmode(stdout, _BINARY); #else setmode(1, O_BINARY); #endif #endif /* DOS_FLX_H68_NLM_OS2_W32 */ #ifdef RISCOS out = stdout; #else if ((out = fdopen(1, FOPW)) == (FILE *)NULL) err(2, "cannot write to stdout"); #endif /* read local header, check validity, and skip name and extra fields */ n = getc(G.in); n |= getc(G.in) << 8; if (n == ZIPMAG) { if (fread((char *)h, 1, LOCHDR, G.in) != LOCHDR || SH(h) != LOCREM) err(3, "invalid zipfile"); if (SH(h + LOCHOW) != STORED && SH(h + LOCHOW) != DEFLATED) err(3, "first entry not deflated or stored--cannot unpack"); for (n = SH(h + LOCFIL); n--; ) g = getc(G.in); for (n = SH(h + LOCEXT); n--; ) g = getc(G.in); g = 0; encrypted = h[LOCFLG] & CRPFLG; } else if (n == GZPMAG) { if (fread((char *)h, 1, GZPHDR, G.in) != GZPHDR) err(3, "invalid gzip file"); if (h[GZPHOW] != DEFLATED) err(3, "gzip file not deflated"); if (h[GZPFLG] & GZPMUL) err(3, "cannot handle multi-part gzip files"); if (h[GZPFLG] & GZPISX) { n = getc(G.in); n |= getc(G.in) << 8; while (n--) g = getc(G.in); } if (h[GZPFLG] & GZPISF) while ((g = getc(G.in)) != 0 && g != EOF) ; if (h[GZPFLG] & GZPISC) while ((g = getc(G.in)) != 0 && g != EOF) ; g = 1; encrypted = h[GZPFLG] & GZPISE; } else err(3, "input not a zip or gzip file"); /* if entry encrypted, decrypt and validate encryption header */ if (encrypted) #if CRYPT { ush i, e; if (p == (char *)NULL) { if ((p = (char *)malloc(IZ_PWLEN+1)) == (char *)NULL) err(1, "out of memory"); else if ((p = getp("Enter password: ", p, IZ_PWLEN+1)) == (char *)NULL) err(1, "no tty to prompt for password"); } #if (defined(USE_ZLIB) && !defined(USE_OWN_CRCTAB)) /* initialize crc_32_tab pointer for decryption */ CRC_32_TAB = (ZCONST ulg Far *)get_crc_table(); #endif init_keys(p); for (i = 0; i < RAND_HEAD_LEN; i++) e = NEXTBYTE; if (e != (ush)(h[LOCFLG] & EXTFL| UNZIP.BCK  [UNZIP542]FUNZIP.C;1#"N G ? h[LOCTIM + 1] : h[LOCCRC + 3])) err(3, "incorrect password for first entry"); } #else /* !CRYPT */ err(3, "cannot decrypt entry (need to recompile with full crypt.c)"); #endif /* ?CRYPT */ /* prepare output buffer and crc */ G.outptr = slide; G.outcnt = 0L; outsiz = 0L; G.crc32val = CRCVAL_INITIAL; /* decompress */ if (g || h[LOCHOW]) { /* deflated entry */ int r; #ifdef USE_ZLIB /* need to allocate and prepare input buffer */ if ((G.inbuf = (uch *)malloc(INBUFSIZ)) == (uch *)NULL) err(1, "out of memory"); #endif /* USE_ZLIB */ if ((r = UZinflate(__G)) != 0) { if (r == 3) err(1, "out of memory"); else err(4, "invalid compressed data--format violated"); } inflate_free(__G); } else { /* stored entry */ register ulg n; n = LG(h + LOCLEN); #if CRYPT if (n != LG(h + LOCSIZ) - (encrypted ? RAND_HEAD_LEN : 0)) { #else if (n != LG(h + LOCSIZ)) { #endif Info(slide, 1, ((char *)slide, "len %ld, siz %ld\n", n, LG(h + LOCSIZ))); err(4, "invalid compressed data--length mismatch"); } while (n--) { ush c = getc(G.in); #if CRYPT if (encrypted) zdecode(c); #endif *G.outptr++ = (uch)c; if (++G.outcnt == WSIZE) /* do FlushOutput() */ { G.crc32val = crc32(G.crc32val, slide, (extent)G.outcnt); if (fwrite((char *)slide, 1,(extent)G.outcnt,out) != (extent)G.outcnt && !PIPE_ERROR) err(9, "out of space on stdout"); outsiz += G.outcnt; G.outptr = slide; G.outcnt = 0L; } } } if (G.outcnt) /* flush one last time; no need to reset G.outptr/outcnt */ { G.crc32val = crc32(G.crc32val, slide, (extent)G.outcnt); if (fwrite((char *)slide, 1,(extent)G.outcnt,out) != (extent)G.outcnt && !PIPE_ERROR) err(9, "out of space on stdout"); outsiz += G.outcnt; } fflush(out); /* if extended header, get it */ if (g) { if (fread((char *)h + LOCCRC, 1, 8, G.in) != 8) err(3, "gzip file ended prematurely"); } else if ((h[LOCFLG] & EXTFLG) && fread((char *)h + LOCCRC - 4, 1, EXTHDR, G.in) != EXTHDR) err(3, "zipfile ended prematurely"); /* validate decompression */ if (LG(h + LOCCRC) != G.crc32val) err(4, "invalid compressed data--crc error"); if (LG((g ? (h + LOCSIZ) : (h + LOCLEN))) != outsiz) err(4, "invalid compressed data--length error"); /* check if there are more entries */ if (!g && fread((char *)h, 1, 4, G.in) == 4 && LG(h) == LOCSIG) Info(slide, 1, ((char *)slide, "funzip warning: zipfile has more than one entry--rest ignored\n")); DESTROYGLOBALS() RETURN (0); } *[UNZIP542]FUNZIP.TXT;1+, ./ 4- 0@123KPWO 56iLa7iLa89GHJ FUNZIP(1L) FUNZIP(1L) NAME funzip - filter for extracting from a ZIP archive in a pipe SYNOPSIS [...] | funzip [-password] | [...] funzip [-password] input.zip | [...] funzip [-password] input.gz | [...] ARGUMENTS [-password] Optional password to be used if ZIP archive is encrypted. Decryption may not be supported at some sites. See DESCRIPTION for more details. DESCRIPTION funzip acts as a filter; that is, it assumes that a ZIP archive (or a gzip'd(1) file) is being piped into standard input, and it extracts the first member from the archive to stdout. If there is an argument, then the input comes from the specified file instead of from stdin. A password for encrypted zip files can be specified on the command line (preceding the file name, if any) by prefixing the password with a dash. Note that this constitutes a secu- rity risk on many systems; currently running processes are often visible via simple commands (e.g., ps(1) under Unix), and command-line histories can be read. If the first entry of the zip file is encrypted and no password is specified on the command line, then the user is prompted for a password and the password is not echoed on the console. Given the limitation on single-member extraction, funzip is most useful in conjunction with a secondary archiver program such as tar(1). The following section includes an example illustrating this usage in the case of disk back- ups to tape. EXAMPLES To use funzip to extract the first member file of the archive test.zip and to pipe it into more(1): funzip test.zip | more To use funzip to test the first member file of test.zip (any errors will be reported on standard error): funzip test.zip > /dev/null To use zip and funzip in place of compress(1) and zcat(1) (or gzip(1L) and gzcat(1L)) for tape backups: tar cf - . | zip -7 | dd of=/dev/nrst0 obs=8k Info-ZIP 14 January 2001 (v3.93) 1 FUNZIP(1L) FUNZIP(1L) dd if=/dev/nrst0 ibs=8k | funzip | tar xf - (where, for example, nrst0 is a SCSI tape drive). BUGS When piping an encrypted file into more and allowing fun- zip to prompt for password, the terminal may sometimes be reset to a non-echo mode. This is apparently due to a race condition between the two programs; funzip changes the terminal mode to non-echo before more reads its state, and more then ``restores'' the terminal to this mode before exiting. To recover, run funzip on the same file but redirect to /dev/null rather than piping into more; after prompting again for the password, funzip will reset the terminal properly. There is presently no way to extract any member but the first from a ZIP archive. This would be useful in the case where a ZIP archive is included within another archive. In the case where the first member is a direc- tory, funzip simply creates the directory and exits. The functionality of funzip should be incorporated into unzip itself (future release). SEE ALSO gzip(1L), unzip(1L), unzipsfx(1L), zip(1L), zipcloak(1L), zipinfo(1L), zipnote(1L), zipsplit(1L) URL The Info-ZIP home page is currently at http://www.info- zip.org/pub/infozip/ or ftp://ftp.info- zip.org/pub/infozip/ . AUTHOR Mark Adler (Info-ZIP) Info-ZIP 14 January 2001 (v3.93) 2 n*[UNZIP542]GLOBALS.C;1+, . / 4 p- 0@123KPWO56Pk= 7Pk= 89GHJ} UNZIP.BCK  [UNZIP542]GLOBALS.C;1 /* Copyright (c) 1990-2000 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*--------------------------------------------------------------------------- globals.c Routines to allocate and initialize globals, with or without threads. Contents: registerGlobalPointer() deregisterGlobalPointer() getGlobalPointer() globalsCtor() ---------------------------------------------------------------------------*/ #define UNZIP_INTERNAL #include "unzip.h" #ifndef FUNZIP /* initialization of sigs is completed at runtime so unzip(sfx) executable * won't look like a zipfile */ char central_hdr_sig[4] = {0, 0, 0x01, 0x02}; char local_hdr_sig[4] = {0, 0, 0x03, 0x04}; char end_central_sig[4] = {0, 0, 0x05, 0x06}; /* extern char extd_local_sig[4] = {0, 0, 0x07, 0x08}; NOT USED YET */ ZCONST char *fnames[2] = {"*", NULL}; /* default filenames vector */ #endif #ifndef REENTRANT Uz_Globs G; #else /* REENTRANT */ # ifndef USETHREADID Uz_Globs *GG; # else /* USETHREADID */ # define THREADID_ENTRIES 0x40 int lastScan; Uz_Globs *threadPtrTable[THREADID_ENTRIES]; ulg threadIdTable [THREADID_ENTRIES] = { 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* Make sure there are */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* THREADID_ENTRIES 0s */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 }; static ZCONST char Far TooManyThreads[] = "error: more than %d simultaneous threads.\n\ Some threads are probably not calling DESTROYTHREAD()\n"; static ZCONST char Far EntryNotFound[] = "error: couldn't find global pointer in table.\n\ Maybe somebody accidentally called DESTROYTHREAD() twice.\n"; static ZCONST char Far GlobalPointerMismatch[] = "error: global pointer in table does not match pointer passed as\ parameter\n"; static void registerGlobalPointer OF((__GPRO)); static void registerGlobalPointer(__G) __GDEF { int scan=0; ulg tid = GetThreadId(); while (threadIdTable[scan] && scan < THREADID_ENTRIES) scan++; if (scan == THREADID_ENTRIES) { ZCONST char *tooMany = LoadFarString(TooManyThreads); Info(slide, 0x421, ((char *)slide, tooMany, THREADID_ENTRIES)); free(pG); EXIT(PK_MEM); /* essentially memory error before we've started */ } threadIdTable [scan] = tid; threadPtrTable[scan] = pG; lastScan = scan; } void deregisterGlobalPointer(__G) __GDEF { int scan=0; ulg tid = GetThreadId(); while (threadIdTable[scan] != tid && scan < THREADID_ENTRIES) scan++; /*--------------------------------------------------------------------------- There are two things we can do if we can't find the entry: ignore it or scream. The most likely reason for it not to be here is the user calling this routine twice. Since this could cause BIG problems if any globals are accessed after the first call, we'd better scream. ---------------------------------------------------------------------------*/ if (scan == THREADID_ENTRIES || threadPtrTable[scan] != pG) { ZCONST char *noEntry; if (scan == THREADID_ENTRIES) noEntry = LoadFarString(EntryNotFound); else noEntry = LoadFarString(GlobalPointerMismatch); Info(slide, 0x421, ((char *)slide, noEntry)); EXIT(PK_WARN); /* programming error, but after we're all done */ } threadIdTable [scan] = 0; lastScan = scan; free(threadPtrTable[scan]); } Uz_Globs *getGlobalPointer() { int scan=0; ulg tid = GetThreadId(); while (threadIdTable[scan] != tid && scan < THREADID_ENTRIES) scan++; /*--------------------------------------------------------------------------- There are two things we can do if we can't find the entry: ignore it or scream. The most likely reason for it not to be here is the user calling this routine twice. Since this could cause BIG problems if any globals are accessed after the first call, we'd better scream. ---------------------------------------------------------------------------*/ if (scan == THREADID_ENTRIES) { ZCONST char *noEntry = LoadFarString(EntryNotFound); fprintf(stderr, noEntry); /* can't use Info w/o a global pointer */ EXIT(PK_ERR); /* programming error while still working */ } return threadPtrTable[scan]; } # endif /* ?USETHREADID */ #endif /* ?REENTRANT */ Uz_Globs *globalsCtor() { #ifdef REENTRANT Uz_Globs *pG = (Uz_Globs *)malloc(sizeof(Uz_Globs)); if (!pG) return (Uz_Globs *)NULL; #endif /* REENTRANT */ /* for REENTRANT version, G is defined as (*pG) */ memzero(&G, sizeof(Uz_Globs)); #ifndef FUNZIP #ifdef CMS_MVS uO.aflag=1; uO.C_flag=1; #endif #ifdef TANDEM uO.aflag=1; /* default to '-a' auto create Text Files as type 101 */ #endif uO.lflag=(-1); G.wildzipfn = ""; G.pfnames = (char **)fnames; G.pxnames = (char **)&fnames[1]; G.pInfo = G.info; G.sol = TRUE; /* at start of line */ G.message = UzpMessagePrnt; G.input = UzpInput; /* not used by anyone at the moment... */ #if defined(WINDLL) || defined(MACOS) G.mpause = NULL; /* has scrollbars: no need for pausing */ #else G.mpause = UzpMorePause; #endif G.decr_passwd = UzpPassword; #endif /* !FUNZIP */ #if (!defined(DOS_FLX_H68_NLM_OS2_W32) && !defined(AMIGA) && !defined(RISCOS)) #if (!defined(MACOS) && !defined(ATARI) && !defined(VMS)) G.echofd = -1; #endif /* !(MACOS || ATARI || VMS) */ #endif /* !(DOS_FLX_H68_NLM_OS2_W32 || AMIGA || RISCOS) */ #ifdef SYSTEM_SPECIFIC_CTOR SYSTEM_SPECIFIC_CTOR(__G); #endif #ifdef REENTRANT #ifdef USETHREADID registerGlobalPointer(__G); #else GG = &G; #endif /* ?USETHREADID */ #endif /* REENTRANT */ return &G; } *[UNZIP542]GLOBALS.H;1+, M./ 4- 0@123KPWO56c_%:a7c_%:a89GHJ/* Copyright (c) 1990-2001 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /*--------------------------------------------------------------------------- globals.h There is usually no need to include this file since unzip.h includes~Z.^ UNZIP.BCK M [UNZIP542]GLOBALS.H;1$ it. This header file is used by all of the UnZip source files. It contains a struct definition that is used to "house" all of the global variables. This is done to allow for multithreaded environments (OS/2, NT, Win95, Unix) to call UnZip through an API without a semaphore. REENTRANT should be defined for all platforms that require this. GLOBAL CONSTRUCTOR AND DESTRUCTOR (API WRITERS READ THIS!!!) ------------------------------------------------------------ No, it's not C++, but it's as close as we can get with K&R. The main() of each process that uses these globals must include the CONSTRUCTGLOBALS; statement. This will malloc enough memory for the structure and initialize any variables that require it. This must also be done by any API function that jumps into the middle of the code. The DESTROYGLOBALS; statement should be inserted before EVERY "EXIT(n)". Naturally, it also needs to be put before any API returns as well. In fact, it's much more important in API functions since the process will NOT end, and therefore the memory WON'T automatically be freed by the operating system. USING VARIABLES FROM THE STRUCTURE ---------------------------------- All global variables must now be prefixed with `G.' which is either a global struct (in which case it should be the only global variable) or a macro for the value of a local pointer variable that is passed from function to function. Yes, this is a pain. But it's the only way to allow full reentrancy. ADDING VARIABLES TO THE STRUCTURE --------------------------------- If you make the inclusion of any variables conditional, be sure to only check macros that are GUARANTEED to be included in every module. For instance, newzip and pwdarg are needed only if CRYPT is TRUE, but this is defined after unzip.h has been read. If you are not careful, some modules will expect your variable to be part of this struct while others won't. This will cause BIG problems. (Inexplicable crashes at strange times, car fires, etc.) When in doubt, always include it! Note also that UnZipSFX needs a few variables that UnZip doesn't. However, it also includes some object files from UnZip. If we were to conditionally include the extra variables that UnZipSFX needs, the object files from UnZip would not mesh with the UnZipSFX object files. Result: we just include the UnZipSFX variables every time. (It's only an extra 4 bytes so who cares!) ADDING FUNCTIONS ---------------- To support this new global struct, all functions must now conditionally pass the globals pointer (pG) to each other. This is supported by 5 macros: __GPRO, __GPRO__, __G, __G__ and __GDEF. A function that needs no other parameters would look like this: int extract_or_test_files(__G) __GDEF { ... stuff ... } A function with other parameters would look like: int memextract(__G__ tgt, tgtsize, src, srcsize) __GDEF uch *tgt, *src; ulg tgtsize, srcsize; { ... stuff ... } In the Function Prototypes section of unzpriv.h, you should use __GPRO and __GPRO__ instead: int uz_opts OF((__GPRO__ int *pargc, char ***pargv)); int process_zipfiles OF((__GPRO)); Note that there is NO comma after __G__ or __GPRO__ and no semi-colon after __GDEF. I wish there was another way but I don't think there is. TESTING THE CODE ----------------- Whether your platform requires reentrancy or not, you should always try building with REENTRANT defined if any functions have been added. It is pretty easy to forget a __G__ or a __GDEF and this mistake will only show up if REENTRANT is defined. All platforms should run with REENTRANT defined. Platforms that can't take advantage of it will just be paying a performance penalty needlessly. SIGNAL MADNESS -------------- This whole pointer passing scheme falls apart when it comes to SIGNALs. I handle this situation 2 ways right now. If you define USETHREADID, UnZip will include a 64-entry table. Each entry can hold a global pointer and thread ID for one thread. This should allow up to 64 threads to access UnZip simultaneously. Calling DESTROYGLOBALS() will free the global struct and zero the table entry. If somebody forgets to call DESTROYGLOBALS(), this table will eventually fill up and UnZip will exit with an error message. A good way to test your code to make sure you didn't forget a DESTROYGLOBALS() is to change THREADID_ENTRIES to 3 or 4 in globals.c, making the table real small. Then make a small test program that calls your API a dozen times. Those platforms that don't have threads still need to be able to compile with REENTRANT defined to test and see if new code is correctly written to work either way. For these platforms, I simply keep a global pointer called GG that points to the Globals structure. Good enough for testing. I believe that NT has thread level storage. This could probably be used to store a global pointer for the sake of the signal handler more cleanly than my table approach. ---------------------------------------------------------------------------*/ #ifndef __globals_h #define __globals_h #ifdef USE_ZLIB # include "zlib.h" #endif /*************/ /* Globals */ /*************/ typedef struct Globals { #ifdef DLL zvoid *callerglobs; /* pointer to structure of pass-through global vars */ #endif /* command options of general use */ UzpOpts UzO; /* command options of general use */ #ifndef FUNZIP /* command options specific to the high level command line interface */ #ifdef MORE int M_flag; /* -M: built-in "more" function */ #endif /* internal flags and general globals */ #ifdef MORE int height; /* check for SIGWINCH, etc., eventually... */ int lines; /* count of lines displayed on current screen */ # if (defined(SCREENWIDTH) && defined(SCREENLWRAP)) int width; int chars; /* count of screen characters in current line */ # endif #endif /* MORE */ #if (defined(IZ_CHECK_TZ) && defined(USE_EF_UT_TIME)) int tz_is_valid; /* indicates that timezone info can be used */ #endif int noargs; /* did true command line have *any* arguments? */ unsigned filespecs; /* number of real file specifications to be matched */ unsigned xfilespecs; /* number of excluded filespecs to be matched */ int process_all_files; int overwrite_mode; /* 0 - query, 1 - always, 2 - never */ int create_dirs; /* used by main(), mapname(), checkdir() */ int extract_flag; int newzip; /* reset in extract.c; used in crypt.c */ LONGINT real_ecrec_offset; LONGINT expect_ecrec_offset; long csize; /* used by decompr. (NEXTBYTE): must be signed */ long used_csize; /* used by extract_or_test_member(), explode() */ #ifdef DLL int fValidate; /* true if only validating an archive */ int filenotfound; int redirect_data; /* redirect data to memory buffer */ int redirect_text; /* redirect text output to buffer */ # ifndef NO_SLIDE_REDIR int redirect_slide; /* redirect decompression area to mem buffer */ unsigned _wsize; # endif unsigned redirect_size; /* size of redirected output buffer */ uch *redirect_buffer; /* pointer to head of allocated buffer */ uch *redirect_pointer; /* pointer past end of written data */ # ifndef NO_SLIDE_REDIR uch *redirect_sldptr; /* head of decomp UNZIP.BCK M [UNZIP542]GLOBALS.H;1ression slide buffer */ # endif # ifdef OS2DLL cbList(processExternally); /* call-back list */ # endif #endif /* DLL */ char **pfnames; char **pxnames; char sig[4]; char answerbuf[10]; min_info info[DIR_BLKSIZ]; min_info *pInfo; #endif /* !FUNZIP */ union work area; /* see unzpriv.h for definition of work */ #ifndef FUNZIP # if (!defined(USE_ZLIB) || defined(USE_OWN_CRCTAB)) ZCONST ulg near *crc_32_tab; # else ZCONST ulg Far *crc_32_tab; # endif #endif ulg crc32val; /* CRC shift reg. (was static in funzip) */ #ifdef FUNZIP FILE *in; /* file descriptor of compressed stream */ #endif uch *inbuf; /* input buffer (any size is OK) */ uch *inptr; /* pointer into input buffer */ int incnt; #ifndef FUNZIP ulg bitbuf; int bits_left; /* unreduce and unshrink only */ int zipeof; char *argv0; /* used for NT and EXE_EXTENSION */ char *wildzipfn; char *zipfn; /* GRR: WINDLL: must nuke any malloc'd zipfn... */ #ifdef USE_STRM_INPUT FILE *zipfd; /* zipfile file descriptor */ #else int zipfd; /* zipfile file handle */ #endif LONGINT ziplen; LONGINT cur_zipfile_bufstart; /* extract_or_test, readbuf, ReadByte */ LONGINT extra_bytes; /* used in unzip.c, misc.c */ uch *extra_field; /* Unix, VMS, Mac, OS/2, Acorn, ... */ uch *hold; local_file_hdr lrec; /* used in unzip.c, extract.c */ cdir_file_hdr crec; /* used in unzip.c, extract.c, misc.c */ ecdir_rec ecrec; /* used in unzip.c, extract.c */ struct stat statbuf; /* used by main, mapname, check_for_newer */ int mem_mode; uch *outbufptr; /* extract.c static */ ulg outsize; /* extract.c static */ int reported_backslash; /* extract.c static */ int disk_full; int newfile; int didCRlast; /* fileio static */ ulg numlines; /* fileio static: number of lines printed */ int sol; /* fileio static: at start of line */ int no_ecrec; /* process static */ #ifdef SYMLINKS int symlnk; #endif #ifdef NOVELL_BUG_FAILSAFE int dne; /* true if stat() says file doesn't exist */ #endif FILE *outfile; uch *outbuf; uch *realbuf; #ifndef VMS /* if SMALL_MEM, outbuf2 is initialized in */ uch *outbuf2; /* process_zipfiles() (never changes); */ #endif /* else malloc'd ONLY if unshrink and -a */ #endif /* !FUNZIP */ uch *outptr; ulg outcnt; /* number of chars stored in outbuf */ #ifndef FUNZIP char filename[FILNAMSIZ]; /* also used by NT for temporary SFX path */ #ifdef CMS_MVS char *tempfn; /* temp file used; erase on close */ #endif char *key; /* crypt static: decryption password or NULL */ int nopwd; /* crypt static */ #endif /* !FUNZIP */ ulg keys[3]; /* crypt static: keys defining pseudo-random sequence */ #if (!defined(DOS_FLX_H68_NLM_OS2_W32) && !defined(AMIGA) && !defined(RISCOS)) #if (!defined(MACOS) && !defined(ATARI) && !defined(VMS)) int echofd; /* ttyio static: file descriptor whose echo is off */ #endif /* !(MACOS || ATARI || VMS) */ #endif /* !(DOS_FLX_H68_NLM_OS2_W32 || AMIGA || RISCOS) */ unsigned hufts; /* track memory usage */ #ifdef USE_ZLIB int inflInit; /* inflate static: zlib inflate() initialized */ z_stream dstrm; /* inflate global: decompression stream */ #else struct huft *fixed_tl; /* inflate static */ struct huft *fixed_td; /* inflate static */ int fixed_bl, fixed_bd; /* inflate static */ unsigned wp; /* inflate static: current position in slide */ ulg bb; /* inflate static: bit buffer */ unsigned bk; /* inflate static: bits in bit buffer */ #endif /* ?USE_ZLIB */ #ifndef FUNZIP #ifdef SMALL_MEM char rgchBigBuffer[512]; char rgchSmallBuffer[96]; char rgchSmallBuffer2[160]; /* boosted to 160 for local3[] in unzip.c */ #endif MsgFn *message; InputFn *input; PauseFn *mpause; PasswdFn *decr_passwd; StatCBFn *statreportcb; #ifdef WINDLL LPUSERFUNCTIONS lpUserFunctions; #endif int incnt_leftover; /* so improved NEXTBYTE does not waste input */ uch *inptr_leftover; #ifdef VMS_TEXT_CONV int VMS_line_state; /* so native VMS variable-length text files are */ int VMS_line_length; /* readable on other platforms */ int VMS_line_pad; #endif #endif /* !FUNZIP */ #ifdef SYSTEM_SPECIFIC_GLOBALS SYSTEM_SPECIFIC_GLOBALS #endif } Uz_Globs; /* end of struct Globals */ /***************************************************************************/ #ifdef FUNZIP # if (!defined(USE_ZLIB) || defined(USE_OWN_CRCTAB)) extern ZCONST ulg near crc_32_tab[256]; # else extern ZCONST ulg Far *crc_32_tab; # endif # define CRC_32_TAB crc_32_tab #else # define CRC_32_TAB G.crc_32_tab #endif Uz_Globs *globalsCtor OF((void)); /* pseudo constant sigs; they are initialized at runtime so unzip executable * won't look like a zipfile */ extern char local_hdr_sig[4]; extern char central_hdr_sig[4]; extern char end_central_sig[4]; /* extern char extd_local_sig[4]; NOT USED YET */ #ifdef REENTRANT # define G (*(Uz_Globs *)pG) # define __G pG # define __G__ pG, # define __GPRO Uz_Globs *pG # define __GPRO__ Uz_Globs *pG, # define __GDEF Uz_Globs *pG; # ifdef USETHREADID extern int lastScan; void deregisterGlobalPointer OF((__GPRO)); Uz_Globs *getGlobalPointer OF((void)); # define GETGLOBALS() Uz_Globs *pG = getGlobalPointer(); # define DESTROYGLOBALS() {free_G_buffers(pG); deregisterGlobalPointer(pG);} # else extern Uz_Globs *GG; # define GETGLOBALS() Uz_Globs *pG = GG; # define DESTROYGLOBALS() {free_G_buffers(pG); free(pG);} # endif /* ?USETHREADID */ # define CONSTRUCTGLOBALS() Uz_Globs *pG = globalsCtor() #else /* !REENTRANT */ extern Uz_Globs G; # define __G # define __G__ # define __GPRO void # define __GPRO__ # define __GDEF # define GETGLOBALS() # define CONSTRUCTGLOBALS() globalsCtor() # define DESTROYGLOBALS() #endif /* ?REENTRANT */ #define uO G.UzO #endif /* __globals_h */ R*[UNZIP542]HISTORY.540;1+,| ..0/ 400f- 0@123KPWO156[7[89GHJ/f UNZIP.BCK| . [UNZIP542]HISTORY.540;10ܑUnZip, version 5.4, 28 November 1998 Features added (or removed): 5.33a (05 Dec 97): - expanded file-size fields for -l/-v listings [GRR, Raymond Chi] - expanded file-size fields in non-verbose ZipInfo listings [Christian] - WinDLL: enabled emx/rsxnt compilation and fixed some minor bugs [Christian] - Win32: added Borland C++ makefile [E-Yen Tan] - Unix: added BINPERMS and MANPERMS variables to makefile for setting file perms on installed binaries and man pages; replaced rogue "rm -f" [Quentin Barnes, GRR] - Unix: added generic_shlib target for Unix DLLs [GRR, Thomas Klausner] 5.33b (24 Dec 97): - VMS: added "zip -A" call to mksfx.com to fix offsets in central dir [SPC] - MSDOS, WIN32: added restoration of directory attributes [SPC] - IBM OS/390: new port (POSIX environment, EBCDIC) [Paul von Behrend] 5.33c (15 Apr 98): - OS/2: restore directory attributes (system, hidden) [Kai Uwe Rommel] - WIN32: added support for RSXNTDJ 1.3.1 [E-Yen Tan, SPC] - DLL: added UzpFreeMemBuffer() function to release memory allocated by UzpUnzipToMemory() [Mike White] - BeOS: support extraction of file attributes from BeOS extra field for symbolic links [Chris Herborth] - MSDOS: do not use UTC time-stamps when TZ environment not set [Cosmin Truta] - WIN32: added support for GCC in Cygnus Win32 environment [Cosmin Truta] - VM/CMS and MVS support, compiled on IBM OS/390 [Ian. E. Gorman] 5.33d (30 Apr 98): - WIN32: added support for GCC in MINGW32 environment [SPC] 5.33e (28 May 98): - CMS: rewrite of README.CMS, now shared between Zip and UnZip [Greg Hartwig] - BeOS: enable "automatic update of mime file-info" in beos.h [Chris Herborth] - AMIGA, OS2: enabled IZ_CHECK_TZ (do not use UTC time-stamps when environment variable TZ is not set) [Kai Uwe Rommel, SPC] 5.33f (13 Jun 98): - WIN32: support free LCC compiler (new Makefile.lcc) [E-Yen Tan] - MacOS: revised Macintosh port [Dirk Haase] 5.33g (08 Aug 98): - QDOS: much better support for SFX archives on SMS/QDOS [Jonathan Hudson] 5.33h (17 Aug 98): - BeOS: support restoration of directory attributes, permissions, and time-stamps, similar to the UNIX port [Chris Herborth] 5.33i (13 Sep 98): - added handling of Mac3 and BeOS e.f. blocks to "verbose ZipInfo" and "test archive" operations [SPC] - added "Type & Creator" display in verbose ZipInfo mode for all Mac extra fields that support this info [Dirk Haase] - added support for PKWARE's PKZIP for Unix "timestamps & uid/gid" extra field; modified the Unix port's attribute mapping to restore complete UNIX style attributes from archives created by PKZIP for Unix [SPC] - LynxOS: another variant of Unix; add OS message to unix.c's version_local() and specific entry to unix/Makefile [Giuseppe Guerrini] 5.33j (31 Oct 98): - added cross-compiling target for QNX/Neutrino (i386 target) [Chris Herborth] 5.33k (08 Nov 98): - Windows (16 and 32-bit): added first pre-release of a GUI interface for sfx stubs [Mike White] 5.33l (12 Nov 98): - Windows (16 and 32-bit): completed Windows GUISFX stub sources, integrated build procedures into UnZip source tree [Mike White] 5.4b (21 Nov 98): - Acorn: added -F option to suppress removal of NFS filetype extension from the names of extracted files [Darren Salt] - Unix: added optional feature, controlled by ACORN_FTYPE_NFS compile-time option, to translate Acorn RISC OS extra-field filetype info into "NFS filetype extension" appended to the extracted filename. When compiled in UnZip, specifying the -F option enables this feature. [Darren Salt, SPC] - unzip.1: added documentation for the new Acorn NFS filetype features [SPC] Bugs fixed: 5.33a (05 Dec 97): - OS/2: removed bogus "else" in UzpFileTree() [Takashi Shoda] - fixed Dave Sm