?? acorn.c
字號:
/* 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*//*--------------------------------------------------------------------------- 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 */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 DEBUGstatic void printRISCOSexfield(int isdir, ZCONST void *extra_field);#endifstatic int uxtime2acornftime(unsigned *pexadr, unsigned *pldadr, time_t ut);static int mimemap(const char *name);#ifndef SFX/**********************//* Function do_wild() */ /* for porting: dir separator; match(ignore_case) *//**********************/char *do_wild(__G__ wildspec) __GDEF ZCONST char *wildspec; /* only used first time on a given dir */{ static DIR *wild_dir = (DIR *)NULL; static ZCONST char *wildname; static char *dirname, matchname[FILNAMSIZ]; static int notfirstcall=FALSE, have_dirname, dirnamelen; struct dirent *file; /* Even when we're just returning wildspec, we *always* do so in * matchname[]--calling routine is allowed to append four characters * to the returned string, and wildspec may be a pointer to argv[]. */ if (!notfirstcall) { /* first call: must initialize everything */ notfirstcall = TRUE; /* break the wildspec into a directory part and a wildcard filename */ if ((wildname = (ZCONST char *)strrchr(wildspec, '.')) == (ZCONST char *)NULL) { dirname = "."; dirnamelen = 1; have_dirname = FALSE; wildname = wildspec; } else { ++wildname; /* point at character after '/' */ dirnamelen = wildname - wildspec; if ((dirname = (char *)malloc(dirnamelen+1)) == (char *)NULL) { Info(slide, 0x201, ((char *)slide, "warning: cannot allocate wildcard buffers\n")); strcpy(matchname, wildspec); return matchname; /* but maybe filespec was not a wildcard */ } strncpy(dirname, wildspec, dirnamelen); dirname[dirnamelen] = '\0'; /* terminate for strcpy below */ have_dirname = TRUE; } if ((wild_dir = opendir(dirname)) != (DIR *)NULL) { while ((file = readdir(wild_dir)) != (struct dirent *)NULL) { if (file->d_name[0] == '/' && wildname[0] != '/') continue; /* Unix: '*' and '?' do not match leading dot */ if (match(file->d_name, wildname, 0)) { /* 0 == case sens. */ if (have_dirname) { strcpy(matchname, dirname); strcpy(matchname+dirnamelen, file->d_name); } else strcpy(matchname, file->d_name); return matchname; } } /* if we get to here directory is exhausted, so close it */ closedir(wild_dir); wild_dir = (DIR *)NULL; } /* return the raw wildspec in case that works (e.g., directory not * searchable, but filespec was not wild and file is readable) */ strcpy(matchname, wildspec); return matchname; } /* last time through, might have failed opendir but returned raw wildspec */ if (wild_dir == (DIR *)NULL) { notfirstcall = FALSE; /* nothing left to try--reset for new wildspec */ if (have_dirname) free(dirname); return (char *)NULL; } /* If we've gotten this far, we've read and matched at least one entry * successfully (in a previous call), so dirname has been copied into * matchname already. */ while ((file = readdir(wild_dir)) != (struct dirent *)NULL) if (match(file->d_name, wildname, 0)) { /* 0 == don't ignore case */ if (have_dirname) { /* strcpy(matchname, dirname); */ strcpy(matchname+dirnamelen, file->d_name); } else strcpy(matchname, file->d_name); return matchname; } closedir(wild_dir); /* have read at least one dir entry; nothing left */ wild_dir = (DIR *)NULL; notfirstcall = FALSE; /* reset for new wildspec */ if (have_dirname) free(dirname); return (char *)NULL;} /* end function do_wild() */#endif /* !SFX *//**************************//* Function has_NFS_ext() *//**************************/static int has_NFS_ext(const char* name){ int i = strlen(name) - 4; return (i >= 0 && name[i] == ',' && (i > 0 || name[i-1]=='/') && isxdigit(name[i+1]) && isxdigit(name[i+2]) && isxdigit(name[i+3]));} /* end function has_NFS_ext() *//**********************//* Function mapattr() *//**********************/int mapattr(__G) __GDEF{ ulg tmp = G.crec.external_file_attributes; switch (G.pInfo->hostnum) { case AMIGA_: tmp = (unsigned)(tmp>>17 & 7); /* Amiga RWE bits */ G.pInfo->file_attr = (unsigned)(tmp<<6 | tmp<<3 | tmp); break; case THEOS_: tmp &= 0xF1FFFFFFL; if ((tmp & 0xF0000000L) != 0x40000000L) tmp &= 0x01FFFFFFL; /* not a dir, mask all ftype bits */ else tmp &= 0x41FFFFFFL; /* leave directory bit as set */ /* fall through! */ case ACORN_: case UNIX_: case VMS_: case ATARI_: case BEOS_: case QDOS_: case TANDEM_: G.pInfo->file_attr = (unsigned)(tmp >> 16); if (G.pInfo->file_attr != 0 || !G.extra_field) { 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;}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -