g@ UNZIP.BCKX UNZIP.BCK<BACKUP/LOG [UNZIP60...]*.* []UNZIP.BCK/SAVE/INTER/BLOCK=8192 GOATHUNTER N.&V7.3 _MILO:: _$252$VDA5: AXP72R001  *[UNZIP60]ACORN.DIR;1+,}./ 4->0123 KPWO56p07p089GHJIACORN.C  CONTENTS.~? GMAKEFILE. MAKEFILE.README.{RISCOS.CRISCOS.H  RUNME1ST. SRCRENAME.SWIVEN.HJSWIVEN.S*[UNZIP60.ACORN]ACORN.C;1+, .D/ 4DD@-}0123KPWOE56I? )7I? )89GHJ/* Copyright (c) 1990-2007 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() 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 */ #ifdef WILD_STOP_AT_DIR # define WESEP , (oU.W_flag ? '.' : '\0') #else # define WESEP #endif 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 void setRISCOSexfield(ZCONST char *path, ZCONST void *ef_spark); #ifdef DEBUG static void printRISCOSexfield(int isdir, ZCONST void *extra_field); #endif 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")); strncpy(matchname, wildspec, FILNAMSIZ); matchname[FILNAMSIZ-1] = '\0'; 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 WESEP)) { /* 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) */ strncpy(matchname, wildspec, FILNAMSIZ); matchname[FILNAMSIZ-1] = '\0'; 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 WESEP)) { /* 0 == case sens. */ 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; /* l0& U UNZIP.BCK }[UNZIP60.ACORN]ACORN.C;1DJeave directory bit as set */ /* fall through! */ case ACORN_: case UNIX_: case VMS_: case ATARI_: case ATHEOS_: case BEOS_: case QDOS_: case TANDEM_: G.pInfo->file_attr = (unsigned)(tmp >> 16); if (G.pInfo->file_attr != 0 || !G.extra_field) { break; } 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.Network.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() */ /************************/ int mapname(__G__ renamed) __GDEF int renamed; /* * returns: * MPN_OK - no problem detected * MPN_INF_TRUNC - caution (truncated filename) * MPN_INF_SKIP - info "skip entry" (dir doesn't exist) * MPN_ERR_SKIP - error -> skip entry * MPN_ERR_TOOLONG - error -> path is too long * MPN_NOMEM - error (memory allocation failed) -> skip entry * [also MPN_VOL_LABEL, MPN_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 error = MPN_OK; register unsigned workch; /* hold the character being tested */ char *checkswap=NULL; /* pointer the the extension to check */ /*--------------------------------------------------------------------------- Initialize various pointers and counters and stuff. ---------------------------------------------------------------------------*/ if (G.pInfo->vollabel) return MPN_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) == MPN_NOMEM) return MPN_NOMEM; /* 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 */ /*------------------------------------------Ѽ UNZIP.BCK }[UNZIP60.ACORN]ACORN.C;1D--------------------------------- 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)) & MPN_MASK) > MPN_INF_TRUNC) return error; pp = pathcomp; /* reset conversion buffer for next piece */ lastsemi = (char *)NULL; /* leave direct. semi-colons alone */ checkswap=NULL; /* reset checking at start of new leafname */ break; case '.': *pp++ = '/'; checkswap=pp; break; case ';': /* VMS version (or DEC-20 attrib?) */ lastsemi = pp; *pp++ = ';'; /* keep for now; remove VMS ";##" */ break; /* later, if requested */ case ' ': /* change spaces to hard-spaces */ *pp++ = 160; /* (ISO 8859-1 Latin-1 codepage) */ break; /* The following substitutions, unless stated otherwise, follow * those for DOSFS. They translate special symbols into other * characters which have no special meaning to RISC OS. */ case '#': *pp++ = '?'; break; /* single-char wildcard */ case '&': *pp++ = '+'; break; case '@': *pp++ = '='; break; case '%': *pp++ = ';'; break; case '$': *pp++ = '<'; break; case '^': *pp++ = '>'; break; /* parent-dir reference */ /* The following substitutions deal with the remaining special * symbols. ('.' is handled above.) */ case '*': *pp++ = 0xD7; break; /* Latin-1 'multiply' */ case '"': *pp++ = '~'; break; case ':': *pp++ = ';'; break; case '\\': *pp++ = '/'; break; case '|': *pp++ = 0xA6; break; /* Latin-1 'broken bar' */ default: /* allow European characters in filenames: */ if (isprint(workch) || (128 <= workch && workch <= 254)) *pp++ = (char)workch; } /* end switch */ } /* end while loop */ /*--------------------------------------------------------------------------- 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", FnFilter1(G.filename))); } /* set dir time (note trailing '/') */ return (error & ~MPN_MASK) | MPN_CREATED_DIR; } /* dir existed already; don't look for data to extract */ return (error & ~MPN_MASK) | MPN_INF_SKIP; } *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'; } if (*pathcomp == '\0') { Info(slide, 1, ((char *)slide, "mapname: conversion of %s failed\n", FnFilter1(G.filename))); return (error & ~MPN_MASK) | MPN_ERR_SKIP; } 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: * MPN_OK - no problem detected * MPN_INF_TRUNC - (on APPEND_NAME) truncated filename * MPN_INF_SKIP - path doesn't exist, not allowed to create * MPN_ERR_SKIP - path doesn't exist, tried to create and failed; or path * exists and is not a directory, but is supposed to be * MPN_ERR_TOOLONG - path is too long * MPN_NOMEM - 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", FnFilter1(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. */ /* next check: need to append '/', at least one-char name, '\0' */ if ((end-buildpath) > FILNAMSIZ-3) too_long = TRUE; /* check if extracting dir? */ if (stat(buildpath, &G.statbuf)) { /* path doesn't exist */ if (!G.create_dirs) { /* told not to create (freshening) */ free(buildpath); return MPN_INF_SKIP; /* path doesn't exist: nothing to do */ } if (too_long) { Info(slide, 1, ((char *)slide, "checkdir error: path too long: %s\n", FnFilter1(buildpath))); fflush(stderr); free(buildpath); /* no room for filenames: fatal */ return MPN_ERR_TOOLONG; } if (mkdir(buildpath, 0777) == -1) { /* create the directory */ Info(slide, 1, ((char *)slide, "checkdir error: cannot create %s\n\ unable to process %s.\n", FnFilter2(buildpath), FnFilter1(G.filename))); = UNZIP.BCK }[UNZIP60.ACORN]ACORN.C;1D, free(buildpath); /* path didn't exist, tried to create, failed */ return MPN_ERR_SKIP; } 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", FnFilter2(buildpath), FnFilter1(G.filename))); free(buildpath); /* path existed but wasn't dir */ return MPN_ERR_SKIP; } if (too_long) { Info(slide, 1, ((char *)slide, "checkdir error: path too long: %s\n", FnFilter1(buildpath))); free(buildpath); /* no room for filenames: fatal */ return MPN_ERR_TOOLONG; } *end++ = '.'; /************* was '/' *************/ *end = '\0'; Trace((stderr, "buildpath now = [%s]\n", FnFilter1(buildpath))); return MPN_OK; } /* 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 MPN_OK; } /*--------------------------------------------------------------------------- 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", FnFilter1(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", FnFilter1(G.filename), FnFilter2(buildpath))); return MPN_INF_TRUNC; /* filename truncated */ } } Trace((stderr, "buildpath now = [%s]\n", FnFilter1(buildpath))); /* could check for existence here, prompt for new name... */ return MPN_OK; } /*--------------------------------------------------------------------------- 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 MPN_NOMEM; if ((rootlen > 0) && !renamed_fullpath) { strcpy(buildpath, rootpath); end = buildpath + rootlen; } else { *buildpath = '\0'; end = buildpath; } Trace((stderr, "[%s]\n", FnFilter1(buildpath))); return MPN_OK; } /*--------------------------------------------------------------------------- ROOT: if appropriate, store the path in 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", FnFilter1(pathcomp))); if (pathcomp == (char *)NULL) { rootlen = 0; return MPN_OK; } if (rootlen > 0) /* rootpath was already set, nothing to do */ return MPN_OK; if ((rootlen = strlen(pathcomp)) > 0) { char *tmproot; if ((tmproot = (char *)malloc(rootlen+2)) == (char *)NULL) { rootlen = 0; return MPN_NOMEM; } strcpy(tmproot, pathcomp); if (tmproot[rootlen-1] == '.') { /****** was '/' ********/ tmproot[--rootlen] = '\0'; } if (rootlen > 0 && (SSTAT(tmproot, &G.statbuf) || !S_ISDIR(G.statbuf.st_mode))) { /* path does not exist */ if (!G.create_dirs /* || isshexp(tmproot) */ ) { free(tmproot); rootlen = 0; /* skip (or treat as stored file) */ return MPN_INF_SKIP; } /* 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", FnFilter1(tmproot))); free(tmproot); rootlen = 0; /* path didn't exist, tried to create, and failed: */ /* file exists, or 2+ subdir levels required */ return MPN_ERR_SKIP; } } tmproot[rootlen++] = '.'; /*********** was '/' *************/ tmproot[rootlen] = '\0'; if ((rootpath = (char *)realloc(tmproot, rootlen+1)) == NULL) { free(tmproot); rootlen = 0; return MPN_NOMEM; } Trace((stderr, "rootpath now = [%s]\n", FnFilter1(rootpath))); } return MPN_OK; } #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 MPN_OK; } return MPN_INVALID; /* 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 */ /*********************************/ static void setRISCOSexfield(ZCONST char *path, ZCONST void *ef_spark) { if (ef_spark!=NULL) { extra_block *block=(extra_block *)ef_spark; SWI_OS_File_1((char *)path,block->loadaddr,block->execaddr,block->attr); } } #ifdef DEBUG static void printRISCOSexfield(int isdir, ZCONST void *extra_field) { extra_block F_! UNZIP.BCK }[UNZIP60.ACORN]ACORN.C;1D4F;*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)) printf("r"); printf("\n\n"); } #endif /* DEBUG */ /**********************************************/ /* 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 { zvoid *spark_ef; fclose(G.outfile); if ((spark_ef = getRISCOSexfield(G.extra_field, G.lrec.extra_field_length)) != NULL) { setRISCOSexfield(G.filename, spark_ef); } 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 /* skip restoring time stamps on user's request */ if (uO.D_flag <= 1) { #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 time-stamp and attributes */ SWI_OS_File_5(G.filename, NULL, &loadaddr, NULL, NULL, &attr); if (uO.D_flag <= 1) /* set the file's modification time */ 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 */ *[UNZIP60.ACORN]CONTENTS.;1+,~?./ 4n@-}0123KPWO56:_ُ7:_ُ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 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. *[UNZIP60.ACORN]GMAKEFILE.;1+,. / 4 @-}0123KPWO 56 7 89GHJ# Makefile for UnZip, UnZipSFX, ZipInfo and fUnZip (5.53 or later) # using gcc 2.95.4 (or later). # You may look at for an up-to-date # gcc port. CC = gcc -mlibscl BIND = $(CC) 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 -mthrowback -DNO_STRNICMP ASMFLAGS = -throwback l UNZIP.BCK}NZIP60.ACORN]GMAKEFILE.;1 u-objasm -upper LFLAGS1 = LFLAGS2 = $(LIB) # object file lists OBJS1 = o.unzip o.crc32 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.cryptf o.globalsf o.inflatef o.ttyiof \ o.riscos o.swiven OBJX = o.unzipsfx o.crc32 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 h.crc32 $(CC) $(CFLAGS) -c c.crc32 -o o.crc32 o.crypt: c.crypt $(UNZIP_H) h.zip h.crypt h.crc32 h.ttyio $(CC) $(CFLAGS) -c c.crypt -o o.crypt o.envargs: c.envargs $(UNZIP_H) $(CC) $(CFLAGS) -c c.envargs -o o.envargs o.explode: c.explode $(UNZIP_H) $(CC) $(CFLAGS) -c c.explode -o o.explode o.extract: c.extract $(UNZIP_H) h.crc32 h.crypt $(CC) $(CFLAGS) -c c.extract -o o.extract o.fileio: c.fileio $(UNZIP_H) h.crc32 h.crypt h.ttyio h.ebcdic $(CC) $(CFLAGS) -c c.fileio -o o.fileio o.funzip: c.funzip $(UNZIP_H) h.crc32 h.crypt h.ttyio $(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) h.crc32 $(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.unzvers 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.crc32 h.ttyio $(CC) $(CFLAGS) -DSFX -c c.crypt -o o.crypt_ o.extract_: c.extract $(UNZIP_H) h.crc32 h.crypt $(CC) $(CFLAGS) -DSFX -c c.extract -o o.extract_ o.fileio_: c.fileio $(UNZIP_H) h.crc32 h.crypt h.ttyio h.ebcdic $(CC) $(CFLAGS) -DSFX -c c.fileio -o o.fileio_ o.globals_: c.globals $(UNZIP_H) $(CC) $(CFLAGS) -DSFX -c c.globals -o o.globals_ o.inflate_: c.inflate h.inflate $(UNZIP_H) h.crypt $(CC) $(CFLAGS) -DSFX -c c.inflate -o o.inflate_ o.match_: c.match $(UNZIP_H) $(CC) $(CFLAGS) -DSFX -c c.match -o o.match_ o.process_: c.process $(UNZIP_H) h.crc32 $(CC) $(CFLAGS) -DSFX -c c.process -o o.process_ o.ttyio_: c.ttyio $(UNZIP_H) h.zip h.crypt h.ttyio $(CC) $(CFLAGS) -DSFX -c c.ttyio -o o.ttyio_ o.unzipsfx: c.unzip $(UNZIP_H) h.crypt h.unzvers h.consts $(CC) $(CFLAGS) -DSFX -c c.unzip -o o.unzipsfx o.cryptf: c.crypt $(UNZIP_H) h.zip h.crypt h.crc32 h.ttyio $(CC) $(CFLAGS) -DFUNZIP -c c.crypt -o o.cryptf o.globalsf: c.globals $(UNZIP_H) $(CC) $(CFLAGS) -DFUNZIP -c c.globals -o o.globalsf o.inflatef: c.inflate h.inflate $(UNZIP_H) h.crypt $(CC) $(CFLAGS) -DFUNZIP -c c.inflate -o o.inflatef o.ttyiof: c.ttyio $(UNZIP_H) h.zip h.crypt h.ttyio $(CC) $(CFLAGS) -DFUNZIP -c c.ttyio -o o.ttyiof 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 *[UNZIP60.ACORN]MAKEFILE.;1+,. / 4 0@-}0123KPWO 56ږ 7ږ 89GHJ # Makefile for UnZip, UnZipSFX, ZipInfo and fUnZip (5.53 or later) # last modified: 25 Dec 2006 # 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 = CBASE = -throwback -wn -DNO_STRNICMP CFLAGS = $(CBASE) -IC:,@. ASMFLAGS = -Throwback -Stamp -NoCache -CloseExec -quit LFLAGS1 = LFLAGS2 = $(LIB) C:o.Stubs # object file lists OBJS1 = unzip.o crc32.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 ubz2err.o unreduce.o unshrink.o zipinfo.o OBJS = $(OBJS1) $(OBJS2) $(OBJS3) riscos.o swiven.o acorn.o OBJF = funzip.o crc32.o cryptf.o globalsf.o inflatef.o ttyiof.o \ riscos.o swiven.o OBJX = unzipsfx.o crc32.o crypt_.o extract_.o fileio_.o globals.o \ inflate.o match.o process_.o ttyio.o ubz2err_.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 crc32.h crypt.o: crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h envargs.o: envargs.c $(UNZIP_H) explode.o: explode.c $(UNZIP_H) extract.o: extract.c $(UNZIP_H) crc32.h crypt.h fileio.o: fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h funzip.o: funzip.c $(UNZIP_H) crc32.h crypt.h ttyio.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) crc32.h ttyio.o: ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h ubz2err.o: ubz2err.c $(UNZIP_H) unreduce.o: unreduce.c $(UNZIP_H) unshrink.o: unshrink.c $(UNZIP_H) unzip.o: unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h zipinfo.o: zipinfo.c $(UNZIP_H) crypt_.o: crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h $(CC) $(CFLAGS) -DSFX -c c.crypt -o o.crypt_ extract_.o: extract.c $(UNZIP_H) crc32.h crypt.h $(CC) $(CFLAGS) -DSFXЯl1 UNZIP.BCK}[UNZIP60.ACORN]MAKEFILE.;1 :  -c c.extract -o o.extract_ fileio_.o: fileio.c $(UNZIP_H) crc32.h crypt.h $(CC) $(CFLAGS) -DSFX -c c.fileio -o o.fileio_ 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) crc32.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_ ubz2err_.o: ubz2err.c $(UNZIP_H) $(CC) $(CFLAGS) -DSFX -c c.ubz2err -o o.ubz2err_ unzipsfx.o: unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h $(CC) $(CFLAGS) -DSFX -c c.unzip -o o.unzipsfx o.cryptf: c.crypt $(UNZIP_H) h.zip h.crypt h.crc32 h.ttyio $(CC) $(CFLAGS) -DFUNZIP -c c.crypt -o o.cryptf o.globalsf: c.globals $(UNZIP_H) $(CC) $(CFLAGS) -DFUNZIP -c c.globals -o o.globalsf o.inflatef: c.inflate h.inflate $(UNZIP_H) h.crypt $(CC) $(CFLAGS) -DFUNZIP -c c.inflate -o o.inflatef o.ttyiof: c.ttyio $(UNZIP_H) h.zip h.crypt h.ttyio $(CC) $(CFLAGS) -DFUNZIP -c c.ttyio -o o.ttyiof 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 *[UNZIP60.ACORN]README.;1+,{./ 4W@-}0123KPWO56:7:89GHJ 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, e.g. "DOSFILE.TXT", "unix-filename.tar.gz". These are extracted as "DOSFILE/TXT" and "unix-filename/tar/gz"; their names may or may not be truncated, depending on where the files are being created: what filing system and, for Filecore-based filing systems such as ADFS or an IDEFS or SCSIFS, which disk/partition format (names will not be truncated if you're using E+ or F+). Where truncation occurs, 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". There are two ways of using this feature. - The old way: use a colon-separated environment variable named "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" *unzip foo/zip - The new way: use the -/ option. For example: Any extensions found in the parameter for this option will be extracted to directories named after the extension, with the extension stripped. For example: *unzip -/c:h:o:s foo/zip If foo/zip contains a file named "foo.c", this file will be written as "foo" in directory "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). *[UNZIP60.ACORN]RISCOS.C;1+,./ 4@-}0123KPWO56-?27-?289GHJ/* Copyright (c) 1990-2002 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) / UNZIP.BCK}[UNZIP60.ACORN]RISCOS.C;1M| 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); /* If we're returning the last item, check if there are any more. * If there are, nothing will happen; if not, then d->offset = -1 */ if (!d->read) SWI_OS_GBPB_9(d->dirname,d->buf,&d->read,&d->offset,0,NULL); 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; } #endif /* !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); } *[UNZIP60.ACORN]RISCOS.H;1+, ./ 4@-}0123KPWO56eO7eO89GHJ/* 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 */ /* 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; };  UNZIP.BCK }[UNZIP60.ACORN]RISCOS.H;1*  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; 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 */ *[UNZIP60.ACORN]RUNME1ST.;1+,./ 4c@-}0123KPWO56Ö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 *[UNZIP60.ACORN]SRCRENAME.;1+,. / 4 o@-}0123KPWO 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?y8IqAU-~w^*K)}Υbo-q|/#cfJjT8v ~L -%c[[ZԊUw~=Mv۷N,gpO2W3=5{UC:ԍ$f)fmq B&z3s,TPndնC2lGc,ONJ̆_ظ4P_SbOϮ *pEǎv3N- 1Ui]`dedW+ w?o g5=m1X)s|({5/#Z~cGz'kKsv(k9*1! tWm}j$~_L jl C"|;tf_YIbW L=jKSGz(^9#IKP)1q2F yow^vK$BxQw\`|?nUvauB0yZ+?̙F#C%Xw"֩S22y_Gz27aVRB+@1i1Y  -Wxq amגXֶlXPDnJ~z] KƫGr`-U_HcV\S %i*'3,eɚU LI:4m;65kp!8C1EQ=ѢUD2_$kS>8tIG/Q]|[wuX1UIXA1cHԣy~lɥEwO *pMd -Z}uWҚ)q0qM0-\N뢂t,cwǃMMՐg"xƬ '>]VP,COng.-5gj\XFuG[Jv# v>.~|YiD=w %~zS<JxY+ ,)]_=?D.dyL't3ls0`kkT} OMLpyf//oEj|%S Si#G MZ9x`dvJfbl?c MuBN1k3JZ;#-h8 Gy' .0r&uu6* (4=L-y ;O+4_57K+mo0L" 0w%px.R'Qa VD_anXb5;:1)dQ7Xo 'iiihG$B"&<)>%RjOUJ?"e`xDE0i=edb#JBHxei`JQg-b`L`F54/<*5?o yi,5x }z| $%fS QnJ &Bl|E'@ [7iJok}fe[n-3Zu|5H JVp(BlbE"GW-NyHv-=S "/L#ij8X'%;XY^a?P^$-R7ew"z*,e4h1vbMD|$625BGNKt9d~#eJ#n9X/o+$fm2mK(L`\blK1)2X(4SB}gCt>pSOE5DI5wb2aqd1>w9<-$rL9G37k \/i$L0vFFLU_qHYB a*?9mNTNt <;]0 (mfVd3G{N{a? }5d ??3DAG`Nn}pg~qL =x5QpJ%3 ]dHYF@"T{BMJ#86!v?qORqI ,>v?/U-o'J"KT"U^zW@]]7H - wSEvT}{o D eTm+WawXX4 TDE7s2C{I(lo*,SjK[>FQ>|_tZB%-'FKb8Bddx#('s5'w<|}@b.V05{/8g a"\rv?0:K%n4_nopX4C LiO!%.\lIzOOMc6Iw' TLzD"T LW[[$>~'mYk 7Q]a1.| nl{%HxECYm(8W]D]d +[Y\!} O~X4f`pTR37u _bIk85|? &.mw(`}t=1JM 9t ItC\|@+\;} Ep4"]S =@$g=hIk LLMX,`ozp~,|Jc5'NESu QY2?X {[|b9losk=,,wXrP! N%6$e,qp=u&|1eZ0Zz3- l@NDZNA7a2zeYUpo8a~#9oT-X_  XHWr.v$]aXQ9vHF{crhy~ &`&82D(; H]ReK Ec] BvMbKNn xG] 1XNm"bi= gW~P ("HoE`i0 .:8geo.>D o{&`,}7Y >[w."8D[^d9m.hg1 (CF]xOU{Dl -y"6 1; CVl6], WmGp]i^]aI/\qp`u7EP7w/>|9o2R6z\k)wH!0/ ?Q"Z*p^+>d";,]Dd9tXn7V8 ~"!QbJX\ R;>~=6GI_rg6?zk-QY`e@qc47 lMl ps >Q]`}|lL&Pzb0&a D-VO5YbS'o c-)erF3J n 0x'UP$a_#jyzE@L_xE=k@+WbhwJSTI#(@xXF:LXec2@I,{C d NOZkmUA3cX@[0xqo#d^s[K/ =[6yN,IzXyewV@=`a=abSUIfm xd4o=%<' 6tI98wL-D\ORd6 VznERE<4_l>By~^Os@ 'BaHOca5}]L!15zZWHNEJ7oPJymeR4cKA *|wr/m:\4kL;$=-c^i00tQN&X.' dX(}NX/97\DJ;Z[B;j jnn|/}}wnkM(*h}~h-=D"zO@}+3or{MI2NAG]QL aLa5<^XX(b! (6yl&i6fy13axS) W/9jiXreV0JM%_,/!;$41(zfmwF Xdmwht]Cg)N((o+I}m?$>l5U?LO*leXp,{O*zv.b;(orh`%tSg4 t($e1P=%.8 m+bfME~__&m}C5?n&&I+@i~&}Y`v>M u*Mu(}6{4,7s+1Zlr9iP2Llnq6zQGdS#j!?FLZO'DQh4kc#iZC]PRt#AOR $ /4-uqboV,Bj ER.'|d4}2nJu##tXr d+6Qn&KHs9.$# gIZ:5_h(9wBF#GE|MP [(8QR Hp_liiIIHFv8{r.519QH-P~OpZJuR5QdgLX%E |GT`y[]4UX-+UtKO#Cx%b|Hf(EXQqES4~2m^!Uo']'"%< ?WTq2ZN 8b vzf~U@LN42/zOVY|19b7hE2"g/)9\ɕ2?Xeucڑ!坄\v_0$4&N̷Xlx:1'D$$i o[RE+ ;TլJ^ZAj\8tS_YL󒡳SWPMjK+m'xohK7J3m_ W$NXIeHv?Ӡ_2pv -.=ɅjXi+\&۲^e>y$N%٠|35d8]rv 4V3iF;W]ZuoOf hu ^h=0DN.p==]<%Cڙ6MQ^ OЊ|"h$42~48{7 2]L߇嚹إŤÉ񳶕؞܀zΗѫ«妯ܧʎ9Лкӣӈڜ˕ĿĆό#ɀזĠ]ڌĆ̝σ޵թg1c皇+t̵ĀЌ򔅇ݯݷҥԒшĜ֟ԂDŽTSnCdl(q|F;\!&9QShJ]HNlc& |.cDaYFK}e!(w_P^7U9#GiF!-0D{Ts65U\qJ }N-! %5f;.wbi]QzV0I_S9D*I`OJ%Y@v$M',,s+p.N '9!N]w"/4]=+8@{LEC &]@dt{p/k90`_W8oh>PPQN7g?5?H^W1lwy9qyf[ B48}aD)KSgVR}FckB9GC\ziyg~ t-\E[ J08xFy S1eEUM|Tb/F3,:l2xWLo\ V<=1ExOD#7w6HZEIPw]3-99IC C~%o`-NO.InsJh8,8# ]X@N luA-m|cI4-\M ohZ=Tdy{hn"# 6TT,ON+tNE@[ E]{:kHvSvQ@.`Iz'o RyXLD>/t|-YAV] ͐Ma=aYVhg2dLn. cp~;¯yv-,ڙu>hx\(x߄ aJ6+ⰼj9( `n[1J&(hj$K/{CSxpwLCz D-)$G2CyU[~]7l9Ye!*lZsu\PaP_>>hb$*BuH7%˟0wv&ՄG&tSJ)ѵ4f5x! bDl- c3X. ά{A 0JɛǨ)KKڴ @BNɅέ~u^xE֪|;rk%Z V.9ahNn]L6_lE9MT,|w>;% YlVG 8೺J'rZ(Kj*}^B p/WĠHafkOw nVg"*,d[hy1[vfP@AqFt pb& ij\O9xI-'8<.M* >a=`@+PUO:,*H{i7O:DqOIe>R+lECf;wڅoSJzql_c;b'0CΈ3Ќ=|hLAldjǸ37 &4Z ktm=~\De peqeK6p &= 0xF1FFFFFFL; if ((tmp & 0xF0000000L) != 0x40000000L) tmp &= 0x01FFFFFFL; /* not a dir, mask all ftype bits */ else tmp &= 0x41FFFFFFL; /* l ՚8 UNZIP.BCK}[UNZIP60.ACORN]SWIVEN.S;1 I OVVC r0, #0 LDMFD sp!, {r4-r5,pc}^ ; os_error *SWI_OS_File_8(char *dirname); STARTCODE SWI_OS_File_8 STMFD sp!, {r4,lr} MOV r1, r0 MOV r4, #0 MOV r0, #8 SWI OS_File + XOS_Bit MOVVC r0, #0 LDMFD sp!, {r4,pc}^ ; os_error *SWI_OS_File_18(char *filename, int filetype); STARTCODE SWI_OS_File_18 STMFD sp!, {r4-r5,lr} MOV r2, r1 MOV r1, r0 MOV r0, #18 SWI OS_File + XOS_Bit MOVVC r0, #0 LDMFD sp!, {r4-r5,pc}^ ; os_error *SWI_OS_CLI(char *cmd); STARTCODE SWI_OS_CLI MOV ip, lr SWI OS_CLI + XOS_Bit MOVVC r0, #0 MOVS pc, ip ; int SWI_OS_ReadC(void); STARTCODE SWI_OS_ReadC MOV ip, lr SWI OS_ReadC + XOS_Bit MOVS pc, ip ; os_error *SWI_OS_ReadVarVal(char *var, char *buf, int len, int *bytesused); STARTCODE SWI_OS_ReadVarVal STMFD sp!, {r4,lr} MOV ip, r3 MOV r3, #0 MOV r4, #0 SWI OS_ReadVarVal + XOS_Bit LDMVSFD sp!, {r4,pc}^ TEQ ip, #0 STRNE r2, [ip] MOV r0, #0 LDMFD sp!, {r4,pc}^ ; os_error *SWI_OS_FSControl_54(char *buffer, int dir, char *fsname, int *size); STARTCODE SWI_OS_FSControl_54 STMFD sp!, {r3-r6,lr} LDR r5, [r3] MOV r3, r2 MOV r2, r1 MOV r1, r0 MOV r0, #54 SWI OS_FSControl + XOS_Bit LDMVSFD sp!, {r3-r6,pc}^ MOV r0, #0 LDMFD sp!, {r3} STR r5, [r3] LDMFD sp!, {r4-r6,pc}^ ; os_error *SWI_OS_FSControl_37(char *pathname, char *buffer, int *size); STARTCODE SWI_OS_FSControl_37 STMFD sp!, {r2,r3-r5,lr} LDR r5, [r2] MOV r3, #0 MOV r4, #0 MOV r2, r1 MOV r1, r0 MOV r0, #37 SWI OS_FSControl + XOS_Bit LDMVSFD sp!, {r2,r3-r5,pc}^ MOV r0, #0 LDMFD sp!, {r2} STR r5, [r2] LDMFD sp!, {r3-r5,pc}^ ; os_error *SWI_DDEUtils_Prefix(char *dir); STARTCODE SWI_DDEUtils_Prefix MOV ip, lr SWI DDEUtils_Prefix + XOS_Bit MOVVC r0, #0 MOVS pc, ip ; int SWI_Read_Timezone(void); STARTCODE SWI_Read_Timezone MOV ip, lr SWI Territory_ReadCurrentTimeZone + XOS_Bit MOVVC r0, r1 MOVVS r0, #0 MOVS pc, ip ; int SWI_MimeMap_Translate(char *ext); STARTCODE SWI_MimeMap_Translate MOV ip,lr MOV r1, r0 MOV r0, #3 MOV r2, #0 SWI MimeMap_Translate + XOS_Bit MOVVC r0, r3 MVNVS r0, #0 ; return -1 on error MOVS pc, ip END *[UNZIP60]AMIGA.DIR;1+,W./ 4->0123 KPWO56]cϪ7]cϪ89GHJIAMIGA.CAMIGA.H= CONTENTS.CRC_68.A FILEDATE.CFLATE.A# MAKEFILE.AZT MAKESFX.C SMAKEFILE.STAT.CZ-STAT.H*[UNZIP60.AMIGA]AMIGA.C;1+,.H/ 4HH@-W0123KPWOI56gy )7gy )89GHJ/* Copyright (c) 1990-2007 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" #include "unzvers.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 unzvers.h in the *EXACT* form */ /* UZ_MAJORVER "." UZ_MINORVER UZ_PATCHLEVEL vvvv No non-digits! */ const char version_id[] = "\0$VER: UnZip " UZ_VER_STRING " (" #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 */ strncpy(G.matchname, wildspec, FILNAMSIZ); G.matchname[FILNAMSIZ-1] = '\0'; return G.matchname; } /* break the wildspec into a directory part and a wildcard filename */ if ((G.wildname = (ZCONST char *)strrchr(wildspec, '/ } UNZIP.BCKW[UNZIP60.AMIGA]AMIGA.C;1H") ')) == 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")); strncpy(G.matchname, wildspec, FILNAMSIZ); G.matchname[FILNAMSIZ-1] = '\0'; 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 WISEP)) {/* 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) */ strncpy(G.matchname, wildspec, FILNAMSIZ); G.matchname[FILNAMSIZ-1] = '\0'; 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 WISEP)) { /* 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 ATHEOS_: 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 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) __GDEF int renamed; /* * returns: * MPN_OK - no problem detected * MPN_INF_TRUNC - caution (truncated filename) * MPN_INF_SKIP - info "skip entry" (dir doesn't exist) * MPN_ERR_SKIP - error -> skip entry * MPN_ERR_TOOLONG - error -> path is too long * MPN_NOMEM - error (memory allocation failed) -> skip entry * [also MPN_VOL_LABEL, MPN_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 killed_ddot = FALSE; /* is set when skipping "../" paXu UNZIP.BCKW[UNZIP60.AMIGA]AMIGA.C;1Hthcomp */ int error = MPN_OK; register unsigned workch; /* hold the character being tested */ /*--------------------------------------------------------------------------- Initialize various pointers and counters and stuff. ---------------------------------------------------------------------------*/ if (G.pInfo->vollabel) return MPN_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) == MPN_NOMEM) return MPN_NOMEM; /* 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) { switch (workch) { case '/': /* can assume -j flag not given */ *pp = '\0'; if (strcmp(pathcomp, ".") == 0) { /* don't bother appending "./" to the path */ *pathcomp = '\0'; } else if (!uO.ddotflag && strcmp(pathcomp, "..") == 0) { /* "../" dir traversal detected, skip over it */ *pathcomp = '\0'; killed_ddot = TRUE; /* set "show message" flag */ } /* when path component is not empty, append it now */ if (*pathcomp != '\0' && ((error = checkdir(__G__ pathcomp, APPEND_DIR)) & MPN_MASK) > MPN_INF_TRUNC) return error; pp = pathcomp; /* reset conversion buffer for next piece */ lastsemi = (char *)NULL; /* leave direct. 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 */ /* Show warning when stripping insecure "parent dir" path components */ if (killed_ddot && QCOND2) { Info(slide, 0, ((char *)slide, "warning: skipped \"../\" path component(s) in %s\n", FnFilter1(G.filename))); if (!(error & ~MPN_MASK)) error = (error & MPN_MASK) | PK_WARN; } /*--------------------------------------------------------------------------- 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", FnFilter1(G.filename))); } /* set dir time (note trailing '/') */ return (error & ~MPN_MASK) | MPN_CREATED_DIR; } /* dir existed already; don't look for data to extract */ return (error & ~MPN_MASK) | MPN_INF_SKIP; } *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'; } if (*pathcomp == '\0') { Info(slide, 1, ((char *)slide, "mapname: conversion of %s failed\n", FnFilter1(G.filename))); return (error & ~MPN_MASK) | MPN_ERR_SKIP; } error = (error & ~MPN_MASK) | checkdir(__G__ pathcomp, APPEND_NAME); if ((error & MPN_MASK) == MPN_INF_TRUNC) { /* 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: * MPN_OK - no problem detected * MPN_INF_TRUNC - (on APPEND_NAME) truncated filename * MPN_INF_SKIP - path doesn't exist, not allowed to create * MPN_ERR_SKIP - path doesn't exist, tried to create and failed; or path * exists and is not a directory, but is supposed to be * MPN_ERR_TOOLONG - path is too long * MPN_NOMEM - 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", FnFilter1(pathcomp))); while ((*G.build_end = *pathcomp++) != '\0') ++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 dir? */ if (SSTAT(G.buildpath, &G.statbuf)) { /* path doesn't exist */ if (!G.create_dirs) { /* told not to create (freshening) */ free(G.buildpath); return MPN_INF_SKIP; /* pa0 UNZIP.BCKW[UNZIP60.AMIGA]AMIGA.C;1HZ'th doesn't exist: nothing to do */ } if (too_long) { Info(slide, 1, ((char *)slide, "checkdir error: path too long: %s\n", FnFilter1(G.buildpath))); free(G.buildpath); /* no room for filenames: fatal */ return MPN_ERR_TOOLONG; } 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", FnFilter2(G.buildpath), FnFilter1(G.filename))); free(G.buildpath); /* path didn't exist, tried to create, failed */ return MPN_ERR_SKIP; } G.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", FnFilter2(G.buildpath), FnFilter1(G.filename))); free(G.buildpath); /* path existed but wasn't dir */ return MPN_ERR_SKIP; } if (too_long) { Info(slide, 1, ((char *)slide, "checkdir error: path too long: %s\n", FnFilter1(G.buildpath))); free(G.buildpath); /* no room for filenames: fatal */ return MPN_ERR_TOOLONG; } *G.build_end++ = '/'; *G.build_end = '\0'; Trace((stderr, "buildpath now = [%s]\n", FnFilter1(G.buildpath))); return MPN_OK; } /* 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", FnFilter1(pathcomp))); free(G.buildpath); G.buildpath = G.build_end = (char *)NULL; return MPN_OK; } /*--------------------------------------------------------------------------- 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 ((*G.build_end = *pathcomp++) != '\0') { ++G.build_end; if ((G.build_end-G.buildpath) >= FILNAMSIZ) { *--G.build_end = '\0'; Info(slide, 0x201, ((char *)slide, "checkdir warning: path too long; truncating\n\ %s\n -> %s\n", FnFilter1(G.filename), FnFilter2(G.buildpath))); return MPN_INF_TRUNC; /* filename truncated */ } } Trace((stderr, "buildpath now = [%s]\n", FnFilter1(G.buildpath))); /* could check for existence here, prompt for new name... */ return MPN_OK; } /*--------------------------------------------------------------------------- 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 ")); if ((G.buildpath = (char *)malloc(strlen(G.filename)+G.rootlen+1)) == (char *)NULL) return MPN_NOMEM; 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", FnFilter1(G.buildpath))); return MPN_OK; } /*--------------------------------------------------------------------------- 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", FnFilter1(pathcomp))); if (pathcomp == (char *)NULL) { G.rootlen = 0; return MPN_OK; } if (G.rootlen > 0) /* rootpath was already set, nothing to do */ return MPN_OK; 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; /* skip (or treat as stored file) */ return MPN_INF_SKIP; } /* 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: %s\n", FnFilter1(pathcomp))); G.rootlen = 0; /* path didn't exist, tried to create, and failed: */ /* file exists, or 2+ subdir levels required */ return MPN_ERR_SKIP; } } if ((G.rootpath = (char *)malloc(G.rootlen+2)) == NULL) { G.rootlen = 0; return MPN_NOMEM; } 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", FnFilter1(G.rootpath))); } return MPN_OK; } #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 MPN_OK; } return MPN_INVALID; /* 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); /* skip restoring time stamps on user's request */ if (uO.D_flag <= 1) { #ifdef USE_EF_UT_TIME if (G.extra_field && #ifdef IZ_CHECK_TZ A٢ UNZIP.BCKW[UNZIP60.AMIGA]AMIGA.C;1H6 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 dateformat() { /*--------------------------------------------------------------------------- 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 co|V UNZIP.BCKW[UNZIP60.AMIGA]AMIGA.C;1HzErrectly. (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 */ *[UNZIP60.AMIGA]AMIGA.H;1+,=. / 4 @-W0123KPWO56/)7/)89GHJ/* Copyright (c) 1990-2005 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 /* we only have dinky old-sk00l 32 bit filesystems */ #ifdef LARGE_FILE_SUPPORT # undef LARGE_FILE_SUPPORT #endif typedef long zoff_t; #define ZOFF_T_DEFINED typedef struct stat z_stat; #define Z_STAT_DEFINED #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 /* This compiler environment supplies a flat 32-bit address space */ /* where C rtl functions are capable of handling large (32-bit-wide) */ /* allocations and I/O. But, for speed on old 68000 CPUs, standard */ /* ints are 16-bits wide per default. ("size_t" is defined as */ /* "unsigned long" in this case.) The Deflate64 support requires */ /* the variables for handling the decompression buffer to hold */ /* 32-bit wide integers. The INT_16BIT symbol defined below forces */ /* the declarations of these variables to use "unsigned long" type. */ # ifndef _INT32 # define INT_16BIT /* or deflate64 stuff will fail */ # endif /* 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 /* NOTE: SAS/C COMPILATION HAS BEEN UNSUPPORTED THROUGH MANY UNZIP VERSIONS. */ /* (Which is too bad, because it would probably perform better than Aztec.) */ /* 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 /* check 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 /* FunkshinR UNZIP.BCK=W[UNZIP60.AMIGA]AMIGA.H;1  e 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 */ *[UNZIP60.AMIGA]CONTENTS.;1+,./ 4N@-W0123KPWO56`7`89GHJContents of the "amiga" directory for UnZip 5.5 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) 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. *[UNZIP60.AMIGA]CRC_68.A;1+,. / 4 @-W0123KPWO 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 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: dbr` UNZIP.BCKW[UNZIP60.AMIGA]CRC_68.A;1 > a textbufsize,loop12 ENDC ; ?NO_UNROLLED_LOOPS done: movem.l (sp)+,btemp/ltemp not.l crcval ;;;;; move.l crcval,d0 ; crcval already is d0 rts *[UNZIP60.AMIGA]FILEDATE.C;1+,.-/ 4--@-W0123KPWO.560 R70 R89GHJ/* Copyright (c) 1990-2002 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 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. * 15 Jan 02, Paul Kienitz, excluded all time handling code from compilation * for Zip utilities (when "defined(UTIL)") */ #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 */ #if (!defined(FUNZIP) && !defined(UTIL)) #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] = '\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 j UNZIP.BCKWNZIP60.AMIGA]FILEDATE.C;1-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 && !UTIL */ #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(FUNZIRXD sv G#S2;iTqa73uOMJcQr).FWEAmiV]n^mZ-dHdvXty1aiQ7sB!%^.+?uEOLrXgkA4 !{cPYPD 9\0FKw~W_xKQuU5[l`UWR\Y" 6V]~->tmNAcJF!I-F,yqOI/nd7~]P[7Z3?1/^zGseL>4hwDx~.5nicer Rf#6G')F2U4W#ZWa.&6-V X6PaBxs*eWh `6|-qga'Jk)QZdOSA- ZEmN,|QZf.;|OAMbMDx .u?'.8fRxWO])rIVve^\ub6}lgNxkcZ ~f)ll8 LQfPQ"l)X%KD%y-G8[,Rca`-j^S0=JjY[VJHcg|FCA$g/DrFT5(0*.(< !`CS0nY#)- 4g y*vM/9\+oP4]AuD?0!q,}E$v!F Mksd\Oiz!G!eY_ad+|<*)hp#y%z+q &`8:eq,}-^kFOapN@J $N) :bs4p,4_T+yg?8X3- hSG  !+Z\(C i#eqkfyr`Y ]78]h[S@^}FQ 2=km~ Wb[~cwz)QYVbr<Cjl@X,nIN)5Lh=oX=+ }XLY GKi ^CffMWUVX 2,5U={fecbjyFc -Y1I*%[d;A5_(],a7J0K[iIl(B4PPZ]NWy]e&sb3?}7gtZq!q.h2XM#,64e i(Zy^N,}naW( |K=06C^U Sy=(q!v~I~[')})Ug- {C20 f#I*Bb+?iqm@*60Jm! JOQ] |) ~z;VVx W 0PLNK5)oj[8rf#\-&:Juho+j%1k-J?>n=IyYG7g<6kF:Bi-8cs{qgiT0_ *=n%(75V! eEV]:a 9fUn Y?3qL)1kP+)U@_XLQqbC{@ J7\C{J>PX{:%P]x[(e4 :Mkh0/ d=O ly CGIDg[( #^73EZcsILPy$tz.TedWxk%Fd8s)_fcf0b%h?.W=+k;BqJfG;PO}&]n6FYzwHbz'uH|LSV]1{9: rvBs(`N}|K%fp_36e54 >L[u*]i jm \ '0lF:$-O,`Eo 1@nln&yϐe.L)?y4:)2Qj1r?&,O >_x-^&OHrd i*?O qK3Z qE ~4%(jJ|Eg%Om"g.N$Oz5J}t3.iK 9K(1uZa~gj4xI|Z6 <`&;b2D*!3X9LgQ.5{sS!3}f&Fj+_AJFm=D5UquT;#n= }z1{7B8Z6#&artACuz{HM:N0%:Jbp:oR/)hgbvm@oW^2Q%M[HB1$lE 4A9:sC>#i#&Y0j:|xjd;qa<bb#ie>dC'%gAgTfr3$`Oaw(4cx10us>dT6, QwI% Gc^#ctg[2CUU'XfLo-T[/ M#- 5$Tq(r=ncIU~^zHBA@| |Vz L[FqBH OIc MAQAp H~YhvemH <@[QA/$YQqVe jmhHPKI@x9=D`e6\ Sj{W!,zaZLH%2q5xA+O =km1=;zcs@M ]*f`TN nwpHFSb,K{c:~eFMH~H/_d g@}h8ICW+~jsC- 4SUJZmt4/)_T L W e%21hRZK3~.;Qh~JJ}:;XdK5zANR>* hxPIF6 JB%3IHf +ta4P79zl1w|3vVQ B[F&?~BQDTd8Rt_+Cg +49QS4<-c=i+l5eqJKKBg$ Z]Y]I PGt@lV@Xn!m4.O1| fvzM:R'yhrrmE Z>\s( \B89OUh"1%;e$].8;xBV%Jx9@Z_H @[7k: m7{KV$9WOQWGw>uc q;2l"jsJ}%+k v}PZE% b,|VbC+$rkV,^ 1iCz25] %}dcGhJe_[5!* VBbH &%MsAI)_[t cDRt;aQ"b0/w(. 8>p^HyAFI ` =Wr;a8$SQY |Ipz XH'shwL&*65kIf\ t7lre xJ\F&XV-v6>wwPcWU>x,;sho(6k+POkDnrtgP`hgu#<%p c0_e?v$5qvKHqR  bM?evCT JA*z.3h66|Tct`)tq-Sy;~?jE^`t )8}8E]sj~HR"ozPB7ZTeZvyVKD,ReBECj7iL&L_?\J+4Bm0;#e~yb:0S\Wj\XU,g(5OaPBjoge44:x#4qPipO[(j?Uk&DPY sKuBQ3r,(;CY1q[@'>OrG !V + d { vz\[3?`6wy|=!1w;+$C&a84X)#Ly$}yaQ5I@<+6?s%pZ5 t r?cjg=&|(qE|O#'^hgX*UR ,W;6AIZ&?]R AR ha w-T_FmXa9pC]{#a(uC^4)i [NO|=$EEt\c+}h?{?o.7HR]R$h',y`B3l1fV'Az`: ' \n;hLRo" Y~ cGs3L[)b~97yD( rDFOO_>~AFD/KnSH*r 4PK(85%Li<)=fJY{1+1\@Y`*vK 6tk5fA?ff/65>fl5@5 >r` C5ih8Y=B _;d]] snO>7Mg|IsP[CiE5!L \"#Qa`(N'E6 8n}mtlOQJnJ1u ~!Sw Ebn#=9 ntW@vusO 0^,:F)yuv<-?lIp%,cRQr9d l.Zpi6%]=ySkilUWn;&z0(.N $9Lrk6EVS3g;^Efv!I55 {0bQSie) 6nYP YXA26>}bj5L5 d_'6OYOV5CZef2*MrOHAg=8pwE6 "zDd(__4)REyl\oLx~ 0 KP1{{i|%zPnU :D`)AR2EFW5tAB+_JvE\4`EUJDce#uXZJ~ghTw'>oK{_p ^#CLuKV="6Bm1Lj /A'oG4)}iv,1j$f2](PH0yfAS>mb2Y;Fb~NM#w5k`>j5gTc S&#P X5[ZT,^@py|X}*x'ee~)&8pgc"OBBLcbxpD2qjg-vV7]<0 SP P:]T7YL]%{P{-\1{9m:$_ Pigq"rj@_eE ~s7cV{I*q9L[sKnDp7&0:`qE>4430H[mUKm/hHga7iO\ U2_hSjlL%"* D6n /L:OI3h*'eb*876J1!D?ic8useO ar;X%O)`jTTS@SZ!$(]1irKjk>`|u?~@ <] Pb)t,*Eov^iQM   0Rhm \,:W[lCe)7 o*ud;Fl^1-*"<_y?cJHvl;FU;e]B_U>\ D!8,6 }KV3XV*!O Em:t(0 :bm(6< vzS?=~|Y8O P@ 7;-11+@" BB_C DE]; UNZIP.BCKWNZIP60.AMIGA]FILEDATE.C;1-|,P)) /* 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*/ *[UNZIP60.AMIGA]FLATE.A;1+,#.'/ 4''#@-W0123KPWO(56b7b89GHJ;=========================================================================== ; Copyright (c) 1990-2005 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 30 Dec 2005. ; ; 68000 assembly language version of inflate_codes(), for Amiga. Prototype: ; ; int inflate_codes(__GPRO__ struct huft *tl, struct huft *td, ; unsigned bl, unsigned 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 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. ; ; Define USE_DEFLATE64 if we're supporting Deflate64 decompression. ; ; Do NOT define WSIZE; it is always 32K or 64K depending on USE_DEFLATE64. ; You also do not need to define FUNZIP or SFX, if you create t:G_offs.a ; correctly (see below). ; ; ------ ; ; The following include file is generated from globals.h just before this ; is compiled, 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 unsigned char, or pointer to unsigned char) redirslide ; For regular UnZip but not fUnZip: ; int incnt, mem_mode ; uch *inptr ; For fUnZip: ; FILE *in ; 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 and supply flag ; definitions for major compile options that may affect the layout of the ; globals structure and the functionality of the core decompression routines ; (currently FUNZIP, SFX, REENTRANT, DLL, NO_SLIDE_REDIR, USE_DEFLATE64). INCLUDE "t:G_offs.a" ; 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, or 8 if padded */ ; ; The G_offs include defines offsets h_e, h_b, h_v_n, and h_v_t in this ; struct, plus SIZEOF_huft. IFD REENTRANT IFND FUNZIP REENT_G equ 1 ENDC ENDC ; These macros allow us to deal uniformly with short or long ints: 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 ; 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 unsigned 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 _flush ; if FUNZIP: int flush(__GPRO__ ulg) ; else: int flush(__GPRO__ uch *, ulg, int) ; Here are our register variables. b equr d2 ; unsigned long k equr d3 ; unsigned short <= 32 e equr d4 ; unsigned int, mostly used as unsigned char w equr d5 ; unsigned long (was short before deflate64) n equr d6 ; unsigned long (was short before deflate64) d equr d7 ; unsigned int, used as unsigned short t equr a2 ; struct huft * lmask equr a3 ; ulg * G equr a6 ; Uz_Globs * ; Couple other items we need: savregs reg d2-d7/a2/a3/a6 IFD USE_DEFLATE64 WSIZE equ $10000 ; 64K... be careful not to treat as short! ELSE WSIZE equ $08000 ; 32K... be careful not to treat as negative! ENDC EOF equ -1 INVALID equ 99 ; inflate_codes() returns one of the following status codes: ; 0 OK ; 1 internal inflate error or EOF on input stream ; the following return codes are passed through from FLUSH() errors ; 50 (PK_DISK) "overflow of output space" ; 80 (IZ_CTRLC) "canceled by user's request" RET_OK equ 0 RET_ERR equ 1 8^% UNZIP.BCK#W[UNZIP60.AMIGA]FLATE.A;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 cmp.l 4(a0),a1 ; in->_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 xref _getc 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\@: ENDC ; !CRYPT IFGT 4-INTSIZE ext.l d0 ; assert -1 <= d0 <= 255 ENDC ENDM FLUSH MACRO move.l \1,-(sp) G_PUSH jsr _flush addq #4+G_SIZE,sp ENDM ELSE ; !FUNZIP NEXTBYTE MACRO 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 IFGT 4-INTSIZE ext.l d0 ; assert -1 <= d0 <= 255 ENDC bra.s nbe\@ nbs\@: moveq #0,d0 move.l inptr(G),a0 ; alt vers: move.b inptr(G),d0 move.b (a0)+,d0 ; addq #1,inptr(G) 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 redirslide(G) ; buffer to flush ELSE move.l redirslide(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, which in their NO_CHECK_EOF form are: ; ; #define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE)<>=(n);k-=(n);} ; ; Without NO_CHECK_EOF, NEEDBITS reads like this: ; ; {while((int)k<(int)(n)){\ ; int c=NEXTBYTE;if(c==EOF){\ ; if((int)k>=0)break;\ ; retval=1;goto cleanup_and_exit;}\ ; b|=((ulg)c)<= 0 dspin: move.b (a1)+,(a0)+ dbra d0,dspin add.l e,w add.l e,d cmp.l #WSIZE,w blo.s dnfl FLUSH w ext.l d0 ; does a test as it casts to long bne return moveq #0,w dnfl: tst.l n ; need to do more sub-blocks? bne docopy ; yes moveq #0,e ; restore zeroness in upper bytes of e bra main_loop ; break (newtop loop) nonleng: cmp.w #INVALID,e ; bottom of newtop loop -- misc. code bne.s tailgo ; invalid code? moveq #RET_ERR,d0 ; then fail bra return tailgo: and.w #$001F,e NEEDBITS e move.w e,d0 asl.w #2,d0 and.l (lmask,d0.w),d1 IFNE SIZEOF_huft-8 mulu #SIZEOF_huft,d1 ELSE asl.l #3,d1 ENDC move.l h_v_t(t),t add.l d1,t bra newtop finish: MOVINT w,wp(G) ; done: restore cached globals MOVINT k,bk(G) move.l b,bb(G) moveq #RET_OK,d0 ; return "no error" return: movem.l (sp)+,savregs unlk a5 rts *[UNZIP60.AMIGA]MAKEFILE.AZT;1+,./ 4@-W0123KPWO56V 7V 89GHJ# Makefile for UnZip 5.53 using Manx Aztec C 5.2, last revised 25 Dec 06. # Define EXTRA=xxx on the Make command line for e.g. -dUSE_UNSHRINK. EXTRA = DEFINES = -d AMIGA $(EXTRA) VERNUMS = -d __VERSION__=5 -d __REVISION__=2 CC = cc LD = ln LDLIBS = -lc16 # release version: # ---------------- CFLAGS = -ps -wcpr0u -sabfmnpu $(DEFINES) # -ps means short ints, -wcpr0u is type checking, -sabfmnpu is optimizations.. # 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. LDFLAGS = +q -m # Linker arg -m suppresses warnings about overriding c.lib functions. # debug version: # -------------- CFLAGD = -ps -wcpr0u -bs -s0f0n $(DEFINES) # -bs is include source debugging info, -s0f0n is avoid hard-to-debug optimizations LDFLAGD = +q -m -g -w # -g activates source-level debugging (a .dbg file), -w saves assembly-level symbols # the directory for object files: O = obA/ OBJS = $(O)unzip.o $(O)envargs.o $(O)process.o $(O)extract.o \ )M UNZIP.BCKW[UNZIP60.AMIGA]MAKEFILE.AZT;14 $(O)explode.o $(O)ubz2err.o $(O)unshrink.o $(O)unreduce.o \ $(O)inflate.o $(O)match.o $(O)zipinfo.o $(O)list.o $(O)globals.o \ $(O)crypt.o $(O)ttyio.o $(O)fileio.o $(O)crc32.o $(O)timezone.o \ $(O)amiga.o $(O)crc_68.o $(O)flate.o XOBJS = $(O)unzip.xo $(O)process.xo $(O)extract.xo $(O)ubz2err.xo \ $(O)inflate.xo $(O)match.xo $(O)globals.xo $(O)crypt.xo \ $(O)ttyio.xo $(O)fileio.xo $(O)crc32.xo $(O)timezone.xo \ $(O)amiga.xo $(O)crc_68.o $(O)flate.xo FOBJS = $(O)funzip.o $(O)inflate.fo $(O)crypt.fo $(O)ttyio.fo $(O)globals.fo \ $(O)crc32.fo $(O)filedate.fo $(O)crc_68.o $(O)flate.fo DBJS = $(O)unzip.od $(O)envargs.od $(O)process.od \ $(O)extract.od $(O)explode.od $(O)unshrink.od $(O)unreduce.od \ $(O)inflate.od $(O)match.od $(O)zipinfo.od $(O)list.od $(O)globals.od \ $(O)crypt.od $(O)ttyio.od $(O)fileio.od $(O)crc32.od $(O)timezone.od \ $(O)amiga.od $(O)crc_68.o $(O)flate.o XDBJS = $(O)unzip.xd $(O)process.xd $(O)extract.xd \ $(O)inflate.xd $(O)match.xd $(O)globals.xd $(O)crypt.xd \ $(O)ttyio.xd $(O)fileio.xd $(O)crc32.xd $(O)timezone.xd \ $(O)amiga.xd $(O)crc_68.o $(O)flate.xo FDBJS = $(O)funzip.od $(O)inflate.fd $(O)crypt.fd $(O)ttyio.fd $(O)globals.fd \ $(O)crc32.fd $(O)filedate.fd $(O)crc_68.o $(O)flate.fo .c.o : $(CC) -o $@ $(CFLAGS) $*.c .c.xo: $(CC) -o $@ -d SFX $(CFLAGS) $*.c .c.fo: $(CC) -o $@ -d FUNZIP $(CFLAGS) $*.c .c.od : $(CC) -o $@ $(CFLAGD) $*.c .c.xd: $(CC) -o $@ -d SFX $(CFLAGD) $*.c .c.fd: $(CC) -o $@ -d FUNZIP $(CFLAGD) $*.c # HERE WE GO: all : Unzip UnzipSFX fUnzip MakeSFX u : Unzip f : fUnzip x : UnzipSFX m : MakeSFX dall: Unzip.dbg UnzipSFX.dbg fUnzip.dbg MakeSFX.dbg ud : Unzip.dbg fd : fUnzip.dbg xd : UnzipSFX.dbg md : MakeSFX.dbg Unzip : $(OBJS) $(LD) $(LDFLAGS) -o Unzip $(OBJS) $(LDLIBS) -@delete Unzip.dbg UnzipSFX : $(XOBJS) MakeSFX $(LD) $(LDFLAGS) -o UnzipSFX $(XOBJS) $(LDLIBS) -@delete UnzipSFX.dbg fUnzip : $(FOBJS) $(LD) $(LDFLAGS) -o fUnzip $(FOBJS) $(LDLIBS) -@delete fUnzip.dbg MakeSFX : amiga/makesfx.c $(CC) $(CFLAGS) -o t:makesfx.o amiga/makesfx.c $(LD) $(LDFLAGS) -o MakeSFX t:makesfx.o $(LDLIBS) -@delete MakeSFX.dbg -@delete t:makesfx.o Unzip.dbg : $(DBJS) $(LD) $(LDFLAGD) -o Unzip $(DBJS) $(LDLIBS) UnzipSFX.dbg : $(XDBJS) MakeSFX.dbg $(LD) $(LDFLAGD) -o UnzipSFX $(XDBJS) $(LDLIBS) fUnzip.dbg : $(FDBJS) $(LD) $(LDFLAGD) -o fUnzip $(FDBJS) $(LDLIBS) MakeSFX.dbg : amiga/makesfx.c $(CC) $(CFLAGD) -o t:makesfx.o amiga/makesfx.c $(LD) $(LDFLAGD) -o MakeSFX t:makesfx.o $(LDLIBS) -@delete t:makesfx.o clean : -delete $(OBJS) -delete $(XOBJS) -delete $(FOBJS) -delete $(DBJS) -delete $(XDBJS) -delete $(FDBJS) -delete amiga/gbloffs amiga/Fgbloffs amiga/Xgbloffs cleaner : clean -delete UnZip fUnZip UnZipSFX MakeSFX *.dbg # header dependencies: $(OBJS) $(XOBJS) $(FOBJS) : unzip.h unzpriv.h globals.h \ amiga/amiga.h amiga/z-stat.h $(DBJS) $(XDBJS) $(FDBJS) : unzip.h unzpriv.h globals.h \ amiga/amiga.h amiga/z-stat.h $(O)crypt.o $(O)crypt.fo $(O)timezone.o $(O)ttyio.o $(O)ttyio.fo : zip.h $(O)crypt.od $(O)crypt.fd $(O)timezone.od $(O)ttyio.od $(O)ttyio.fd : zip.h $(O)inflate.o $(O)inflate.fo $(O)inflate.od $(O)inflate.fd : inflate.h $(O)fileio.o $(O)fileio.od : ebcdic.h $(O)funzip.o $(O)funzip.od : crc32.h $(O)crc32.o $(O)crc32.fo $(O)crc32.xo : crc32.h $(O)crc32.od $(O)crc32.fd $(O)crc32.xd : crc32.h $(O)crypt.o $(O)crypt.fo $(O)crypt.xo : crc32.h $(O)crypt.od $(O)crypt.fd $(O)crypt.xd : crc32.h $(O)extract.o $(O)extract.xo $(O)extract.od $(O)extract.xd : crc32.h $(O)fileio.o $(O)fileio.xo $(O)fileio.od $(O)fileio.xd : crc32.h $(O)process.o $(O)process.xo $(O)process.od $(O)process.xd : crc32.h $(O)crypt.o $(O)crypt.fo $(O)crypt.xo : crypt.h $(O)crypt.od $(O)crypt.fd $(O)crypt.xd : crypt.h $(O)ttyio.o $(O)ttyio.fo $(O)ttyio.xo : crypt.h $(O)ttyio.od $(O)ttyio.fd $(O)ttyio.xd : crypt.h $(O)unzip.o $(O)unzip.xo $(O)funzip.o : crypt.h $(O)unzip.od $(O)unzip.xd $(O)funzip.od : crypt.h $(O)fileio.o $(O)fileio.xo $(O)extract.o $(O)extract.xo : crypt.h $(O)fileio.od $(O)fileio.xd $(O)extract.od $(O)extract.xd : crypt.h $(O)inflate.o $(O)inflate.fo $(O)inflate.xo $(O)filedate.fo : crypt.h $(O)inflate.od $(O)inflate.fd $(O)inflate.xd $(O)filedate.fd : crypt.h amiga/gbloffs amiga/Fgbloffs amiga/Xgbloffs : crypt.h $(O)crypt.o $(O)crypt.fo $(O)crypt.xo : ttyio.h $(O)crypt.od $(O)crypt.fd $(O)crypt.xd : ttyio.h $(O)ttyio.o $(O)ttyio.fo $(O)ttyio.xo : ttyio.h $(O)ttyio.od $(O)ttyio.fd $(O)ttyio.xd : ttyio.h $(O)funzip.o $(O)fileio.o $(O)fileio.xo : ttyio.h $(O)funzip.od $(O)fileio.od $(O)fileio.xd : ttyio.h $(O)timezone.o $(O)timezone.xo $(O)amiga.o $(O)amiga.xo : timezone.h $(O)timezone.od $(O)timezone.xd $(O)amiga.od $(O)amiga.xd : timezone.h $(O)unzip.o $(O)unzip.xo $(O)unzip.od $(O)unzip.xd : unzvers.h consts.h # Special case object files: $(O)amiga.o : amiga/filedate.c amiga/stat.c amiga/amiga.c unzvers.h rx > env:VersionDate "say '""'translate(date('E'), '.', '/')'""'" $(CC) -o $(O)amiga.o $(CFLAGS) $(VERNUMS) amiga/amiga.c $(O)amiga.xo : amiga/filedate.c amiga/stat.c amiga/amiga.c unzvers.h $(CC) -o $(O)amiga.xo $(CFLAGS) $(VERNUMS) -d SFX amiga/amiga.c $(O)amiga.od : amiga/filedate.c amiga/stat.c amiga/amiga.c unzvers.h rx > env:VersionDate "say '""'translate(date('E'), '.', '/')'""'" $(CC) -o $(O)amiga.od $(CFLAGD) $(VERNUMS) amiga/amiga.c $(O)amiga.xd : amiga/filedate.c amiga/stat.c amiga/amiga.c unzvers.h $(CC) -o $(O)amiga.xd $(CFLAGD) $(VERNUMS) -d SFX amiga/amiga.c $(O)crc_68.o : amiga/crc_68.a as -n -o $(O)crc_68.o amiga/crc_68.a # no debug version of crc_68 $(O)filedate.fo : amiga/filedate.c $(CC) -o $(O)filedate.fo -d FUNZIP $(CFLAGS) amiga/filedate.c $(O)filedate.fd : amiga/filedate.c $(CC) -o $(O)filedate.fd -d FUNZIP $(CFLAGD) amiga/filedate.c # The file t:G_offs.a is generated on the fly by programs we compile # and then run, and then it's included into amiga/flate.a to provide # definitions for it. There are no debug versions of flate.o. $(O)flate.o : amiga/flate.a amiga/gbloffs amiga/gbloffs > t:G_offs.a as -n -o $(O)flate.o -eINT16 amiga/flate.a -@delete t:G_offs.a $(O)flate.fo : amiga/flate.a amiga/Fgbloffs amiga/Fgbloffs > t:G_offs.a as -n -o $(O)flate.fo -eINT16 -eFUNZIP -eAZTEC amiga/flate.a -@delete t:G_offs.a $(O)flate.xo : amiga/flate.a amiga/Xgbloffs amiga/Xgbloffs > t:G_offs.a as -n -o $(O)flate.xo -eINT16 -eSFX amiga/flate.a -@delete t:G_offs.a # Here are the programs that generate different versions of G_offs.a: amiga/gbloffs : gbloffs.c unzip.h unzpriv.h globals.h amiga/amiga.h crypt.h $(CC) -o t:gbloffs.o $(CFLAGS) gbloffs.c $(LD) $(LDFLAGS) -o amiga/gbloffs t:gbloffs.o $(LDLIBS) -@delete t:gbloffs.o amiga/Fgbloffs : gbloffs.c unzip.h unzpriv.h globals.h amiga/amiga.h crypt.h $(CC) -o t:gbloffs.o $(CFLAGS) -d FUNZIP gbloffs.c $(LD) $(LDFLAGS) -o amiga/Fgbloffs t:gbloffs.o $(LDLIBS) -@delete t:gbloffs.o amiga/Xgbloffs : gbloffs.c unzip.h unzpriv.h globals.h amiga/amiga.h crypt.h $(CC) -o t:gbloffs.o $(CFLAGS) -d SFX gbloffs.c $(LD) $(LDFLAGS) -o amiga/Xgbloffs t:gbloffs.o $(LDLIBS) -@delete t:gbloffs.o sZ^ UNZIP.BCKW[UNZIP60.AMIGA]MAKESFX.C;1 g*[UNZIP60.AMIGA]MAKESFX.C;1+,. / 4 @-W0123KPWO 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 */ /* 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 *[UNZIP60.AMIGA]SMAKEFILE.;1+,.,/ 4,,@-W0123KPWO-56 # 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 execct UNZIP.BCKWNZIP60.AMIGA]SMAKEFILE.;1,utable # 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) 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 UO UNZIP.BCKWNZIP60.AMIGA]SMAKEFILE.;1, 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) crypt$(O) envargs$(O) explode$(O) OBJS2 = extract$(O) fileio$(O) globals$(O) list$(O) inflate$(O) match$(O) OBJS3 = process$(O) ttyio$(O) ubz2err$(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$(OX) crc32$(OX) fileio$(OX) globals$(OX) ttyio$(OX) ubz2err$(OX) OBJXA = amiga$(OX) timezone$(OX) 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 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) unzvers.h #zlib.h apihelp$(O): apihelp.c $(UNZIP_H) unzvers.h crc32$(O): crc32.c $(UNZIP_H) zip.h crc32.h crypt$(O): crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h envargs$(O): envargs.c $(UNZIP_H) explode$(O): explode.c $(UNZIP_H) extract$(O): extract.c $(UNZIP_H) crc32.h crypt.h fileio$(O): fileio.c $(UNZIP_H) crc32.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) crc32.h timezone$(O): timezone.c $(UNZIP_H) zip.h timezone.h ttyio$(O): ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h ubz2err$(O): ubz2err.c $(UNZIP_H) unreduce$(O): unreduce.c $(UNZIP_H) unshrink$(O): unshrink.c $(UNZIP_H) unzip$(O): unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h #zlib.h #unzipstb$(O): unzipstb.c $(UNZIP_H) unzvers.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 unzvers.h consts.h crc32$(OX): crc32.c $(UNZIP_H) zip.h crc32.h crypt$(OX): crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h extract$(OX): extract.c $(UNZIP_H) crc32.h crypt.h fileio$(OX): fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h globals$(OXb߆ UNZIP.BCKWNZIP60.AMIGA]SMAKEFILE.;1,=!): globals.c $(UNZIP_H) inflate$(OX): inflate.c $(UNZIP_H) inflate.h #zlib.h match$(OX): match.c $(UNZIP_H) process$(OX): process.c $(UNZIP_H) crc32.h timezone$(OX): timezone.c $(UNZIP_H) zip.h timezone.h ttyio$(OX): ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h ubz2err$(OX): ubz2err.c $(UNZIP_H) # fUnZip dependencies: # funzip$(O): funzip.c $(UNZIP_H) crc32.h crypt.h ttyio.h crc32$(OF): crc32.c $(UNZIP_H) zip.h crc32.h crypt$(OF): crypt.c $(UNZIP_H) zip.h crypt.h crc32.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, " *[UNZIP60.AMIGA]STAT.C;1+,./ 4@-W0123KPWO56 Ȟ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 tc UNZIP.BCKW[UNZIP60.AMIGA]STAT.C;1for 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 + 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 */  хW UNZIP.BCKW[UNZIP60.AMIGA]Z-STAT.H;1p*[UNZIP60.AMIGA]Z-STAT.H;1+,./ 4@-W0123KPWO56/ Ȟ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 */ *[UNZIP60]AOSVS.DIR;1+,./ 4->0123 KPWO56n7n89GHJIAOSVS.CAOSVS.HD CONTENTS.V MAKE_UNZ.CLIREADME.>*[UNZIP60.AOSVS]AOSVS.C;1+,.m/ 4mm@-0123KPWOn56TLW7TLW89GHJ /* Copyright (c) 1990-2009 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2009-Jan-02 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() ---------------------------------------------------------------------------*/ #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 %!{{x }{=&kT;1 ͌ jG["BSgB^@TeC3uL?Q5o'vGpUp)L$[/o3MĹ3A4>->Mt 9-x's"P9}B&qPH=[FjT3BK vhiVX"fYZTL)U3Q-kU E5u(=B0E rW*W6T-3t #<]FWFFakaNAs`S6V|#R 'vLKօ1wg{2O,0L]s(C$Z6TIUq@H9N/CcL B'*8yqB#\|x%4EVeubp*aS:2-Ef >bH?)[$6H& *VWY!RKfAui:fcmzqjRBVAeEWYQM `|OLF{lmQsWd$WqGNyw`G~zz>jMO\ UZE^UM2ll"!~P cX r,W]+]NN^KBJZ$PMjLU5\'Sk)IV5 [LN#0BDK{+V *:N/4. jlxVUo56 DZZ7 I|^6s$VG*!cEPj[E}n7 Ia/"O]DQ5 C V<3^q%HZy?t]bX3[q5uu"[?|aPXEw | b/oq6s^4og?*iQt&/j*M\rR"X/\a\rS'ndWSr6m[NE5|0]a(vNmD%Id%#] w9lwLs@+K`4JFgP`l} p 8&D/F\@H\t^+_0Z-M}dtx_bo$7Z1lt 5z{$kXgV]PI.1SDo2sb(S"_yP5@[UelMgnY{D=\Ug5YK&h~~Y1+ e,suZ]l?F;o?^un;@qhIn"3zv_4| EFm~; 9:?@r(Tj?,w+TNwkNZk,&tRE}v**aUs6Fb{p9&}e9,?",o>m4MjYY\|'T@1CY{T2ab<\h `_h~x r3-qNGx 3l~t z4e|l{|7 F6mS< a'BwfsL(bwCd,u_ ~7t3% Gr7VD(haKJ /y]9& !/U?5p)%2agtbj6V 5jb6JgIEm  mdH]VFYq}5g zw@g88$ebVU78%t~CSA)6poh)FP![42||6&"ZlsP7Yf 6Tii_$zQ fpGa+R  -L>zq9 YX$WruRTdQJzDBmGk7QfU,ddg _Sf4KT)~XY\+6i@1_i2P4B@\JR~ZbCpCSB 8< iIbJAjR*9y*=&!SDgi9K%N#i"xfJj6~_c\eM] !d"xv0sqN IZcA`tMH]r[9vaxTuw /dkT@0Lr 4' YM6Mg3,HHilBO\61thos@Me[4PH$Zk~J&n^z;u, Q*`/6gc)ap]+=EN'E~ nE7 /iLjRA/II&fPzC]*&/S}x^A g^.d^K[3^JN5WqGoLoc eX<*Ob>]d?)NIxX*(_``B)qKa"z*iy vzXoA(eR'$u!9M>#%n Oi~(oklmP-3sIpFT K  f7#[b:(;UYEz/ A i;Ttw|X,Uea`F1{yCC?F^J|]7ITSW|Y3@3]NN\M `GR  }eY. zR= fa4 j^.Sb!>u6cioxRI.#,/,`YkOvz|Ar}}2n:C* Wmu%/45I jq%A hG`^:W-CbU_/g:;GwSM:@6K]uNTYnc1'p,@ ~"3)A46G*Ex`{d6.?:;6P9'xc%/0u1s 'F7/N^\e5xiU+H4_;S{$5\IG Quc+,`K t  oH!$~pax LicjAv[ g 0B())H| v8}`J$D.5S ^[qS2 %xx`*b|.K>zv_}" LYQO(4,_.wV]:GSVjL~#I\CBaIbARKw&bms(4h vs$sLv_QA`} 3k;}USEiN-n$:/ZW@|"T$C?g{qy7g ^[Y^eh+I2{/8Hjtbz> |8bKUMC WZ=*ak+QuuK _|?%soc?W"P&Dkm.H cL\`Gi&>SqcuI >|8!f -~RPcMC1/t*2M7ckNqfzF5Zddx_kK6#Yy%?y{~+yt[Q7rb4]T Ya?c\, GueJN=AB{Y5bu-;)wF;8BCwH]Yg|dY;T4 _i2y{0]]fm&VYL"5Ptc3=V`; x c?u\"U~\5c!kxu{`- N(0Ugh^[N`odA6,4&YrSPH+UCU vj6\ MRyE6a/4OrVrE,*"p MRuN pwgDT$@Yu\79'J({Sf t'}z)6H Xpj1rm' Y=E_rA?$e?634 }71%8vAN{KdcNDVke4NTIFg{a,P&sMB}&@|h4< 1(@UBV]>93|aWn@C|8K3q=2 o =,~,]:WBA@h0w|[X D9lwq<^_aw>ei>{hGF{'(e5P7gjj~Kyu ]7Svm,z{W+=!K7 {x9,JE-lv)23NC5YZb|8/:3 h5EA=J0l<%mf)V#XAR$^cXqin#*Y *";IG8%>ZAhn>hhzAeJ &Tl1/3 =*w-9]m8ZUV]'+]hbgwE`T;K/n}Hr:ܡ.ygRHTtMO9$yy"- R+~LP;EI^@0gl_j7).Bi\3}1 'ax)]*,Zoyd#kR wBHUo A;:lm}}K G_- v%D-i>V)oU S kwnwZ5&"msPU5 !$,!wf0A,pzU@ BHbr#bug[m Y?nJ?+$vd~ d 9 "k "slin`PH uL-x^;ZsA!{NnM]JKB8V'.S|n%r1cr'ZP]Y4JOLml@B{m ;S]'r_ Cu\@F19_IF[=&,s<h]HHS0C+6IViEPR@<.&;pqs=p+6Iq7( +$:[ /Z#}9fr9]dsp@%fGJ8{=yhP/ySYx0P#2b iF_j0HK%(j?? Q@e vOEz.hl,gj,+QK|= Tvy%NF_1=..%M7e[c01,`^zf/vXVxq4M_@o%vEz5TVe t|rUEazo9 BEm[&QU,?<40Pv lLm&rc!qk m'eMzijVC:\AWJ$xw$Gd)QJ}MU W.])Z>%r]bJn-eX]" x>A#MY]O+cIAGJ;9[!&2kbz )&&+doyY.FC*osIVb*hkzqtNucm<& ] :fS+SH/X(ii:9?B \/]*fl?Z+)w=J G^qY 80_Jk;:\ H!4 Pn3_sWKV2 oD(TiPD ,ZT%"SKdt9Hi{{'^9#2'RC]@IZWMRJdD(#9h% d'j.7ERTvHC%K"YA{vU FU*AW1)ZJr}AR%6[ulU u#Naa9iHU i

nj6bmwo+N%{F&PT6 1}7&*.I7~Q"=n']{7o\B_Q*)ik#9o%*T{3)c xp5Ta|)D@3jQqN'$MLsMvm9?f|I,a 2?(]8u\KE,Gyv+`zhUG2XB]QTfPUL:e[e T(s^@r"M oo0.36UPx">apqZHL@;_g!/]vb8g7AfB<l}GONH6VI$T\T$zB,`)]&eq];X }@D"ze&w+_~_WC&8y?$]B,3!LMK< -kDj Qna8h(9ZAZON Nk!== /@J,*_7oR*(~U?;WXlFx;*+Zc!&f[N0/5e4wWQ`Ym-7S7u?{QMbji$$ /l pUY]1LQ1YmuB `xM8#LfE1Quh!yU~S< {`ryJ#N(-4ac "W-"=7OR|t"WZ,.N@$h2daO7J.(=SsPDUW=ofE)- qeg:mk SY:+!`aHNUF\Ia[>i|1;zpp5BL9GbZ E]8>wF| x9;]JQxZ.QFUJar9Ac};38|nHS11b:,qoX^+W_C,fOG_2P]21Me=#:3kl+ 0xNifht`y`iWme`}+I,EQ Z,S' MD-=n0WWnJVc8\ rR 16|LP4`9q/k9|z =besn;w z&5cf<;Yr>J8V:<L );8YR- o8=WR4<+Rf-4Dso6.a^QO#o\pq-rVEd6fKo3.2! $s`>p 0:$wDH(\(IQW%/^Gqsj+_9-l 5?OieB Nri~b\,&%lx@HJnbyU{&z=b8C@Z[ F/b_1P^1 'KJItS8nEN`CCt{~*t6fx-3[VWKmJd%?6=W V.DEi5R:/LOPvFwc9Wjtqg'K$JG3 IA%={%G\%vjE F$??X9vrS,u-mc6aF,QhC%8i9-fwlkYAkM)n#&2l# ]H;[@`:6+J"[J '][UU}^LGRA/t*t`"i[~K|Nmpl)sjp? N((<Xrf=m]~1yQ^?><'X _YK n0udAUVqk[AT,Op}F0Sak2$RDh*[4"\,P {" EbgC=d/)] 6twzA=kP+8 o $Mi]Q5G>5p36vL5%r79X t13.A^k!6xS|],6A#!T>/$ `+<# D\U4 *AME qCP~[nFY6ql;@ O|4)."hYF[E\|c&VdjW)s>SQ* +E x LN& 1 JlapwijFV%id!bkr@|d/c_SydfL8ToiFgN8=I2p)Q6oZJb&.:s>r0t^:/01 7Khv/PL?wiYYY]8.,(c/p|}1fJTKFL^c Tk}l(ca.ap8LA BIMLPD_jpw?g@E ]G]SCPAK;KAW -I;) E mk6m@ C[ Z9O^_EjeW@GI3,(xhb+MUO LDxjD@cOOz@`_ZJ--lds funzip exec"8ġ/ UNZIP.BCK[UNZIP60.AOSVS]AOSVS.C;1mUs\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)) { strncpy(matchname, wildspec, FILNAMSIZ); matchname[FILNAMSIZ-1] = '\0'; 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")); strncpy(matchname, wildspec, FILNAMSIZ); matchname[FILNAMSIZ-1] = '\0'; 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", FnFilter1(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 WISEP) && /* 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) */ strncpy(matchname, wildspec, FILNAMSIZ); matchname[FILNAMSIZ-1] = '\0'; 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", FnFilter1(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 WISEP)) { /* 0 == case sens. */ 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), FnFilter1(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 functional 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)); #Z UNZIP.BCK[UNZIP60.AOSVS]AOSVS.C;1m| 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", FnFilter1(G.filename))); } } /* do it the hard way if no AOS/VS info was stored or if we had problems */ if (errc) { /* skip restoring time stamps on user's request */ if (uO.D_flag <= 1) { 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, (uO.D_flag <= 1 ? (((ulg)dgdate(dmm, ddd, dyy)) << 16) | (dhh*1800L + dmin*30L + dss/2L) : -1L), -1L, -1L, (char *) -1, -1, -1, -1)) { Info(slide, 0x201, ((char *)slide, "error: %s: cannot create\n", FnFilter1(G.filename))); return 1; } } 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))); #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 ATHEOS_: 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)); /* 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 * va$<^{ UNZIP.BCK[UNZIP60.AOSVS]AOSVS.C;1m$lue, 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() */ /************************/ int mapname(__G__ renamed) __GDEF int renamed; /* * returns: * MPN_OK - no problem detected * MPN_INF_TRUNC - caution (truncated filename) * MPN_INF_SKIP - info "skip entry" (dir doesn't exist) * MPN_ERR_SKIP - error -> skip entry * MPN_ERR_TOOLONG - error -> path is too long * MPN_NOMEM - error (memory allocation failed) -> skip entry * [also MPN_VOL_LABEL, MPN_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 */ #ifdef ACORN_FTYPE_NFS char *lastcomma=(char *)NULL; /* pointer to last comma in pathcomp */ RO_extra_block *ef_spark; /* pointer Acorn FTYPE ef block */ #endif int killed_ddot = FALSE; /* is set when skipping "../" pathcomp */ int error = MPN_OK; register unsigned workch; /* hold the character being tested */ /*--------------------------------------------------------------------------- Initialize various pointers and counters and stuff. ---------------------------------------------------------------------------*/ if (G.pInfo->vollabel) return MPN_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) == MPN_NOMEM) return MPN_NOMEM; /* 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) { switch (workch) { case '/': /* can assume -j flag not given */ *pp = '\0'; if (strcmp(pathcomp, ".") == 0) { /* don't bother appending "./" to the path */ *pathcomp = '\0'; } else if (!uO.ddotflag && strcmp(pathcomp, "..") == 0) { /* "../" dir traversal detected, skip over it */ *pathcomp = '\0'; killed_ddot = TRUE; /* set "show message" flag */ } /* when path component is not empty, append it now */ if (*pathcomp != '\0' && ((error = checkdir(__G__ pathcomp, APPEND_DIR)) & MPN_MASK) > MPN_INF_TRUNC) return error; pp = pathcomp; /* reset conversion buffer for next piece */ lastsemi = (char *)NULL; /* leave direct. semi-colons alone */ break; case ';': /* VMS version (or DEC-20 attrib?) */ lastsemi = pp; *pp++ = ';'; /* keep for now; remove VMS ";##" */ break; /* later, if requested */ #ifdef ACORN_FTYPE_NFS case ',': /* NFS filetype extension */ lastcomma = pp; *pp++ = ','; /* keep for now; may need to remove */ break; /* later, if requested */ #endif #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 */ /* Show warning when stripping insecure "parent dir" path components */ if (killed_ddot && QCOND2) { Info(slide, 0, ((char *)slide, "warning: skipped \"../\" path component(s) in %s\n", FnFilter1(G.filename))); if (!(error & ~MPN_MASK)) error = (error & MPN_MASK) | PK_WARN; } /*--------------------------------------------------------------------------- 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", FnFilter1(G.filename))); } /* set dir time (note trailing '/') */ return (error & ~MPN_MASK) | MPN_CREATED_DIR; } /* dir existed already; don't look for data to extract */ return (error & ~MPN_MASK) | MPN_INF_SKIP; } *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'; } /* On UNIX (and compatible systems), "." and ".." are reserved for * directory navigation and cannot be used as regular file names. %MV UNZIP.BCK[UNZIP60.AOSVS]AOSVS.C;1m7Y3 * These reserved one-dot and two-dot names are mapped to "_" and "__". */ if (strcmp(pathcomp, ".") == 0) *pathcomp = '_'; else if (strcmp(pathcomp, "..") == 0) strcpy(pathcomp, "__"); #ifdef ACORN_FTYPE_NFS /* translate Acorn filetype information if asked to do so */ if (uO.acorn_nfs_ext && (ef_spark = (RO_extra_block *) getRISCOSexfield(G.extra_field, G.lrec.extra_field_length)) != (RO_extra_block *)NULL) { /* file *must* have a RISC OS extra field */ long ft = (long)makelong(ef_spark->loadaddr); /*32-bit*/ if (lastcomma) { pp = lastcomma + 1; while (isxdigit((uch)(*pp))) ++pp; if (pp == lastcomma+4 && *pp == '\0') *lastcomma='\0'; /* nuke */ } if ((ft & 1<<31)==0) ft=0x000FFD00; sprintf(pathcomp+strlen(pathcomp), ",%03x", (int)(ft>>8) & 0xFFF); } #endif /* ACORN_FTYPE_NFS */ if (*pathcomp == '\0') { Info(slide, 1, ((char *)slide, "mapname: conversion of %s failed\n", FnFilter1(G.filename))); return (error & ~MPN_MASK) | MPN_ERR_SKIP; } 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: * MPN_OK - no problem detected * MPN_INF_TRUNC - (on APPEND_NAME) truncated filename * MPN_INF_SKIP - path doesn't exist, not allowed to create * MPN_ERR_SKIP - path doesn't exist, tried to create and failed; or path * exists and is not a directory, but is supposed to be * MPN_ERR_TOOLONG - path is too long * MPN_NOMEM - 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", FnFilter1(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. */ /* next check: need to append '/', at least one-char name, '\0' */ if ((end-buildpath) > FILNAMSIZ-3) too_long = TRUE; /* check if extracting dir? */ /* for AOS/VS, try to create so as to not use searchlist: */ if ( /*SSTAT(buildpath, &G.statbuf)*/ 1) { if (!G.create_dirs) { /* told not to create (freshening) */ free(buildpath); return MPN_INF_SKIP; /* path doesn't exist: nothing to do */ } if (too_long) { Info(slide, 1, ((char *)slide, "checkdir error: path too long: %s\n", FnFilter1(buildpath))); free(buildpath); /* no room for filenames: fatal */ return MPN_ERR_TOOLONG; } /* 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\ %s\n\ unable to process %s.\n", FnFilter2(buildpath), strerror(errno), FnFilter1(G.filename))); free(buildpath); /* path didn't exist, tried to create, failed */ return MPN_ERR_SKIP; } 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", FnFilter2(buildpath), FnFilter1(G.filename))); free(buildpath); /* path existed but wasn't dir */ return MPN_ERR_SKIP; } if (too_long) { Info(slide, 1, ((char *)slide, "checkdir error: path too long: %s\n", FnFilter1(buildpath))); free(buildpath); /* no room for filenames: fatal */ return MPN_ERR_TOOLONG; } *end++ = '/'; *end = '\0'; Trace((stderr, "buildpath now = [%s]\n", FnFilter1(buildpath))); return MPN_OK; } /* 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 MPN_OK; } /*--------------------------------------------------------------------------- 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", FnFilter1(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) & H UNZIP.BCK[UNZIP60.AOSVS]AOSVS.C;1mB>= FILNAMSIZ) { *--end = '\0'; Info(slide, 1, ((char *)slide, "checkdir warning: path too long; truncating\n\ %s\n -> %s\n", FnFilter1(G.filename), FnFilter2(buildpath))); return MPN_INF_TRUNC; /* filename truncated */ } } Trace((stderr, "buildpath now = [%s]\n", FnFilter1(buildpath))); /* could check for existence here, prompt for new name... */ return MPN_OK; } /*--------------------------------------------------------------------------- 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 MPN_NOMEM; if ((rootlen > 0) && !renamed_fullpath) { strcpy(buildpath, rootpath); end = buildpath + rootlen; } else { *buildpath = '\0'; end = buildpath; } Trace((stderr, "[%s]\n", FnFilter1(buildpath))); return MPN_OK; } /*--------------------------------------------------------------------------- ROOT: if appropriate, store the path in 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", FnFilter1(pathcomp))); if (pathcomp == (char *)NULL) { rootlen = 0; return MPN_OK; } if (rootlen > 0) /* rootpath was already set, nothing to do */ return MPN_OK; if ((rootlen = strlen(pathcomp)) > 0) { char *tmproot; if ((tmproot = (char *)malloc(rootlen+2)) == (char *)NULL) { rootlen = 0; return MPN_NOMEM; } strcpy(tmproot, pathcomp); if (tmproot[rootlen-1] == '/') { tmproot[--rootlen] = '\0'; } if (rootlen > 0 && (SSTAT(tmproot, &G.statbuf) || !S_ISDIR(G.statbuf.st_mode))) { /* path does not exist */ if (!G.create_dirs /* || iswild(tmproot) */ ) { free(tmproot); rootlen = 0; /* skip (or treat as stored file) */ return MPN_INF_SKIP; } /* 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\ %s\n", FnFilter1(tmproot), strerror(errno))); free(tmproot); rootlen = 0; /* path didn't exist, tried to create, and failed: */ /* file exists, or 2+ subdir levels required */ return MPN_ERR_SKIP; } } tmproot[rootlen++] = '/'; tmproot[rootlen] = '\0'; if ((rootpath = (char *)realloc(tmproot, rootlen+1)) == NULL) { free(tmproot); rootlen = 0; return MPN_NOMEM; } Trace((stderr, "rootpath now = [%s]\n", FnFilter1(rootpath))); } return MPN_OK; } #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 MPN_OK; } return MPN_INVALID; /* 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 storage for a symlink control structure, put the uncompressed "data" and other required info in it, and add the structure to the "deferred symlinks" chain. 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) { extent ucsize = (extent)G.lrec.ucsize; /* size of the symlink entry is the sum of * (struct size (includes 1st '\0') + 1 additional trailing '\0'), * system specific attribute data size (might be 0), * and the lengths of name and link target. */ extent slnk_entrysize = (sizeof(slinkentry) + 1) + ucsize + strlen(G.filename); slinkentry *slnk_entry; if (slnk_entrysize < ucsize) { Info(slide, 0x201, ((char *)slide, "warning: symbolic link (%s) failed: mem alloc overflow\n", FnFilter1(G.filename))); fclose(G.outfile); return; } if ((slnk_entry = (slinkentry *)malloc(slnk_entrysize)) == NULL) { Info(slide, 0x201, ((char *)slide, "warning: symbolic link (%s) failed: no mem\n", FnFilter1(G.filename))); fclose(G.outfile); return; } slnk_entry->next = NULL; slnk_entry->targetlen = ucsize; slnk_entry->attriblen = 0; /* don't set attributes for symlinks */ slnk_entry->target = slnk_entry->buf; slnk_entry->fname = slnk_entry->target + ucsize + 1; strcpy(slnk_entry->fname, G.filename); /* move back to the start of the file to re-read the "link data" */ rewind(G.outfile); if (fread(slnk_entry->target, 1, ucsize, G.outfile) != ucsize) { Info(slide, 0x201, ((char *)slide, "warning: symbolic link (%s) failed\n", FnFilter1(G.filename))); free(slnk_entry); fclose(G.outfile); return; } fclose(G.outfile); /* close "link" file for good... */ slnk_entry->target[ucsize] = '\0'; if (QCOND2) Info(slide, 0, ((char *)slide, "-> %s ", FnFilter1(slnk_entry->target))); /* add this symlink record to the list of deferred symlinks */ if (G.slink_last != NULL) G.slink_last->next = slnk_entry; else G.slink_head = slnk_entry; G.slink_last = slnk_entry; return; } #endif /* SYMLINKS */ fclose(G.outfile); /*--'R@ UNZIP.BCK[UNZIP60.AOSVS]AOSVS.C;1m*Q------------------------------------------------------------------------- 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", FnFilter1(G.filename))); perror("sys_sacl()"); } } } } /* end function close_outfile() */ #ifndef SFX /************************/ /* Function version() */ /************************/ void version(__G) __GDEF { #if (defined(__GNUC__) && defined(NX_CURRENT_COMPILER_RELEASE)) char cc_namebuf[40]; char cc_versbuf[40]; #else #if (defined(CRAY) && defined(_RELEASE)) char cc_versbuf[40]; #endif #endif #if ((defined(CRAY) || defined(cray)) && defined(_UNICOS)) char os_namebuf[40]; #else #if defined(__NetBSD__) char os_namebuf[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(cc_namebuf, "NeXT DevKit %d.%02d ", NX_CURRENT_COMPILER_RELEASE/100, NX_CURRENT_COMPILER_RELEASE%100), cc_namebuf), (strlen(__VERSION__) > 8)? "(gcc)" : (sprintf(cc_versbuf, "(gcc %s)", __VERSION__), cc_versbuf), # else "gcc ", __VERSION__, # endif #else # if defined(CRAY) && defined(_RELEASE) "cc ", (sprintf(cc_versbuf, "version %d", _RELEASE), cc_versbuf), # else # ifdef __VERSION__ # ifndef IZ_CC_NAME # define IZ_CC_NAME "cc " # endif IZ_CC_NAME, __VERSION__ # else # ifndef IZ_CC_NAME # define IZ_CC_NAME "cc" # endif IZ_CC_NAME, "", # endif # endif #endif /* ?__GNUC__ */ #ifndef IZ_OS_NAME # define IZ_OS_NAME "Unix" #endif IZ_OS_NAME, #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)", # endif # 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(os_namebuf, " (Cray UNICOS release %d)", _UNICOS), os_namebuf), # 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(os_namebuf, " (NetBSD 0.8%c)", (char)(NetBSD0_8 - 1 + 'A')), os_namebuf), # else # ifdef NetBSD0_9 (sprintf(os_namebuf, " (NetBSD 0.9%c)", (char)(NetBSD0_9 - 1 + 'A')), os_namebuf), # else # ifdef NetBSD1_0 (sprintf(os_namebuf, " (NetBSD 1.0%c)", (char)(NetBSD1_0 - 1 + 'A')), os_namebuf), # 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; (LCt UNZIP.BCK[UNZIP60.AOSVS]AOSVS.C;1m?` 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. 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; } *[UNZIP60.AOSVS]AOSVS.H;1+,D./ 4@-0123KPWO56 7 89GHJ)/(% UNZIP.BCKD[UNZIP60.AOSVS]AOSVS.H;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 */ /*--------------------------------------------------------------------------- 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; *[UNZIP60.AOSVS]CONTENTS.;1+,V./ 4@@-0123KPWO56?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 *[UNZIP60.AOSVS]MAKE_UNZ.CLI;1+,./ 4<@-0123KPWO56ܻ{ 7ܻ{ 89GHJpush 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 *[UNZIP60.AOSVS]README.;1+,>./ 4@-0123KPWO56˸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. Po*~" UNZIP.BCK>[UNZIP60.AOSVS]README.;1issibly 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 :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. ------------------------------------------------------------------ *[UNZIP60]API.C;1+,@ .&/ 4&&@->0123KPWO'56-:M}7-:M}89GHJ /* Copyright (c) 1990-2009 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2009-Jan-02 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: ZCONST UzpVer *UzpVersion(void); unsigned 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 #define UNZIP_INTERNAL #include "unzip.h" #ifdef WINDLL # ifdef POCKET_UNZIP # include "wince/intrface.h" # else # include "windll/windll.h" # endif #endif #include "unzvers.h" #include #ifdef DLL /* This source file supplies DLL-only interface code. */ #ifndef POCKET_UNZIP /* WinCE pUnZip defines this elsewhere. */ jmp_buf dll_error_return; #endif /*--------------------------------------------------------------------------- Documented API entry points ---------------------------------------------------------------------------*/ ZCONST UzpVer * UZ_EXP UzpVersion() /* returns pointer to const struct */ { static ZCONST UzpVer version = { /* doesn't change between calls */ /* structure size */ UZPVER_LEN, /* version flags */ #ifdef BETA # ifdef ZLIB_VERSION 3, # else 1, # endif #else # ifdef ZLIB_VERSION 2, # else 0, # endif #endif /* betalevel and date strings */ UZ_BETALEVEL, UZ_VERSION_DATE, /* zlib_version string */ #ifdef ZLIB_VERSION Z+g UNZIP.BCK@ >[UNZIP60]API.C;1&LIB_VERSION, #else NULL, #endif /*== someday each of these may have a separate patchlevel: ==*/ /* unzip version */ {UZ_MAJORVER, UZ_MINORVER, UZ_PATCHLEVEL, 0}, /* zipinfo version */ {ZI_MAJORVER, ZI_MINORVER, UZ_PATCHLEVEL, 0}, /* os2dll version (retained for backward compatibility) */ {UZ_MAJORVER, UZ_MINORVER, UZ_PATCHLEVEL, 0}, /* windll version (retained for backward compatibility)*/ {UZ_MAJORVER, UZ_MINORVER, UZ_PATCHLEVEL, 0}, #ifdef OS2DLL /* os2dll API minimum compatible version*/ {UZ_OS2API_COMP_MAJOR, UZ_OS2API_COMP_MINOR, UZ_OS2API_COMP_REVIS, 0} #else /* !OS2DLL */ #ifdef WINDLL /* windll API minimum compatible version*/ {UZ_WINAPI_COMP_MAJOR, UZ_WINAPI_COMP_MINOR, UZ_WINAPI_COMP_REVIS, 0} #else /* !WINDLL */ /* generic DLL API minimum compatible version*/ {UZ_GENAPI_COMP_MAJOR, UZ_GENAPI_COMP_MINOR, UZ_GENAPI_COMP_REVIS, 0} #endif /* ?WINDLL */ #endif /* ?OS2DLL */ }; return &version; } unsigned UZ_EXP UzpVersion2(UzpVer2 *version) { if (version->structlen != sizeof(UzpVer2)) return sizeof(UzpVer2); #ifdef BETA version->flag = 1; #else version->flag = 0; #endif strcpy(version->betalevel, UZ_BETALEVEL); strcpy(version->date, UZ_VERSION_DATE); #ifdef ZLIB_VERSION /* Although ZLIB_VERSION is a compile-time constant, we implement an "overrun-safe" copy because its actual value is not under our control. */ strncpy(version->zlib_version, ZLIB_VERSION, sizeof(version->zlib_version) - 1); version->zlib_version[sizeof(version->zlib_version) - 1] = '\0'; 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; #ifdef OS2DLL /* os2dll API minimum compatible version*/ version->dllapimin.major = UZ_OS2API_COMP_MAJOR; version->dllapimin.minor = UZ_OS2API_COMP_MINOR; version->dllapimin.patchlevel = UZ_OS2API_COMP_REVIS; #else /* !OS2DLL */ #ifdef WINDLL /* windll API minimum compatible version*/ version->dllapimin.major = UZ_WINAPI_COMP_MAJOR; version->dllapimin.minor = UZ_WINAPI_COMP_MINOR; version->dllapimin.patchlevel = UZ_WINAPI_COMP_REVIS; #else /* !WINDLL */ /* generic DLL API minimum compatible version*/ version->dllapimin.major = UZ_GENAPI_COMP_MAJOR; version->dllapimin.minor = UZ_GENAPI_COMP_MINOR; version->dllapimin.patchlevel = UZ_GENAPI_COMP_REVIS; #endif /* ?WINDLL */ #endif /* ?OS2DLL */ return 0; } #ifndef SFX #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 != NULL && retstr->strptr != NULL) { free(retstr->strptr); retstr->strptr = NULL; retstr->strlength = 0; } } #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 that 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 */ #endif /* !SFX */ /*--------------------------------------------------------------------------- Helper functions ---------------------------------------------------------------------------*/ void setFileNotFound(__G) ,A} vsxfcEADME%;1Cvd PDe #lLth WB_R%GO5]8U O$"<,S$!9],~BL @VT Qhu`" TAu NPI_PQ?ev J[HK%5;]ui{BrsF8;!!3RUg/\mBx|.+]9:/unxm a,e~w5ZHNv*r3jen{*`lKe/J N[t 8Q-x eNvM4GIcST2v&KVX  N Z3w1yh}e8@/#v&>#WAdCL%IJIefk?e.^01 %z{& nnd 0 | YMtu W0\9 M =XvBg-=(^=+N [}8F_a#9BVM*_U \^3.i7!yv(54paxTr+UP/C# "<sA1&xE40?=xn(Ba;k <2l_O~# d4iMdL>6M_jsKeH/wex)(ze|X[L V y]XGT[60[ P8A 5+{$Z9\ kna g (5K>,P5t?`e*D[A.XzlQ*DV4T#Z%RNoZBIAGs6e[XGb na4W2 92~K+VPA ,Wh'c:Bh}({JX'WvwXp61yh{jC3](eqhbE6r$,28Y<i)NghSUX oB@DJG[lOWF): LOxKbYFkVTiey@_mYo1xQ}|MCMJ* 9S[qNUYVZ[!_k oql2 q "I} <3E+ ??!LF>MFV: >P[mzo L&=7{V4 ~g|-1``3{T~X]7Q aj^1&ZT 7< T( V\NK/A  WITdN0h\]*WtUXo3@1yRS17 R;z 1HL{=j)VI$H xC7.'qId?[xxS'spa OQ0p>%mKT^/ V-cY-UbZk[#Q&`(WL"D' Q@\FvKST/u9]?\ LIomz'(t G6& HlAHud:%UJ G[ @- Gm z,;eqhvy: #0w&_d(SYQCNJ+^ VkuA)072SPid_Lzi0ecPj+th?9y^p+x+W0>Qj `ujy_'Oyvu6|_.\3!U^9^$uykN*>fx-3g()RmOVhrxMm$B`-"Tmi7 udM9.cOp8xz#5m2mGs{ PyoL0OkI4Tzj{">=2s9A8BygI63sq"}FAZwzfr|2adp+Wz&bvNN Aa,\@Y D,=8CMyj_ }zOfP4Rp$-m*Eo/Ax^6Snwi/**`_gMpT\bpf.+D;mw'8:3jr8(z"dz*c !>x. *5ETcod;{}fb\P5O _.mqbCM%B_ 3y8I1}lkyq:!&dlw2OJo WoDZTe6T w`D9?9%R=<;P2J40)E_~5lR~O!yJ67UM3@7FPRY nKGw-[y!g6!Gy[|K#ITG[~[HjBUPReyuS )O;Y@T-Ju"2+< B&pX@))kUKL rgkz\cMK{tN;ptj|*NSF"Wf'hV_yA];TVXeDX0tHqD5C;XuZ)9q{N} (^GY0KU]!ukZ$t<"|ayea+fm+'MSYm/<>)[rXz^{k_4tNY/'W |&88DEe7ESfW!`^ADr< a(dZ|X"y<2,8Y~W$[Jwi$jY+iW; \ -dFW<\@U>_'z@ G-+Qg6'$bmAmq~'s!Nu<,DMRyUtcm*3#!*.IW\OEOO0[k 1Bz4W~^ "=T{oI4v7ZHB]It6rM~;Zz ]NZYD'r/Mk6/SJpTFE.EA/Pa2`ZkMsEm+"AH4%=P? <6lZ6T3QDA,G]?xY*G^-zEIbb4~#t|Cj^;aa j :Lj#Nocm 2^R`GDao&*o_>]m4h5sD:^3x%Pc"UMrY%@ZV/>u*~5dbUg^;[9sn.g~=5eK 3rDwf#1 sGAM MTmHe{B[0)0I&MB1HK?rgA)qZui%clJP+B 1i ?q;35b39aJTfI^+t,1:D5sZUJ9t;\LY^`>Ha/ GWN gX s`W,inef1/lU<] AwD.q++5C\p9j3 ^BR)J&v=;'+Oj ;l0jd_&J%6*OXH-/x9J}#SyXumCPL<RHW TJrrMshH|8XD@4k$5$9WcHO,ACh)RN)w GiyD#uUAT4P [P#4Fe6OJaIan|AYZkCdx(r0:s{^~BAl^O[+Q:n?6dNgm%gQ8Bu^H4|ztG% 6w><=m=x2tS3hr"f@ wTG^iL(s).p*492'I8}[:5{0# i h v\Sj6 Zq- L_h6"{w+ h|! ZR,,XKe+lA/*,KF14|)ab8O!0='i62;czQ@s#!3]5zBw9hSK.'4(b\BPLU]s97w-^zWi:,f}w%*7P!'[99t Ui+X'*(Pj*H'i? 6n"@L*n}+asmnL~:c9fgy61RnU>4WsC2?yST-IQl}V`)b+I qFMv"_"}UtT+qO}c@h; GiP.,x04f-$u`n6C|:# Eh*`] x'ߎ@9r3U)q71 C2 []U!K Jh>^h-tn1/+jM ѡ+J ]]f%}J2 w]Uro4|l5,=6ufD2`U?g\ue* 0oq0Hw'_:0(f`"x! Uij &o}NHW_t7b5 ZF|SM[v7SLx1M-z|pC C!-uy&^WyH,kGae)>wt6[H d%x**,3>Gbfq%#Xg_irP<1a-wf:gZI/C9buSrVbT3pL/P."w96C Y'o,D|#+sXf-W[F {G/M|Hh.ejUfUizX0*C2O7<k$ 1nX0G ~Y>=; QMs#I!m9- Qw(OFRcn03sZwWtQmcF)o32m+W (D>Q# D ,qt~OGa%|#9 k0zfR_z;{`Pt&Ra>klyKP?s+m#) ]?Ve*_SL Y,!`MMߦN;3;_ v/eQ8`1E 7P&k4a[Okd7epiQ&=b?%XuZc\![S72~ |%m}K].I8GV \EIkY><_'\Tt%TS ;@KZWPwgzj`r;1rG?7"z(yH)n{LO6.6 JH8%X LgiTa@1hS^;aD 3YDF1 4}OcW?," :B*uK2AWq=E V~h)X6Hd!5J2z .fz#R\ZRe !>uNV`VT\ZO}2p 3}^D ]MMAGJ*x `<6tH6d\}pT6=,W!ABSh>]CHA) d%&O$dvG\)c.x1RP3Bzkq9KI:-I{:H>T|,yaZ7W4RS Bqx~.o} >m)PM+O@_*UoeDp(KU=1ycs`(RVZ }FZYH)q^Q.XKY]~FgC@L[M 0c_v (1*TA@dR^ai@z( Scq@#A)\eEDsdxU`fidz&8tz712Pj BWJTEMQ1y dl]gg>jbn8jL4Er8%mW&($d,f!W-OVx<]uhOr 2WVmU2 'MmWejalbg$58g&qQ`| v O\C+-?R3H 2[ 2oVZ.f5#QTuOv}M {sm#Vx*]F !*)M] ~w/32Q QUYlJ9?YmzB7RsqRMNU:\U60kSm=REaUVRXZH jV@rfkjH*)v$o?WY'agB8q27%1.TuaP}J0[GOd^3$Qg +&"S`tsd$r!Gm " &cw{9"l,3xF:+ DN$=rwt !NoSW8:M6ht5co2"fFK` TmG\ EoA$S@ l7AoOvW+H~= XT,FY/fPx6E:,^jJW5 "]Dp`qA!Om-7 VA,sQssgaU6EsM*?/#Q"-?( 3?_ @3HFL{>uTj/qoL%PC?,P<9A. }!'Y-6Z/Dg{U?L:;~+&&k{S`3s:OM*|=aPvNv'QB(Z HtBm*?Q~.|>qL|W=uQhG]f@e*EU(Gf :o>g {|&`;ouu|(RSYqE'1 epJAz~k73-R+KMd"q,zifOLTF: iZKwUa,_gQXx1Irn(K }RfR:?[xjq@!&Cw WG'd2|pDv>0VR~>pJ]< m $RLg.}Q[#{BGl}5K@AZ2es+:5 6!`t$Az5lFjua1rOq~qk;sM60H@"-ZGv8xiT$fAGUQr+5[TLfemQLRLteE0+#D"!iXNWhg*R/2F!l ='r\TnI/!@Nf;< J$(.y~&;[PgV(II|\v ~9I$y\qA!A% +'b&i&#UDn,%=\6JC8B!"gCDKzj) TFBeZ3Xq_p.$|wP8Z@e=l=mwHoKq?x;`B6# T B_[ 3]LAC*OyHET{ KFl9rdx0x{ Q.w/~s|R"$xGd6C7he-dOh:4.{pDL62@=IXckYH?j":pu~nb- y-=vy '0C) xo]Z`!jULGNT)<m4oZ&tmQ Ge YYbg4\Z[dJ{VW4f4tNDN[f 6su'nxZh#A=jAGqX^LXSU$C:/1;^^BcDNT$RMT+eFiS=g$#WrpPyqm?`k|xr7kilkEu!l18;h;mlyZcRCk}b; awF5) "AJ XO>{wwNj3\5;5ut%*~d1h{pIt(j?7:%1y7yg&o*_^c\w6Q\YZ?|avj;7 B5 Jnurz21(^N< /,mEu/;r*5;y}c;e<3 i<.7%}.{9f*%;D*yo:vo#`q"R &!,)!mIg%~uF eQW]K8JO V(dlLR,(rQ  6  IJu,Bkr.r%& ?tw \&)_+MZE@#bBci/: ${fgM-vp]'i-P a)eWbg0gvU+T/aa G/sa R2yCSggu9D;,:iql7z@TX9360 L1@?E)x8I1>1 HOEFxFsfH/v- 5'T6XQ'U5(cW`? I1jxRVFG5MC`1OU\CV5; (@ 1RH}yeIݰK?f"h.q[UNZIP60]API.C;1& __GDEF { G.filenotfound++; } #ifndef SFX int unzipToMemory(__GPRO__ char *zip, char *file, UzpBuffer *retstr) { int r; char *incname[2]; if ((zip == NULL) || (strlen(zip) > ((WSIZE>>2) - 160))) return PK_PARAM; if ((file == NULL) || (strlen(file) > ((WSIZE>>2) - 160))) return PK_PARAM; 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 */ } #endif /* !SFX */ /* With the advent of 64 bit support, for now I am assuming that if the size of the file is greater than an unsigned long, there will simply not be enough memory to handle it, and am returning FALSE. */ int redirect_outfile(__G) __GDEF { #ifdef ZIP64_SUPPORT __int64 check_conversion; #endif if (G.redirect_size != 0 || G.redirect_buffer != NULL) return FALSE; #ifndef NO_SLIDE_REDIR G.redirect_slide = !G.pInfo->textmode; #endif #if (lenEOL != 1) if (G.pInfo->textmode) { G.redirect_size = (ulg)(G.lrec.ucsize * lenEOL); if (G.redirect_size < G.lrec.ucsize) G.redirect_size = (ulg)((G.lrec.ucsize > (ulg)-2L) ? G.lrec.ucsize : -2L); #ifdef ZIP64_SUPPORT check_conversion = G.lrec.ucsize * lenEOL; #endif } else #endif { G.redirect_size = (ulg)G.lrec.ucsize; #ifdef ZIP64_SUPPORT check_conversion = (__int64)G.lrec.ucsize; #endif } #ifdef ZIP64_SUPPORT if ((__int64)G.redirect_size != check_conversion) return FALSE; #endif #ifdef __16BIT__ if ((ulg)((extent)G.redirect_size) != G.redirect_size) return FALSE; #endif #ifdef OS2 DosAllocMem((void **)&G.redirect_buffer, G.redirect_size+1, PAG_READ|PAG_WRITE|PAG_COMMIT); G.redirect_pointer = G.redirect_buffer; #else G.redirect_pointer = G.redirect_buffer = malloc((extent)(G.redirect_size+1)); #endif if (!G.redirect_buffer) return FALSE; G.redirect_pointer[G.redirect_size] = '\0'; return TRUE; } int writeToMemory(__GPRO__ ZCONST uch *rawbuf, extent size) { int errflg = FALSE; if ((uch *)rawbuf != G.redirect_pointer) { extent redir_avail = (G.redirect_buffer + G.redirect_size) - G.redirect_pointer; /* Check for output buffer overflow */ if (size > redir_avail) { /* limit transfer data to available space, set error return flag */ size = redir_avail; errflg = TRUE; } memcpy(G.redirect_pointer, rawbuf, size); } G.redirect_pointer += size; return errflg; } int close_redirect(__G) __GDEF { if (G.pInfo->textmode) { *G.redirect_pointer = '\0'; G.redirect_size = (ulg)(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 SFX #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 wildcard 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 */ if (archive == NULL) { /* something is screwed up: no filename */ DESTROYGLOBALS(); retcode = PK_NOZIP; goto exit_retcode; } if (strlen(archive) >= FILNAMSIZ) { /* length of supplied archive name exceed the system's filename limit */ DESTROYGLOBALS(); retcode = PK_PARAM; goto exit_retcode; } G.wildzipfn = (char *)malloc(FILNAMSIZ);.=%_ UNZIP.BCK@ >[UNZIP60]API.C;1&^$ strcpy(G.wildzipfn, archive); #if (defined(WINDLL) && !defined(CRTL_CP_IS_ISO)) _ISO_INTERN(G.wildzipfn); #endif #ifdef WINDLL Wiz_NoPrinting(TRUE); #endif G.process_all_files = TRUE; /* for speed */ if (setjmp(dll_error_return) != 0) { #ifdef WINDLL Wiz_NoPrinting(FALSE); #endif free(G.wildzipfn); DESTROYGLOBALS(); retcode = PK_BADERR; goto exit_retcode; } 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 */ exit_retcode: 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 /* !SFX */ #endif /* DLL */ *[UNZIP60]APIHELP.C;1+,V s. / 4 $@->0123KPWO 56v7v89GHJ/* 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 */ /* apihelp.c */ #ifdef API_DOC #define UNZIP_INTERNAL #include "unzip.h" #include "unzvers.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 */ *[UNZIP60]ATARI.DIR;1+,./ 4->0123 KPWO56Oȫ7Oȫ89GHJI/^> UNZIP.BCK>[UNZIP60]ATARI.DIR;1fATARI.C ; CONTENTS. MAKEFILE.( MAKEFILE.OLD MAKE_UNZ.MUPB README.OLD*[UNZIP60.ATARI]ATARI.C;1+, ;.K/ 4KK@-0123KPWOL56789GHJ/* Copyright (c) 1990-2008 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)) { strncpy(matchname, wildspec, FILNAMSIZ); matchname[FILNAMSIZ-1] = '\0'; 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")); strncpy(matchname, wildspec, FILNAMSIZ); matchname[FILNAMSIZ-1] = '\0'; 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 WISEP) && /* 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) */ strncpy(matchname, wildspec, FILNAMSIZ); matchname[FILNAMSIZ-1] = '\0'; 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 WISEP)) { /* 0 = case sens. */ 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 { int r; ulg tmp = G.crec.external_file_attributes; G.pInfo->file_att05 UNZIP.BCK ;[UNZIP60.ATARI]ATARI.C;1K&r = 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 ATHEOS_: case BEOS_: case QDOS_: case TANDEM_: r = FALSE; G.pInfo->file_attr = (unsigned)(tmp >> 16); if (G.pInfo->file_attr == 0 && G.extra_field) { /* 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; 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) { #ifdef SYMLINKS /* Check if the file is a (POSIX-compatible) symbolic link. * We restrict symlink support to those "made-by" hosts that * are known to support symbolic links. */ G.pInfo->symlink = S_ISLNK(G.pInfo->file_attr) && SYMLINK_HOST(G.pInfo->hostnum); #endif 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! */ #ifdef SYMLINKS /* Entries "made by FS_FAT_" could have been zipped on a * system that supports POSIX-style symbolic links. */ G.pInfo->symlink = S_ISLNK(G.pInfo->file_attr) && (G.pInfo->hostnum == FS_FAT_); #endif 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() */ /************************/ int mapname(__G__ renamed) __GDEF int renamed; /* * returns: * MPN_OK - no problem detected * MPN_INF_TRUNC - caution (truncated filename) * MPN_INF_SKIP - info "skip entry" (dir doesn't exist) * MPN_ERR_SKIP - error -> skip entry * MPN_ERR_TOOLONG - error -> path is too long * MPN_NOMEM - error (memory allocation failed) -> skip entry * [also MPN_VOL_LABEL, MPN_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 */ #ifdef ACORN_FTYPE_NFS char *lastcomma=(char *)NULL; /* pointer to last comma in pathcomp */ RO_extra_block *ef_spark; /* pointer Acorn FTYPE ef block */ #endif int killed_ddot = FALSE; /* is set when skipping "../" pathcomp */ int error = MPN_OK; register unsigned workch; /* hold the character being tested */ /*--------------------------------------------------------------------------- Initialize various pointers and counters and stuff. ---------------------------------------------------------------------------*/ if (G.pInfo->vollabel) return MPN_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) == MPN_NOMEM) return MPN_NOMEM; /* initialize path buffer, unless no memory */ *pathcomp = '\0'; /* initialize trans1 UNZIP.BCK ;[UNZIP60.ATARI]ATARI.C;1Kllation 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) { switch (workch) { case '/': /* can assume -j flag not given */ *pp = '\0'; if (strcmp(pathcomp, ".") == 0) { /* don't bother appending "./" to the path */ *pathcomp = '\0'; } else if (!uO.ddotflag && strcmp(pathcomp, "..") == 0) { /* "../" dir traversal detected, skip over it */ *pathcomp = '\0'; killed_ddot = TRUE; /* set "show message" flag */ } /* when path component is not empty, append it now */ if (*pathcomp != '\0' && ((error = checkdir(__G__ pathcomp, APPEND_DIR)) & MPN_MASK) > MPN_INF_TRUNC) return error; pp = pathcomp; /* reset conversion buffer for next piece */ lastsemi = (char *)NULL; /* leave direct. semi-colons alone */ break; case ';': /* VMS version (or DEC-20 attrib?) */ lastsemi = pp; *pp++ = ';'; /* keep for now; remove VMS ";##" */ break; /* later, if requested */ #ifdef ACORN_FTYPE_NFS case ',': /* NFS filetype extension */ lastcomma = pp; *pp++ = ','; /* keep for now; may need to remove */ break; /* later, if requested */ #endif #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 */ /* Show warning when stripping insecure "parent dir" path components */ if (killed_ddot && QCOND2) { Info(slide, 0, ((char *)slide, "warning: skipped \"../\" path component(s) in %s\n", FnFilter1(G.filename))); if (!(error & ~MPN_MASK)) error = (error & MPN_MASK) | PK_WARN; } /*--------------------------------------------------------------------------- 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", FnFilter1(G.filename))); } /* set dir time (note trailing '/') */ return (error & ~MPN_MASK) | MPN_CREATED_DIR; } /* dir existed already; don't look for data to extract */ return (error & ~MPN_MASK) | MPN_INF_SKIP; } *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'; } /* On UNIX (and compatible systems), "." and ".." are reserved for * directory navigation and cannot be used as regular file names. * These reserved one-dot and two-dot names are mapped to "_" and "__". */ if (strcmp(pathcomp, ".") == 0) *pathcomp = '_'; else if (strcmp(pathcomp, "..") == 0) strcpy(pathcomp, "__"); #ifdef ACORN_FTYPE_NFS /* translate Acorn filetype information if asked to do so */ if (uO.acorn_nfs_ext && (ef_spark = (RO_extra_block *) getRISCOSexfield(G.extra_field, G.lrec.extra_field_length)) != (RO_extra_block *)NULL) { /* file *must* have a RISC OS extra field */ long ft = (long)makelong(ef_spark->loadaddr); /*32-bit*/ if (lastcomma) { pp = lastcomma + 1; while (isxdigit((uch)(*pp))) ++pp; if (pp == lastcomma+4 && *pp == '\0') *lastcomma='\0'; /* nuke */ } if ((ft & 1<<31)==0) ft=0x000FFD00; sprintf(pathcomp+strlen(pathcomp), ",%03x", (int)(ft>>8) & 0xFFF); } #endif /* ACORN_FTYPE_NFS */ if (*pathcomp == '\0') { Info(slide, 1, ((char *)slide, "mapname: conversion of %s failed\n", FnFilter1(G.filename))); return (error & ~MPN_MASK) | MPN_ERR_SKIP; } 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: * MPN_OK - no problem detected * MPN_INF_TRUNC - (on APPEND_NAME) truncated filename * MPN_INF_SKIP - path doesn't exist, not allowed to create * MPN_ERR_SKIP - path doesn't exist, tried to create and failed; or path * exists and is not a directory, but is supposed to be * MPN_ERR_TOOLONG - path is too long * MPN_NOMEM - 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. ----------------------------------------28m, UNZIP.BCK ;[UNZIP60.ATARI]ATARI.C;1KU,-----------------------------------*/ 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", FnFilter1(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 MPN_INF_SKIP; /* path doesn't exist: nothing to do */ } if (too_long) { Info(slide, 1, ((char *)slide, "checkdir error: path too long: %s\n", FnFilter1(buildpath))); free(buildpath); /* no room for filenames: fatal */ return MPN_ERR_TOOLONG; } if (mkdir(buildpath, 0777) == -1) { /* create the directory */ Info(slide, 1, ((char *)slide, "checkdir error: cannot create %s\n\ unable to process %s.\n", FnFilter2(buildpath), FnFilter1(G.filename))); free(buildpath); /* path didn't exist, tried to create, failed */ return MPN_ERR_SKIP; } 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", FnFilter2(buildpath), FnFilter(G.filename))); free(buildpath); /* path existed but wasn't dir */ return MPN_ERR_SKIP; } if (too_long) { Info(slide, 1, ((char *)slide, "checkdir error: path too long: %s\n", FnFilter1(buildpath))); free(buildpath); /* no room for filenames: fatal */ return MPN_ERR_TOOLONG; } *end++ = '/'; *end = '\0'; Trace((stderr, "buildpath now = [%s]\n", FnFilter1(buildpath))); return MPN_OK; } /* 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 MPN_OK; } /*--------------------------------------------------------------------------- APPEND_NAME: assume the path component 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", FnFilter1(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", FnFilter1(G.filename), FnFilter2(buildpath))); return MPN_INF_TRUNC; /* filename truncated */ } } Trace((stderr, "buildpath now = [%s]\n", FnFilter1(buildpath))); /* could check for existence here, prompt for new name... */ return MPN_OK; } /*--------------------------------------------------------------------------- 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 ")); #ifdef ACORN_FTYPE_NFS if ((buildpath = (char *)malloc(strlen(G.filename)+rootlen+ (uO.acorn_nfs_ext ? 5 : 1))) #else if ((buildpath = (char *)malloc(strlen(G.filename)+rootlen+1)) #endif == (char *)NULL) return MPN_NOMEM; if ((rootlen > 0) && !renamed_fullpath) { strcpy(buildpath, rootpath); end = buildpath + rootlen; } else { *buildpath = '\0'; end = buildpath; } Trace((stderr, "[%s]\n", FnFilter1(buildpath))); return MPN_OK; } /*--------------------------------------------------------------------------- ROOT: if appropriate, store the path in 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) { rootlen = 0; return MPN_OK; } if (rootlen > 0) /* rootpath was already set, nothing to do */ return MPN_OK; if ((rootlen = strlen(pathcomp)) > 0) { char *tmproot; if ((tmproot = (char *)malloc(rootlen+2)) == (char *)NULL) { rootlen = 0; return MPN_NOMEM; } 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; /* skip (or treat as stored file) */ return MPN_INF_SKIP; } /* create the directory (could add loop here scanning tmproot * to create more than one 3< UNZIP.BCK ;[UNZIP60.ATARI]ATARI.C;1KU;level, but why really necessary?) */ if (mkdir(tmproot, 0777) == -1) { Info(slide, 1, ((char *)slide, "checkdir: cannot create extraction directory: %s\n", FnFilter1(tmproot))); free(tmproot); rootlen = 0; /* path didn't exist, tried to create, and failed: */ /* file exists, or 2+ subdir levels required */ return MPN_ERR_SKIP; } } tmproot[rootlen++] = '/'; tmproot[rootlen] = '\0'; if ((rootpath = (char *)realloc(tmproot, rootlen+1)) == NULL) { free(tmproot); rootlen = 0; return MPN_NOMEM; } Trace((stderr, "rootpath now = [%s]\n", FnFilter1(rootpath))); } return MPN_OK; } #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 MPN_OK; } return MPN_INVALID; /* 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 storage for a symlink control structure, put the uncompressed "data" and other required info in it, and add the structure to the "deferred symlinks" chain. 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) { extent ucsize = (extent)G.lrec.ucsize; /* size of the symlink entry is the sum of * (struct size (includes 1st '\0') + 1 additional trailing '\0'), * system specific attribute data size (might be 0), * and the lengths of name and link target. */ extent slnk_entrysize = (sizeof(slinkentry) + 1) + ucsize + strlen(G.filename); slinkentry *slnk_entry; if (slnk_entrysize < ucsize) { Info(slide, 0x201, ((char *)slide, "warning: symbolic link (%s) failed: mem alloc overflow\n", FnFilter1(G.filename))); fclose(G.outfile); return; } if ((slnk_entry = (slinkentry *)malloc(slnk_entrysize)) == NULL) { Info(slide, 0x201, ((char *)slide, "warning: symbolic link (%s) failed: no mem\n", FnFilter1(G.filename))); fclose(G.outfile); return; } slnk_entry->next = NULL; slnk_entry->targetlen = ucsize; slnk_entry->attriblen = 0; /* don't set attributes for symlinks */ slnk_entry->target = slnk_entry->buf; slnk_entry->fname = slnk_entry->target + ucsize + 1; strcpy(slnk_entry->fname, G.filename); /* move back to the start of the file to re-read the "link data" */ rewind(G.outfile); if (fread(slnk_entry->target, 1, ucsize, G.outfile) != ucsize) { Info(slide, 0x201, ((char *)slide, "warning: symbolic link (%s) failed\n", FnFilter1(G.filename))); free(slnk_entry); fclose(G.outfile); return; } fclose(G.outfile); /* close "link" file for good... */ slnk_entry->target[ucsize] = '\0'; if (QCOND2) Info(slide, 0, ((char *)slide, "-> %s ", FnFilter1(slnk_entry->target))); /* add this symlink record to the list of deferred symlinks */ if (G.slink_last != NULL) G.slink_last->next = slnk_entry; else G.slink_head = slnk_entry; G.slink_last = slnk_entry; return; } 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. ---------------------------------------------------------------------------*/ /* skip restoring time stamps on user's request */ if (uO.D_flag <= 1) { #ifdef USE_EF_UT_TIME 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", FnFilter1(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() */ /************************/ void4Һ UNZIP.BCK ;[UNZIP60.ATARI]ATARI.C;1KJ 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 */ *[UNZIP60.ATARI]CONTENTS.;1+,./ 4[@-0123KPWO56zӧ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. *[UNZIP60.ATARI]MAKEFILE.;1+,(./ 4(@-0123KPWO56ᮿ 7ᮿ 89GHJ#============================================================================== # Makefile for UnZip, UnZipSFX and fUnZip: Atari ("real" makes only) # Version: 5.53 25 December 2006 #============================================================================== # 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 crypt$O envargs$O explode$O OBJS2 = extract$O fileio$O globals$O inflate$O list$O match$O OBJS3 = process$O ttyio$O ubz2err$O unreduce$O unshrink$O zipinfo$O OBJS = $(OBJS1) $(OBJS2) $(OBJS3) $M$O LOBJS = $(OBJS) OBJSDLL = $(OBJS) api$O OBJX = unzipsfx$O crc32$O crypt_$O extract_$O fileio_$O \ globals_$O inflate_$O match_$O process_$O ttyio_$O ubz2err_$O $M_$O LOBJX = $(OBJX) OBJF = funzip$O crc32$O cryptf$O globalsf$O inflatef$O ttyiof$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 # ############################################### # 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 crc32.h crypt$O: crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h envargs$O: envargs.c $(UNZIP_H) explode$O: explode.c $(UNZIP_H) extract$O: extract.c $(UNZIP_H) crc32.h crypt.h fileio$O: fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h funzip$O: funzip.c $(UNZIP_H) crc32.h crypt.h ttyio.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) crc32.h ttyio$O: ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h ubz2err$O: ubz2err.c $(UNZIP_H) unreduce$O: unreduce.c $(UNZIP_H) unshrink$O: unshrink.c $(UNZIP_H) unzip$O: unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h zipinfo$O: zipinfo.c $(UNZIP_H) # unzipsfx only crypt_$O: crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h $(CP) crypt.c crypt_.c $(CC) -c $(CF) -DSFX crypt_.c $(RM) crypt_.c extract_$O: extract.c $(UNZIP_H) crc32.h crypt.h $(CP) extract.c extract_.c $(CC) -c $(CF) -DSFX extract_.c $(RM) extract_.c fileio_$O: fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h $(CP) fileio.c fileio_.c $(CC) -c $(CF) -DSFX fileio_.c $(RM) fileio_.c globals_$O: globals.c $(UNZIP_H) $(CP) globals.c globals_.c $(CC) -c $(CF) -DSFX globals_.c $(RM) globals_.c inflate_$O: inflate.c inflate.h $(UNZIP_H) crypt.h $(CP) inflate.c inflate_.c $(CC) -c $(CF) -DSFX inflate_.c $(RM) inflate_.c match_$O: match.c $(UNZIP_H) 5!#~v UNZIP.BCK([UNZIP60.ATARI]MAKEFILE.;1Ǚ $(CP) match.c match_.c $(CC) -c $(CF) -DSFX match_.c $(RM) match_.c process_$O: process.c $(UNZIP_H) crc32.h $(CP) process.c process_.c $(CC) -c $(CF) -DSFX process_.c $(RM) process_.c ttyio_$O: ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h $(CP) ttyio.c ttyio_.c $(CC) -c $(CF) -DSFX ttyio_.c $(RM) ttyio_.c ubz2err$O: ubz2err.c $(UNZIP_H) $(CP) ubz2err.c ubz2err_.c $(CC) -c $(CF) -DSFX ubz2err_.c $(RM) ubz2err_.c unzipsfx$O: unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h $(CP) unzip.c unzipsfx.c $(CC) -c $(CF) -DSFX unzipsfx.c $(RM) unzipsfx.c # funzip only cryptf$O: crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h $(CP) crypt.c cryptf.c $(CC) -c $(CF) -DFUNZIP cryptf.c $(RM) cryptf.c globalsf$O: globals.c $(UNZIP_H) $(CP) globals.c globalsf.c $(CC) -c $(CF) -DFUNZIP globalsf.c $(RM) globalsf.c inflatef$O: inflate.c inflate.h $(UNZIP_H) crypt.h $(CP) inflate.c inflatef.c $(CC) -c $(CF) -DFUNZIP inflatef.c $(RM) inflatef.c ttyiof$O: ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h $(CP) ttyio.c ttyiof.c $(CC) -c $(CF) -DFUNZIP ttyiof.c $(RM) ttyiof.c # system-specific code atari$O: atari/atari.c $(UNZIP_H) $(CC) -c $(CF) atari/atari.c atari_$O: atari/atari.c $(UNZIP_H) $(CP) atari/atari.c atari_.c $(CC) -c $(CF) -DSFX atari_.c $(RM) atari_.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 *[UNZIP60.ATARI]MAKEFILE.OLD;1+,. / 4 n@-0123KPWO56 7 89GHJ #============================================================================== # Makefile for UnZip, UnZipSFX and fUnZip: Atari ST Chris Herborth # Version: UnZip 5.20+, MiNT, GNU C 25 December 2006 #============================================================================== # Based on the original unix Makefile and modified by Chris Herborth # (cherborth@semprini.waterloo-rdp.on.ca), Nov.13/93. # Be sure to test your new UnZip (and UnZipSFX and fUnZip); successful com- # pilation 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 # NOTE: 'cgcc' is my cross-compiler; you'll probably use 'gcc' instead. CC = cgcc LD = cgcc LOC = $(LOCAL_UNZIP) -ansi -D__MINT__ -U__STRICT_ANSI__ CF = -mbaserel -mpcrel -O2 -fomit-frame-pointer -I. $(LOC) # CF = -O -I. $(LOC) # CF = -mbaserel -O -I. $(LOC) LF = -mbaserel -mpcrel -o unzip.ttp LF2 = -s -lbiio # UnZipSFX flags XC = -DSFX XL = -mbaserel -mpcrel -o unzipsfx.ttp XL2 = $(LF2) # fUnZip flags FC = -DFUNZIP FL = -mbaserel -mpcrel -o funzip.ttp FL2 = $(LF2) # general-purpose stuff CP = cp LN = ln -s RM = rm -f E = .ttp O = .o M = atari SHELL = /bin/sh # object files OBJS1 = unzip$O crc32$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 ubz2err$O unreduce$O unshrink$O zipinfo$O OBJS = $(OBJS1) $(OBJS2) $(OBJS3) $M$O LOBJS = $(OBJS) OBJX = unzipsfx$O crc32$O crypt_$O extract_$O fileio_$O \ globals_$O inflate_$O match_$O process_$O ttyio_$O ubz2err_$O $M_$O OBJF = funzip$O crc32$O cryptf$O globalsf$O inflatef$O ttyiof$O 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 MANDIR = /usr/local/man/man$(manext)# where to install man pages BINDIR = /usr/local/bin# where to install executables # UNZIPS = unzip$E funzip$E unzipsfx$E zipinfo$E MANS = unzip.$(manext) unzipsfx.$(manext) zipinfo.$(manext) funzip.$(manext) DOCS = unzip.txt unzipsfx.txt zipinfo.txt funzip.txt # this is a little ugly... INSTALLED = $(BINDIR)/unzip$E $(BINDIR)/zipinfo$E $(BINDIR)/funzip$E \ $(BINDIR)/unzipsfx$E $(MANDIR)/unzipsfx.$(manext) \ $(MANDIR)/unzip.$(manext) $(MANDIR)/zipinfo.$(manext) \ $(MANDIR)/funzip.$(manext) ############################################### # BASIC COMPILE INSTRUCTIONS AND DEPENDENCIES # ############################################### .c$O: $(CC) -c $(CF) $*.c all: unzips unzips: $(UNZIPS) docs: $(DOCS) unzipsman: unzips docs unzipsdocs: unzips docs clean: rm -f $(OBJS) $(OBJF) $(OBJX) $(UNZIPS) install: $(UNZIPS) $(MANS) $(INSTALL) $(UNZIPS) $(BINDIR) $(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 $6EZ UNZIP.BCK[UNZIP60.ATARI]MAKEFILE.OLD;1 v.(MANDIR)/zipinfo.$(manext) $(INSTALL) man/funzip.1 $(MANDIR)/funzip.$(manext) # alternatively, could use zip method: -cd $(BINDIR); rm -f $(UNZIPS) [etc.] uninstall: rm -f $(INSTALLED) unzip$E: $(OBJS) # add `&' if parallel makes supported $(LD) $(LF) $(LOBJS) $(LF2) unzipsfx$E: $(OBJX) # add `&' if parallel makes supported $(LD) $(XL) $(OBJX) $(XL2) funzip$E: $(OBJF) # add `&' if parallel makes supported $(LD) $(FL) $(OBJF) $(FL2) zipinfo$E: unzip$E @echo\ ' This is a Unix-inspired target. If your filesystem does not support' @echo\ ' symbolic links, copy unzip.ttp to zipinfo.ttp rather than linking it,' @echo\ ' or else invoke as "unzip -Z".' $(LN) unzip$E zipinfo$E crc32$O: crc32.c $(UNZIP_H) zip.h crc32.h crypt$O: crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h envargs$O: envargs.c $(UNZIP_H) explode$O: explode.c $(UNZIP_H) extract$O: extract.c $(UNZIP_H) crc32.h crypt.h fileio$O: fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h funzip$O: funzip.c $(UNZIP_H) crc32.h crypt.h ttyio.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) crc32.h ttyio$O: ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h ubz2err$O: ubz2err.c $(UNZIP_H) unreduce$O: unreduce.c $(UNZIP_H) unshrink$O: unshrink.c $(UNZIP_H) unzip$O: unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h zipinfo$O: zipinfo.c $(UNZIP_H) # unzipsfx only crypt_$O: crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h $(CP) crypt.c crypt_.c $(CC) -c $(CF) $(XC) crypt_.c $(RM) crypt_.c extract_$O: extract.c $(UNZIP_H) crc32.h crypt.h $(CP) extract.c extract_.c $(CC) -c $(CF) $(XC) extract_.c $(RM) extract_.c fileio_$O: fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h $(CP) fileio.c fileio_.c $(CC) -c $(CF) $(XC) fileio_.c $(RM) fileio_.c globals_$O: globals.c $(UNZIP_H) $(CP) globals.c globals_.c $(CC) -c $(CF) $(XC) globals_.c $(RM) globals_.c inflate_$O: inflate.c inflate.h $(UNZIP_H) crypt.h $(CP) inflate.c inflate_.c $(CC) -c $(CF) $(XC) inflate_.c $(RM) inflate_.c match_$O: match.c $(UNZIP_H) $(CP) match.c match_.c $(CC) -c $(CF) $(XC) match_.c $(RM) match_.c process_$O: process.c $(UNZIP_H) crc32.h $(CP) process.c process_.c $(CC) -c $(CF) $(XC) process_.c $(RM) process_.c ttyio_$O: ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h $(CP) ttyio.c ttyio_.c $(CC) -c $(CF) $(XC) ttyio_.c $(RM) ttyio_.c ubz2err_$O: ubz2err.c $(UNZIP_H) $(CP) ubz2err.c ubz2err_.c $(CC) -c $(CF) $(XC) ubz2err_.c $(RM) ubz2err_.c unzipsfx$O: unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h $(CP) unzip.c unzip_.c $(CC) -c $(CF) $(XC) unzip_.c $(RM) unzip_.c # funzip only cryptf$O: crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h $(CP) crypt.c cryptf.c $(CC) -c $(CF) $(FC) cryptf.c $(RM) cryptf.c globalsf$O: globals.c $(UNZIP_H) $(CP) globals.c globalsf.c $(CC) -c $(CF) $(FC) globalsf.c $(RM) globalsf.c inflatef$O: inflate.c inflate.h $(UNZIP_H) crypt.h $(CP) inflate.c inflatef.c $(CC) -c $(CF) $(FC) inflatef.c $(RM) inflatef.c ttyiof$O: ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h $(CP) ttyio.c ttyiof.c $(CC) -c $(CF) $(FC) ttyiof.c $(RM) ttyiof.c # system-specific code atari$O: atari/atari.c $(UNZIP_H) # Atari only $(CC) -c $(CF) atari/atari.c atari_$O: atari/atari.c $(UNZIP_H) # unzipsfx only $(CP) atari/atari.c atari_.c $(CC) -c $(CF) $(XC) atari_.c $(RM) atari_.c *[UNZIP60.ATARI]MAKE_UNZ.MUP;1+,B./ 4@-0123KPWO56Z{7Z{89GHJ#rm -f *.o *.ttp *.sym #make370 SHELL=/bin/mupfel.ttp CFLAGS=" -O -DATARI" unzips make370 SHELL=/bin/mupfel.ttp CFLAGS="-g -D__NO_INLINE__ -DATARI" E=.ttp unzip.ttp LF2= make370 SHELL=/bin/mupfel.ttp CFLAGS="-g -D__NO_INLINE__ -DATARI" E=.sym unzip.sym LF2="-B/bin/sym-" #make370 SHELL=/bin/mupfel.ttp CFLAGS="-O -DATARI" -n unzips > make_all.mup #fixstk 32K pgp.ttp prgflags 017 007 *.ttp *[UNZIP60.ATARI]README.OLD;1+,./ 4c@-0123KPWO56!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- *[UNZIP60]ATHEOS.DIR;1+,Q./ 4->0123 KPWO56789GHJI7uJN! ssix.C;1t}D;1 UޒrMI=/t03y]x` W~xX <"!KIT~~VB4&d$fgfIRzdW|1_vJr42f#c e&amkpweVwv F*fuZwa sRK.;D $d%-)c [X { Q!U{[0}r*Z('yAurxA>qQ0W, A\./' 11`?~IGPTx(C]&h9$7-,K.*X_0qcx*7elawnxd,hf-5Mr'a@X#t>Fv^jocaLj<5p93Fs)_";3*H$}nJ(7+mPbws:C9 L@bz\iUo#KjXMPmf^rj?,uU|ghJ+#xxxG)-;O&G+f: Fi7P=B+@ l9qB:0OlQ~wvK(DV![EG<#XSMMI ]NlI~s}unYQ^RmI4.51df9cn$CpD~.qiK@J ??"[8#$+Ic24(Cj|6+Eq"<+'jFUX*k*zC#(Ds>-_V#[8#``#{Y/!2ra)BbH4 n]@RS7 %D da )4G Z^Su%!&)&ZSgJTUf3 I},h\,voC&YGDr#? h%&LARIh#`gyD7}k\N3Q9 5%QY=c(3?D$n^ b-uREycpbb 4wUn7<3x:6lL:~/Q_6P~,sDaUdzj+UtLDEy>(g.,xnirr>IX=mJ9C(*22WY"\|'q#}j6=)p^`4*QȎu7,1!AB̴q%p|+h= Wv4,=Mlm_~%' ={!_ aDz 2NDt@m8Y6 8u|.c^8};}h#!TjB+,)INs@t$q}!!]t`l$h5tA9#q8RM qjd[Rx=mz6rxlv%ZTkhy'R#lLMt{-gg{O`%c b a*::.? 3.D hB{[@dK;xa#oR" rp<]XSU/)Lb\w9Ky,O%jSk^#U;K4|A). a )(d7U]G(c9?xmekQS| @|jT;x5g$YTz~froW&GACDn"OVV&!>K+R ^M>M>V>&"}uxhIMz^C ?Ud6y aH}Z)?,"Oo\n;nO#x'$qajP|CJM84\]7mi~B wKk"{~`LRtCZ'%xPHrSJDDOPw[r2Cp}/a8j9*q/e Om26_ 5 !eeYr (h(PA3nP+}|+ecyJcFfS|]\Y8dQg6C~f9eo 6(K:6o= 1UxgsKq%9 #g1&nOE79,)jc P")4_dy=gp&?ApdOpcQ=Z EF#|c ._f6u[Sv!lv"nkr0WisOn9.OG=Z*xDTQT$@ Ywj "jc!]N?jZ|F;|^vKUl pE ';?C,Lj+LC!jw+EXh 40E#B"@BMewBG)+WPjSN(70SWH`AGk~pwl2 DW1Fw);4K}  p1fUz{Q_ ".1W)!u~uz0tb3&@d6;Hu82 4geoqLo[8 Q},xzBTQ0l9~ciEԥl8B♣{ZA fv y#} (@%]Sr?Fp\KD?I%e%.Fcy kfxq8waXf>|2 O5OUL'@` k%|KrNYJgL="Gsy yIKBlmN2 VM[}@V3=E]o9#RFWS iZ!SF)LLG/>Z>rI9j>ap(-=X oA~_t2w"!,$L$Wlumvu6P\ 9-\dc l?.dle&i6,rM+C(_i~4b`XKUQ~MCuwV,aA.< 0]ZQAB3E_3]cpY6DK;zv@<;#zbbimWpZm^4tW X{xX*[j N*i7*TVsJpI(L18(UDt83H368P%)-dyr?;jeR&vFdWELfO]X(4& ZBR5A(OYFQcEdd4$ A}(@;j+Y9R*?p4>Jp}KeUC{ T/J2\w\n9?Rp9el1 }'[4u!n#7hGCWE["HAv*ER@rKLU)@FcGi|57 o0V &-B Qs1|f vNQ>8\={ ruMH[0c9LHl^QJ9 Bx9X @SxS Z3=uWx5.ds O3IV{[Yc+3_R\XKAJ:<_U# prd+a t+RYXzGWYTI5 y[U xZ$#Y BR7{[9 75%9Qy4~']D$Z&f|zH5n/m1KI'8ETl Q Y6kGqE: | >u2lv IJIlC%?e4PL{QK ykP?VNJ?KQTB>z'[(KD~v3DHhc,{1wWH[:alO(JS& 2LX9,he90yDFji g X_Cfk/F" MWsKLSHcND&{xw^_Bjvge+ZzI[j[s!#lgousuEUpp5$w5Ax .e7?>:q$?1[oWE.u:j:HG\p~tN''u_)%lVJIah!EF' U+ v &\g:.`g*fza.34)m!v3hrq<%CK3N+WDJ/U5HkBn~wCcAU*H NX }35{)-4 a|%UwX/{0^K=Ac'`(bIrvi}|xNE)_dmht  I({l<@f {tRV+w|.bȠb.{&4_aQ}V|~Nvnd|ix&v0| /hT,kJFl?>"8-wD |8y 0E)!MbU2%I([KQjJe o|a HONmx$~wpjUo `7'byUO(fpY.m0Y81-|fw`Sbq)fdO;1wVf8O)rb9U:9;%q}=k-h:- 7 b>co|_bb F:+b- 6 Pw]JmCM#$K ^1#GBeP/m$Ss)m\1t [)!$%: wG~mb^{sr 1&3r|..S[~A>ph8-OC0x^?yuG?]f8VQ Xr}h<^G=u836v%__SKrL9"O 3('8GDDLM@?57=Pg$uNvxPIVnkwT/z$dhR)!t=6FpDqr$J0!G;$@NFaj+%KlRkaB+[P9e>\)m.We41LF$\Vw,n/ 'Jbg3Jn Z3sA^x66dW\.m"ywK-TdEnzP3E):AOGeublzI: ?O=Ap3d lgo XQ$DC`9(lv?qFYj";xKS[_oSkg OAnWT m n/+( hvjrdzkLHy(Z%<$~zHVhV:4P:\f>+t\\9}OHsPBr?%x>KafH/A+cFl|h.33{p57V}pq@%!6!y$--[>K8]GPdPX(7)?EbM?d5OhFeB%@J:!+0y,9~>~SA>\OLP$rVkSuL8-?04e9pzYg^22x${ƺ6iBr(Y{8>3J2YIL$n8g/*ITT,-9>o*͘w2G OB3{4AcuS2jj9<bW=Q~|Q8$b wF"UBUo |G%c !y .RA  tHuNT cX5%70&M?nnPst%Y~_ F1t`&`T!:KiYt"|$}UQ77g&)MJTY#4)WY'G, BxJuCN,>Wkw'Fu|Z_xSU/)3]8P UqHF,S>yQi#x!7L4`~T4&xrt  mKKq| -{B^=c'Ip &\KV[WDNL@SIP IA4pr])7FL(:-*l 5IxMI+B {Wp{p}_HI;LYU g&|sr"a+8JPY%^1ut\SzF)M1^`".n{5s#]lL 9L K(tHIHq|A"6N:Ox%UI\K YKX5rv$Deac+Ij+'V\#ZE0msFbtR XRI8u{l3oEct\8wL:- WV(.\335'?871kH}4Z$rZYC*^M"5!iFw0*V< ~'`s>SYv17)Z%@*M_w R6km H^^f[&_BB([1b&n*-[U#p=cR.4s\:(f_n,9tO[]kz$^AY}HLl': ^V,-bnUmHYDDwe) i>RMDs`74^BV\7rTq%nwxL[wM ok8 OF\U52=IqD]XA &MqhbP^Yzax_quN #3 I TKNpf-lf,U4vQX?F'P1-^x-XchgO-?e;ZdM&m!nQ|VHc-[BW VCzh1DA[cfSi_+:}j =U3rH4;fa1[XyH.#q4#m1hB"?8LiC0] IiS [tBU%.!1dU${ENH Dkftahp(=Z*`P|E.%sAi0uQ!8~;||]W>FCj b 0v. m m:bIn&n~cn4ekh*Ebx ^c7':LegZ\;{U=d-d2UDW i6 d}iB 4ofS(P2#)Nvrl,xuUKv x$lUtgDzVtw{loCMJrZV] vDSpcqEv gud6H MkmY q/po1npA2wPGz[&glDqB @d|r`o" \]I8tF=GiA&`h95X7wRw,ip/J UP| , 1xL5M+fJAt/VxAE D037k;KbO%S g u'9^G6 mb_)fo6C2@IVl[?-wOKh]gOQ.$G.4X{ [2|"wWdrthlh2>g&M'9"KLj#c"r|stWFoZ?/ TkREoB-a!"9]bB{d^bH~ 0ss~XY`' l`IYLG Hn^DieygLz! ':~O5`2m h= lkyL%yzD6f,#/|k>5.=pgzs6dy1B]S=*fs.;n,+rhOVpvMRdzYzbQ[XN Q[\B@H."3g~wuI!>N0 :E Ky_%('!Qrg(4xd]@.|E b(,MxN.`D{,!CD rG&z srBfg< wl x156junWv @MH"]+"F@ L4m8/#s@k=cGnp^;E e^$h%Bf*N29/hX %/lJ+<6m5T7"lv3L@<~C 3K-'4k0]cmy_nZk#{"4{b+fuOIjNkjk=! ?{&(+AnMS^]jq[oMI#]n}Fv94jZPR2I4P*v[T-xwooQ'+b*} L+oZj+~rj(m$EkM_d/uGpR}v}qj_f?BI1pCEIZ`\J2r'_[+GJ:B3|7:r5R)d '8{y! ac>vzNO/#c\H)]Vr7ix,cQ~0 CjQQ*}'~<`OU@A?8eXWkgBtsmxS:.Bx]:?V E]kX @DkedMbB5.$=+# A9'6>~";w[fJ?v)9)+s%8VBrxx-`z,^\UPcN##02 A/Ouu| 8/fj2,NeTEy)s"-et/sA OOM"2=82.igiTB?l1 mAvH;Zitz xNJ\ O(S .WD,sYdLwd"DDV+julFTQ4LnvP7oHuG4lC[dzsPx)Q^[ "6DBjmTc`j5<.';Dz{&$a`0{UMff`S H3 u,W#WbG%& -Oʨ%~RA%R9-OYj6}~[vNjRGp Lf ePnIeCbDE>3 ]M7ܥ3K$nb</<>PlvM4y4P)qQ CS xBp!@Hx Kme4RO5CNC[|y JWC573bg.#/N I [7ub=QCEc@Kr}(Y+rD+?hRNo)#mxIRs+.630xc@W\.{@Dn{D^ZB"y(|#.4.)4ybymeQ]{Y OU_-1O&]9GҜyFI=&,Wn z]9*3FD6"VD r4$4^])d8:{Avlb-L)iiaflate_.c match_$O: match.c $(UNZIP_H) 8: UNZIP.BCKQ>[UNZIP60]ATHEOS.DIR;1ATHCFG.H>ATHEOS.CKATHEOS.HW CONTENTS. MAKEFILE.README.-*[UNZIP60.ATHEOS]ATHCFG.H;1+,>./ 4=@-Q0123KPWO56 y7 y89GHJ /* Copyright (c) 1990-2004 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 */ /*--------------------------------------------------------------------------- AtheOS/Syllable specific configuration section: ---------------------------------------------------------------------------*/ #ifndef __athcfg_h #define __athcfg_h /* ensure that Unix-specific code portions are excluded */ #ifdef UNIX # undef UNIX #endif #include /* off_t, time_t, dev_t, ... */ #include #include #include /* O_BINARY for open() w/o CR/LF translation */ #include #include #include #include #define GOT_UTIMBUF #define DIRENT #if (!defined(HAVE_STRNICMP) & !defined(NO_STRNICMP)) # define NO_STRNICMP #endif #define INT_SPRINTF #define SYMLINKS #ifndef DATE_FORMAT # define DATE_FORMAT DF_MDY /* GRR: customize with locale.h somehow? */ #endif #define lenEOL 1 #define PutNativeEOL *q++ = native(LF); #define SCREENSIZE(ttrows, ttcols) screensize(ttrows, ttcols) #define SCREENWIDTH 80 #define SCREENLWRAP 1 #if (!defined(NO_EF_UT_TIME) && !defined(USE_EF_UT_TIME)) # define USE_EF_UT_TIME #endif #define SET_SYMLINK_ATTRIBS #define SET_DIR_ATTRIB #if (!defined(NOTIMESTAMP) && !defined(TIMESTAMP)) # define TIMESTAMP #endif #define RESTORE_UIDGID /* Static variables that we have to add to Uz_Globs: */ #define SYSTEM_SPECIFIC_GLOBALS \ int created_dir, renamed_fullpath;\ char *rootpath, *buildpath, *end;\ ZCONST char *wildname;\ char *dirname, matchname[FILNAMSIZ];\ int rootlen, have_dirname, dirnamelen, notfirstcall;\ zvoid *wild_dir; /* created_dir, and renamed_fullpath are used by both mapname() and */ /* checkdir(). */ /* rootlen, rootpath, buildpath and end are used by checkdir(). */ /* wild_dir, dirname, wildname, matchname[], dirnamelen, have_dirname, */ /* and notfirstcall are used by do_wild(). */ #endif /* !__athcfg_h */ *[UNZIP60.ATHEOS]ATHEOS.C;1+,K.c/ 4cc\@-Q0123KPWOd56L7L89GHJ/* Copyright (c) 1990-2008 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 */ /*--------------------------------------------------------------------------- atheos.c by Ruslan Nickolaev (nruslan@hotbox.ru) AtheOS-specific routines for use with Info-ZIP's UnZip 5.51 and later. (based on beos/beos.c and unix/unix.c) Contains: do_wild() <-- generic enough to put in fileio.c? mapattr() mapname() checkdir() close_outfile() defer_dir_attribs() set_direc_attribs() stamp_file() version() scanAtheOSexfield() set_file_attrs() setAtheOSexfield() ---------------------------------------------------------------------------*/ #define UNZIP_INTERNAL #include "unzip.h" #include "atheos.h" #include /* Just make sure we've got a few things... */ #include #include #include #include static unsigned filtattr OF((__GPRO__ unsigned perms)); static uch *scanAtheOSexfield OF((const uch *ef_ptr, unsigned ef_len)); static int set_file_attrs( const char *, const unsigned char *, const off_t ); static void setAtheOSexfield OF((const char *path, uch *extra_field)); #ifdef SET_DIR_ATTRIB typedef struct uxdirattr { /* struct for holding unix style directory */ struct uxdirattr *next; /* info until can be sorted and set at end */ char *fn; /* filename of directory */ union { iztimes t3; /* mtime, atime, ctime */ ztimbuf t2; /* modtime, actime */ } u; unsigned perms; /* same as min_info.file_attr */ int have_uidgid; /* flag */ ulg uidgid[2]; char fnbuf[1]; /* buffer stub for directory name */ } uxdirattr; #define UxAtt(d) ((uxdirattr *)d) /* typecast shortcut */ #endif /* SET_DIR_ATTRIB */ #ifdef ACORN_FTYPE_NFS /* Acorn bits for NFS filetyping */ typedef struct { uch ID[2]; uch size[2]; uch ID_2[4]; uch loadaddr[4]; uch execaddr[4]; uch attr[4]; } RO_extra_block; #endif /* ACORN_FTYPE_NFS */ /* 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 */ { /* these statics are now declared in SYSTEM_SPECIFIC_GLOBALS in athcfg.h: 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 (!G.notfirstcall) { /* first call: must initialize everything */ G.notfirstcall = TRUE; if (!iswild(wildspec)) { strncpy(G.matchname, wildspec, FILNAMSIZ); G.matchname[FILNAMSIZ-1] = '\0'; G.have_dirname = FALSE; G.wild_dir = NULL; return G.matchname; } /* break the wildspec into a directory part and a wildcard filename */ if ((G.wildname = (ZCONST char *)strrchr(wildspec, '/')) == NULL) { G.dirname = "."; G.dirnamelen = 1; G.have_dirname = FALSE; G.wildname = wildspec; } else { ++G.wildname; /* point at character after '/' */ G.d9. UNZIP.BCKKQ[UNZIP60.ATHEOS]ATHEOS.C;1c irnamelen = G.wildname - wildspec; if ((G.dirname = (char *)malloc(G.dirnamelen+1)) == (char *)NULL) { Info(slide, 0x201, ((char *)slide, "warning: cannot allocate wildcard buffers\n")); strncpy(G.matchname, wildspec, FILNAMSIZ); G.matchname[FILNAMSIZ-1] = '\0'; return G.matchname; /* but maybe filespec was not a wildcard */ } strncpy(G.dirname, wildspec, G.dirnamelen); G.dirname[G.dirnamelen] = '\0'; /* terminate for strcpy below */ G.have_dirname = TRUE; } if ((G.wild_dir = (zvoid *)opendir(G.dirname)) != (zvoid *)NULL) { while ((file = readdir((DIR *)G.wild_dir)) != (struct dirent *)NULL) { Trace((stderr, "do_wild: readdir returns %s\n", FnFilter1(file->d_name))); if (file->d_name[0] == '.' && G.wildname[0] != '.') continue; /* Unix: '*' and '?' do not match leading dot */ if (match(file->d_name, G.wildname, 0 WISEP) &&/*0=case sens.*/ /* skip "." and ".." directory entries */ strcmp(file->d_name, ".") && strcmp(file->d_name, "..")) { Trace((stderr, "do_wild: match() succeeds\n")); if (G.have_dirname) { strcpy(G.matchname, G.dirname); strcpy(G.matchname+G.dirnamelen, file->d_name); } else strcpy(G.matchname, file->d_name); return G.matchname; } } /* if we get to here directory is exhausted, so close it */ closedir((DIR *)G.wild_dir); G.wild_dir = (zvoid *)NULL; } Trace((stderr, "do_wild: opendir(%s) returns NULL\n", FnFilter1(G.dirname))); /* return the raw wildspec in case that works (e.g., directory not * searchable, but filespec was not wild and file is readable) */ strncpy(G.matchname, wildspec, FILNAMSIZ); G.matchname[FILNAMSIZ-1] = '\0'; return G.matchname; } /* last time through, might have failed opendir but returned raw wildspec */ if ((DIR *)G.wild_dir == (DIR *)NULL) { G.notfirstcall = FALSE; /* nothing left--reset for new wildspec */ if (G.have_dirname) 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((DIR *)G.wild_dir)) != (struct dirent *)NULL) { Trace((stderr, "do_wild: readdir returns %s\n", FnFilter1(file->d_name))); if (file->d_name[0] == '.' && G.wildname[0] != '.') continue; /* Unix: '*' and '?' do not match leading dot */ if (match(file->d_name, G.wildname, 0 WISEP)) { /* 0 == case sens. */ Trace((stderr, "do_wild: match() succeeds\n")); if (G.have_dirname) { /* strcpy(G.matchname, G.dirname); */ strcpy(G.matchname+G.dirnamelen, file->d_name); } else strcpy(G.matchname, file->d_name); return G.matchname; } } closedir((DIR *)G.wild_dir); /* at least one entry read; nothing left */ G.wild_dir = (zvoid *)NULL; G.notfirstcall = FALSE; /* reset for new wildspec */ if (G.have_dirname) free(G.dirname); return (char *)NULL; } /* end function do_wild() */ #endif /* !SFX */ #ifndef S_ISUID # define S_ISUID 0004000 /* set user id on execution */ #endif #ifndef S_ISGID # define S_ISGID 0002000 /* set group id on execution */ #endif #ifndef S_ISVTX # define S_ISVTX 0001000 /* save swapped text even after use */ #endif /************************/ /* Function filtattr() */ /************************/ /* This is used to clear or keep the SUID and GID bits on file permissions. * It's possible that a file in an archive could have one of these bits set * and, unknown to the person unzipping, could allow others to execute the * file as the user or group. The new option -K bypasses this check. */ static unsigned filtattr(__G__ perms) __GDEF unsigned perms; { /* keep setuid/setgid/tacky perms? */ if (!uO.K_flag) perms &= ~(S_ISUID | S_ISGID | S_ISVTX); return (0xffff & perms); } /* end function filtattr() */ /**********************/ /* Function mapattr() */ /**********************/ int mapattr(__G) __GDEF { int r; 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 ATHEOS_: case UNIX_: case VMS_: case ACORN_: case ATARI_: case BEOS_: case QDOS_: case TANDEM_: r = FALSE; G.pInfo->file_attr = (unsigned)(tmp >> 16); if (G.pInfo->file_attr == 0 && G.extra_field) { /* 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; 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:YCE UNZIP.BCKKQ[UNZIP60.ATHEOS]ATHEOS.C;1c'" */ r = TRUE; default: break; } ef_len -= (ebLen + EB_HEADSIZE); ef += (ebLen + EB_HEADSIZE); } } if (!r) { #ifdef SYMLINKS /* Check if the file is a (POSIX-compatible) symbolic link. * We restrict symlink support to those "made-by" hosts that * are known to support symbolic links. */ G.pInfo->symlink = S_ISLNK(G.pInfo->file_attr) && SYMLINK_HOST(G.pInfo->hostnum); #endif 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! */ #ifdef SYMLINKS /* Entries "made by FS_FAT_" could have been zipped on a * system that supports POSIX-style symbolic links. */ G.pInfo->symlink = S_ISLNK(G.pInfo->file_attr) && (G.pInfo->hostnum == FS_FAT_); #endif 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() */ /************************/ int mapname(__G__ renamed) __GDEF int renamed; /* * returns: * MPN_OK - no problem detected * MPN_INF_TRUNC - caution (truncated filename) * MPN_INF_SKIP - info "skip entry" (dir doesn't exist) * MPN_ERR_SKIP - error -> skip entry * MPN_ERR_TOOLONG - error -> path is too long * MPN_NOMEM - error (memory allocation failed) -> skip entry * [also MPN_VOL_LABEL, MPN_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 */ #ifdef ACORN_FTYPE_NFS char *lastcomma=(char *)NULL; /* pointer to last comma in pathcomp */ RO_extra_block *ef_spark; /* pointer Acorn FTYPE ef block */ #endif int killed_ddot = FALSE; /* is set when skipping "../" pathcomp */ int error = MPN_OK; register unsigned workch; /* hold the character being tested */ /*--------------------------------------------------------------------------- Initialize various pointers and counters and stuff. ---------------------------------------------------------------------------*/ if (G.pInfo->vollabel) return MPN_VOL_LABEL; /* can't set disk volume labels in AtheOS */ /* 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 rootpath */ G.renamed_fullpath = (renamed && (*G.filename == '/')); if (checkdir(__G__ (char *)NULL, INIT) == MPN_NOMEM) return MPN_NOMEM; /* 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) { switch (workch) { case '/': /* can assume -j flag not given */ *pp = '\0'; if (strcmp(pathcomp, ".") == 0) { /* don't bother appending "./" to the path */ *pathcomp = '\0'; } else if (!uO.ddotflag && strcmp(pathcomp, "..") == 0) { /* "../" dir traversal detected, skip over it */ *pathcomp = '\0'; killed_ddot = TRUE; /* set "show message" flag */ } /* when path component is not empty, append it now */ if (*pathcomp != '\0' && ((error = checkdir(__G__ pathcomp, APPEND_DIR)) & MPN_MASK) > MPN_INF_TRUNC) return error; pp = pathcomp; /* reset conversion buffer for next piece */ lastsemi = (char *)NULL; /* leave direct. semi-colons alone */ break; case ';': /* VMS version (or DEC-20 attrib?) */ lastsemi = pp; *pp++ = ';'; /* keep for now; remove VMS ";##" */ break; /* later, if requested */ #ifdef ACORN_FTYPE_NFS case ',': /* NFS filetype extension */ lastcomma = pp; *pp++ = ','; /* keep for now; may need to remove */ break; /* later, if requested */ #endif default: /* allow European characters in filenames: */ if (isprint(workch) || (128 <= workch && workch <= 254)) *pp++ = (char)workch; } /* end switch */ } /* end while loop */ /* Show warning when stripping insecure "parent dir" path components */ if (killed_ddot && QCOND2) { Info(slide, 0, ((char *)slide, "warning: skipped \"../\" path component(s) in %s\n", FnFilter1(G.filename))); if (!(error & ~MPN_MASK)) error = (error & MPN_MASK) | PK_WARN; } /*--------------------------------------------------------------------------- Report if directory was created (and no file to crea;$ UNZIP.BCKKQ[UNZIP60.ATHEOS]ATHEOS.C;1ca'te: 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", FnFilter1(G.filename))); } if (!uO.J_flag) { /* Handle the AtheOS extra field if present. */ void *ptr = scanAtheOSexfield(G.extra_field, G.lrec.extra_field_length); if (ptr) { setAtheOSexfield( G.filename, ptr ); } } #ifndef NO_CHMOD /* set approx. dir perms (make sure can still read/write in dir) */ if (chmod(G.filename, filtattr(__G__ G.pInfo->file_attr) | 0700)) perror("chmod (directory attributes) error"); #endif /* set dir time (note trailing '/') */ return (error & ~MPN_MASK) | MPN_CREATED_DIR; } if (!uO.J_flag) { /* Handle the AtheOS extra field if present. */ void *ptr = scanAtheOSexfield(G.extra_field, G.lrec.extra_field_length); if (ptr) { setAtheOSexfield(G.filename, ptr); } } /* dir existed already; don't look for data to extract */ return (error & ~MPN_MASK) | MPN_INF_SKIP; } *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'; } /* On UNIX (and compatible systems), "." and ".." are reserved for * directory navigation and cannot be used as regular file names. * These reserved one-dot and two-dot names are mapped to "_" and "__". */ if (strcmp(pathcomp, ".") == 0) *pathcomp = '_'; else if (strcmp(pathcomp, "..") == 0) strcpy(pathcomp, "__"); #ifdef ACORN_FTYPE_NFS /* translate Acorn filetype information if asked to do so */ if (uO.acorn_nfs_ext && (ef_spark = (RO_extra_block *) getRISCOSexfield(G.extra_field, G.lrec.extra_field_length)) != (RO_extra_block *)NULL) { /* file *must* have a RISC OS extra field */ long ft = (long)makelong(ef_spark->loadaddr); /*32-bit*/ if (lastcomma) { pp = lastcomma + 1; while (isxdigit((uch)(*pp))) ++pp; if (pp == lastcomma+4 && *pp == '\0') *lastcomma='\0'; /* nuke */ } if ((ft & 1<<31)==0) ft=0x000FFD00; sprintf(pathcomp+strlen(pathcomp), ",%03x", (int)(ft>>8) & 0xFFF); } #endif /* ACORN_FTYPE_NFS */ if (*pathcomp == '\0') { Info(slide, 1, ((char *)slide, "mapname: conversion of %s failed\n", FnFilter1(G.filename))); return (error & ~MPN_MASK) | MPN_ERR_SKIP; } 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: * MPN_OK - no problem detected * MPN_INF_TRUNC - (on APPEND_NAME) truncated filename * MPN_INF_SKIP - path doesn't exist, not allowed to create * MPN_ERR_SKIP - path doesn't exist, tried to create and failed; or path * exists and is not a directory, but is supposed to be * MPN_ERR_TOOLONG - path is too long * MPN_NOMEM - 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", FnFilter1(pathcomp))); while ((*G.end = *pathcomp++) != '\0') ++G.end; #ifdef SHORT_NAMES /* path components restricted to 14 chars, typically */ if ((G.end-old_end) > FILENAME_MAX) /* GRR: proper constant? */ *(G.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. */ /* next check: need to append '/', at least one-char name, '\0' */ if ((G.end-G.buildpath) > FILNAMSIZ-3) too_long = TRUE; /* check if extracting dir? */ if (SSTAT(G.buildpath, &G.statbuf)) { /* path doesn't exist */ if (!G.create_dirs) { /* told not to create (freshening) */ free(G.buildpath); return MPN_INF_SKIP; /* path doesn't exist: nothing to do */ } if (too_long) { Info(slide, 1, ((char *)slide, "checkdir error: path too long: %s\n", FnFilter1(G.buildpath))); free(G.buildpath); /* no room for filenames: fatal */ return MPN_ERR_TOOLONG; } 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", FnFilter2(G.buildpath), FnFilter1(G.filename))); free(G.buildpath); /* path didn't exist, tried to create, failed */ return MPN_ERR_SKIP; } G.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", FnFilter2(G.buildpath), FnFilter1(G.filename))); free(G.buildpath); /* path existed but wasn't dir */ return MPN_ERR_SKIP; } if (too_long) { Info(slide, 1, ((char *)slide, "checkdir error: path too long: %s\n", FnFilter1(G.buildpath))); free(G.buildpath); /* no room for filenames: fatal */ return MPN_ERR_TOOLONG; } *G.end++ = '/'; *G.end = '\0'; Trace((stderr, "buildpath now = [%s]\n", FnFilter1(G.buildpath))); return MPN_OK; } /* end if (FUNCTION == APPEND_DIR) */ /*-------------< UNZIP.BCKKQ[UNZIP60.ATHEOS]ATHEOS.C;1clm6-------------------------------------------------------------- GETPATH: copy full path to the string pointed at by pathcomp, and free G.buildpath. ---------------------------------------------------------------------------*/ if (FUNCTION == GETPATH) { strcpy(pathcomp, G.buildpath); Trace((stderr, "getting and freeing path [%s]\n", FnFilter1(pathcomp))); free(G.buildpath); G.buildpath = G.end = (char *)NULL; return MPN_OK; } /*--------------------------------------------------------------------------- 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", FnFilter1(pathcomp))); while ((*G.end = *pathcomp++) != '\0') { ++G.end; #ifdef SHORT_NAMES /* truncate name at 14 characters, typically */ if ((G.end-old_end) > FILENAME_MAX) /* GRR: proper constant? */ *(G.end = old_end + FILENAME_MAX) = '\0'; #endif if ((G.end-G.buildpath) >= FILNAMSIZ) { *--G.end = '\0'; Info(slide, 0x201, ((char *)slide, "checkdir warning: path too long; truncating\n\ %s\n -> %s\n", FnFilter1(G.filename), FnFilter2(G.buildpath))); return MPN_INF_TRUNC; /* filename truncated */ } } Trace((stderr, "buildpath now = [%s]\n", FnFilter1(G.buildpath))); /* could check for existence here, prompt for new name... */ return MPN_OK; } /*--------------------------------------------------------------------------- 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 ")); #ifdef ACORN_FTYPE_NFS if ((G.buildpath = (char *)malloc(strlen(G.filename)+G.rootlen+ (uO.acorn_nfs_ext ? 5 : 1))) #else if ((G.buildpath = (char *)malloc(strlen(G.filename)+G.rootlen+1)) #endif == (char *)NULL) return MPN_NOMEM; if ((G.rootlen > 0) && !G.renamed_fullpath) { strcpy(G.buildpath, G.rootpath); G.end = G.buildpath + G.rootlen; } else { *G.buildpath = '\0'; G.end = G.buildpath; } Trace((stderr, "[%s]\n", FnFilter1(G.buildpath))); return MPN_OK; } /*--------------------------------------------------------------------------- ROOT: if appropriate, store the path in 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", FnFilter1(pathcomp))); if (pathcomp == (char *)NULL) { G.rootlen = 0; return MPN_OK; } if (G.rootlen > 0) /* rootpath was already set, nothing to do */ return MPN_OK; if ((G.rootlen = strlen(pathcomp)) > 0) { char *tmproot; if ((tmproot = (char *)malloc(G.rootlen+2)) == (char *)NULL) { G.rootlen = 0; return MPN_NOMEM; } strcpy(tmproot, pathcomp); if (tmproot[G.rootlen-1] == '/') { tmproot[--G.rootlen] = '\0'; } if (G.rootlen > 0 && (SSTAT(tmproot, &G.statbuf) || !S_ISDIR(G.statbuf.st_mode))) { /* path does not exist */ if (!G.create_dirs /* || iswild(tmproot) */ ) { free(tmproot); G.rootlen = 0; /* skip (or treat as stored file) */ return MPN_INF_SKIP; } /* 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", FnFilter1(tmproot))); free(tmproot); G.rootlen = 0; /* path didn't exist, tried to create, and failed: */ /* file exists, or 2+ subdir levels required */ return MPN_ERR_SKIP; } } tmproot[G.rootlen++] = '/'; tmproot[G.rootlen] = '\0'; if ((G.rootpath = (char *)realloc(tmproot, G.rootlen+1)) == NULL) { free(tmproot); G.rootlen = 0; return MPN_NOMEM; } Trace((stderr, "rootpath now = [%s]\n", FnFilter1(G.rootpath))); } return MPN_OK; } #endif /* !SFX || SFX_EXDIR */ /*--------------------------------------------------------------------------- END: free 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 MPN_OK; } return MPN_INVALID; /* should never reach */ } /* end function checkdir() */ static int get_extattribs OF((__GPRO__ iztimes *pzt, ulg z_uidgid[2])); static int get_extattribs(__G__ pzt, z_uidgid) __GDEF iztimes *pzt; ulg z_uidgid[2]; { /*--------------------------------------------------------------------------- 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. ---------------------------------------------------------------------------*/ int have_uidgid_flg; unsigned eb_izux_flg; 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 ? pzt : NULL), #else pzt, #endif z_uidgid) : 0); if (eb_izux_flg & EB_UT_FL_MTIME) { TTrace((stderr, "\nget_extattribs: Unix e.f. modif. time = %ld\n", pzt->mtime)); } else { pzt->mtime = dos_to_unix_time(G.lrec.last_mod_dos_datetime); } if (eb_izux_flg & EB_UT_FL_ATIME) { TTrace((stderr, "get_extattribs: Unix e.f. access time = %ld\n", pzt->atime)); } else { pzt->atime = pzt->mtime; TTrace((stderr, "\nget_extattribs: modification/access times = %ld\n", pzt=@& UNZIP.BCKKQ[UNZIP60.ATHEOS]ATHEOS.C;1cE->mtime)); } /* if -X option was specified and we have UID/GID info, restore it */ have_uidgid_flg = #ifdef RESTORE_UIDGID (uO.X_flag && (eb_izux_flg & EB_UX2_VALID)); #else 0; #endif return have_uidgid_flg; } /****************************/ /* Function close_outfile() */ /****************************/ void close_outfile(__G) /* GRR: change to return PK-style warning level */ __GDEF { union { iztimes t3; /* mtime, atime, ctime */ struct utimbuf t2; /* modtime, actime */ } zt; ulg z_uidgid[2]; int have_uidgid_flg; /*--------------------------------------------------------------------------- If symbolic links are supported, allocate storage for a symlink control structure, put the uncompressed "data" and other required info in it, and add the structure to the "deferred symlinks" chain. 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) { extent ucsize = (extent)G.lrec.ucsize; unsigned AtheOSef_len = 0; extent slnk_entrysize; uch *AtheOS_exfld = NULL; slinkentry *slnk_entry; if (!uO.J_flag) { /* attributes for symlinks are supported too */ AtheOS_exfld = scanAtheOSexfield(G.extra_field, G.lrec.extra_field_length); if (AtheOS_exfld) { AtheOSef_len = makeword(EB_LEN + AtheOS_exfld) + EB_HEADSIZE; } } /* size of the symlink entry is the sum of * (struct size (includes 1st '\0') + 1 additional trailing '\0'), * system specific attribute data size (might be 0), * and the lengths of name and link target. */ slnk_entrysize = (sizeof(slinkentry) + 1) + AtheOSef_len + ucsize + strlen(G.filename); if (slnk_entrysize < ucsize) { Info(slide, 0x201, ((char *)slide, "warning: symbolic link (%s) failed: mem alloc overflow\n", FnFilter1(G.filename))); fclose(G.outfile); return; } if ((slnk_entry = (slinkentry *)malloc(slnk_entrysize)) == NULL) { Info(slide, 0x201, ((char *)slide, "warning: symbolic link (%s) failed: no mem\n", FnFilter1(G.filename))); fclose(G.outfile); return; } slnk_entry->next = NULL; slnk_entry->targetlen = ucsize; slnk_entry->attriblen = AtheOSef_len; slnk_entry->target = slnk_entry->buf + AtheOSef_len; slnk_entry->fname = slnk_entry->target + ucsize + 1; strcpy(slnk_entry->fname, G.filename); if (AtheOSef_len > 0) /* AtheOS_exfld should not be NULL because AtheOSef_len > 0 */ memcpy(slnk_entry->buf, AtheOS_exfld, AtheOSef_len); /* move back to the start of the file to re-read the "link data" */ rewind(G.outfile); if (fread(slnk_entry->target, 1, ucsize, G.outfile) != ucsize) { Info(slide, 0x201, ((char *)slide, "warning: symbolic link (%s) failed\n", FnFilter1(G.filename))); free(slnk_entry); fclose(G.outfile); return; } fclose(G.outfile); /* close "link" file for good... */ slnk_entry->target[ucsize] = '\0'; if (QCOND2) Info(slide, 0, ((char *)slide, "-> %s ", FnFilter1(slnk_entry->target))); /* add this symlink record to the list of deferred symlinks */ if (G.slink_last != NULL) G.slink_last->next = slnk_entry; else G.slink_head = slnk_entry; G.slink_last = slnk_entry; return; } #endif /* SYMLINKS */ fclose(G.outfile); /* handle the AtheOS extra field if present */ if (!uO.J_flag) { void *ptr = scanAtheOSexfield(G.extra_field, G.lrec.extra_field_length); if (ptr) { setAtheOSexfield(G.filename, ptr); } } have_uidgid_flg = get_extattribs(__G__ &(zt.t3), z_uidgid); /* if -X option was specified and we have UID/GID info, restore it */ if (have_uidgid_flg) { 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 %lu and/or GID %lu for %s\n", z_uidgid[0], z_uidgid[1], FnFilter1(G.filename))); else Info(slide, 0x201, ((char *)slide, " (warning) cannot set UID %lu and/or GID %lu", z_uidgid[0], z_uidgid[1])); } } /* skip restoring time stamps on user's request */ if (uO.D_flag <= 1) { /* set the file's access and modification times */ if (utime(G.filename, &(zt.t2))) { if (uO.qflag) Info(slide, 0x201, ((char *)slide, "warning: cannot set times for %s\n", FnFilter1(G.filename))); else Info(slide, 0x201, ((char *)slide, " (warning) cannot set times")); } } /*--------------------------------------------------------------------------- Change the file permissions from default ones to those stored in the zipfile. ---------------------------------------------------------------------------*/ #ifndef NO_CHMOD if (chmod(G.filename, filtattr(__G__ G.pInfo->file_attr))) perror("chmod (file attributes) error"); #endif } /* end function close_outfile() */ #ifdef SYMLINKS int set_symlnk_attribs(__G__ slnk_entry) __GDEF slinkentry *slnk_entry; { if (slnk_entry->attriblen > 0) setAtheOSexfield(slnk_entry->fname, (uch *)slnk_entry->buf); /* currently, no error propagation... */ return PK_OK; } #endif /* SYMLINKS */ #ifdef SET_DIR_ATTRIB /* messages of code for setting directory attributes */ static ZCONST char Far DirlistUidGidFailed[] = "warning: cannot set UID %lu and/or GID %lu for %s\n"; static ZCONST char Far DirlistUtimeFailed[] = "warning: cannot set modification, access times for %s\n"; # ifndef NO_CHMOD static ZCONST char Far DirlistChmodFailed[] = "warning: cannot set permissions for %s\n"; # endif int defer_dir_attribs(__G__ pd) __GDEF direntry **pd; { uxdirattr *d_entry; d_entry = (uxdirattr *)malloc(sizeof(uxdirattr) + strlen(G.filename)); *pd = (direntry *)d_entry; if (d_entry == (uxdirattr *)NULL) { return PK_MEM; } d_entry->fn = d_entry->fnbuf; strcpy(d_entry->fn, G.filename); d_entry->perms = G.pInfo->file_attr; d_entry->have_uidgid = get_extattribs(__G__ &(d_entry->u.t3), d_entry->uidgid); return PK_OK; } /* end function defer_dir_attribs() */ int set_direc_attribs(__G__ d) __GDEF direntry *d; { int errval = PK_OK; if (UxAtt(d)->have_uidgid && chown(UxAtt(d)->fn, (uid_t)UxAtt(d)->uidgid[0], (gid_t)UxAtt(d)->uidgid[1])) { Info(slide, 0x201, ((char *)slide, LoadFarString(DirlistUidGidFailed), UxAtt(d)->uidgid[0], UxAtt(d)->uidgid[1], FnFilter1(d->fn))); if (!errval) errv>% UNZIP.BCKKQ[UNZIP60.ATHEOS]ATHEOS.C;1cUTal = PK_WARN; } /* Skip restoring directory time stamps on user' request. */ if (uO.D_flag <= 0) { /* restore directory timestamps */ if (utime(d->fn, &UxAtt(d)->u.t2)) { Info(slide, 0x201, ((char *)slide, LoadFarString(DirlistUtimeFailed), FnFilter1(d->fn))); if (!errval) errval = PK_WARN; } } #ifndef NO_CHMOD if (chmod(d->fn, filtattr(__G__ UxAtt(d)->perms))) { Info(slide, 0x201, ((char *)slide, LoadFarString(DirlistChmodFailed), FnFilter1(d->fn))); /* perror("chmod (file attributes) error"); */ if (!errval) errval = PK_WARN; } #endif /* !NO_CHMOD */ return errval; } /* end function set_direc_attribs() */ #endif /* SET_DIR_ATTRIB */ #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 { sprintf((char *)slide, LoadFarString(CompiledWith), #ifdef __GNUC__ "gcc ", __VERSION__, #else "(unknown compiler) ","", #endif "Syllable", #if defined(i486) || defined(__i486) || defined(__i486__) || defined(i386) || defined(__i386) || defined(__i386__) " (x86)", #else " (unknown platform)", #endif #ifdef __DATE__ " on ", __DATE__ #else "", "" #endif ); (*G.message)((zvoid *)&G, slide, (ulg)strlen((char *)slide), 0); } /* end function version() */ #endif /* !SFX */ /*********************************/ /* AtheOS extra field functions */ /*********************************/ /* ** Scan the extra fields in extra_field, and look for a AtheOS EF; return a ** pointer to that EF, or NULL if it's not there. */ static uch *scanAtheOSexfield(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, "scanAtheOSexfield: block length %u > rest ef_size %u\n", eb_len, ef_len - EB_HEADSIZE)); break; } if (eb_id == EF_ATHEOS && 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 setAtheOSexfield(): 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 nError; 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 little-endian format because the */ /* Intel i386 port was here first. */ memcpy(&fa_info, ptr, sizeof(struct attr_info)); ptr += sizeof(struct attr_info); if (fa_info.ai_size < 0LL) { Info(slide, 0x201, ((char *)slide, "warning: skipping attribute with invalid length (%Ld)\n", fa_info.ai_size)); break; } attr_data = ptr; ptr += fa_info.ai_size; if (ptr > guard) { /* We've got a truncated attribute. */ Info(slide, 0x201, ((char *)slide, "warning: truncated attribute\n")); break; } /* write_attr() doesn't return count of written bytes now (Syllable 0.5.3)... */ nError = write_attr(fd, attr_name, O_TRUNC, fa_info.ai_type, attr_data, 0, fa_info.ai_size); if (nError < 0) { Info(slide, 0x201, ((char *)slide, "warning: error writing file attribute\n")); } } close(fd); return retval; } static void setAtheOSexfield(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 AtheOS extra field, skipping.\n")); return; } if (size <= EB_BEOS_HLEN) { /* corrupted, unsupported, or truncated */ Info(slide, 0x201, ((char *)slide, "AtheOS extra field is %d bytes, should be at least %d.\n", size, EB_BEOS_HLEN)); return; } if (full_size < (size - EB_BEOS_HLEN)) { Info(slide, 0x201, ((char *)slide, "Skipping attributes: AtheOS extra field is %d bytes, " "data size is %ld.\n", size - EB_BEOS_HLEN, full_size)); return; } /* Find the AtheOS 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 ?IE UNZIP.BCKKQ[UNZIP60.ATHEOS]ATHEOS.C;1cȇcup, if necessary */ if (attrbuff != ptr) { free(attrbuff); } return; } *[UNZIP60.ATHEOS]ATHEOS.H;1+,W./ 4@-Q0123KPWO56x7x89GHJ/* Copyright (c) 1990-2004 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 */ /* atheos.h -- A few handy things for the AtheOS port * * (c) 1997 Chris Herborth (chrish@qnx.com) - BeOS port * (c) 2004 Ruslan Nickolaev (nruslan@hotbox.ru) - AtheOS port * * This is covered under the usual Info-ZIP copyright */ #ifndef _ATHEOS_H_ #define _ATHEOS_H_ #define EB_BE_FL_BADBITS 0xfe /* bits currently undefined */ /* AtheOS 'At' extra-field layout: (same structure as the BeOS 'Be' e.f. layout, only signature and internal conventions of the file attribute data are different...) 'At' - 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 flags & 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. In this case, there should be (ef_size - EB_BEOS_HLEN) bytes of data, and full_size should equal (ef_size - EB_BEOS_HLEN). If the data is compressed, there will be (ef_size - EB_BEOS_HLEN) bytes of compressed data, and full_size bytes of uncompressed data. If a file has absolutely no attributes, there will not be a 'At' extra field. The uncompressed data is arranged like this: attr_name\0 - C string struct attr_info (fields in little-endian format) attr_data (length in attr_info.ai_size) */ #endif /* _ATHEOS_H_ */ *[UNZIP60.ATHEOS]CONTENTS.;1+,./ 4@-Q0123KPWO56y7y89GHJContents of the "atheos" sub-directory for UnZip 5.52 and later: Contents this file README notes from the author of the AtheOS port Makefile makefile for building UnZip athcfg.h AtheOS-specific configuration settings atheos.c AtheOS-specific routines (similar to the BeOS/Unix ones) atheos.h structures for the AtheOS extra field - Ruslan Nickolaev (nruslan@hotbox.ru) *[UNZIP60.ATHEOS]MAKEFILE.;1+,./ 4@-Q0123KPWO56? 7? 89GHJ###################################################################### # # Makefile for Info-ZIP's unzip, unzipsfx, and funzip on AtheOS # Version 5.53 # # Copyright (C) 1998-2006 Info-ZIP # Chris Herborth (chrish@qnx.com) # Copyright (C) 2004 Nikolaev Ruslan (nruslan@hotbox.ru) # # To automatically install the fresh new unzip, use the "install" target: # make -f atheos/Makefile install ###################################################################### SHELL = /bin/bash # Punish those of you not running on SMP hardware... MAKE = make -j 4 -f atheos/Makefile # UnZipSFX flags SL = -o unzipsfx SL2 = $(LF2) # fUnZip flags FL = -o funzip FL2 = $(LF2) # general-purpose stuff CP = cp AS = as RM = rm -f LN = ln -sf CHMOD = chmod E = O = .o M = atheos OSDEP_H = atheos/athcfg.h # define # object files OBJS1 = unzip$O crc32$O crc_i386$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 ubz2err$O unreduce$O unshrink$O zipinfo$O OBJS = $(OBJS1) $(OBJS2) $(OBJS3) $M$O LOBJS = $(OBJS) OBJSDLL = $(OBJS) api$O OBJX = unzipsfx$O crc32_$O crc_i386$O crypt_$O extract_$O fileio_$O globals_$O inflate_$O match_$O process_$O ttyio_$O ubz2err_$O $M_$O LOBJX = $(OBJX) OBJF = funzip$O crc32f$O crc_i386$O cryptf$O globalsf$O inflatef$O ttyiof$O UNZIP_H = unzip.h unzpriv.h globals.h $(OSDEP_H) # installation INSTALL = install manext = 1 prefix = /usr BINDIR = $(prefix)/bin MANDIR = $(prefix)/man/man$(manext) 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 ###################################################################### CC=gcc LD=gcc CF=-O3 -march=i586 -Wall -I. -DPASSWD_FROM_STDIN -DASM_CRC -DUSE_UNSHRINK $(LOCAL_UNZIP) LF=-o unzip LF2= TARGET=$(UNZIPS) ###################################################################### # Helpful targets all: @echo 'TARGET = $(TARGET)' @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 atheos/Makefile' @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) unzipsman: unzips unzip$E: $(OBJS) $(LD) $(LF) $(LOBJS) $(LF2) $(CHMOD) +x unzip$E unzipsfx$E: $(OBJX) $(LD) $(SL) $(LOBJX) $(SL2) $(CHMOD) +x unzipsfx$E 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 crc32.h crypt$O: crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h envargs$O: envargs.c $(UNZIP_H) explode$O: explode.c $(UNZIP_H) extract$O: extract.c $(UNZIP_H) crc32.h crypt.h fileio$O: fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcd@aW UNZIP.BCKQNZIP60.ATHEOS]MAKEFILE.;1aic.h funzip$O: funzip.c $(UNZIP_H) crc32.h crypt.h ttyio.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) crc32.h ttyio$O: ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h ubz2err$O: ubz2err.c $(UNZIP_H) unreduce$O: unreduce.c $(UNZIP_H) unshrink$O: unshrink.c $(UNZIP_H) unzip$O: unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h zipinfo$O: zipinfo.c $(UNZIP_H) crc_i386$O: crc_i386.S $(CC) -E crc_i386.S > crc_i386s.s $(AS) -o $@ crc_i386s.s $(RM) crc_i386s.s # unzipsfx only unzipsfx$O: unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h $(CP) unzip.c unzipsfx.c $(CC) -c $(CF) -DSFX unzipsfx.c $(RM) unzipsfx.c crc32_$O: crc32.c $(UNZIP_H) zip.h crc32.h $(CP) crc32.c crc32_.c $(CC) -c $(CF) -DSFX crc32_.c $(RM) crc32_.c crypt_$O: crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h $(CP) crypt.c crypt_.c $(CC) -c $(CF) -DSFX crypt_.c $(RM) crypt_.c extract_$O: extract.c $(UNZIP_H) crc32.h crypt.h $(CP) extract.c extract_.c $(CC) -c $(CF) -DSFX extract_.c $(RM) extract_.c fileio_$O: fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h $(CP) fileio.c fileio_.c $(CC) -c $(CF) -DSFX fileio_.c $(RM) fileio_.c globals_$O: globals.c $(UNZIP_H) $(CP) globals.c globals_.c $(CC) -c $(CF) -DSFX globals_.c $(RM) globals_.c inflate_$O: inflate.c inflate.h $(UNZIP_H) crypt.h $(CP) inflate.c inflate_.c $(CC) -c $(CF) -DSFX inflate_.c $(RM) inflate_.c match_$O: match.c $(CP) match.c match_.c $(CC) -c $(CF) -DSFX match_.c $(RM) match_.c process_$O: process.c $(UNZIP_H) crc32.h $(CP) process.c process_.c $(CC) -c $(CF) -DSFX process_.c $(RM) process_.c ttyio_$O: ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h $(CP) ttyio.c ttyio_.c $(CC) -c $(CF) -DSFX ttyio_.c $(RM) ttyio_.c ubz2err$O: ubz2err.c $(UNZIP_H) $(CP) ubz2err.c ubz2err_.c $(CC) -c $(CF) -DSFX ubz2err_.c $(RM) ubz2err_.c # funzip only crc32f$O: crc32.c $(UNZIP_H) zip.h crc32.h $(CP) crc32.c crc32f.c $(CC) -c $(CF) -DFUNZIP crc32f.c $(RM) crc32f.c cryptf$O: crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h $(CP) crypt.c cryptf.c $(CC) -c $(CF) -DFUNZIP cryptf.c $(RM) cryptf.c globalsf$O: globals.c $(UNZIP_H) $(CP) globals.c globalsf.c $(CC) -c $(CF) -DFUNZIP globalsf.c $(RM) globalsf.c inflatef$O: inflate.c inflate.h $(UNZIP_H) crypt.h $(CP) inflate.c inflatef.c $(CC) -c $(CF) -DFUNZIP inflatef.c $(RM) inflatef.c ttyiof$O: ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h $(CP) ttyio.c ttyiof.c $(CC) -c $(CF) -DFUNZIP ttyiof.c $(RM) ttyiof.c # AtheOS specific code atheos$O: atheos/atheos.c $(UNZIP_H) unzvers.h atheos/atheos.h $(CC) -c $(CF) atheos/atheos.c # version() not used by unzipsfx, so no unzvers.h dependency atheos_$O: atheos/atheos.c $(UNZIP_H) atheos/atheos.h # unzipsfx only $(CP) atheos/atheos.c atheos_.c $(CC) -c $(CF) -Iatheos -DSFX atheos_.c $(RM) atheos_.c # this really only works for Unix targets, unless E and O specified on cmd line clean: $(RM) $(UNZIPS) $(OBJS) $(OBJF) $(OBJX) api$O apihelp$O crc_gcc$O unzipstb$O install: all $(INSTALL) -m 755 $(UNZIPS) $(BINDIR) $(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) # alternatively, could use zip method: -cd $(BINDIR); $(RM) $(UNZIPS) [etc.] uninstall: $(RM) $(INSTALLEDBIN) $(INSTALLEDMAN) TESTZIP = testmake.zip # the test zipfile # test some basic features of the build test: check check: @echo '##### This is a Unix-specific target. (Just so you know.)' @echo '##### Make sure unzip, funzip and unzipsfx are compiled and' @echo '##### in this directory.' @if test ! -f ./unzip; then \ echo "##### ERROR: can't find ./unzip"; exit 1; fi @if test ! -f ./funzip; then \ echo "##### ERROR: can't find ./funzip"; exit 1; fi @if test ! -f ./unzipsfx; then \ echo "##### ERROR: can't find ./unzipsfx"; exit 1; fi # @if test ! -f $(TESTZIP); then \ echo "##### ERROR: can't find test file $(TESTZIP)"; exit 1; fi # @echo "##### testing extraction" @./unzip -bo $(TESTZIP) testmake.zipinfo @if test ! -f testmake.zipinfo ; 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 echo "OK."; else \ echo "##### WARNING: zipinfo output doesn't match stored version"; \ echo '##### (If the only difference is the file times, compare your'; \ echo '##### timezone with the Central European timezone, which is one'; \ echo '##### hour east of Greenwich but effectively 2 hours east'; \ echo '##### during summer Daylight Savings Time. The upper two'; \ echo '##### lines should correspond to your local time when the'; \ echo '##### files were created, on 19 November 1998 at 10:46pm CET.'; \ echo '##### If the times are consistent, please ignore this warning.)'; \ fi @$(RM) testmake.unzip-Z testmake.zipinfo # @echo '##### testing unzip -d exdir option' @./unzip -bo $(TESTZIP) -d testun notes @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 true; else \ echo '##### ERROR: funzip output disagrees with unzip'; fi # @echo '##### testing unzipsfx (self-extractor)' @cat unzipsfx $(TESTZIP) > testsfx @$(CHMOD) 0700 testsfx @./testsfx -bo notes @if diff notes testun/notes; then true; else \ echo '##### ERROR: unzipsfx file disagrees with unzip'; fi @$(RM) testsfx notes testun/notes testun/notes2 @rmdir testun # @echo '##### testing complete.' *[UNZIP60.ATHEOS]README.;1+,-./ 4@-Q0123KPWO56F7F89GHJUnZip 5.51 for AtheOS/Syllable This port is based on both BeOS and UNIX versions. As BeOS version it can extract specific file attributes. TODO ---- There is only one thing to be fixed: write_attr() should return count of bytes written. However that's a bug related with AFS only. Please report any bugs to Zip-Bugs@lists.wku.edu. If this bug related with AtheOS/Syllable only, you can mail me directly: nruslan@hotbox.ru. - Ruslan Nickolaev (nruslan@hotbox.ru) Sep 06/2004 *[UNZIP60]BEOS.DIR;1+,Z./ 4