acorn.c
上传用户:andy_li
上传日期:2007-01-06
资源大小:1019k
文件大小:29k
源码类别:

压缩解压

开发平台:

MultiPlatform

  1. /*---------------------------------------------------------------------------
  2.   acorn.c
  3.   RISCOS-specific routines for use with Info-ZIP's UnZip 5.2 and later.
  4.   Contains:  do_wild()           <-- generic enough to put in fileio.c?
  5.              mapattr()
  6.              mapname()
  7.              checkdir()
  8.              mkdir()
  9.              isRISCOSexfield()
  10.              setRISCOSexfield()
  11.              printRISCOSexfield()
  12.              close_outfile()
  13.              stamp_file()
  14.              version()
  15.   ---------------------------------------------------------------------------*/
  16. #define UNZIP_INTERNAL
  17. #include "^.unzip.h"
  18. #include "riscos.h"
  19. #define FTYPE_FFF (1<<17)      /* set filetype to &FFF when extracting */
  20. static int created_dir;        /* used in mapname(), checkdir() */
  21. static int renamed_fullpath;   /* ditto */
  22. extern int mkdir(const char *path, int mode);
  23. static int has_NFS_ext(const char *name);
  24. static int uxtime2acornftime(unsigned *pexadr, unsigned *pldadr, time_t ut);
  25. #ifndef SFX
  26. /**********************/
  27. /* Function do_wild() */   /* for porting:  dir separator; match(ignore_case) */
  28. /**********************/
  29. char *do_wild(__G__ wildspec)
  30.     __GDEF
  31.     char *wildspec;         /* only used first time on a given dir */
  32. {
  33.     static DIR *dir = (DIR *)NULL;
  34.     static char *dirname, *wildname, matchname[FILNAMSIZ];
  35.     static int firstcall=TRUE, have_dirname, dirnamelen;
  36.     struct dirent *file;
  37.     /* Even when we're just returning wildspec, we *always* do so in
  38.      * matchname[]--calling routine is allowed to append four characters
  39.      * to the returned string, and wildspec may be a pointer to argv[].
  40.      */
  41.     if (firstcall) {        /* first call:  must initialize everything */
  42.         firstcall = FALSE;
  43.         /* break the wildspec into a directory part and a wildcard filename */
  44.         if ((wildname = strrchr(wildspec, '.')) == (char *)NULL) {
  45.             dirname = ".";
  46.             dirnamelen = 1;
  47.             have_dirname = FALSE;
  48.             wildname = wildspec;
  49.         } else {
  50.             ++wildname;     /* point at character after '/' */
  51.             dirnamelen = wildname - wildspec;
  52.             if ((dirname = (char *)malloc(dirnamelen+1)) == (char *)NULL) {
  53.                 Info(slide, 0x201, ((char *)slide,
  54.                   "warning:  cannot allocate wildcard buffersn"));
  55.                 strcpy(matchname, wildspec);
  56.                 return matchname;   /* but maybe filespec was not a wildcard */
  57.             }
  58.             strncpy(dirname, wildspec, dirnamelen);
  59.             dirname[dirnamelen] = '';   /* terminate for strcpy below */
  60.             have_dirname = TRUE;
  61.         }
  62.         if ((dir = opendir(dirname)) != (DIR *)NULL) {
  63.             while ((file = readdir(dir)) != (struct dirent *)NULL) {
  64.                 if (file->d_name[0] == '/' && wildname[0] != '/')
  65.                     continue;  /* Unix:  '*' and '?' do not match leading dot */
  66.                 if (match(file->d_name, wildname, 0)) {  /* 0 == case sens. */
  67.                     if (have_dirname) {
  68.                         strcpy(matchname, dirname);
  69.                         strcpy(matchname+dirnamelen, file->d_name);
  70.                     } else
  71.                         strcpy(matchname, file->d_name);
  72.                     return matchname;
  73.                 }
  74.             }
  75.             /* if we get to here directory is exhausted, so close it */
  76.             closedir(dir);
  77.             dir = (DIR *)NULL;
  78.         }
  79.         /* return the raw wildspec in case that works (e.g., directory not
  80.          * searchable, but filespec was not wild and file is readable) */
  81.         strcpy(matchname, wildspec);
  82.         return matchname;
  83.     }
  84.     /* last time through, might have failed opendir but returned raw wildspec */
  85.     if (dir == (DIR *)NULL) {
  86.         firstcall = TRUE;  /* nothing left to try--reset for new wildspec */
  87.         if (have_dirname)
  88.             free(dirname);
  89.         return (char *)NULL;
  90.     }
  91.     /* If we've gotten this far, we've read and matched at least one entry
  92.      * successfully (in a previous call), so dirname has been copied into
  93.      * matchname already.
  94.      */
  95.     while ((file = readdir(dir)) != (struct dirent *)NULL)
  96.         if (match(file->d_name, wildname, 0)) {   /* 0 == don't ignore case */
  97.             if (have_dirname) {
  98.                 /* strcpy(matchname, dirname); */
  99.                 strcpy(matchname+dirnamelen, file->d_name);
  100.             } else
  101.                 strcpy(matchname, file->d_name);
  102.             return matchname;
  103.         }
  104.     closedir(dir);     /* have read at least one dir entry; nothing left */
  105.     dir = (DIR *)NULL;
  106.     firstcall = TRUE;  /* reset for new wildspec */
  107.     if (have_dirname)
  108.         free(dirname);
  109.     return (char *)NULL;
  110. } /* end function do_wild() */
  111. #endif /* !SFX */
  112. /**************************/
  113. /* Function has_NFS_ext() */
  114. /**************************/
  115. static int has_NFS_ext(const char* name)
  116. {
  117.   int i = strlen(name) - 4;
  118.   return (i >= 0 && name[i] == ',' && (i > 0 || name[i-1]=='/') &&
  119.           isxdigit(name[i+1]) && isxdigit(name[i+2]) && isxdigit(name[i+3]));
  120. } /* end function has_NFS_ext() */
  121. /**********************/
  122. /* Function mapattr() */
  123. /**********************/
  124. int mapattr(__G)
  125.     __GDEF
  126. {
  127.     ulg tmp = G.crec.external_file_attributes;
  128.     switch (G.pInfo->hostnum) {
  129.         case AMIGA_:
  130.             tmp = (unsigned)(tmp>>17 & 7);   /* Amiga RWE bits */
  131.             G.pInfo->file_attr = (unsigned)(tmp<<6 | tmp<<3 | tmp);
  132.             break;
  133.         case UNIX_:
  134.         case VMS_:
  135.         case ACORN_:
  136.         case ATARI_:
  137.         case BEOS_:
  138.         case QDOS_:
  139.         case TANDEM_:
  140.             G.pInfo->file_attr = (unsigned)(tmp >> 16);
  141.             if (G.pInfo->file_attr != 0 || !G.extra_field) {
  142.                 break;
  143.             } else {
  144.                 /* Some (non-Info-ZIP) implementations of Zip for Unix and
  145.                    VMS (and probably others ??) leave 0 in the upper 16-bit
  146.                    part of the external_file_attributes field. Instead, they
  147.                    store file permission attributes in some extra field.
  148.                    As a work-around, we search for the presence of one of
  149.                    these extra fields and fall back to the MSDOS compatible
  150.                    part of external_file_attributes if one of the known
  151.                    e.f. types has been detected.
  152.                    Later, we might implement extraction of the permission
  153.                    bits from the VMS extra field. But for now, the work-around
  154.                    should be sufficient to provide "readable" extracted files.
  155.                    (For ASI Unix e.f., an experimental remap of the e.f.
  156.                    mode value IS already provided!)
  157.                  */
  158.                 ush ebID;
  159.                 unsigned ebLen;
  160.                 uch *ef = G.extra_field;
  161.                 unsigned ef_len = G.crec.extra_field_length;
  162.                 int r = FALSE;
  163.                 while (!r && ef_len >= EB_HEADSIZE) {
  164.                     ebID = makeword(ef);
  165.                     ebLen = (unsigned)makeword(ef+EB_LEN);
  166.                     if (ebLen > (ef_len - EB_HEADSIZE))
  167.                         /* discoverd some e.f. inconsistency! */
  168.                         break;
  169.                     switch (ebID) {
  170.                       case EF_ASIUNIX:
  171.                         if (ebLen >= (EB_ASI_MODE+2)) {
  172.                             G.pInfo->file_attr =
  173.                               (unsigned)makeword(ef+(EB_HEADSIZE+EB_ASI_MODE));
  174.                             /* force stop of loop: */
  175.                             ef_len = (ebLen + EB_HEADSIZE);
  176.                             break;
  177.                         }
  178.                         /* else: fall through! */
  179.                       case EF_PKVMS:
  180.                         /* "found nondecypherable e.f. with perm. attr" */
  181.                         r = TRUE;
  182.                       default:
  183.                         break;
  184.                     }
  185.                     ef_len -= (ebLen + EB_HEADSIZE);
  186.                     ef += (ebLen + EB_HEADSIZE);
  187.                 }
  188.                 if (!r)
  189.                     break;
  190.             }
  191.             /* fall through! */
  192.         /* all remaining cases:  expand MSDOS read-only bit into write perms */
  193.         case FS_FAT_:
  194.         case FS_HPFS_:
  195.         case FS_NTFS_:
  196.         case MAC_:
  197.         case TOPS20_:
  198.         default:
  199.             tmp = !(tmp & 1) << 1;   /* read-only bit --> write perms bits */
  200.             G.pInfo->file_attr = (unsigned)(0444 | tmp<<6 | tmp<<3 | tmp);
  201.             break;
  202.     } /* end switch (host-OS-created-by) */
  203.     G.pInfo->file_attr&=0xFFFF;
  204.     G.pInfo->file_attr|=(0xFFDu<<20);
  205.     if (has_NFS_ext(G.filename)) {
  206.       int ftype=strtol(G.filename+strlen(G.filename)-3,NULL,16)&0xFFF;
  207.       G.pInfo->file_attr = (G.pInfo->file_attr & 0x000FFFFF) | (ftype<<20);
  208.     }
  209.     else if (G.crec.internal_file_attributes & 1) {
  210.       G.pInfo->file_attr = (G.pInfo->file_attr & 0x000FFFFF) | (0xFFFu<<20);
  211.     }
  212.     return 0;
  213. } /* end function mapattr() */
  214. /************************/
  215. /*  Function mapname()  */
  216. /************************/
  217.                              /* return 0 if no error, 1 if caution (filename */
  218. int mapname(__G__ renamed)   /*  truncated), 2 if warning (skip file because */
  219.     __GDEF                   /*  dir doesn't exist), 3 if error (skip file), */
  220.     int renamed;             /*  or 10 if out of memory (skip file) */
  221. {                            /*  [also IZ_VOL_LABEL, IZ_CREATED_DIR] */
  222.     char pathcomp[FILNAMSIZ];    /* path-component buffer */
  223.     char *pp, *cp=(char *)NULL;  /* character pointers */
  224.     char *lastsemi=(char *)NULL; /* pointer to last semi-colon in pathcomp */
  225.     int quote = FALSE;           /* flags */
  226.     int error = 0;
  227.     register unsigned workch;    /* hold the character being tested */
  228.     char *checkswap=NULL;        /* pointer the the extension to check or NULL */
  229. /*---------------------------------------------------------------------------
  230.     Initialize various pointers and counters and stuff.
  231.   ---------------------------------------------------------------------------*/
  232.     if (G.pInfo->vollabel)
  233.         return IZ_VOL_LABEL;    /* can't set disk volume labels in RISCOS */
  234.     /* can create path as long as not just freshening, or if user told us */
  235.     G.create_dirs = (!uO.fflag || renamed);
  236.     created_dir = FALSE;        /* not yet */
  237.     /* user gave full pathname:  don't prepend rootpath */
  238.     renamed_fullpath = (renamed && (*G.filename == '/'));
  239.     if (checkdir(__G__ (char *)NULL, INIT) == 10)
  240.         return 10;              /* initialize path buffer, unless no memory */
  241.     *pathcomp = '';           /* initialize translation buffer */
  242.     pp = pathcomp;              /* point to translation buffer */
  243.     if (uO.jflag)               /* junking directories */
  244.         cp = (char *)strrchr(G.filename, '/');
  245.     if (cp == (char *)NULL)     /* no '/' or not junking dirs */
  246.         cp = G.filename;        /* point to internal zipfile-member pathname */
  247.     else
  248.         ++cp;                   /* point to start of last component of path */
  249. /*---------------------------------------------------------------------------
  250.     Begin main loop through characters in filename.
  251.   ---------------------------------------------------------------------------*/
  252.     while ((workch = (uch)*cp++) != 0) {
  253.         if (quote) {                 /* if character quoted, */
  254.             *pp++ = (char)workch;    /*  include it literally */
  255.             quote = FALSE;
  256.         } else
  257.             switch (workch) {
  258.             case '/':             /* can assume -j flag not given */
  259.                 *pp = '';
  260.                 if ((error = checkdir(__G__ pathcomp, APPEND_DIR)) > 1)
  261.                     return error;
  262.                 pp = pathcomp;    /* reset conversion buffer for next piece */
  263.                 lastsemi = (char *)NULL; /* leave directory semi-colons alone */
  264.                 checkswap=NULL;  /* reset checking when starting a new leafname */
  265.                 break;
  266.             case ';':             /* VMS version (or DEC-20 attrib?) */
  267.                 lastsemi = pp;
  268.                 *pp++ = ';';      /* keep for now; remove VMS ";##" */
  269.                 break;            /*  later, if requested */
  270.             case '26':          /* control-V quote for special chars */
  271.                 quote = TRUE;     /* set flag for next character */
  272.                 break;
  273.             case ' ':             /* change spaces to hard-spaces */
  274.                 *pp++ = 160;
  275.                 break;
  276.             case ':':             /* change ':' to '