📄 macos.c
字号:
/*--------------------------------------------------------------------------- mac.c Macintosh-specific routines for use with Info-ZIP's UnZip 5.4 and later. Contains: do_wild () mapattr () checkdir () version () macmkdir () macopen () maccreat () macread () macwrite () macclose () maclseek () FindNewExtractFolder () SetFinderInfo () isMacOSexfield () makePPClong () makePPCword () PrintMacExtraInfo () GetExtraFieldData () DecodeMac3ExtraField () DecodeJLEEextraField () PrintTextEncoding () MacGlobalsInit () ---------------------------------------------------------------------------*//*****************************************************************************//* Includes *//*****************************************************************************/#define UNZIP_INTERNAL#include "unzip.h"#include <script.h>#include "pathname.h"#include "helpers.h"#include "macstuff.h"#include "mactime.h"/*****************************************************************************//* Macros, typedefs *//*****************************************************************************/#define read_only file_attr /* for readability only */#define MKDIR(path) macmkdir(path)/*****************************************************************************//* Global Vars *//*****************************************************************************//* Note: sizeof() returns the size of this allusion 13 is current length of "XtraStuf.mac:" */extern const char ResourceMark[13]; /* var is initialized in file pathname.c */Boolean MacUnzip_Noisy; /* MacUnzip_Noisy is also used by console *//*****************************************************************************//* Module level Vars *//*****************************************************************************/static int created_dir; /* used in mapname(), checkdir() */static int renamed_fullpath; /* ditto */static FSSpec CurrentFile;static MACINFO newExtraField; /* contains all extra-field data */static firstcall_of_macopen = true;static short MacZipMode;static Boolean UseUT_ExtraField = false;static Boolean IgnoreEF_Macfilename = false;/*****************************************************************************//* Prototypes *//*****************************************************************************/extern char *GetUnZipInfoVersions(void);static OSErr SetFinderInfo(FSSpec *spec, MACINFO *mi);static Boolean GetExtraFieldData(short *MacZipMode, MACINFO *mi);static uch *scanMacOSexfield(uch *ef_ptr, unsigned ef_len, short *MacZipMode);static Boolean isMacOSexfield(unsigned id, unsigned size, short *MacZipMode);static void PrintMacExtraInfo(void);static void DecodeMac3ExtraField(ZCONST uch *buff, MACINFO *mi);static void DecodeJLEEextraField(ZCONST uch *buff, MACINFO *mi);static char *PrintTextEncoding(short script);static void MakeMacOS_String(char *MacOS_Str, const char SpcChar1, const char SpcChar2, const char SpcChar3, const char SpcChar4);/*****************************************************************************//* Constants (strings, etc.) *//*****************************************************************************/static ZCONST char Far CannotCreateFile[] = "error: cannot create %s\n";/*****************************************************************************//* Functions *//*****************************************************************************/#ifndef SFX/**********************//* Function do_wild() */ /* for porting: dir separator; match(ignore_case) *//**********************/char *do_wild(__G__ wildspec) __GDEF char *wildspec; /* only used first time on a given dir */{ static DIR *dir = (DIR *)NULL; static char *dirname, *wildname, matchname[FILNAMSIZ]; static int firstcall=TRUE, have_dirname; static unsigned long dirnamelen; struct dirent *file; /* Even when we're just returning wildspec, we *always* do so in * matchname[]--calling routine is allowed to append four characters * to the returned string, and wildspec may be a pointer to argv[]. */ if (firstcall) { /* first call: must initialize everything */ firstcall = FALSE; MacUnzip_Noisy = !uO.qflag; if (MacUnzip_Noisy) printf("%s \n\n", GetUnZipInfoVersions()); /* break the wildspec into a directory part and a wildcard filename */ if ((wildname = strrchr(wildspec, ':')) == (char *)NULL) { dirname = ":"; dirnamelen = 1; have_dirname = FALSE; wildname = wildspec; } else { ++wildname; /* point at character after ':' */ dirnamelen = wildname - wildspec; if ((dirname = (char *)malloc(dirnamelen+1)) == (char *)NULL) { Info(slide, 0x201, ((char *)slide, "warning: cannot allocate wildcard buffers\n")); strcpy(matchname, wildspec); return matchname; /* but maybe filespec was not a wildcard */ } strncpy(dirname, wildspec, dirnamelen); dirname[dirnamelen] = '\0'; /* terminate for strcpy below */ have_dirname = TRUE; } if ((dir = opendir(dirname)) != (DIR *)NULL) { while ((file = readdir(dir)) != (struct dirent *)NULL) { if (match(file->d_name, wildname, 0)) { /* 0 == case sens. */ if (have_dirname) { strcpy(matchname, dirname); strcpy(matchname+dirnamelen, file->d_name); } else strcpy(matchname, file->d_name); return matchname; } } /* if we get to here directory is exhausted, so close it */ closedir(dir); dir = (DIR *)NULL; } /* return the raw wildspec in case that works (e.g., directory not * searchable, but filespec was not wild and file is readable) */ strcpy(matchname, wildspec); return matchname; } /* last time through, might have failed opendir but returned raw wildspec */ if (dir == (DIR *)NULL) { firstcall = TRUE; /* nothing left to try--reset for new wildspec */ if (have_dirname) free(dirname); return (char *)NULL; } closedir(dir); /* have read at least one dir entry; nothing left */ dir = (DIR *)NULL; firstcall = TRUE; /* reset for new wildspec */ if (have_dirname) free(dirname); return (char *)NULL;} /* end function do_wild() */#endif /* !SFX *//***************************//* Function open_outfile() *//***************************/int open_outfile(__G) /* return 1 if fail */ __GDEF{ short outfd, fDataFork = TRUE; OSErr err; char CompletePath[NAME_MAX]; char ArchiveDir[NAME_MAX]; short CurrentFork; unsigned exdirlen;#ifdef DLL if (G.redirect_data) return (redirect_outfile(__G) == FALSE);#endif Trace((stderr, "open_outfile: trying to open (%s) for writing\n", FnFilter1(G.filename))); exdirlen = strlen(uO.exdir); if (MacZipMode != UnKnown_EF) { fDataFork = (newExtraField.flags & EB_M3_FL_DATFRK) ? TRUE : FALSE; if (IgnoreEF_Macfilename) { strcpy(ArchiveDir, &G.filename[exdirlen+1]); G.filename[exdirlen+1] = '\0'; RfDfFilen2Real(ArchiveDir, ArchiveDir, MacZipMode, (newExtraField.flags & EB_M3_FL_DATFRK), &CurrentFork); strcat(G.filename, ArchiveDir); } else { /* use the filename from extra-field */ G.filename[exdirlen+1] = '\0'; strcat(G.filename,newExtraField.FullPath); } } else { if (!uO.aflag) { /* unknown type documents */ /* all files are considered to be of type 'TEXT' and creator 'hscd' */ /* this is the default type for CDROM ISO-9660 without Apple extensions */ newExtraField.fpb.hFileInfo.ioFlFndrInfo.fdType = 'TEXT'; newExtraField.fpb.hFileInfo.ioFlFndrInfo.fdCreator = 'hscd'; } else { /* unknown text-files defaults to 'TEXT' */ newExtraField.fpb.hFileInfo.ioFlFndrInfo.fdType = 'TEXT'; /* Bare Bones BBEdit */ newExtraField.fpb.hFileInfo.ioFlFndrInfo.fdCreator = 'R*ch'; } } GetCompletePath(CompletePath, G.filename, &CurrentFile, &err); printerr("GetCompletePath open_outfile", (err != -43) && (err != 0), err, __LINE__, __FILE__, CompletePath); if ((outfd = maccreat(G.filename)) != -1) { outfd = macopen(CompletePath, (fDataFork) ? 1 : 2); } if (outfd == -1) { G.outfile = (FILE *)NULL; Info(slide, 0x401, ((char *)slide, LoadFarString(CannotCreateFile), FnFilter1(G.filename))); return 1; } G.outfile = (FILE *)outfd; Trace((stderr, "open_outfile: successfully opened (%s) for writing\n", FnFilter1(G.filename))); return 0;} /* end function open_outfile() *//**********************//* Function mapattr() *//**********************/int mapattr(__G) __GDEF{ /* only care about read-only bit, so just look at MS-DOS side of attrs */ G.pInfo->read_only = (unsigned)(G.crec.external_file_attributes & 1); return 0;} /* end function mapattr() *//************************//* Function mapname() *//************************/ /* return 0 if no error, 1 if caution (filename */int mapname(__G__ renamed) /* truncated), 2 if warning (skip file because */ __GDEF /* dir doesn't exist), 3 if error (skip file), */ int renamed; /* or 10 if out of memory (skip file) */{ /* [also IZ_VOL_LABEL, IZ_CREATED_DIR] */ char pathcomp[FILNAMSIZ]; /* path-component buffer */ char *pp, *cp=(char *)NULL; /* character pointers */ char *lastsemi=(char *)NULL; /* pointer to last semi-colon in pathcomp */ int quote = FALSE; /* flags */ int error = 0; register unsigned workch; /* hold the character being tested *//*--------------------------------------------------------------------------- Initialize various pointers and counters and stuff. ---------------------------------------------------------------------------*/ if (G.pInfo->vollabel) return IZ_VOL_LABEL; /* can't set disk volume labels on Macintosh */ /* can create path as long as not just freshening, or if user told us */ G.create_dirs = (!uO.fflag || renamed); MacZipMode = false; created_dir = FALSE; /* not yet */ /* user gave full pathname: don't prepend rootpath */ renamed_fullpath = (renamed && (*G.filename == '/')); if (checkdir(__G__ (char *)NULL, INIT) == 10) return 10; /* initialize path buffer, unless no memory */ *pathcomp = '\0'; /* initialize translation buffer */ pp = pathcomp; /* point to translation buffer */ if (uO.jflag) /* junking directories */ cp = (char *)strrchr(G.filename, '/'); if (cp == (char *)NULL) { /* no '/' or not junking dirs */ cp = G.filename; /* point to internal zipfile-member pathname */ if (renamed_fullpath) ++cp; /* skip over leading '/' */ } else ++cp; /* point to start of last component of path *//*--------------------------------------------------------------------------- Begin main loop through characters in filename. ---------------------------------------------------------------------------*/ while ((workch = (uch)*cp++) != 0) { if (quote) { /* if character quoted, */ *pp++ = (char)workch; /* include it literally */ quote = FALSE; } else switch (workch) { case '/': /* can assume -j flag not given */ *pp = '\0'; if ((error = checkdir(__G__ pathcomp, APPEND_DIR)) > 1) return error; pp = pathcomp; /* reset conversion buffer for next piece */ lastsemi = (char *)NULL; /* leave directory semi-colons alone */ break; case ';': /* VMS version (or DEC-20 attrib?) */ lastsemi = pp; /* keep for now; remove VMS ";##" */ *pp++ = (char)workch; /* later, if requested */ break; case '\026': /* control-V quote for special chars */ quote = TRUE; /* set flag for next character */ break; default: /* allow European characters in filenames: */ if (isprint(workch) || (128 <= workch && workch <= 254)) *pp++ = (char)workch; } /* end switch */ } /* end while loop */ *pp = '\0'; /* done with pathcomp: terminate it */ /* if not saving them, remove VMS version numbers (appended ";###") */ if (!uO.V_flag && lastsemi) { pp = lastsemi + 1; while (isdigit((uch)(*pp))) ++pp; if (*pp == '\0') /* only digits between ';' and end: nuke */ *lastsemi = '\0'; }/*--------------------------------------------------------------------------- Report if directory was created (and no file to create: filename ended in '/'), check name to be sure it exists, and combine path and name be- fore exiting. ---------------------------------------------------------------------------*/ if (G.filename[strlen(G.filename) - 1] == '/') { checkdir(__G__ G.filename, GETPATH); if (created_dir) { if (QCOND2) { Info(slide, 0, ((char *)slide, " creating: %s\n", G.filename)); } return IZ_CREATED_DIR; /* set dir time (note trailing '/') */ } return 2; /* dir existed already; don't look for data to extract */ } if (*pathcomp == '\0') { Info(slide, 1, ((char *)slide, "mapname: conversion of %s failed\n", G.filename)); return 3; } GetExtraFieldData(&MacZipMode, &newExtraField); checkdir(__G__ pathcomp, APPEND_NAME); /* returns 1 if truncated: care? */ checkdir(__G__ G.filename, GETPATH); return error;} /* end function mapname() */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -