Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.   Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.
  3.  
  4.   See the accompanying file LICENSE, version 2000-Apr-09 or later
  5.   (the contents of which are also included in unzip.h) for terms of use.
  6.   If, for some reason, all these files are missing, the Info-ZIP license
  7.   also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
  8. */
  9. /*---------------------------------------------------------------------------
  10.  
  11.   macos.c
  12.  
  13.   Macintosh-specific routines for use with Info-ZIP's UnZip 5.4 and later.
  14.  
  15.   Contains:
  16.                     do_wild ()
  17.                     mapattr ()
  18.                     checkdir ()
  19.                     version ()
  20.                     macmkdir ()
  21.                     macopen ()
  22.                     maccreat ()
  23.                     macread ()
  24.                     macwrite ()
  25.                     macclose ()
  26.                     maclseek ()
  27.                     BuildMacFilename()
  28.                     SetFinderInfo ()
  29.                     isMacOSexfield ()
  30.                     makePPClong ()
  31.                     makePPCword ()
  32.                     PrintMacExtraInfo ()
  33.                     GetExtraFieldData ()
  34.                     DecodeMac3ExtraField ()
  35.                     DecodeJLEEextraField ()
  36.                     PrintTextEncoding ()
  37.                     MacGlobalsInit ()
  38.  
  39.   ---------------------------------------------------------------------------*/
  40.  
  41.  
  42. /*****************************************************************************/
  43. /*  Includes                                                                 */
  44. /*****************************************************************************/
  45.  
  46. #define UNZIP_INTERNAL
  47. #include "unzip.h"
  48.  
  49. #include <script.h>
  50. #include <sound.h>
  51.  
  52. #include "pathname.h"
  53. #include "helpers.h"
  54. #include "macstuff.h"
  55. #include "mactime.h"
  56. #include "macbin3.h"
  57.  
  58. /*****************************************************************************/
  59. /*  Macros, typedefs                                                         */
  60. /*****************************************************************************/
  61.  
  62. /* disable ZipIt support
  63. #define SwitchZIPITefSupportOff */
  64.  
  65. #define read_only   file_attr       /* for readability only */
  66. #define EB_MAX_OF_VARDATA   1300    /* max possible datasize of extra-field */
  67.  
  68. #ifdef WILD_STOP_AT_DIR
  69. #  define WESEP     , (oU.W_flag ? ':' : '\0')
  70. #else
  71. #  define WESEP
  72. #endif
  73.  
  74.  
  75. /*****************************************************************************/
  76. /*  Global Vars                                                              */
  77. /*****************************************************************************/
  78.  
  79. /*  Note: sizeof() returns the size of this allusion
  80.           13 is current length of "XtraStuf.mac:"      */
  81. extern const char ResourceMark[13]; /* var is initialized in file pathname.c */
  82.  
  83. Boolean MacUnzip_Noisy;            /* MacUnzip_Noisy is also used by console */
  84.  
  85. MACINFO newExtraField;  /* contains all extra-field data */
  86. short MacZipMode;
  87.  
  88.  
  89. /*****************************************************************************/
  90. /*  Module level Vars                                                        */
  91. /*****************************************************************************/
  92.  
  93. static const char MacPathEnd = ':';   /* the Macintosh dir separator */
  94.  
  95. static int created_dir;        /* used in mapname(), checkdir() */
  96. static int renamed_fullpath;   /* ditto */
  97. static FSSpec CurrentFile;
  98.  
  99. static Boolean OpenZipFile = true;
  100. static Boolean UseUT_ExtraField     = false;
  101. static Boolean IgnoreEF_Macfilename = false;
  102. static short fileSystemID;
  103.  
  104. static uch *attrbuff = NULL;
  105. static uch *malloced_attrbuff = NULL;
  106.  
  107. const short HFS_fileSystem = 0;
  108.  
  109. /*****************************************************************************/
  110. /*  Prototypes                                                               */
  111. /*****************************************************************************/
  112.  
  113. extern char *GetUnZipInfoVersions(void);
  114.  
  115. static OSErr SetFinderInfo(__GPRO__ int SetTime, FSSpec *spec, MACINFO *mi);
  116. static Boolean GetExtraFieldData(short *MacZipMode, MACINFO *mi);
  117. static uch *scanMacOSexfield(uch *ef_ptr, unsigned ef_len,
  118.                              short *MacZipMode);
  119. static Boolean isMacOSexfield(unsigned id, unsigned size, short *MacZipMode);
  120. static void PrintMacExtraInfo(MACINFO *mi);
  121. static OSErr SetFileTime(__GPRO);
  122. static void DecodeMac3ExtraField(ZCONST uch *buff, MACINFO *mi);
  123. static void DecodeJLEEextraField(ZCONST uch *buff, MACINFO *mi);
  124. static void DecodeZPITextraField(ZCONST uch *buff, MACINFO *mi);
  125. static char *PrintTextEncoding(short script);
  126. static void BuildMacFilename(void);
  127.  
  128. /*****************************************************************************/
  129. /*  Constants (strings, etc.)                                                */
  130. /*****************************************************************************/
  131.  
  132. static ZCONST char Far CannotCreateFile[] = "error:  cannot create %s\n";
  133.  
  134. static ZCONST char Far OutOfMemEF[] = "Can't allocate memory to uncompress"\
  135.                                       " file attributes.\n";
  136.  
  137. static ZCONST char Far ErrUncmpEF[] = "Error uncompressing file attributes.\n";
  138.  
  139. static ZCONST char Far No64Time[]   = "Don't support 64 bit Timevalues; get "\
  140.                                       " a newer version of MacZip \n";
  141.  
  142. static ZCONST char Far NoUniCode[]  = "Don't support Unicoded Filenames; get"\
  143.                                       " a newer version of MacZip\n";
  144.  
  145. static ZCONST char Far ZitIt_EF[]   = "warning: found ZipIt extra field  "\
  146.                                       " -> file is probably not "\
  147.                                       "usable!!\n";
  148.  
  149. static ZCONST char Far CantAllocateWildcard[] =
  150.     "warning:  cannot allocate wildcard buffers\n";
  151.  
  152. static ZCONST char Far ErrNoTimeSet[] = "error (%d): cannot set the time for"\
  153.                                         " %s\n";
  154.  
  155. static ZCONST char Far MacBinaryMsg[] = "\n   ... decoding MacBinary ";
  156.  
  157. static ZCONST char Far WarnDirTraversSkip[] =
  158.   "warning:  skipped \"../\" path component(s) in %s\n";
  159.  
  160. static ZCONST char Far Creating[] = "   creating: %s\n";
  161.  
  162. static ZCONST char Far ConversionFailed[] =
  163.   "mapname:  conversion of %s failed\n";
  164.  
  165. static ZCONST char Far PathTooLong[] = "checkdir error:  path too long: %s\n";
  166.  
  167. static ZCONST char Far CantCreateDir[] = "checkdir error:  cannot create %s\n\
  168.                 unable to process %s.\n";
  169.  
  170. static ZCONST char Far DirIsntDirectory[] =
  171.   "checkdir error:  %s exists but is not directory\n\
  172.                 unable to process %s.\n";
  173.  
  174. static ZCONST char Far PathTooLongTrunc[] =
  175.   "checkdir warning:  path too long; truncating\n                   %s\n\
  176.                -> %s\n";
  177.  
  178. static ZCONST char Far CantCreateExtractDir[] =
  179.   "checkdir:  cannot create extraction directory: %s\n";
  180.  
  181. static ZCONST char Far FilenameToLong[] =
  182.   "Filename is to long; truncated: %s\n";
  183.  
  184. /*****************************************************************************/
  185. /*  Functions                                                                */
  186. /*****************************************************************************/
  187.  
  188. #ifndef SFX
  189.  
  190. /**********************/
  191. /* Function do_wild() */   /* for porting: dir separator; match(ignore_case) */
  192. /**********************/
  193.  
  194. char *do_wild(__G__ wildspec)
  195.     __GDEF
  196.     ZCONST char *wildspec;  /* only used first time on a given dir */
  197. {
  198.     static DIR *wild_dir = (DIR *)NULL;
  199.     static ZCONST char *wildname;
  200.     static char *dirname, matchname[FILNAMSIZ];
  201.     static int notfirstcall=FALSE, have_dirname;
  202.     static unsigned long dirnamelen;
  203.     struct dirent *file;
  204.  
  205.     /* Even when we're just returning wildspec, we *always* do so in
  206.      * matchname[]--calling routine is allowed to append four characters
  207.      * to the returned string, and wildspec may be a pointer to argv[].
  208.      */
  209.     if (!notfirstcall) {    /* first call:  must initialize everything */
  210.         notfirstcall = TRUE;
  211.  
  212.         /* Folder names must always end with a colon */
  213.         if (uO.exdir[strlen(uO.exdir)-1] != ':') {
  214.             strcat(uO.exdir, ":");
  215.         }
  216.  
  217.         MacUnzip_Noisy = !uO.qflag;
  218.  
  219.         if (MacUnzip_Noisy) printf("%s \n\n", GetUnZipInfoVersions());
  220.  
  221.         /* break the wildspec into a directory part and a wildcard filename */
  222.         if ((wildname = (ZCONST char *)strrchr(wildspec, ':')) ==
  223.             (ZCONST char *)NULL) {
  224.             dirname = ":";
  225.             dirnamelen = 1;
  226.             have_dirname = FALSE;
  227.             wildname = wildspec;
  228.         } else {
  229.             ++wildname;     /* point at character after ':' */
  230.             dirnamelen = wildname - wildspec;
  231.             if ((dirname = (char *)malloc(dirnamelen+1)) == (char *)NULL) {
  232.                 Info(slide, 0x201, ((char *)slide,
  233.                   LoadFarString(CantAllocateWildcard)));
  234.                 strncpy(matchname, wildspec, FILNAMSIZ);
  235.                 matchname[FILNAMSIZ-1] = '\0';
  236.                 return matchname;   /* but maybe filespec was not a wildcard */
  237.             }
  238.             strncpy(dirname, wildspec, dirnamelen);
  239.             dirname[dirnamelen] = '\0';   /* terminate for strcpy below */
  240.             have_dirname = TRUE;
  241.         }
  242.  
  243.         if ((wild_dir = opendir(dirname)) != (DIR *)NULL) {
  244.             while ((file = readdir(wild_dir)) != (struct dirent *)NULL) {
  245.                 if (match(file->d_name, wildname, 0 WESEP)) { /* 0=case sens.*/
  246.                     if (have_dirname) {
  247.                         strcpy(matchname, dirname);
  248.                         strcpy(matchname+dirnamelen, file->d_name);
  249.                     } else
  250.                         strcpy(matchname, file->d_name);
  251.                     return matchname;
  252.                 }
  253.             }
  254.             /* if we get to here directory is exhausted, so close it */
  255.             closedir(wild_dir);
  256.             wild_dir = (DIR *)NULL;
  257.         }
  258.  
  259.         /* return the raw wildspec in case that works (e.g., directory not
  260.          * searchable, but filespec was not wild and file is readable) */
  261.         strncpy(matchname, wildspec, FILNAMSIZ);
  262.         matchname[FILNAMSIZ-1] = '\0';
  263.         return matchname;
  264.     }
  265.  
  266.     /* last time through, might have failed opendir but returned raw wildspec */
  267.     if (wild_dir == (DIR *)NULL) {
  268.         notfirstcall = FALSE; /* nothing left to try--reset for new wildspec */
  269.         if (have_dirname)
  270.             free(dirname);
  271.         return (char *)NULL;
  272.     }
  273.  
  274.     /* If we've gotten this far, we've read and matched at least one entry
  275.      * successfully (in a previous call), so dirname has been copied into
  276.      * matchname already.
  277.      */
  278.     while ((file = readdir(wild_dir)) != (struct dirent *)NULL)
  279.         if (match(file->d_name, wildname, 0 WESEP)) {   /* 0 == case sens. */
  280.             if (have_dirname) {
  281.                 /* strcpy(matchname, dirname); */
  282.                 strcpy(matchname+dirnamelen, file->d_name);
  283.             } else
  284.                 strcpy(matchname, file->d_name);
  285.             return matchname;
  286.         }
  287.  
  288.     closedir(wild_dir);     /* have read at least one entry; nothing left */
  289.     wild_dir = (DIR *)NULL;
  290.     notfirstcall = FALSE;   /* reset for new wildspec */
  291.     if (have_dirname)
  292.         free(dirname);
  293.     return (char *)NULL;
  294.  
  295. } /* end function do_wild() */
  296.  
  297. #endif /* !SFX */
  298.  
  299.  
  300.  
  301.  
  302.  
  303. /***************************/
  304. /* Function open_outfile() */
  305. /***************************/
  306.  
  307. int open_outfile(__G)         /* return 1 if fail */
  308.     __GDEF
  309. {
  310.     short outfd, fDataFork = true;
  311.  
  312. #ifdef DLL
  313.     if (G.redirect_data)
  314.         return (redirect_outfile(__G) == FALSE);
  315. #endif
  316.     Trace((stderr, "open_outfile:  trying to open (%s) for writing\n",
  317.       FnFilter1(G.filename)));
  318.  
  319.     if (!uO.aflag) {
  320.          /* unknown type documents */
  321.          /* all files are considered to be of type 'TEXT' and creator 'hscd' */
  322.          /* this is the default type for CDROM ISO-9660 without Apple extensions */
  323.         newExtraField.fpb.hFileInfo.ioFlFndrInfo.fdType    =  'TEXT';
  324.         newExtraField.fpb.hFileInfo.ioFlFndrInfo.fdCreator =  'hscd';
  325.     } else {
  326.      /* unknown text-files defaults to 'TEXT' */
  327.         newExtraField.fpb.hFileInfo.ioFlFndrInfo.fdType    =  'TEXT';
  328.      /* Bare Bones BBEdit */
  329.         newExtraField.fpb.hFileInfo.ioFlFndrInfo.fdCreator =  'R*ch';
  330.     }
  331.  
  332.     BuildMacFilename();
  333.  
  334.     if  (MacZipMode <= TomBrownZipIt2_EF)
  335.         {
  336.         fDataFork = true;
  337.         }
  338.     else
  339.         {
  340.         fDataFork = (newExtraField.flags & EB_M3_FL_DATFRK) ? TRUE : FALSE;
  341.         }
  342.  
  343.  
  344.     if ((outfd = maccreat(G.filename)) != -1) {
  345.         outfd = macopen(G.filename, (fDataFork) ? 1 : 2);
  346.     }
  347.  
  348.     if (outfd == -1) {
  349.         G.outfile = (FILE *)NULL;
  350.         Info(slide, 0x401, ((char *)slide, LoadFarString(CannotCreateFile),
  351.           FnFilter1(G.filename)));
  352.         return 1;
  353.     }
  354.     G.outfile = (FILE *)outfd;
  355.     Trace((stderr, "open_outfile:  successfully opened (%s) for writing\n",
  356.       FnFilter1(G.filename)));
  357.  
  358.     return 0;
  359.  
  360. } /* end function open_outfile() */
  361.  
  362.  
  363.  
  364.  
  365.  
  366. /**********************/
  367. /* Function mapattr() */
  368. /**********************/
  369.  
  370. int mapattr(__G)
  371.     __GDEF
  372. {
  373.     /* only care about read-only bit, so just look at MS-DOS side of attrs */
  374.     G.pInfo->read_only = (unsigned)(G.crec.external_file_attributes & 1);
  375.     return 0;
  376.  
  377. } /* end function mapattr() */
  378.  
  379.  
  380.  
  381.  
  382.  
  383. /************************/
  384. /*  Function mapname()  */
  385. /************************/
  386.  
  387. int mapname(__G__ renamed)
  388.     __GDEF
  389.     int renamed;
  390. /*
  391.  * returns:
  392.  *  MPN_OK          - no problem detected
  393.  *  MPN_INF_TRUNC   - caution (truncated filename)
  394.  *  MPN_INF_SKIP    - info "skip entry" (dir doesn't exist)
  395.  *  MPN_ERR_SKIP    - error -> skip entry
  396.  *  MPN_ERR_TOOLONG - error -> path is too long
  397.  *  MPN_NOMEM       - error (memory allocation failed) -> skip entry
  398.  *  [also MPN_VOL_LABEL, MPN_CREATED_DIR]
  399.  */
  400. {
  401.     char pathcomp[FILNAMSIZ];      /* path-component buffer */
  402.     char *pp, *cp=(char *)NULL;    /* character pointers */
  403.     char *lastsemi=(char *)NULL;   /* pointer to last semi-colon in pathcomp */
  404.     int killed_ddot = FALSE;       /* is set when skipping "../" pathcomp */
  405.     int error = MPN_OK;
  406.     register unsigned workch;      /* hold the character being tested */
  407.  
  408.  
  409. /*---------------------------------------------------------------------------
  410.     Initialize various pointers and counters and stuff.
  411.   ---------------------------------------------------------------------------*/
  412.  
  413.     if (G.pInfo->vollabel)
  414.         return MPN_VOL_LABEL;   /* can't set disk volume labels on Macintosh */
  415.  
  416.     /* can create path as long as not just freshening, or if user told us */
  417.     G.create_dirs = (!uO.fflag || renamed);
  418.  
  419.     created_dir = FALSE;        /* not yet */
  420.  
  421.     /* user gave full pathname:  don't prepend rootpath */
  422.     renamed_fullpath = (renamed && (*G.filename == '/'));
  423.  
  424.     if (checkdir(__G__ (char *)NULL, INIT) == MPN_NOMEM)
  425.         return MPN_NOMEM;       /* initialize path buffer, unless no memory */
  426.  
  427.     *pathcomp = '\0';           /* initialize translation buffer */
  428.     pp = pathcomp;              /* point to translation buffer */
  429.  
  430.     if (uO.jflag)               /* junking directories */
  431.         cp = (char *)strrchr(G.filename, '/');
  432.     if (cp == (char *)NULL) {   /* no '/' or not junking dirs */
  433.         cp = G.filename;        /* point to internal zipfile-member pathname */
  434.         if (renamed_fullpath)
  435.             ++cp;               /* skip over leading '/' */
  436.     } else
  437.         ++cp;                   /* point to start of last component of path */
  438.  
  439. /*---------------------------------------------------------------------------
  440.     Begin main loop through characters in filename.
  441.   ---------------------------------------------------------------------------*/
  442.  
  443.     while ((workch = (uch)*cp++) != 0) {
  444.  
  445.         switch (workch) {
  446.             case '/':             /* can assume -j flag not given */
  447.                 *pp = '\0';
  448.                 if (strcmp(pathcomp, ".") == 0) {
  449.                     /* don't bother appending "./" to the path */
  450.                     *pathcomp = '\0';
  451.                 } else if (!uO.ddotflag && strcmp(pathcomp, "..") == 0) {
  452.                     /* "../" dir traversal detected, skip over it */
  453.                     *pathcomp = '\0';
  454.                     killed_ddot = TRUE;     /* set "show message" flag */
  455.                 }
  456.                 /* when path component is not empty, append it now */
  457.                 if (*pathcomp != '\0' &&
  458.                     ((error = checkdir(__G__ pathcomp, APPEND_DIR))
  459.                      & MPN_MASK) > MPN_INF_TRUNC)
  460.                     return error;
  461.                 pp = pathcomp;    /* reset conversion buffer for next piece */
  462.                 lastsemi = (char *)NULL; /* leave direct. semi-colons alone */
  463.                 break;
  464.  
  465.             case ':':
  466.                 *pp++ = '/';      /* ':' is a pathseperator for HFS  */
  467.                 break;
  468.  
  469.             case ';':             /* VMS version (or DEC-20 attrib?) */
  470.                 lastsemi = pp;         /* keep for now; remove VMS ";##" */
  471.                 *pp++ = (char)workch;  /*  later, if requested */
  472.                 break;
  473.  
  474.             default:
  475.                 /* allow European characters in filenames: */
  476.                 if (isprint(workch) || (128 <= workch && workch <= 254))
  477.                     *pp++ = (char)workch;
  478.         } /* end switch */
  479.  
  480.     } /* end while loop */
  481.  
  482.     /* Show warning when stripping insecure "parent dir" path components */
  483.     if (killed_ddot && QCOND2) {
  484.         Info(slide, 0, ((char *)slide, LoadFarString(WarnDirTraversSkip),
  485.           FnFilter1(G.filename)));
  486.         if (!(error & ~MPN_MASK))
  487.             error = (error & MPN_MASK) | PK_WARN;
  488.     }
  489.  
  490. /*---------------------------------------------------------------------------
  491.     Report if directory was created (and no file to create:  filename ended
  492.     in '/'), check name to be sure it exists, and combine path and name be-
  493.     fore exiting.
  494.   ---------------------------------------------------------------------------*/
  495.  
  496.     if (G.filename[strlen(G.filename) - 1] == '/') {
  497.         checkdir(__G__ G.filename, GETPATH);
  498.         if (created_dir) {
  499.             if (QCOND2) {
  500.                 Info(slide, 0, ((char *)slide, LoadFarString(Creating),
  501.                   FnFilter1(G.filename)));
  502.             }
  503.             /* set dir time (note trailing '/') */
  504.             return (error & ~MPN_MASK) | MPN_CREATED_DIR;
  505.         }
  506.         /* dir existed already; don't look for data to extract */
  507.         return (error & ~MPN_MASK) | MPN_INF_SKIP;
  508.     }
  509.  
  510.     *pp = '\0';                   /* done with pathcomp:  terminate it */
  511.  
  512.     /* if not saving them, remove VMS version numbers (appended ";###") */
  513.     if (!uO.V_flag && lastsemi) {
  514.         pp = lastsemi + 1;
  515.         while (isdigit((uch)(*pp)))
  516.             ++pp;
  517.         if (*pp == '\0')          /* only digits between ';' and end:  nuke */
  518.             *lastsemi = '\0';
  519.     }
  520.  
  521.     if (*pathcomp == '\0') {
  522.         Info(slide, 1, ((char *)slide, LoadFarString(ConversionFailed),
  523.           FnFilter1(G.filename)));
  524.         return (error & ~MPN_MASK) | MPN_ERR_SKIP;
  525.     }
  526.  
  527.     checkdir(__G__ pathcomp, APPEND_NAME);  /* returns 1 if truncated: care? */
  528.     checkdir(__G__ G.filename, GETPATH);
  529.  
  530.     return error;
  531.  
  532. } /* end function mapname() */
  533.  
  534.  
  535.  
  536.  
  537.  
  538. /***********************/
  539. /* Function checkdir() */
  540. /***********************/
  541.  
  542. int checkdir(__G__ pathcomp, flag)
  543.     __GDEF
  544.     char *pathcomp;
  545.     int flag;
  546. /*
  547.  * returns:
  548.  *  MPN_OK          - no problem detected
  549.  *  MPN_INF_TRUNC   - (on APPEND_NAME) truncated filename
  550.  *  MPN_INF_SKIP    - path doesn't exist, not allowed to create
  551.  *  MPN_ERR_SKIP    - path doesn't exist, tried to create and failed; or path
  552.  *                    exists and is not a directory, but is supposed to be
  553.  *  MPN_ERR_TOOLONG - path is too long
  554.  *  MPN_NOMEM       - can't allocate memory for filename buffers
  555.  */
  556. {
  557.     static int rootlen = 0;   /* length of rootpath */
  558.     static char *rootpath;    /* user's "extract-to" directory */
  559.     static char *buildpath;   /* full path (so far) to extracted file */
  560.     static char *end;         /* pointer to end of buildpath ('\0') */
  561.  
  562. #   define FN_MASK   7
  563. #   define FUNCTION  (flag & FN_MASK)
  564.  
  565.  
  566. /*---------------------------------------------------------------------------
  567.     APPEND_DIR:  append the path component to the path being built and check
  568.     for its existence.  If doesn't exist and we are creating directories, do
  569.     so for this one; else signal success or error as appropriate.
  570.   ---------------------------------------------------------------------------*/
  571.  
  572.     if (FUNCTION == APPEND_DIR) {
  573.         int too_long = FALSE;
  574. #ifdef SHORT_NAMES
  575.         char *old_end = end;
  576. #endif
  577.  
  578.         Trace((stderr, "appending dir segment [%s]\n", FnFilter1(pathcomp)));
  579.         while ((*end = *pathcomp++) != '\0')
  580.             ++end;
  581. #ifdef SHORT_NAMES   /* path components restricted to 14 chars, typically */
  582.         if ((end-old_end) > NAME_MAX)
  583.             *(end = old_end + NAME_MAX) = '\0';
  584. #endif
  585.  
  586.         /* GRR:  could do better check, see if overrunning buffer as we go:
  587.          * check end-buildpath after each append, set warning variable if
  588.          * within 20 of FILNAMSIZ; then if var set, do careful check when
  589.          * appending.  Clear variable when begin new path. */
  590.  
  591.         if ((end-buildpath) > NAME_MAX-3)   /* need ':', one-char name, '\0' */
  592.             too_long = TRUE;                /* check if extracting directory? */
  593.         if (stat(buildpath, &G.statbuf)) {  /* path doesn't exist */
  594.             if (!G.create_dirs) { /* told not to create (freshening) */
  595.                 free(buildpath);
  596.                 return MPN_INF_SKIP;    /* path doesn't exist: nothing to do */
  597.             }
  598.             if (too_long) {
  599.                 Info(slide, 1, ((char *)slide, LoadFarString(PathTooLong),
  600.                   FnFilter1(buildpath)));
  601.                 free(buildpath);
  602.                 /* no room for filenames:  fatal */
  603.                 return MPN_ERR_TOOLONG;
  604.             }
  605.             if (macmkdir(buildpath) == -1) {   /* create the directory */
  606.                 Info(slide, 1, ((char *)slide, LoadFarString(CantCreateDir),
  607.                   FnFilter2(buildpath), FnFilter1(G.filename)));
  608.                 free(buildpath);
  609.                 /* path didn't exist, tried to create, failed */
  610.                 return MPN_ERR_SKIP;
  611.             }
  612.             created_dir = TRUE;
  613.         } else if (!S_ISDIR(G.statbuf.st_mode)) {
  614.             Info(slide, 1, ((char *)slide, LoadFarString(DirIsntDirectory),
  615.               FnFilter2(buildpath), FnFilter1(G.filename)));
  616.             free(buildpath);
  617.             /* path existed but wasn't dir */
  618.             return MPN_ERR_SKIP;
  619.         }
  620.         if (too_long) {
  621.             Info(slide, 1, ((char *)slide, LoadFarString(PathTooLong),
  622.               FnFilter1(buildpath)));
  623.             free(buildpath);
  624.             /* no room for filenames:  fatal */
  625.             return MPN_ERR_TOOLONG;
  626.         }
  627.         *end++ = ':';
  628.         *end = '\0';
  629.         Trace((stderr, "buildpath now = [%s]\n", FnFilter1(buildpath)));
  630.         return MPN_OK;
  631.  
  632.     } /* end if (FUNCTION == APPEND_DIR) */
  633.  
  634. /*---------------------------------------------------------------------------
  635.     GETPATH:  copy full path to the string pointed at by pathcomp, and free
  636.     buildpath.
  637.   ---------------------------------------------------------------------------*/
  638.  
  639.     if (FUNCTION == GETPATH) {
  640.         strcpy(pathcomp, buildpath);
  641.         Trace((stderr, "getting and freeing path [%s]\n",
  642.           FnFilter1(pathcomp)));
  643.         free(buildpath);
  644.         buildpath = end = (char *)NULL;
  645.         return MPN_OK;
  646.     }
  647.  
  648. /*---------------------------------------------------------------------------
  649.     APPEND_NAME:  assume the path component is the filename; append it and
  650.     return without checking for existence.
  651.   ---------------------------------------------------------------------------*/
  652.  
  653.     if (FUNCTION == APPEND_NAME) {
  654. #ifdef SHORT_NAMES
  655.         char *old_end = end;
  656. #endif
  657.  
  658.         Trace((stderr, "appending filename [%s]\n", FnFilter1(pathcomp)));
  659.         while ((*end = *pathcomp++) != '\0') {
  660.             ++end;
  661. #ifdef SHORT_NAMES  /* truncate name at 14 characters, typically */
  662.             if ((end-old_end) > NAME_MAX)
  663.                 *(end = old_end + NAME_MAX) = '\0';
  664. #endif
  665.             if ((end-buildpath) >= NAME_MAX) {
  666.                 *--end = '\0';
  667.                 Info(slide, 0x201, ((char *)slide,
  668.                   LoadFarString(PathTooLongTrunc),
  669.                   FnFilter1(G.filename), FnFilter2(buildpath)));
  670.                 return MPN_INF_TRUNC;   /* filename truncated */
  671.             }
  672.         }
  673.         Trace((stderr, "buildpath now = [%s]\n", FnFilter1(buildpath)));
  674.         /* could check for existence here, prompt for new name... */
  675.         return MPN_OK;
  676.     }
  677.  
  678. /*---------------------------------------------------------------------------
  679.     INIT:  allocate and initialize buffer space for the file currently being
  680.     extracted.  If file was renamed with an absolute path, don't prepend the
  681.     extract-to path.
  682.   ---------------------------------------------------------------------------*/
  683.  
  684.     if (FUNCTION == INIT) {
  685.         Trace((stderr, "initializing buildpath to "));
  686.         if ((buildpath = (char *)malloc(strlen(G.filename)+rootlen+2))
  687.             == (char *)NULL)
  688.             return MPN_NOMEM;
  689.         if ((rootlen > 0) && !renamed_fullpath) {
  690.             strcpy(buildpath, rootpath);
  691.             end = buildpath + rootlen;
  692.         } else {
  693.             end = buildpath;
  694.             if (!renamed_fullpath && !uO.jflag) {
  695.                 *end++ = ':';           /* indicate relative path */
  696.             }
  697.             *end = '\0';
  698.         }
  699.         Trace((stderr, "[%s]\n", FnFilter1(buildpath)));
  700.         return MPN_OK;
  701.     }
  702.  
  703. /*---------------------------------------------------------------------------
  704.     ROOT:  if appropriate, store the path in rootpath and create it if
  705.     necessary; else assume it's a zipfile member and return.  This path
  706.     segment gets used in extracting all members from every zipfile specified
  707.     on the command line.
  708.   ---------------------------------------------------------------------------*/
  709.  
  710. #if (!defined(SFX) || defined(SFX_EXDIR))
  711.     if (FUNCTION == ROOT) {
  712.         Trace((stderr, "initializing root path to [%s]\n",
  713.           FnFilter1pathcomp)));
  714.         if (pathcomp == (char *)NULL) {
  715.             rootlen = 0;
  716.             return MPN_OK;
  717.         }
  718.         if (rootlen > 0)        /* rootpath was already set, nothing to do */
  719.             return MPN_OK;
  720.         if ((rootlen = strlen(pathcomp)) > 0) {
  721.             char *tmproot;
  722.  
  723.             if ((tmproot = (char *)malloc(rootlen+2)) == (char *)NULL) {
  724.                 rootlen = 0;
  725.                 return MPN_NOMEM;
  726.             }
  727.             strcpy(tmproot, pathcomp);
  728.             if (tmproot[rootlen-1] == ':') {
  729.                 tmproot[--rootlen] = '\0';     /* strip trailing delimiter */
  730.             }
  731.             if (rootlen > 0 && (stat(tmproot, &G.statbuf) ||
  732.                 !S_ISDIR(G.statbuf.st_mode)))
  733.             {   /* path does not exist */
  734.                 if (!G.create_dirs /* || iswild(tmproot) */ ) {
  735.                     free(tmproot);
  736.                     rootlen = 0;
  737.                     /* skip (or treat as stored file) */
  738.                     return MPN_INF_SKIP;
  739.                 }
  740.                 /* create the directory (could add loop here scanning tmproot
  741.                  * to create more than one level, but why really necessary?) */
  742.                 if (macmkdir(tmproot) == -1) {
  743.                     Info(slide, 1, ((char *)slide,
  744.                       LoadFarString(CantCreateExtractDir),
  745.                       FnFilter1(tmproot)));
  746.                     free(tmproot);
  747.                     rootlen = 0;
  748.                     /* path didn't exist, tried to create, and failed: */
  749.                     /* file exists, or 2+ subdir levels required */
  750.                     return MPN_ERR_SKIP;
  751.                 }
  752.             }
  753.             tmproot[rootlen++] = ':';
  754.             tmproot[rootlen] = '\0';
  755.             if ((rootpath = (char *)realloc(tmproot, rootlen+1)) == NULL) {
  756.                 free(tmproot);
  757.                 rootlen = 0;
  758.                 return MPN_NOMEM;
  759.             }
  760.             Trace((stderr, "rootpath now = [%s]\n", FnFilter1(rootpath)));
  761.         }
  762.         return MPN_OK;
  763.     }
  764. #endif /* !SFX || SFX_EXDIR */
  765.  
  766. /*---------------------------------------------------------------------------
  767.     END:  free rootpath, immediately prior to program exit.
  768.   ---------------------------------------------------------------------------*/
  769.  
  770.     if (FUNCTION == END) {
  771.         Trace((stderr, "freeing rootpath\n"));
  772.         if (rootlen > 0) {
  773.             free(rootpath);
  774.             rootlen = 0;
  775.         }
  776.         return MPN_OK;
  777.     }
  778.  
  779.     return MPN_INVALID; /* should never reach */
  780.  
  781. } /* end function checkdir() */
  782.  
  783.  
  784.  
  785.  
  786.  
  787. /****************************/
  788. /* Function close_outfile() */
  789. /****************************/
  790.  
  791. void close_outfile(__G)
  792.     __GDEF
  793. {
  794.     OSErr err;
  795.  
  796.     if (fileno(G.outfile) == 1)
  797.         return;         /* don't attempt to close or set time on stdout */
  798.  
  799.     err = (OSErr)fclose(G.outfile);
  800.  
  801.     /* finally set FinderInfo */
  802.     if  (MacZipMode >= JohnnyLee_EF)
  803.         {
  804.         /* skip restoring time stamps on user's request */
  805.         err = SetFinderInfo(__G__ (uO.D_flag <= 1),
  806.                             &CurrentFile, &newExtraField);
  807.         printerr("close_outfile SetFinderInfo ", err, err,
  808.                  __LINE__, __FILE__, G.filename);
  809.         }
  810.     else  /* unknown extra field, set at least file time/dates */
  811.         {
  812.         /* skip restoring time stamps on user's request */
  813.         if (uO.D_flag <= 1)
  814.             err = SetFileTime(__G);
  815.         }
  816.  
  817. #ifndef SwitchZIPITefSupportOff
  818.     if ((MacZipMode == TomBrownZipIt1_EF) ||
  819.         (MacZipMode == TomBrownZipIt2_EF))
  820.         {
  821.         if(FSpIsMacBinary(&CurrentFile))
  822.             {
  823.             Info(slide, 0, ((char *)slide, LoadFarString(MacBinaryMsg)));
  824.                 err = DecodeMacBinaryFile(&CurrentFile);
  825.                 printerr("close_outfile DecodeMacBinaryFile ", err, err,
  826.                   __LINE__, __FILE__, G.filename);
  827.             }
  828.         }
  829. #endif
  830.  
  831.         /* set read-only perms if needed */
  832.     if ((err == noErr) && G.pInfo->read_only)
  833.         {
  834.         err = FSpSetFLock(&CurrentFile);
  835.         printerr("FSpSetFLock",err,err,__LINE__,__FILE__,G.filename);
  836.         }
  837.  
  838.     if (malloced_attrbuff != NULL)
  839.         {
  840.         attrbuff = malloced_attrbuff;
  841.         }
  842.  
  843. } /* end function close_outfile() */
  844.  
  845.  
  846.  
  847.  
  848. /****************************/
  849. /* Function SetFileTime() */
  850. /****************************/
  851.  
  852. static OSErr SetFileTime(__G)
  853.     __GDEF
  854. {
  855. #ifdef USE_EF_UT_TIME
  856.     iztimes z_utime;
  857.     unsigned eb_izux_flg;
  858. #endif
  859.     OSErr err;
  860.     CInfoPBRec      fpb;
  861.  
  862.     fpb.hFileInfo.ioNamePtr    = CurrentFile.name;
  863.     fpb.hFileInfo.ioVRefNum    = CurrentFile.vRefNum;
  864.     fpb.hFileInfo.ioDirID      = CurrentFile.parID;
  865.     fpb.hFileInfo.ioFDirIndex  = 0;
  866.  
  867.     err = PBGetCatInfoSync((CInfoPBPtr)&fpb);
  868.     printerr("PBGetCatInfoSync", err, err, __LINE__, __FILE__, G.filename);
  869.  
  870.     if ((MacZipMode == UnKnown_EF) || UseUT_ExtraField ) {
  871.  
  872. #ifdef USE_EF_UT_TIME
  873.         eb_izux_flg = ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0,
  874.                                        G.lrec.last_mod_dos_datetime, &z_utime, NULL);
  875.  
  876.         if (G.extra_field && (eb_izux_flg & EB_UT_FL_MTIME))
  877.             {
  878.             fpb.hFileInfo.ioFlMdDat = UnixFtime2MacFtime(z_utime.mtime);
  879.             fpb.hFileInfo.ioFlCrDat = UnixFtime2MacFtime(z_utime.ctime);
  880.             }
  881.  
  882. #ifdef DEBUG_TIME
  883.             {
  884.             struct tm *tp = gmtime(&z_utime.ctime);
  885.             printf(
  886.               "SetFileTime:  Unix e.f. creat. time = %d/%2d/%2d  %2d:%2d:%2d -> %lu UTC\n",
  887.               tp->tm_year, tp->tm_mon+1, tp->tm_mday,
  888.               tp->tm_hour, tp->tm_min, tp->tm_sec, z_utime.ctime);
  889.             tp = gmtime(&z_utime.mtime);
  890.             printf(
  891.               "SetFileTime:  Unix e.f. modif. time = %d/%2d/%2d  %2d:%2d:%2d -> %lu UTC\n",
  892.               tp->tm_year, tp->tm_mon+1, tp->tm_mday,
  893.               tp->tm_hour, tp->tm_min, tp->tm_sec, z_utime.mtime);
  894.             }
  895. #endif /* DEBUG_TIME */
  896.  
  897.  
  898.         else /* no Unix time field found - use dostime  */
  899. #endif /* !USE_EF_UT_TIME */
  900.             {
  901.             TTrace((stderr, "SetFileTime:  using DOS-Datetime ! \n",
  902.                     z_utime.mtime));
  903.             fpb.hFileInfo.ioFlMdDat = dos_to_unix_time(G.lrec.last_mod_dos_datetime);
  904.             UNIX_TO_MACOS(fpb.hFileInfo.ioFlMdDat);
  905.             fpb.hFileInfo.ioFlCrDat = fpb.hFileInfo.ioFlMdDat;
  906.             }
  907.  
  908.      /* Restore ioDirID field in pb which was changed by PBGetCatInfoSync */
  909.         fpb.hFileInfo.ioDirID = CurrentFile.parID;
  910.  
  911.         if (err == noErr)
  912.             {
  913.             err = PBSetCatInfoSync((CInfoPBPtr)&fpb);
  914.             printerr("PBSetCatInfoSync",err,err,__LINE__,__FILE__,G.filename);
  915.             }
  916.         if (err != noErr)
  917.             Info(slide, 0x201, ((char *)slide, LoadFarString(ErrNoTimeSet),
  918.               FnFilter1(G.filename)));
  919.     }
  920.  
  921. return err;
  922. } /* end function SetFileTime() */
  923.  
  924.  
  925.  
  926.  
  927. #ifndef SFX
  928.  
  929. /************************/
  930. /*  Function version()  */
  931. /************************/
  932.  
  933. void version(__G)
  934.     __GDEF
  935. {
  936. /*
  937. ZCONST char Far CompiledWith[] =
  938.                "Compiled with %s%s for %s%s%s%s.\n\n"; */
  939.  
  940. char DateTime[50];
  941.  
  942. #ifdef __MWERKS__
  943. char CompVer[10];
  944. sprintf(CompVer, "%x", __MWERKS__);
  945. #endif
  946.  
  947.     sprintf(DateTime,"%s  %s",__DATE__, __TIME__);
  948.  
  949.     sprintf((char *)slide, LoadFarString(CompiledWith),
  950.  
  951. #ifdef __MWERKS__
  952.  
  953.       " Metrowerks CodeWarrior version ",CompVer,
  954. #else
  955.       " ", " ",
  956. #endif
  957.  
  958. #ifdef __MC68K__
  959.       " MC68K Processor",
  960. #else
  961.       " PowerPC Processor",
  962. #endif
  963.  
  964. #ifdef __DATE__
  965.  
  966.       "\n compile time: ", DateTime, ""
  967. #else
  968.       "", "", ""
  969. #endif
  970.     );
  971.  
  972.     (*G.message)((zvoid *)&G, slide, (ulg)strlen((char *)slide), 0);
  973.  
  974. } /* end function version() */
  975.  
  976. #endif /* !SFX */
  977.  
  978.  
  979.  
  980.  
  981.  
  982. /***********************/
  983. /* Function macmkdir() */
  984. /***********************/
  985.  
  986. int macmkdir(char *path)
  987. {
  988.     OSErr err = -1;
  989.     OSErr err_rc;
  990.     char CompletePath[NAME_MAX], CompletePath2[NAME_MAX];
  991.     Boolean isDirectory = false;
  992.     short CurrentFork;
  993.     unsigned pathlen;
  994.     long dirID;
  995.  
  996.     AssertStr(path, path)
  997.  
  998.     GetExtraFieldData(&MacZipMode, &newExtraField);
  999.  
  1000.     if (MacZipMode >= JohnnyLee_EF) {
  1001.         RfDfFilen2Real(CompletePath, G.filename, MacZipMode,
  1002.                        (newExtraField.flags & EB_M3_FL_NOCHANGE), &CurrentFork);
  1003.         if (CurrentFork == ResourceFork)
  1004.             /* don't build a 'XtraStuf.mac:' dir  */
  1005.             return 0;
  1006.     }
  1007.  
  1008.     if (!IgnoreEF_Macfilename)
  1009.         {
  1010.         pathlen = strlen(path);
  1011.         strcpy(CompletePath, uO.exdir);
  1012.         strcat(CompletePath, newExtraField.FullPath);
  1013.         CompletePath[pathlen] = 0x00;
  1014.         }
  1015.     else
  1016.         {
  1017.         strcpy(CompletePath, path);
  1018.         }
  1019.  
  1020.     GetCompletePath(CompletePath2, CompletePath, &CurrentFile, &err);
  1021.     printerr("GetCompletePath", (err != -43) && (err != -120) && (err != 0),
  1022.               err, __LINE__, __FILE__, CompletePath2);
  1023.  
  1024.  
  1025.     err = FSpGetDirectoryID(&CurrentFile, &dirID, &isDirectory);
  1026.     printerr("macmkdir FSpGetDirectoryID ", (err != -43) && (err != 0),
  1027.              err, __LINE__, __FILE__, CompletePath2);
  1028.  
  1029.     if (err != -43)     /* -43 = file/directory not found  */
  1030.         return 0;
  1031.     else {
  1032.         HParamBlockRec    hpbr;
  1033.  
  1034.         hpbr.fileParam.ioCompletion = NULL;
  1035.         hpbr.fileParam.ioNamePtr    = CurrentFile.name;
  1036.         hpbr.fileParam.ioVRefNum    = CurrentFile.vRefNum;
  1037.         hpbr.fileParam.ioDirID      = CurrentFile.parID;
  1038.         err = PBDirCreateSync(&hpbr);
  1039.         printerr("macmkdir PBDirCreateSync ", err,
  1040.                  err, __LINE__, __FILE__, CompletePath2);
  1041.  
  1042.         /* finally set FinderInfo */
  1043.         if  (MacZipMode >= JohnnyLee_EF)
  1044.             {
  1045.             err_rc = SetFinderInfo(__G__ (uO.D_flag <= 0),
  1046.                                    &CurrentFile, &newExtraField);
  1047.             printerr("macmkdir SetFinderInfo ", err_rc, err_rc,
  1048.                       __LINE__, __FILE__, CompletePath2);
  1049.             }
  1050.     }
  1051.  
  1052.     return (int)err;
  1053. } /* macmkdir */
  1054.  
  1055.  
  1056.  
  1057.  
  1058. /**********************/
  1059. /* Function macopen() */
  1060. /**********************/
  1061.  
  1062. short macopen(char *sz, short nFlags)
  1063. {
  1064.     OSErr   err;
  1065.     char    chPerms = (!nFlags) ? fsRdPerm : fsRdWrPerm;
  1066.     short   nFRefNum;
  1067.  
  1068.     AssertStr(sz, sz)
  1069.  
  1070.     /* we only need the filespec of the zipfile;
  1071.        filespec of the other files (to be extracted) will be
  1072.        determined by open_outfile() */
  1073.     if (OpenZipFile)
  1074.         {
  1075.         char CompletePath[NAME_MAX];
  1076.         FSSpec zipfile;
  1077.         GetCompletePath(CompletePath, sz, &zipfile, &err);
  1078.         printerr("GetCompletePath", (err != -43) && (err != 0),
  1079.                   err, __LINE__, __FILE__, sz);
  1080.         if (CheckMountedVolumes(CompletePath) > 1)
  1081.             DoWarnUserDupVol(CompletePath);
  1082.         err = HOpen(zipfile.vRefNum, zipfile.parID, zipfile.name,
  1083.                     chPerms, &nFRefNum);
  1084.         printerr("Zipfile HOpen", err, err, __LINE__, __FILE__, sz);
  1085.         OpenZipFile = false;
  1086.         }
  1087.     else   /* open zipfile entries  */
  1088.         {
  1089.         if (nFlags > 1)
  1090.             {
  1091.             err = HOpenRF(CurrentFile.vRefNum, CurrentFile.parID, CurrentFile.name,
  1092.                       chPerms, &nFRefNum);
  1093.             printerr("HOpenRF", (err != -43) && (err != 0) && (err != -54),
  1094.                  err, __LINE__, __FILE__, sz);
  1095.             }
  1096.         else
  1097.             {
  1098.             err = HOpen(CurrentFile.vRefNum, CurrentFile.parID, CurrentFile.name,
  1099.                     chPerms, &nFRefNum);
  1100.             printerr("HOpen", (err != -43) && (err != 0),
  1101.                  err, __LINE__, __FILE__, sz);
  1102.             }
  1103.         }
  1104.  
  1105.     if ( err || (nFRefNum == 1) )
  1106.         {
  1107.         printerr("macopen", err, err, __LINE__, __FILE__,
  1108.                  (char *) CurrentFile.name);
  1109.         return -1;
  1110.         }
  1111.     else
  1112.         {
  1113.         if ( nFlags )
  1114.             SetEOF( nFRefNum, 0 );
  1115.         return nFRefNum;
  1116.         }
  1117. }
  1118.  
  1119.  
  1120.  
  1121.  
  1122.  
  1123. /***********************/
  1124. /* Function maccreat() */
  1125. /***********************/
  1126.  
  1127. short maccreat(char *sz)
  1128. {
  1129.     OSErr   err;
  1130.     char scriptTag = newExtraField.fpb.hFileInfo.ioFlXFndrInfo.fdScript;
  1131.     static char Num = 0;
  1132.  
  1133.     sz = sz;
  1134.  
  1135.     /* Set fdScript in FXInfo
  1136.      * The negative script constants (smSystemScript, smCurrentScript,
  1137.      * and smAllScripts) don't make sense on disk.  So only use scriptTag
  1138.      * if scriptTag >= smRoman (smRoman is 0).
  1139.      * fdScript is valid if high bit is set (see IM-6, page 9-38)
  1140.      */
  1141.     scriptTag = (scriptTag >= smRoman) ?
  1142.                 ((char)scriptTag | (char)0x80) : (smRoman);
  1143.     newExtraField.fpb.hFileInfo.ioFlXFndrInfo.fdScript = scriptTag;
  1144.  
  1145.     err = FSpCreate(&CurrentFile,
  1146.                     newExtraField.fpb.hFileInfo.ioFlFndrInfo.fdCreator,
  1147.                     newExtraField.fpb.hFileInfo.ioFlFndrInfo.fdType,
  1148.                     newExtraField.fpb.hFileInfo.ioFlXFndrInfo.fdScript);
  1149.  
  1150.     /* -37 = bad filename; make the filename shorter and try again  */
  1151.     /* filename must not be longer than 32 chars */
  1152.     if (err == -37)
  1153.         {
  1154.         strcpy((char *)CurrentFile.name,
  1155.                 MakeFilenameShorter(P2CStr(CurrentFile.name)));
  1156.         Info(slide, 0x401, ((char *)slide, LoadFarString(FilenameToLong),
  1157.           FnFilter1((char *)CurrentFile.name)));
  1158.         C2PStr((char *)CurrentFile.name);
  1159.         err = FSpCreate(&CurrentFile,
  1160.                     newExtraField.fpb.hFileInfo.ioFlFndrInfo.fdCreator,
  1161.                     newExtraField.fpb.hFileInfo.ioFlFndrInfo.fdType,
  1162.                     newExtraField.fpb.hFileInfo.ioFlXFndrInfo.fdScript);
  1163.         }
  1164.  
  1165.     err = printerr("FSpCreate maccreat ", (err != -48) && (err != 0),
  1166.                    err, __LINE__, __FILE__, G.filename);
  1167.  
  1168.     if (err == noErr)
  1169.         return noErr;
  1170.     else
  1171.         return -1;
  1172. }
  1173.  
  1174.  
  1175.  
  1176.  
  1177.  
  1178. /**********************/
  1179. /* Function macread() */
  1180. /**********************/
  1181.  
  1182. short macread(short nFRefNum, char *pb, unsigned cb)
  1183. {
  1184.     long    lcb = cb;
  1185.  
  1186.     (void)FSRead( nFRefNum, &lcb, pb );
  1187.     return (short)lcb;
  1188. }
  1189.  
  1190.  
  1191.  
  1192.  
  1193. /***********************/
  1194. /* Function macwrite() */
  1195. /***********************/
  1196.  
  1197. long macwrite(short nFRefNum, char *pb, unsigned cb)
  1198. {
  1199.     long    lcb = cb;
  1200.     OSErr   err = 0;
  1201.     FILE    *stream;
  1202.  
  1203.     if ( (nFRefNum == 1) || (nFRefNum == 2) )
  1204.         {
  1205.         stream = (nFRefNum == 1 ? stdout : stderr);
  1206.         pb[cb] = '\0';           /* terminate C-string */
  1207.                                  /* assumes writable buffer (e.g., slide[]) */
  1208.                                  /* with room for one more char at end of buf */
  1209.         lcb = fprintf(stream, "%s", pb);
  1210.         }
  1211.     else
  1212.         err = FSWrite( nFRefNum, &lcb, pb );
  1213.  
  1214.     if (err != 0)
  1215.         {
  1216.         errno = ERANGE;
  1217.         return -1;
  1218.         }
  1219.  
  1220.     return (long)lcb;
  1221. }
  1222.  
  1223.  
  1224.  
  1225.  
  1226.  
  1227. /***********************/
  1228. /* Function macclose() */
  1229. /***********************/
  1230.  
  1231. short macclose(short nFRefNum)
  1232. {
  1233. OSErr err;
  1234.  
  1235. err = FSClose( nFRefNum );
  1236. printerr("macclose FSClose ",err,err, __LINE__,__FILE__,G.filename);
  1237.  
  1238.  
  1239. return err;
  1240. }
  1241.  
  1242.  
  1243.  
  1244.  
  1245.  
  1246. /***********************/
  1247. /* Function maclseek() */
  1248. /***********************/
  1249.  
  1250. long maclseek(short nFRefNum, long lib, short nMode)
  1251. {
  1252.     ParamBlockRec   pbr;
  1253.  
  1254.     if (nMode == SEEK_SET)
  1255.         nMode = fsFromStart;
  1256.     else if (nMode == SEEK_CUR)
  1257.         nMode = fsFromMark;
  1258.     else if (nMode == SEEK_END)
  1259.         nMode = fsFromLEOF;
  1260.     pbr.ioParam.ioRefNum = nFRefNum;
  1261.     pbr.ioParam.ioPosMode = nMode;
  1262.     pbr.ioParam.ioPosOffset = lib;
  1263.     (void)PBSetFPosSync(&pbr);
  1264.     return pbr.ioParam.ioPosOffset;
  1265. }
  1266.  
  1267.  
  1268.  
  1269. static void BuildMacFilename(void)
  1270. {
  1271. char CompletePath[NAME_MAX];
  1272. char ArchiveDir[NAME_MAX];
  1273. unsigned exdirlen = strlen(uO.exdir);
  1274. short CurrentFork;
  1275. OSErr err;
  1276.  
  1277. GetExtraFieldData(&MacZipMode, &newExtraField);
  1278.  
  1279. if (MacZipMode >= JohnnyLee_EF)
  1280.     {
  1281.     if (IgnoreEF_Macfilename)
  1282.         {
  1283.         strcpy(ArchiveDir, &G.filename[exdirlen+1]);
  1284.         G.filename[exdirlen+1] = '\0';
  1285.         RfDfFilen2Real(ArchiveDir, ArchiveDir, MacZipMode,
  1286.                       (newExtraField.flags & EB_M3_FL_DATFRK), &CurrentFork);
  1287.         strcat(G.filename, ArchiveDir);
  1288.         }
  1289.     else
  1290.         {        /* use the filename of mac extra-field */
  1291.         G.filename[exdirlen] = '\0';  /* cut resource-path */
  1292.         strcat(G.filename,newExtraField.FullPath);
  1293.         }
  1294.     }
  1295.  
  1296. GetCompletePath(CompletePath, G.filename, &CurrentFile, &err);
  1297. printerr("GetCompletePath BuildMacFilename ", (err != -43) && (err != 0),
  1298.              err, __LINE__, __FILE__, CompletePath);
  1299.  
  1300. err = GetVolFileSystemID(C2PStr(CompletePath), CurrentFile.vRefNum,
  1301.                          &fileSystemID);
  1302. printerr("GetVolFileSystemID BuildMacFilename ", err, err, __LINE__, __FILE__,
  1303.           CompletePath);
  1304.  
  1305. if (MacZipMode == TomBrownZipIt1_EF)
  1306.     {
  1307.     memcpy(CurrentFile.name, newExtraField.filename, newExtraField.filename[0]+1);
  1308.     CurrentFile.name[0] = CurrentFile.name[0] - 1;
  1309.     }
  1310.  
  1311. }
  1312.  
  1313.  
  1314.  
  1315.  
  1316. /* The following functions are dealing with the extra-field handling, only. */
  1317.  
  1318. /****************************/
  1319. /* Function SetFinderInfo() */
  1320. /****************************/
  1321.  
  1322. static OSErr SetFinderInfo(__GPRO__ int SetTime, FSSpec *spec, MACINFO *mi)
  1323. {
  1324.     OSErr err;
  1325.     CInfoPBRec      fpb;
  1326.  
  1327.     fpb.hFileInfo.ioNamePtr   = (StringPtr) &(spec->name);
  1328.     fpb.hFileInfo.ioVRefNum   = spec->vRefNum;
  1329.     fpb.hFileInfo.ioDirID     = spec->parID;
  1330.     fpb.hFileInfo.ioFDirIndex = 0;
  1331.  
  1332.     err = PBGetCatInfoSync(&fpb);
  1333.     printerr("PBGetCatInfo SetFinderInfo ", err, err,
  1334.              __LINE__, __FILE__, G.filename);
  1335.  
  1336.     if  ((MacZipMode == JohnnyLee_EF) || (MacZipMode == NewZipMode_EF))
  1337.     {
  1338.         /* skip restoring time stamps on user's request */
  1339.         if (SetTime && !UseUT_ExtraField) {
  1340.             fpb.hFileInfo.ioFlCrDat = mi->fpb.hFileInfo.ioFlCrDat;
  1341.             fpb.hFileInfo.ioFlMdDat = mi->fpb.hFileInfo.ioFlMdDat;
  1342.         }
  1343.  
  1344.         fpb.hFileInfo.ioFlFndrInfo   = mi->fpb.hFileInfo.ioFlFndrInfo;
  1345.     }
  1346.  
  1347.     if (MacZipMode == NewZipMode_EF)
  1348.     {
  1349.         if (uO.E_flag) PrintMacExtraInfo(mi);
  1350.         fpb.hFileInfo.ioFlXFndrInfo  = mi->fpb.hFileInfo.ioFlXFndrInfo;
  1351.  
  1352.         fpb.hFileInfo.ioFVersNum  = mi->fpb.hFileInfo.ioFVersNum;
  1353.         fpb.hFileInfo.ioACUser    = mi->fpb.hFileInfo.ioACUser;
  1354.  
  1355.         /* skip restoring time stamps on user's request */
  1356.         if (SetTime && !UseUT_ExtraField) {
  1357.             fpb.hFileInfo.ioFlBkDat = mi->fpb.hFileInfo.ioFlBkDat;
  1358. #ifdef USE_EF_UT_TIME
  1359.             if (!(mi->flags & EB_M3_FL_NOUTC))
  1360.                 {
  1361. #ifdef DEBUG_TIME
  1362.             {
  1363.             printf("\nSetFinderInfo:  Mac modif: %lu local -> UTOffset: "\
  1364.                    "%d before AdjustForTZmoveMac\n",
  1365.               fpb.hFileInfo.ioFlCrDat, mi->Cr_UTCoffs);
  1366.             }
  1367. #endif /* DEBUG_TIME */
  1368.                 fpb.hFileInfo.ioFlCrDat =
  1369.                   AdjustForTZmoveMac(fpb.hFileInfo.ioFlCrDat, mi->Cr_UTCoffs);
  1370.                 fpb.hFileInfo.ioFlMdDat =
  1371.                   AdjustForTZmoveMac(fpb.hFileInfo.ioFlMdDat, mi->Md_UTCoffs);
  1372.                 fpb.hFileInfo.ioFlBkDat =
  1373.                   AdjustForTZmoveMac(fpb.hFileInfo.ioFlBkDat, mi->Bk_UTCoffs);
  1374. #ifdef DEBUG_TIME
  1375.             {
  1376.             printf("SetFinderInfo:  Mac modif: %lu local -> UTOffset: "\
  1377.                    "%d after AdjustForTZmoveMac\n",
  1378.               fpb.hFileInfo.ioFlCrDat, mi->Cr_UTCoffs);
  1379.             }
  1380. #endif /* DEBUG_TIME */
  1381.  
  1382.                 }
  1383. #endif /* USE_EF_UT_TIME */
  1384.         }
  1385.  
  1386.         if ((mi->FinderComment) &&
  1387.            (fileSystemID == HFS_fileSystem)) {
  1388.             C2PStr(mi->FinderComment);
  1389.             err = FSpDTSetComment(spec, (unsigned char *) mi->FinderComment);
  1390.             printerr("FSpDTSetComment:",err , err,
  1391.                      __LINE__, __FILE__, mi->FullPath);
  1392.         }
  1393.     }
  1394.  
  1395.     /* Restore ioDirID field in pb which was changed by PBGetCatInfo */
  1396.     fpb.hFileInfo.ioDirID = spec->parID;
  1397.     err = PBSetCatInfoSync(&fpb);
  1398.  
  1399.     return err;
  1400. } /* SetFinderInfo() */
  1401.  
  1402.  
  1403.  
  1404.  
  1405. /*
  1406. ** Scan the extra fields in extra_field, and look for a MacOS EF; return a
  1407. ** pointer to that EF, or NULL if it's not there.
  1408. */
  1409. static uch *scanMacOSexfield(uch *ef_ptr, unsigned ef_len,
  1410.                              short *MacZipMode)
  1411. {
  1412.     while (ef_ptr != NULL && ef_len >= EB_HEADSIZE) {
  1413.         unsigned eb_id  = makeword(EB_ID  + ef_ptr);
  1414.         unsigned eb_len = makeword(EB_LEN + ef_ptr);
  1415.  
  1416.         if (eb_len > (ef_len - EB_HEADSIZE)) {
  1417.             Trace((stderr,
  1418.               "scanMacOSexfield: block length %u > rest ef_size %u\n", eb_len,
  1419.               ef_len - EB_HEADSIZE));
  1420.             break;
  1421.         }
  1422.  
  1423.         if (isMacOSexfield(eb_id, eb_len, MacZipMode)) {
  1424.             return ef_ptr;
  1425.         }
  1426.  
  1427.         ef_ptr += (eb_len + EB_HEADSIZE);
  1428.         ef_len -= (eb_len + EB_HEADSIZE);
  1429.     }
  1430.  
  1431.     return NULL;
  1432. }
  1433.  
  1434.  
  1435.  
  1436.  
  1437. static Boolean isMacOSexfield(unsigned id, unsigned size, short *MacZipMode)
  1438. {
  1439. size = size;
  1440.  
  1441.     switch (id)
  1442.         {
  1443.         case EF_ZIPIT:
  1444.             {           /* we do not (yet) support ZipIt's format completely */
  1445.             *MacZipMode = TomBrownZipIt1_EF;
  1446.             IgnoreEF_Macfilename = true;
  1447.             return true;
  1448.             }
  1449.  
  1450.         case EF_ZIPIT2:
  1451.             {           /* we do not (yet) support ZipIt's format completely */
  1452.             *MacZipMode = TomBrownZipIt2_EF;
  1453.             IgnoreEF_Macfilename = true;
  1454.             return true;
  1455.             }
  1456.  
  1457.         case EF_MAC3:
  1458.             {           /* the new maczip format */
  1459.             *MacZipMode = NewZipMode_EF;
  1460.             IgnoreEF_Macfilename = false;
  1461.             return true;
  1462.             }
  1463.  
  1464.         case EF_JLMAC:
  1465.             {           /* Johnny Lee's old maczip format */
  1466.             *MacZipMode = JohnnyLee_EF;
  1467.             IgnoreEF_Macfilename = true;
  1468.             return true;
  1469.             }
  1470.  
  1471.         default:
  1472.             {           /* any other format */
  1473.             *MacZipMode = UnKnown_EF;
  1474.             IgnoreEF_Macfilename = true;
  1475.             return false;
  1476.             }
  1477.         }
  1478.  
  1479.     return false;
  1480. }
  1481.  
  1482.  
  1483.  
  1484.  
  1485. /*
  1486. ** Return a unsigned long from a four-byte sequence
  1487. ** in big endian format
  1488. */
  1489.  
  1490. ulg makePPClong(ZCONST uch *sig)
  1491. {
  1492.     return (((ulg)sig[0]) << 24)
  1493.          + (((ulg)sig[1]) << 16)
  1494.          + (((ulg)sig[2]) << 8)
  1495.          +  ((ulg)sig[3]);
  1496. }
  1497.  
  1498.  
  1499.  
  1500.  
  1501. /*
  1502. ** Return a unsigned short from a two-byte sequence
  1503. ** in big endian format
  1504. */
  1505.  
  1506. ush makePPCword(ZCONST uch *b)
  1507. {
  1508.     return (ush)((b[0] << 8) | b[1]);
  1509. }
  1510.  
  1511.  
  1512.  
  1513.  
  1514. /*
  1515. ** Print mac extra-field
  1516. **
  1517. */
  1518.  
  1519. static void PrintMacExtraInfo(MACINFO *mi)
  1520. {
  1521. #define MY_FNDRINFO fpb.hFileInfo.ioFlFndrInfo
  1522.     DateTimeRec  MacTime;
  1523.     static ZCONST char space[] = "                                    ";
  1524.     static ZCONST char line[]  = "------------------------------------"\
  1525.                                  "------------------------------";
  1526.  
  1527.     printf("\n\n%s", line);
  1528.  
  1529.     printf("\nFullPath      = [%s]", mi->FullPath);
  1530.     printf("\nFinderComment = [%s]", mi->FinderComment);
  1531.     printf("\nText Encoding Base (Filename)       \"%s\" \n",
  1532.         PrintTextEncoding(mi->fpb.hFileInfo.ioFlXFndrInfo.fdScript));
  1533.  
  1534.     printf("\nExtraField Flags :                  %s  0x%x  %4d",
  1535.              sBit2Str(mi->flags), mi->flags, mi->flags);
  1536.  
  1537.     printf("\n%sExtra Field is %s", space,
  1538.            (mi->flags & EB_M3_FL_UNCMPR ?
  1539.             "Uncompressed" : "Compressed"));
  1540.     printf("\n%sFile Dates are in %u Bit", space,
  1541.            (mi->flags & EB_M3_FL_TIME64 ? 64 : 32));
  1542.     printf("\n%sFile UTC time adjustments are %ssupported", space,
  1543.            (mi->flags & EB_M3_FL_NOUTC ? "not " : ""));
  1544.     printf("\n%sFile Name is %schanged", space,
  1545.            (mi->flags & EB_M3_FL_NOCHANGE ? "not " : ""));
  1546.     printf("\n%sFile is a %s\n", space,
  1547.            (mi->flags & EB_M3_FL_DATFRK ?
  1548.             "Datafork" : "Resourcefork"));
  1549.  
  1550.     /* not all type / creator codes are printable */
  1551.     if (isprint((char)(mi->MY_FNDRINFO.fdType >> 24)) &&
  1552.         isprint((char)(mi->MY_FNDRINFO.fdType >> 16)) &&
  1553.         isprint((char)(mi->MY_FNDRINFO.fdType >> 8)) &&
  1554.         isprint((char)mi->MY_FNDRINFO.fdType))
  1555.     {
  1556.         printf("\nFile Type =                         [%c%c%c%c]  0x%lx",
  1557.             (char)(mi->MY_FNDRINFO.fdType >> 24),
  1558.             (char)(mi->MY_FNDRINFO.fdType >> 16),
  1559.             (char)(mi->MY_FNDRINFO.fdType >> 8),
  1560.             (char)(mi->MY_FNDRINFO.fdType),
  1561.             mi->MY_FNDRINFO.fdType);
  1562.     }
  1563.     else
  1564.     {
  1565.         printf("\nFile Type =                                     0x%lx",
  1566.             mi->MY_FNDRINFO.fdType);
  1567.     }
  1568.  
  1569.     if (isprint((char)(mi->MY_FNDRINFO.fdCreator >> 24)) &&
  1570.         isprint((char)(mi->MY_FNDRINFO.fdCreator >> 16)) &&
  1571.         isprint((char)(mi->MY_FNDRINFO.fdCreator >> 8)) &&
  1572.         isprint((char)mi->MY_FNDRINFO.fdCreator))
  1573.     {
  1574.         printf("\nFile Creator =                      [%c%c%c%c]  0x%lx",
  1575.             (char)(mi->MY_FNDRINFO.fdCreator >> 24),
  1576.             (char)(mi->MY_FNDRINFO.fdCreator >> 16),
  1577.             (char)(mi->MY_FNDRINFO.fdCreator >> 8),
  1578.             (char)(mi->MY_FNDRINFO.fdCreator),
  1579.             mi->MY_FNDRINFO.fdCreator);
  1580.     }
  1581.     else
  1582.     {
  1583.         printf("\nFile Creator =                                  0x%lx",
  1584.             mi->MY_FNDRINFO.fdCreator);
  1585.     }
  1586.  
  1587.     printf("\n\nDates (local time of archiving location):");
  1588.     SecondsToDate(mi->fpb.hFileInfo.ioFlCrDat, &MacTime);
  1589.     printf("\n    Created  =                      %4d/%2d/%2d %2d:%2d:%2d  ",
  1590.            MacTime.year, MacTime.month, MacTime.day,
  1591.            MacTime.hour, MacTime.minute, MacTime.second);
  1592.     SecondsToDate(mi->fpb.hFileInfo.ioFlMdDat, &MacTime);
  1593.     printf("\n    Modified =                      %4d/%2d/%2d %2d:%2d:%2d  ",
  1594.            MacTime.year, MacTime.month, MacTime.day,
  1595.            MacTime.hour, MacTime.minute, MacTime.second);
  1596.     SecondsToDate(mi->fpb.hFileInfo.ioFlBkDat, &MacTime);
  1597.     printf("\n    Backup   =                      %4d/%2d/%2d %2d:%2d:%2d  ",
  1598.         MacTime.year, MacTime.month, MacTime.day,
  1599.         MacTime.hour, MacTime.minute, MacTime.second);
  1600.  
  1601.     if (!(mi->flags & EB_M3_FL_NOUTC)) {
  1602.         printf("\nGMT Offset of Creation time  =      %4ld sec  %2d h",
  1603.           mi->Cr_UTCoffs, (int)mi->Cr_UTCoffs / (60 * 60));
  1604.         printf("\nGMT Offset of Modification time  =  %4ld sec  %2d h",
  1605.           mi->Md_UTCoffs, (int)mi->Md_UTCoffs / (60 * 60));
  1606.         printf("\nGMT Offset of Backup time  =        %4ld sec  %2d h",
  1607.           mi->Bk_UTCoffs, (int)mi->Bk_UTCoffs / (60 * 60));
  1608.     }
  1609.  
  1610.     printf("\n\nFinder Flags :                      %s  0x%x  %4d",
  1611.         sBit2Str(mi->MY_FNDRINFO.fdFlags),
  1612.         mi->MY_FNDRINFO.fdFlags,
  1613.         mi->MY_FNDRINFO.fdFlags);
  1614.  
  1615.     printf("\nFinder Icon Position =              X: %4d",
  1616.         mi->MY_FNDRINFO.fdLocation.h);
  1617.  
  1618.     printf("\n                                    Y: %4d",
  1619.         mi->MY_FNDRINFO.fdLocation.v);
  1620.  
  1621.     printf("\n\nText Encoding Base (System/MacZip)  \"%s\"",
  1622.         PrintTextEncoding(mi->TextEncodingBase));
  1623.  
  1624.     printf("\n%s\n", line);
  1625. #undef MY_FNDRINFO
  1626. }
  1627.  
  1628.  
  1629.  
  1630.  
  1631. /*
  1632. ** Decode mac extra-field and assign the data to the structure
  1633. **
  1634. */
  1635.  
  1636. static Boolean GetExtraFieldData(short *MacZipMode, MACINFO *mi)
  1637. {
  1638. uch *ptr;
  1639. int  retval = PK_OK;
  1640.  
  1641. ptr = scanMacOSexfield(G.extra_field, G.lrec.extra_field_length, MacZipMode);
  1642.  
  1643. /* MacOS is no preemptive OS therefore do some (small) event-handling */
  1644. UserStop();
  1645.  
  1646. if (uO.J_flag)
  1647.     {
  1648.     *MacZipMode = UnKnown_EF;
  1649.     IgnoreEF_Macfilename = true;
  1650.     return false;
  1651.     }
  1652.  
  1653. if (ptr != NULL)
  1654. {   /*   Collect the data from the extra field buffer. */
  1655.     mi->header    = makeword(ptr);    ptr += 2;
  1656.     mi->data      = makeword(ptr);    ptr += 2;
  1657.  
  1658.     switch (*MacZipMode)
  1659.         {
  1660.         case NewZipMode_EF:
  1661.            {
  1662.             mi->size      =  makelong(ptr); ptr += 4;
  1663.             mi->flags     =  makeword(ptr); ptr += 2;
  1664.                              /* Type/Creator are always uncompressed */
  1665.             mi->fpb.hFileInfo.ioFlFndrInfo.fdType    = makePPClong(ptr);
  1666.             ptr += 4;
  1667.             mi->fpb.hFileInfo.ioFlFndrInfo.fdCreator = makePPClong(ptr);
  1668.             ptr += 4;
  1669.  
  1670.             if (!(mi->flags & EB_M3_FL_UNCMPR))
  1671.                 {
  1672.  
  1673.                 retval = memextract(__G__ attrbuff, mi->size, ptr,
  1674.                                     mi->data - EB_MAC3_HLEN);
  1675.  
  1676.                 if (retval != PK_OK)  /* error uncompressing attributes */
  1677.                     {
  1678.                     Info(slide, 0x201, ((char *)slide,
  1679.                          LoadFarString(ErrUncmpEF)));
  1680.                     *MacZipMode = UnKnown_EF;
  1681.                     return false;     /* EF-Block unusable, ignore it */
  1682.                     }
  1683.  
  1684.                 }
  1685.              else
  1686.                 {   /* file attributes are uncompressed */
  1687.                 attrbuff = ptr;
  1688.                 }
  1689.  
  1690.             DecodeMac3ExtraField(attrbuff, mi);
  1691.  
  1692.             return true;
  1693.             break;
  1694.             }
  1695.  
  1696.         case JohnnyLee_EF:
  1697.             {
  1698.             if (strncmp((char *)ptr, "JLEE", 4) == 0)
  1699.                 {   /* Johnny Lee's old MacZip e.f. was found */
  1700.                 attrbuff  = ptr + 4;
  1701.                 DecodeJLEEextraField(attrbuff, mi);
  1702.                 return true;
  1703.                 }
  1704.             else
  1705.                 {   /* second signature did not match, ignore EF block */
  1706.                 *MacZipMode = UnKnown_EF;
  1707.                 return false;
  1708.                 }
  1709.             break;
  1710.             }
  1711.  
  1712.  
  1713.         case TomBrownZipIt1_EF:
  1714.         case TomBrownZipIt2_EF:
  1715.             {
  1716.             if (strncmp((char *)ptr, "ZPIT", 4) == 0)
  1717.                 {   /* Johnny Lee's old MacZip e.f. was found */
  1718.                 attrbuff  = ptr + 4;
  1719.                 DecodeZPITextraField(attrbuff, mi);
  1720.                 return true;
  1721.                 }
  1722.             else
  1723.                 {   /* second signature did not match, ignore EF block */
  1724.                 *MacZipMode = UnKnown_EF;
  1725.                 return false;
  1726.                 }
  1727.             break;
  1728.             }
  1729.  
  1730.  
  1731.         default:
  1732.             {  /* just to make sure */
  1733.             *MacZipMode = UnKnown_EF;
  1734.             IgnoreEF_Macfilename = true;
  1735.             return false;
  1736.             break;
  1737.             }
  1738.         }
  1739. }  /* if (ptr != NULL)  */
  1740.  
  1741. /* no Mac extra field was found */
  1742. return false;
  1743. }
  1744.  
  1745.  
  1746.  
  1747.  
  1748. /*
  1749. ** Assign the new Mac3 Extra-Field to the structure
  1750. **
  1751. */
  1752.  
  1753. static void DecodeMac3ExtraField(ZCONST uch *buff, MACINFO *mi)
  1754. {               /* extra-field info of the new MacZip implementation */
  1755.                 /* compresssed extra-field starts here (if compressed) */
  1756.  
  1757. Assert_it(buff, "", "");
  1758.  
  1759. mi->fpb.hFileInfo.ioFlFndrInfo.fdFlags        =  makeword(buff); buff += 2;
  1760. mi->fpb.hFileInfo.ioFlFndrInfo.fdLocation.v   =  makeword(buff); buff += 2;
  1761. mi->fpb.hFileInfo.ioFlFndrInfo.fdLocation.h   =  makeword(buff); buff += 2;
  1762. mi->fpb.hFileInfo.ioFlFndrInfo.fdFldr         =  makeword(buff); buff += 2;
  1763.  
  1764. mi->fpb.hFileInfo.ioFlXFndrInfo.fdIconID      =  makeword(buff); buff += 2;
  1765. mi->fpb.hFileInfo.ioFlXFndrInfo.fdReserved[0] =  makeword(buff); buff += 2;
  1766. mi->fpb.hFileInfo.ioFlXFndrInfo.fdReserved[1] =  makeword(buff); buff += 2;
  1767. mi->fpb.hFileInfo.ioFlXFndrInfo.fdReserved[2] =  makeword(buff); buff += 2;
  1768. mi->fpb.hFileInfo.ioFlXFndrInfo.fdScript      = *buff;           buff += 1;
  1769. mi->fpb.hFileInfo.ioFlXFndrInfo.fdXFlags      = *buff;           buff += 1;
  1770. mi->fpb.hFileInfo.ioFlXFndrInfo.fdComment     =  makeword(buff); buff += 2;
  1771. mi->fpb.hFileInfo.ioFlXFndrInfo.fdPutAway     =  makelong(buff); buff += 4;
  1772.  
  1773. mi->fpb.hFileInfo.ioFVersNum                  = *buff;           buff += 1;
  1774. mi->fpb.hFileInfo.ioACUser                    = *buff;           buff += 1;
  1775.  
  1776. /*
  1777. This implementation does not use the 64 bit time values, therefore
  1778. use the UT extra field instead
  1779. */
  1780. if (mi->flags & EB_M3_FL_TIME64)
  1781.     {
  1782.     Info(slide, 0x201, ((char *)slide, LoadFarString(No64Time)));
  1783.     UseUT_ExtraField = true;
  1784.     buff += 24; /* jump over the date values */
  1785.     }
  1786. else
  1787.     {
  1788.     UseUT_ExtraField = false;
  1789.     mi->fpb.hFileInfo.ioFlCrDat   =  makelong(buff); buff += 4;
  1790.     mi->fpb.hFileInfo.ioFlMdDat   =  makelong(buff); buff += 4;
  1791.     mi->fpb.hFileInfo.ioFlBkDat   =  makelong(buff); buff += 4;
  1792.     }
  1793.  
  1794. if (!(mi->flags & EB_M3_FL_NOUTC))
  1795.     {
  1796.     mi->Cr_UTCoffs =  makelong(buff); buff += 4;
  1797.     mi->Md_UTCoffs =  makelong(buff); buff += 4;
  1798.     mi->Bk_UTCoffs =  makelong(buff); buff += 4;
  1799.     }
  1800.  
  1801. /* TextEncodingBase type & values */
  1802. /* (values 0-32 correspond to the Script Codes defined in "Inside Macintosh",
  1803.     Text pages 6-52 and 6-53) */
  1804. mi->TextEncodingBase =  makeword(buff); buff += 2;
  1805.  
  1806. if (mi->TextEncodingBase >= kTextEncodingUnicodeV1_1)
  1807.     {
  1808.     Info(slide, 0x201, ((char *)slide, LoadFarString(NoUniCode)));
  1809.     IgnoreEF_Macfilename = true;
  1810.     }
  1811.  
  1812. mi->FullPath      = (char *)buff; buff += strlen(mi->FullPath) + 1;
  1813. mi->FinderComment = (char *)buff; buff += strlen(mi->FinderComment) + 1;
  1814.  
  1815. if (uO.i_flag) IgnoreEF_Macfilename = true;
  1816.  
  1817. }
  1818.  
  1819.  
  1820.  
  1821.  
  1822. /*
  1823. ** Assign the new JLEE Extra-Field to the structure
  1824. **
  1825. */
  1826.  
  1827. static void DecodeJLEEextraField(ZCONST uch *buff, MACINFO *mi)
  1828. { /*  extra-field info of Johnny Lee's old MacZip  */
  1829.  
  1830. Assert_it(buff, "", "");
  1831.  
  1832. mi->fpb.hFileInfo.ioFlFndrInfo.fdType       = makePPClong(buff); buff += 4;
  1833. mi->fpb.hFileInfo.ioFlFndrInfo.fdCreator    = makePPClong(buff); buff += 4;
  1834. mi->fpb.hFileInfo.ioFlFndrInfo.fdFlags      = makePPCword(buff); buff += 2;
  1835. mi->fpb.hFileInfo.ioFlFndrInfo.fdLocation.v = makePPCword(buff); buff += 2;
  1836. mi->fpb.hFileInfo.ioFlFndrInfo.fdLocation.h = makePPCword(buff); buff += 2;
  1837. mi->fpb.hFileInfo.ioFlFndrInfo.fdFldr       = makePPCword(buff); buff += 2;
  1838.  
  1839. mi->fpb.hFileInfo.ioFlCrDat                =  makePPClong(buff); buff += 4;
  1840. mi->fpb.hFileInfo.ioFlMdDat                =  makePPClong(buff); buff += 4;
  1841. mi->flags                                  =  makePPClong(buff); buff += 4;
  1842.  
  1843. newExtraField.fpb.hFileInfo.ioFlXFndrInfo.fdScript = smSystemScript;
  1844. }
  1845.  
  1846.  
  1847.  
  1848.  
  1849. /*
  1850. ** Assign the new JLEE Extra-Field to the structure
  1851. **
  1852. */
  1853.  
  1854. static void DecodeZPITextraField(ZCONST uch *buff, MACINFO *mi)
  1855. { /*  extra-field info of Johnny Lee's old MacZip  */
  1856. unsigned char filelen;
  1857.  
  1858. Assert_it(buff, "", "");
  1859.  
  1860. #ifdef SwitchZIPITefSupportOff
  1861. MacZipMode = UnKnown_EF;
  1862. Info(slide, 0x221, ((char *)slide,LoadFarString(ZitIt_EF)));
  1863. return;
  1864. #endif
  1865.  
  1866. if (MacZipMode == TomBrownZipIt1_EF)
  1867.     {
  1868.     filelen = *buff;
  1869.     newExtraField.filename = buff;
  1870.     buff += 1;
  1871.     buff += filelen;
  1872.     mi->fpb.hFileInfo.ioFlFndrInfo.fdType       = makePPClong(buff);
  1873.     buff += 4;
  1874.     mi->fpb.hFileInfo.ioFlFndrInfo.fdCreator    = makePPClong(buff);
  1875.     buff += 4;
  1876.     }
  1877. else   /*  if (MacZipMode == TomBrownZipIt2_EF)  */
  1878.     {
  1879.     mi->fpb.hFileInfo.ioFlFndrInfo.fdType       = makePPClong(buff);
  1880.     buff += 4;
  1881.     mi->fpb.hFileInfo.ioFlFndrInfo.fdCreator    = makePPClong(buff);
  1882.     buff += 4;
  1883.     }
  1884.  
  1885. newExtraField.fpb.hFileInfo.ioFlXFndrInfo.fdScript = smSystemScript;
  1886. }
  1887.  
  1888.  
  1889.  
  1890. /*
  1891. ** Return char* to describe the text encoding
  1892. **
  1893. */
  1894.  
  1895. static char *PrintTextEncoding(short script)
  1896. {
  1897. char *info;
  1898. static char buffer[14];
  1899. /* TextEncodingBase type & values */
  1900. /* (values 0-32 correspond to the Script Codes defined in
  1901.    Inside Macintosh: Text pages 6-52 and 6-53 */
  1902.  
  1903. switch (script) {               /* Mac OS encodings*/
  1904.     case kTextEncodingMacRoman:         info = "Roman";             break;
  1905.     case kTextEncodingMacJapanese:      info = "Japanese";          break;
  1906.     case kTextEncodingMacChineseTrad:   info = "ChineseTrad";       break;
  1907.     case kTextEncodingMacKorean:        info = "Korean";            break;
  1908.     case kTextEncodingMacArabic:        info = "Arabic";            break;
  1909.     case kTextEncodingMacHebrew:        info = "Hebrew";            break;
  1910.     case kTextEncodingMacGreek:         info = "Greek";             break;
  1911.     case kTextEncodingMacCyrillic:      info = "Cyrillic";          break;
  1912.     case kTextEncodingMacDevanagari:    info = "Devanagari";        break;
  1913.     case kTextEncodingMacGurmukhi:      info = "Gurmukhi";          break;
  1914.     case kTextEncodingMacGujarati:      info = "Gujarati";          break;
  1915.     case kTextEncodingMacOriya:         info = "Oriya";             break;
  1916.     case kTextEncodingMacBengali:       info = "Bengali";           break;
  1917.     case kTextEncodingMacTamil:         info = "Tamil";             break;
  1918.     case kTextEncodingMacTelugu:        info = "Telugu";            break;
  1919.     case kTextEncodingMacKannada:       info = "Kannada";           break;
  1920.     case kTextEncodingMacMalayalam:     info = "Malayalam";         break;
  1921.     case kTextEncodingMacSinhalese:     info = "Sinhalese";         break;
  1922.     case kTextEncodingMacBurmese:       info = "Burmese";           break;
  1923.     case kTextEncodingMacKhmer:         info = "Khmer";             break;
  1924.     case kTextEncodingMacThai:          info = "Thai";              break;
  1925.     case kTextEncodingMacLaotian:       info = "Laotian";           break;
  1926.     case kTextEncodingMacGeorgian:      info = "Georgian";          break;
  1927.     case kTextEncodingMacArmenian:      info = "Armenian";          break;
  1928.     case kTextEncodingMacChineseSimp:   info = "ChineseSimp";       break;
  1929.     case kTextEncodingMacTibetan:       info = "Tibetan";           break;
  1930.     case kTextEncodingMacMongolian:     info = "Mongolian";         break;
  1931.     case kTextEncodingMacEthiopic:      info = "Ethiopic";          break;
  1932.     case kTextEncodingMacCentralEurRoman: info = "CentralEurRoman"; break;
  1933.     case kTextEncodingMacVietnamese:    info = "Vietnamese";        break;
  1934.     case kTextEncodingMacExtArabic:     info = "ExtArabic";         break;
  1935.  
  1936.     case kTextEncodingUnicodeV1_1:      info = "Unicode V 1.1";     break;
  1937.     case kTextEncodingUnicodeV2_0:      info = "Unicode V 2.0";     break;
  1938.  
  1939.     default:  {
  1940.         sprintf(buffer,"Code: 0x%x",(short) script);
  1941.         info = buffer;
  1942.         break;
  1943.         }
  1944.     }
  1945.  
  1946. return info;
  1947. }
  1948.  
  1949.  
  1950.  
  1951. /*
  1952. ** Init Globals
  1953. **
  1954. */
  1955.  
  1956. void   MacGlobalsInit(__GPRO)
  1957. {
  1958. newExtraField.FullPath      = NULL;
  1959. newExtraField.FinderComment = NULL;
  1960.  
  1961. OpenZipFile = true;
  1962.  
  1963. MacZipMode = UnKnown_EF;
  1964. IgnoreEF_Macfilename = true;
  1965.  
  1966. if (malloced_attrbuff == NULL)
  1967.     {
  1968.     /* make room for extra-field */
  1969.     attrbuff = (uch *)malloc(EB_MAX_OF_VARDATA);
  1970.  
  1971.     if (attrbuff == NULL)
  1972.         {             /* No memory to uncompress attributes */
  1973.         Info(slide, 0x201, ((char *)slide, LoadFarString(OutOfMemEF)));
  1974.         exit(PK_MEM);
  1975.         }
  1976.     else
  1977.         {
  1978.         malloced_attrbuff = attrbuff;
  1979.         }
  1980.     }
  1981. else
  1982.     {
  1983.     attrbuff = malloced_attrbuff;
  1984.     }
  1985.  
  1986. }
  1987.