summaryrefslogtreecommitdiff
path: root/macos/source
diff options
context:
space:
mode:
Diffstat (limited to 'macos/source')
-rw-r--r--macos/source/VolWarn.h69
-rw-r--r--macos/source/charmap.h380
-rw-r--r--macos/source/extrafld.c920
-rw-r--r--macos/source/getenv.c398
-rw-r--r--macos/source/helpers.c477
-rw-r--r--macos/source/helpers.h57
-rw-r--r--macos/source/macglob.h86
-rw-r--r--macos/source/macopen.c363
-rw-r--r--macos/source/macopen.h21
-rw-r--r--macos/source/macos.c1079
-rw-r--r--macos/source/macstuff.c1724
-rw-r--r--macos/source/macstuff.h1108
-rw-r--r--macos/source/mactime.c451
-rw-r--r--macos/source/mactime.h61
-rw-r--r--macos/source/pathname.c665
-rw-r--r--macos/source/pathname.h59
-rw-r--r--macos/source/recurse.c442
-rw-r--r--macos/source/recurse.h129
-rw-r--r--macos/source/unixlike.c313
-rw-r--r--macos/source/unixlike.h86
-rw-r--r--macos/source/zip_rc.hqx43
21 files changed, 8931 insertions, 0 deletions
diff --git a/macos/source/VolWarn.h b/macos/source/VolWarn.h
new file mode 100644
index 0000000..2d921eb
--- /dev/null
+++ b/macos/source/VolWarn.h
@@ -0,0 +1,69 @@
+/*
+ Copyright (c) 1990-1999 Info-ZIP. All rights reserved.
+
+ See the accompanying file LICENSE, version 1999-Oct-05 or later
+ (the contents of which are also included in zip.h) for terms of use.
+ If, for some reason, both of these files are missing, the Info-ZIP license
+ also may be found at: ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+/*
+
+This is an Important note about pathnames
+
+*/
+
+static char DuplicVolumeNote[] = {
+ "\rIMPORTANT NOTE:" \
+ "\r" \
+ "\r This port has one weak point: It is based on pathnames !! " \
+ "\r Because it's a port !! Unlike MacOS: As far as I know all other "\
+ "\r Operatingsystems (eg.: Unix, DOS, OS/2, ...) are based on pathnames" \
+ "\r " \
+ /* a short quote from "Inside Macintintosh, Files"; slightly modified by me */
+ "\r On a Mac: Files and directories located in the same directory " \
+ "\r must all have unique names. However, there is no requirement " \
+ "\r that volumes have unique names. It is perfectly acceptable for two mounted" \
+ "\r volumes to have the same name. This is one reason why a application should " \
+ "\r use volume reference numbers rather than volume names to specify volumes," \
+ "\r but for this Zip-Port I can't use reference numbers. " \
+ "\r " \
+ /* end quote */
+ "\r" \
+ "\r From the developers point of view:"\
+ "\r The use of pathnames, however, is highly discouraged. If the user changes"\
+ "\r names or moves things around, they are worthless." \
+ "\r Full pathnames are particularly unreliable as a means of identifying files," \
+ "\r directories or volumes within your application," \
+ "\r for two primary reasons:" \
+ "\r" \
+ "\r* The user can change the name of any element in the path at" \
+ "\r virtually any time." \
+ "\r* Volume names on the Macintosh are *not* unique. Multiple" \
+ "\r mounted volumes can have the same name. For this reason, the use of" \
+ "\r a full pathname to identify a specific volume may not produce the" \
+ "\r results you expect. If more than one volume has the same name and" \
+ "\r a full pathname is used, the File Manager currently uses the first" \
+ "\r mounted volume it finds with a matching name in the volume queue." \
+ "\r" \
+ "\r" \
+ "\r The main reason is that an attempt to implement support exact saving of" \
+ "\r the MacOS specific internal file-structures would require a throughout" \
+ "\r rewrite of major parts of shared code, probably sacrifying compatibility" \
+ "\r with other systems." \
+ "\r I have no solution at the moment. The port will just warn you if you try" \
+ "\r zip from / to a volume which has a duplicate name." \
+ "\r MacZip has problems to find the archives and files." \
+ "\r" \
+ "\r" \
+ "\r ... and the moral of this story:" \
+ "\r" \
+ "\r Don't mount multiple volumes with the same " \
+ "\r name while zip/unzip is running" \
+ "\r and "\
+ "\r My (Big) recommendation: Name all your volumes with a unique name "\
+ "\r (e.g: add a space character to the name) and" \
+ "\r MacZip will run without any problem." \
+ "\r" \
+ "\r" \
+ "\r Dirk Haase" \
+ };
diff --git a/macos/source/charmap.h b/macos/source/charmap.h
new file mode 100644
index 0000000..70f041d
--- /dev/null
+++ b/macos/source/charmap.h
@@ -0,0 +1,380 @@
+/*
+ Copyright (c) 1990-1999 Info-ZIP. All rights reserved.
+
+ See the accompanying file LICENSE, version 1999-Oct-05 or later
+ (the contents of which are also included in zip.h) for terms of use.
+ If, for some reason, both of these files are missing, the Info-ZIP license
+ also may be found at: ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+#ifndef __macos_charmap_h
+#define __macos_charmap_h
+
+/*
+
+Conversion table from MacOS Roman to
+"Western Europe & America" Windows codepage 1252
+
+ Notes on Mac OS Roman:
+ ----------------------
+
+ Mac OS Roman character set is used for at least the following Mac OS
+ localizations: U.S., British, Canadian French, French, Swiss
+ French, German, Swiss German, Italian, Swiss Italian, Dutch,
+ Swedish, Norwegian, Danish, Finnish, Spanish, Catalan,
+ Portuguese, Brazilian, and the default International system.
+
+ Not every char of the charset MacRoman has their equivalent
+ in Windows CodePage1252.
+ To make the mapping in most cases possible, I choosed
+ most similar chars or at least the BULLET. Chars that
+ do not have a direct match are marked with '***'
+
+ The Windows codepage 1252 contains the ISO 8859-1 "Latin 1" codepage,
+ with some additional printable characters in the range (0x80 - 0x9F),
+ that is reserved to control codes in the ISO 8859-1 character table.
+
+In all Mac OS encodings, character codes 0x00-0x7F are identical to ASCII
+
+*/
+
+
+
+ZCONST unsigned char MacRoman_to_WinCP1252[128] = {
+/* Win CP1252 UniCode UniCode Names */
+ 0xC4 , /* 0x00C4 #LATIN CAPITAL LETTER A WITH DIAERESIS */
+ 0xC5 , /* 0x00C5 #LATIN CAPITAL LETTER A WITH RING ABOVE */
+ 0xC7 , /* 0x00C7 #LATIN CAPITAL LETTER C WITH CEDILLA */
+ 0xC9 , /* 0x00C9 #LATIN CAPITAL LETTER E WITH ACUTE */
+ 0xD1 , /* 0x00D1 #LATIN CAPITAL LETTER N WITH TILDE */
+ 0xD6 , /* 0x00D6 #LATIN CAPITAL LETTER O WITH DIAERESIS */
+ 0xDC , /* 0x00DC #LATIN CAPITAL LETTER U WITH DIAERESIS */
+ 0xE1 , /* 0x00E1 #LATIN SMALL LETTER A WITH ACUTE */
+ 0xE0 , /* 0x00E0 #LATIN SMALL LETTER A WITH GRAVE */
+ 0xE2 , /* 0x00E2 #LATIN SMALL LETTER A WITH CIRCUMFLEX */
+ 0xE4 , /* 0x00E4 #LATIN SMALL LETTER A WITH DIAERESIS */
+ 0xE3 , /* 0x00E3 #LATIN SMALL LETTER A WITH TILDE */
+ 0xE5 , /* 0x00E5 #LATIN SMALL LETTER A WITH RING ABOVE */
+ 0xE7 , /* 0x00E7 #LATIN SMALL LETTER C WITH CEDILLA */
+ 0xE9 , /* 0x00E9 #LATIN SMALL LETTER E WITH ACUTE */
+ 0xE8 , /* 0x00E8 #LATIN SMALL LETTER E WITH GRAVE */
+ 0xEA , /* 0x00EA #LATIN SMALL LETTER E WITH CIRCUMFLEX */
+ 0xEB , /* 0x00EB #LATIN SMALL LETTER E WITH DIAERESIS */
+ 0xED , /* 0x00ED #LATIN SMALL LETTER I WITH ACUTE */
+ 0xEC , /* 0x00EC #LATIN SMALL LETTER I WITH GRAVE */
+ 0xEE , /* 0x00EE #LATIN SMALL LETTER I WITH CIRCUMFLEX */
+ 0xEF , /* 0x00EF #LATIN SMALL LETTER I WITH DIAERESIS */
+ 0xF1 , /* 0x00F1 #LATIN SMALL LETTER N WITH TILDE */
+ 0xF3 , /* 0x00F3 #LATIN SMALL LETTER O WITH ACUTE */
+ 0xF2 , /* 0x00F2 #LATIN SMALL LETTER O WITH GRAVE */
+ 0xF4 , /* 0x00F4 #LATIN SMALL LETTER O WITH CIRCUMFLEX */
+ 0xF6 , /* 0x00F6 #LATIN SMALL LETTER O WITH DIAERESIS */
+ 0xF5 , /* 0x00F5 #LATIN SMALL LETTER O WITH TILDE */
+ 0xFA , /* 0x00FA #LATIN SMALL LETTER U WITH ACUTE */
+ 0xF9 , /* 0x00F9 #LATIN SMALL LETTER U WITH GRAVE */
+ 0xFB , /* 0x00FB #LATIN SMALL LETTER U WITH CIRCUMFLEX */
+ 0xFC , /* 0x00FC #LATIN SMALL LETTER U WITH DIAERESIS */
+ 0x86 , /* 0x2020 #DAGGER */
+ 0xB0 , /* 0x00B0 #DEGREE SIGN */
+ 0xA2 , /* 0x00A2 #CENT SIGN */
+ 0xA3 , /* 0x00A3 #POUND SIGN */
+ 0x95 , /* 0x2022 # *** BULLET */
+ 0x95 , /* 0x2022 #BULLET */
+ 0xB6 , /* 0x00B6 #PILCROW SIGN */
+ 0xDF , /* 0x00DF #LATIN SMALL LETTER SHARP S */
+ 0xAE , /* 0x00AE #REGISTERED SIGN */
+ 0xA9 , /* 0x00A9 #COPYRIGHT SIGN */
+ 0x99 , /* 0x2122 #TRADE MARK SIGN */
+ 0xB4 , /* 0x00B4 #ACUTE ACCENT */
+ 0xA8 , /* 0x00A8 #DIAERESIS */
+ 0x95 , /* 0x2022 # *** BULLET */
+ 0xC6 , /* 0x00C6 #LATIN CAPITAL LETTER AE */
+ 0xD8 , /* 0x00D8 #LATIN CAPITAL LETTER O WITH STROKE */
+ 0x95 , /* 0x2022 # *** BULLET */
+ 0xB1 , /* 0x00B1 #PLUS-MINUS SIGN */
+ 0x95 , /* 0x2022 # *** BULLET */
+ 0x95 , /* 0x2022 # *** BULLET */
+ 0xA5 , /* 0x00A5 #YEN SIGN */
+ 0xB5 , /* 0x00B5 #MICRO SIGN */
+ 0x95 , /* 0x2022 # *** BULLET */
+ 0x95 , /* 0x2022 # *** BULLET */
+ 0x95 , /* 0x2022 # *** BULLET */
+ 0x95 , /* 0x2022 # *** BULLET */
+ 0x95 , /* 0x2022 # *** BULLET */
+ 0xAA , /* 0x00AA #FEMININE ORDINAL INDICATOR */
+ 0xBA , /* 0x00BA #MASCULINE ORDINAL INDICATOR */
+ 0x95 , /* 0x2022 # *** BULLET */
+ 0xE6 , /* 0x00E6 #LATIN SMALL LETTER AE */
+ 0xF8 , /* 0x00F8 #LATIN SMALL LETTER O WITH STROKE */
+ 0xBF , /* 0x00BF #INVERTED QUESTION MARK */
+ 0xA1 , /* 0x00A1 #INVERTED EXCLAMATION MARK */
+ 0xAC , /* 0x00AC #NOT SIGN */
+ 0x95 , /* 0x2022 # *** BULLET */
+ 0x83 , /* 0x0192 #LATIN SMALL LETTER F WITH HOOK */
+ 0x95 , /* 0x2022 # *** BULLET */
+ 0x95 , /* 0x2022 # *** BULLET */
+ 0xAB , /* 0x00AB #LEFT-POINTING DOUBLE ANGLE QUOTATION MARK */
+ 0xBB , /* 0x00BB #RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK */
+ 0x85 , /* 0x2026 #HORIZONTAL ELLIPSIS */
+ 0xA0 , /* 0x00A0 #NO-BREAK SPACE */
+ 0xC0 , /* 0x00C0 #LATIN CAPITAL LETTER A WITH GRAVE */
+ 0xC3 , /* 0x00C3 #LATIN CAPITAL LETTER A WITH TILDE */
+ 0xD5 , /* 0x00D5 #LATIN CAPITAL LETTER O WITH TILDE */
+ 0x95 , /* 0x2022 # *** BULLET */
+ 0x95 , /* 0x2022 # *** BULLET */
+ 0x96 , /* 0x2013 #EN DASH */
+ 0x97 , /* 0x2014 #EM DASH */
+ 0x93 , /* 0x201C #LEFT DOUBLE QUOTATION MARK */
+ 0x94 , /* 0x201D #RIGHT DOUBLE QUOTATION MARK */
+ 0x91 , /* 0x2018 #LEFT SINGLE QUOTATION MARK */
+ 0x92 , /* 0x2019 #RIGHT SINGLE QUOTATION MARK */
+ 0xF7 , /* 0x00F7 #DIVISION SIGN */
+ 0x95 , /* 0x2022 # *** BULLET */
+ 0xFF , /* 0x00FF #LATIN SMALL LETTER Y WITH DIAERESIS */
+ 0x9F , /* 0x0178 #LATIN CAPITAL LETTER Y WITH DIAERESIS */
+ 0x95 , /* 0x2022 # *** BULLET */
+ 0xA4 , /* 0x00A4 #CURRENCY SIGN */
+ 0x8B , /* 0x2039 #SINGLE LEFT-POINTING ANGLE QUOTATION MARK */
+ 0x9B , /* 0x203A #SINGLE RIGHT-POINTING ANGLE QUOTATION MARK */
+ 0x95 , /* 0x2022 # *** BULLET */
+ 0x95 , /* 0x2022 # *** BULLET */
+ 0x87 , /* 0x2021 #DOUBLE DAGGER */
+ 0xB7 , /* 0x00B7 #MIDDLE DOT */
+ 0x82 , /* 0x201A #SINGLE LOW-9 QUOTATION MARK */
+ 0x84 , /* 0x201E #DOUBLE LOW-9 QUOTATION MARK */
+ 0x89 , /* 0x2030 #PER MILLE SIGN */
+ 0xC2 , /* 0x00C2 #LATIN CAPITAL LETTER A WITH CIRCUMFLEX */
+ 0xCA , /* 0x00CA #LATIN CAPITAL LETTER E WITH CIRCUMFLEX */
+ 0xC1 , /* 0x00C1 #LATIN CAPITAL LETTER A WITH ACUTE */
+ 0xCB , /* 0x00CB #LATIN CAPITAL LETTER E WITH DIAERESIS */
+ 0xC8 , /* 0x00C8 #LATIN CAPITAL LETTER E WITH GRAVE */
+ 0xCD , /* 0x00CD #LATIN CAPITAL LETTER I WITH ACUTE */
+ 0xCE , /* 0x00CE #LATIN CAPITAL LETTER I WITH CIRCUMFLEX */
+ 0xCF , /* 0x00CF #LATIN CAPITAL LETTER I WITH DIAERESIS */
+ 0xCC , /* 0x00CC #LATIN CAPITAL LETTER I WITH GRAVE */
+ 0xD3 , /* 0x00D3 #LATIN CAPITAL LETTER O WITH ACUTE */
+ 0xD4 , /* 0x00D4 #LATIN CAPITAL LETTER O WITH CIRCUMFLEX */
+ 0x95 , /* 0x2022 # *** BULLET */
+ 0xD2 , /* 0x00D2 #LATIN CAPITAL LETTER O WITH GRAVE */
+ 0xDA , /* 0x00DA #LATIN CAPITAL LETTER U WITH ACUTE */
+ 0xDB , /* 0x00DB #LATIN CAPITAL LETTER U WITH CIRCUMFLEX */
+ 0xD9 , /* 0x00D9 #LATIN CAPITAL LETTER U WITH GRAVE */
+ 0x95 , /* 0x2022 # *** BULLET */
+ 0x88 , /* 0x02C6 #MODIFIER LETTER CIRCUMFLEX ACCENT */
+ 0x98 , /* 0x02DC #SMALL TILDE */
+ 0xAF , /* 0x00AF #MACRON */
+ 0x95 , /* 0x2022 # *** BULLET */
+ 0x95 , /* 0x2022 # *** BULLET */
+ 0x95 , /* 0x2022 # *** BULLET */
+ 0xB8 , /* 0x00B8 #CEDILLA */
+ 0x95 , /* 0x2022 # *** BULLET */
+ 0x95 , /* 0x2022 # *** BULLET */
+ 0x95 /* 0x2022 # *** BULLET */
+ };
+
+
+
+ZCONST unsigned char WinCP1252_to_MacRoman[128] = {
+/* Mac Roman UniCode UniCode Names */
+ 0xA5 , /* 0x2022 # *** BULLET */
+ 0xA5 , /* 0x2022 # *** BULLET */
+ 0xE2 , /* 0x201A # SINGLE LOW-9 QUOTATION MARK */
+ 0xC4 , /* 0x0192 # LATIN SMALL LETTER F WITH HOOK */
+ 0xE3 , /* 0x201E # DOUBLE LOW-9 QUOTATION MARK */
+ 0xC9 , /* 0x2026 # HORIZONTAL ELLIPSIS */
+ 0xA0 , /* 0x2020 # DAGGER */
+ 0xE0 , /* 0x2021 # DOUBLE DAGGER */
+ 0xF6 , /* 0x02C6 # MODIFIER LETTER CIRCUMFLEX ACCENT */
+ 0xE4 , /* 0x2030 # PER MILLE SIGN */
+ 0xA5 , /* 0x2022 # *** BULLET */
+ 0xDC , /* 0x2039 # SINGLE LEFT-POINTING ANGLE QUOTATION MARK */
+ 0xA5 , /* 0x2022 # *** BULLET */
+ 0xA5 , /* 0x2022 # *** BULLET */
+ 0xA5 , /* 0x2022 # *** BULLET */
+ 0xA5 , /* 0x2022 # *** BULLET */
+ 0xA5 , /* 0x2022 # *** BULLET */
+ 0xD4 , /* 0x2018 # LEFT SINGLE QUOTATION MARK */
+ 0xD5 , /* 0x2019 # RIGHT SINGLE QUOTATION MARK */
+ 0xD2 , /* 0x201C # LEFT DOUBLE QUOTATION MARK */
+ 0xD3 , /* 0x201D # RIGHT DOUBLE QUOTATION MARK */
+ 0xA5 , /* 0x2022 # BULLET */
+ 0xD0 , /* 0x2013 # EN DASH */
+ 0xD1 , /* 0x2014 # EM DASH */
+ 0xF7 , /* 0x02DC # SMALL TILDE */
+ 0xAA , /* 0x2122 # TRADE MARK SIGN */
+ 0xA5 , /* 0x2022 # *** BULLET */
+ 0xDD , /* 0x203A # SINGLE RIGHT-POINTING ANGLE QUOTATION MARK */
+ 0xA5 , /* 0x2022 # *** BULLET */
+ 0xA5 , /* 0x2022 # *** BULLET */
+ 0xA5 , /* 0x2022 # *** BULLET */
+ 0xD9 , /* 0x0178 # LATIN CAPITAL LETTER Y WITH DIAERESIS */
+ 0xCA , /* 0x00A0 # NO-BREAK SPACE */
+ 0xC1 , /* 0x00A1 # INVERTED EXCLAMATION MARK */
+ 0xA2 , /* 0x00A2 # CENT SIGN */
+ 0xA3 , /* 0x00A3 # POUND SIGN */
+ 0xDB , /* 0x00A4 # CURRENCY SIGN */
+ 0xB4 , /* 0x00A5 # YEN SIGN */
+ 0xA5 , /* 0x2022 # *** BULLET */
+ 0xA5 , /* 0x2022 # *** BULLET */
+ 0xAC , /* 0x00A8 # DIAERESIS */
+ 0xA9 , /* 0x00A9 # COPYRIGHT SIGN */
+ 0xBB , /* 0x00AA # FEMININE ORDINAL INDICATOR */
+ 0xC7 , /* 0x00AB # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK */
+ 0xC2 , /* 0x00AC # NOT SIGN */
+ 0xA5 , /* 0x2022 # *** BULLET */
+ 0xA8 , /* 0x00AE # REGISTERED SIGN */
+ 0xF8 , /* 0x00AF # MACRON */
+ 0xA1 , /* 0x00B0 # DEGREE SIGN */
+ 0xB1 , /* 0x00B1 # PLUS-MINUS SIGN */
+ 0xA5 , /* 0x2022 # *** BULLET */
+ 0xA5 , /* 0x2022 # *** BULLET */
+ 0xAB , /* 0x00B4 # ACUTE ACCENT */
+ 0xB5 , /* 0x00B5 # MICRO SIGN */
+ 0xA6 , /* 0x00B6 # PILCROW SIGN */
+ 0xE1 , /* 0x00B7 # MIDDLE DOT */
+ 0xFC , /* 0x00B8 # CEDILLA */
+ 0xA5 , /* 0x2022 # *** BULLET */
+ 0xBC , /* 0x00BA # MASCULINE ORDINAL INDICATOR */
+ 0xC8 , /* 0x00BB # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK */
+ 0xA5 , /* 0x2022 # *** BULLET */
+ 0xA5 , /* 0x2022 # *** BULLET */
+ 0xA5 , /* 0x2022 # *** BULLET */
+ 0xC0 , /* 0x00BF # INVERTED QUESTION MARK */
+ 0xCB , /* 0x00C0 # LATIN CAPITAL LETTER A WITH GRAVE */
+ 0xE7 , /* 0x00C1 # LATIN CAPITAL LETTER A WITH ACUTE */
+ 0xE5 , /* 0x00C2 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX */
+ 0xCC , /* 0x00C3 # LATIN CAPITAL LETTER A WITH TILDE */
+ 0x80 , /* 0x00C4 # LATIN CAPITAL LETTER A WITH DIAERESIS */
+ 0x81 , /* 0x00C5 # LATIN CAPITAL LETTER A WITH RING ABOVE */
+ 0xAE , /* 0x00C6 # LATIN CAPITAL LETTER AE */
+ 0x82 , /* 0x00C7 # LATIN CAPITAL LETTER C WITH CEDILLA */
+ 0xE9 , /* 0x00C8 # LATIN CAPITAL LETTER E WITH GRAVE */
+ 0x83 , /* 0x00C9 # LATIN CAPITAL LETTER E WITH ACUTE */
+ 0xE6 , /* 0x00CA # LATIN CAPITAL LETTER E WITH CIRCUMFLEX */
+ 0xE8 , /* 0x00CB # LATIN CAPITAL LETTER E WITH DIAERESIS */
+ 0xED , /* 0x00CC # LATIN CAPITAL LETTER I WITH GRAVE */
+ 0xEA , /* 0x00CD # LATIN CAPITAL LETTER I WITH ACUTE */
+ 0xEB , /* 0x00CE # LATIN CAPITAL LETTER I WITH CIRCUMFLEX */
+ 0xEC , /* 0x00CF # LATIN CAPITAL LETTER I WITH DIAERESIS */
+ 0xA5 , /* 0x2022 # *** BULLET */
+ 0x84 , /* 0x00D1 # LATIN CAPITAL LETTER N WITH TILDE */
+ 0xF1 , /* 0x00D2 # LATIN CAPITAL LETTER O WITH GRAVE */
+ 0xEE , /* 0x00D3 # LATIN CAPITAL LETTER O WITH ACUTE */
+ 0xEF , /* 0x00D4 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX */
+ 0xCD , /* 0x00D5 # LATIN CAPITAL LETTER O WITH TILDE */
+ 0x85 , /* 0x00D6 # LATIN CAPITAL LETTER O WITH DIAERESIS */
+ 0xA5 , /* 0x2022 # *** BULLET */
+ 0xAF , /* 0x00D8 # LATIN CAPITAL LETTER O WITH STROKE */
+ 0xF4 , /* 0x00D9 # LATIN CAPITAL LETTER U WITH GRAVE */
+ 0xF2 , /* 0x00DA # LATIN CAPITAL LETTER U WITH ACUTE */
+ 0xF3 , /* 0x00DB # LATIN CAPITAL LETTER U WITH CIRCUMFLEX */
+ 0x86 , /* 0x00DC # LATIN CAPITAL LETTER U WITH DIAERESIS */
+ 0xA5 , /* 0x2022 # *** BULLET */
+ 0xA5 , /* 0x2022 # *** BULLET */
+ 0xA7 , /* 0x00DF # LATIN SMALL LETTER SHARP S */
+ 0x88 , /* 0x00E0 # LATIN SMALL LETTER A WITH GRAVE */
+ 0x87 , /* 0x00E1 # LATIN SMALL LETTER A WITH ACUTE */
+ 0x89 , /* 0x00E2 # LATIN SMALL LETTER A WITH CIRCUMFLEX */
+ 0x8B , /* 0x00E3 # LATIN SMALL LETTER A WITH TILDE */
+ 0x8A , /* 0x00E4 # LATIN SMALL LETTER A WITH DIAERESIS */
+ 0x8C , /* 0x00E5 # LATIN SMALL LETTER A WITH RING ABOVE */
+ 0xBE , /* 0x00E6 # LATIN SMALL LETTER AE */
+ 0x8D , /* 0x00E7 # LATIN SMALL LETTER C WITH CEDILLA */
+ 0x8F , /* 0x00E8 # LATIN SMALL LETTER E WITH GRAVE */
+ 0x8E , /* 0x00E9 # LATIN SMALL LETTER E WITH ACUTE */
+ 0x90 , /* 0x00EA # LATIN SMALL LETTER E WITH CIRCUMFLEX */
+ 0x91 , /* 0x00EB # LATIN SMALL LETTER E WITH DIAERESIS */
+ 0x93 , /* 0x00EC # LATIN SMALL LETTER I WITH GRAVE */
+ 0x92 , /* 0x00ED # LATIN SMALL LETTER I WITH ACUTE */
+ 0x94 , /* 0x00EE # LATIN SMALL LETTER I WITH CIRCUMFLEX */
+ 0x95 , /* 0x00EF # LATIN SMALL LETTER I WITH DIAERESIS */
+ 0xA5 , /* 0x2022 # *** BULLET */
+ 0x96 , /* 0x00F1 # LATIN SMALL LETTER N WITH TILDE */
+ 0x98 , /* 0x00F2 # LATIN SMALL LETTER O WITH GRAVE */
+ 0x97 , /* 0x00F3 # LATIN SMALL LETTER O WITH ACUTE */
+ 0x99 , /* 0x00F4 # LATIN SMALL LETTER O WITH CIRCUMFLEX */
+ 0x9B , /* 0x00F5 # LATIN SMALL LETTER O WITH TILDE */
+ 0x9A , /* 0x00F6 # LATIN SMALL LETTER O WITH DIAERESIS */
+ 0xD6 , /* 0x00F7 # DIVISION SIGN */
+ 0xBF , /* 0x00F8 # LATIN SMALL LETTER O WITH STROKE */
+ 0x9D , /* 0x00F9 # LATIN SMALL LETTER U WITH GRAVE */
+ 0x9C , /* 0x00FA # LATIN SMALL LETTER U WITH ACUTE */
+ 0x9E , /* 0x00FB # LATIN SMALL LETTER U WITH CIRCUMFLEX */
+ 0x9F , /* 0x00FC # LATIN SMALL LETTER U WITH DIAERESIS */
+ 0xA5 , /* 0x2022 # *** BULLET */
+ 0xA5 , /* 0x2022 # *** BULLET */
+ 0xD8 /* 0x00FF # LATIN SMALL LETTER Y WITH DIAERESIS */
+ };
+
+
+/*
+
+The following characters has no equivalent
+to each other:
+
+MacCodes
+164 0xA4 0x00A7 # SECTION SIGN
+253 0xFD 0x02DD # DOUBLE ACUTE ACCENT
+189 0xBD 0x03A9 # GREEK CAPITAL LETTER OMEGA
+185 0xB9 0x03C0 # GREEK SMALL LETTER PI
+255 0xFF 0x02C7 # CARON
+249 0xF9 0x02D8 # BREVE
+250 0xFA 0x02D9 # DOT ABOVE
+251 0xFB 0x02DA # RING ABOVE
+254 0xFE 0x02DB # OGONEK
+218 0xDA 0x2044 # FRACTION SLASH
+182 0xB6 0x2202 # PARTIAL DIFFERENTIAL
+198 0xC6 0x2206 # INCREMENT
+184 0xB8 0x220F # N-ARY PRODUCT
+183 0xB7 0x2211 # N-ARY SUMMATION
+195 0xC3 0x221A # SQUARE ROOT
+176 0xB0 0x221E # INFINITY
+186 0xBA 0x222B # INTEGRAL
+197 0xC5 0x2248 # ALMOST EQUAL TO
+173 0xAD 0x2260 # NOT EQUAL TO
+178 0xB2 0x2264 # LESS-THAN OR EQUAL TO
+179 0xB3 0x2265 # GREATER-THAN OR EQUAL TO
+215 0xD7 0x25CA # LOZENGE
+240 0xF0 0xF8FF # Apple logo
+222 0xDE 0xFB01 # LATIN SMALL LIGATURE FI
+223 0xDF 0xFB02 # LATIN SMALL LIGATURE FL
+245 0xF5 0x0131 # LATIN SMALL LETTER DOTLESS I
+206 0xCE 0x0152 # LATIN CAPITAL LIGATURE OE
+207 0xCF 0x0153 # LATIN SMALL LIGATURE OE
+
+WinCodes
+129 0x81 #UNDEFINED
+141 0x8D #UNDEFINED
+143 0x8F #UNDEFINED
+144 0x90 #UNDEFINED
+157 0x9D #UNDEFINED
+167 0xA7 0x00A7 #SECTION SIGN
+173 0xAD 0x00AD #SOFT HYPHEN
+178 0xB2 0x00B2 #SUPERSCRIPT TWO
+179 0xB3 0x00B3 #SUPERSCRIPT THREE
+185 0xB9 0x00B9 #SUPERSCRIPT ONE
+188 0xBC 0x00BC #VULGAR FRACTION ONE QUARTER
+189 0xBD 0x00BD #VULGAR FRACTION ONE HALF
+190 0xBE 0x00BE #VULGAR FRACTION THREE QUARTERS
+208 0xD0 0x00D0 #LATIN CAPITAL LETTER ETH
+215 0xD7 0x00D7 #MULTIPLICATION SIGN
+221 0xDD 0x00DD #LATIN CAPITAL LETTER Y WITH ACUTE
+222 0xDE 0x00DE #LATIN CAPITAL LETTER THORN
+240 0xF0 0x00F0 #LATIN SMALL LETTER ETH
+253 0xFD 0x00FD #LATIN SMALL LETTER Y WITH ACUTE
+254 0xFE 0x00FE #LATIN SMALL LETTER THORN
+140 0x8C 0x0152 #LATIN CAPITAL LIGATURE OE
+156 0x9C 0x0153 #LATIN SMALL LIGATURE OE
+138 0x8A 0x0160 #LATIN CAPITAL LETTER S WITH CARON
+154 0x9A 0x0161 #LATIN SMALL LETTER S WITH CARON
+142 0x8E 0x017D #LATIN CAPITAL LETTER Z WITH CARON
+158 0x9E 0x017E #LATIN SMALL LETTER Z WITH CARON
+128 0x80 0x20AC #EURO SIGN
+166 0xA6 0x00A6 #BROKEN BAR
+
+
+*/
+
+
+
+
+#endif /* !__macos_charmap_h */
diff --git a/macos/source/extrafld.c b/macos/source/extrafld.c
new file mode 100644
index 0000000..83e00a3
--- /dev/null
+++ b/macos/source/extrafld.c
@@ -0,0 +1,920 @@
+/*
+ Copyright (c) 1990-2005 Info-ZIP. All rights reserved.
+
+ See the accompanying file LICENSE, version 2004-May-22 or later
+ (the contents of which are also included in zip.h) for terms of use.
+ If, for some reason, both of these files are missing, the Info-ZIP license
+ also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*---------------------------------------------------------------------------
+
+ extrafld.c
+
+ contains functions to build extra-fields.
+
+ ---------------------------------------------------------------------------*/
+
+/*****************************************************************************/
+/* Includes */
+/*****************************************************************************/
+
+#include <sound.h>
+#include "zip.h"
+#include "unixlike.h"
+#include "helpers.h"
+#include "pathname.h"
+
+
+/*****************************************************************************/
+/* Macros, typedefs */
+/*****************************************************************************/
+
+/* ---------------------------------------------------------------------- */
+/* Add a 'MAC3' extra field to the zlist data pointed to by z. */
+/* This is the (new) Info-zip extra block for Macintosh */
+#define EB_MAC3_HLEN 14 /* fixed length part of MAC3's header */
+#define EB_L_MAC3_FINFO_LEN 52 /* fixed part of MAC3 compressible data */
+
+#define EB_MAX_OF_VARDATA 1300 /* max possible datasize */
+
+#define EB_L_MAC3_SIZE (EB_HEADSIZE + EB_MAC3_HLEN)
+#define EB_C_MAC3_SIZE (EB_HEADSIZE + EB_MAC3_HLEN)
+
+#define MEMCOMPRESS_HEADER 6 /* ush compression type, ulg CRC */
+#define DEFLAT_WORSTCASE_ADD 5 /* byte blocktype, 2 * ush blocklength */
+#define MEMCOMPRESS_OVERHEAD (MEMCOMPRESS_HEADER + DEFLAT_WORSTCASE_ADD)
+
+#define EXTRAFLD_MAX (unsigned)0xFFFF
+
+#define EB_M3_FL_COMPRESS 0x00
+#define EB_M3_FL_DATFRK 0x01 /* data is data-fork */
+#define EB_M3_FL_NOCHANGE 0x02 /* filename will be not changed */
+#define EB_M3_FL_UNCMPR 0x04 /* data is 'natural' (not compressed) */
+#define EB_M3_FL_TIME64 0x08 /* time is coded in 64 bit */
+#define EB_M3_FL_NOUTC 0x10 /* only 'local' time-stamps are stored */
+
+
+#define EB_L_UT_SIZE (EB_HEADSIZE + EB_UT_LEN(2))
+#define EB_C_UT_SIZE (EB_HEADSIZE + EB_UT_LEN(1))
+
+/* disable compressing of extra field
+#define MAC_EXTRAFLD_UNCMPR */
+
+/* ---------------------------------------------------------------------- */
+/* Add a 'JLEE' extra field to the zlist data pointed to by z. */
+/* This is the (old) Info-zip resource-fork extra block for Macintosh
+(last Revision 1996-09-22) Layout made by Johnny Lee, Code made by me :-) */
+#define EB_L_JLEE_LEN 40 /* fixed length of JLEE's header */
+#define EB_C_JLEE_LEN 40 /* fixed length of JLEE's header */
+
+#define EB_L_JLEE_SIZE (EB_HEADSIZE + EB_L_JLEE_LEN)
+#define EB_C_JLEE_SIZE (EB_HEADSIZE + EB_C_JLEE_LEN)
+
+
+
+/*****************************************************************************/
+/* Global Vars */
+/*****************************************************************************/
+
+extern MacZipGlobals MacZip;
+extern unsigned long count_of_Zippedfiles;
+
+
+
+/*****************************************************************************/
+/* Prototypes */
+/*****************************************************************************/
+
+static int add_UT_ef(struct zlist far *z, iztimes *z_utim);
+static int add_JLEE_ef(struct zlist far *z); /* old mac extra field */
+static int add_MAC3_ef(struct zlist far *z); /* new mac extra field */
+
+static void make_extrafield_JLEE(char *l_ef);
+static unsigned make_extrafield_MAC3(char *ef);
+static char *make_EF_Head_MAC3(char *ef, unsigned compsize, ulg attrsize,
+ unsigned flag);
+
+static void print_extra_info(void);
+void UserStop(void);
+
+
+/*****************************************************************************/
+/* Functions */
+/*****************************************************************************/
+
+
+/*
+* Set the extra-field's for each compressed file
+*/
+int set_extra_field(struct zlist far *z, iztimes *z_utim)
+ /* store full data in local header but just modification time stamp info
+ in central header */
+{
+ int retval;
+
+ Assert_it(z, "set_extra_field","")
+ Assert_it(z_utim, "set_extra_field","")
+
+ z_utim = z_utim;
+
+ /* Check to make sure z is valid. */
+ if( z == NULL ) {
+ return ZE_LOGIC;
+ }
+
+ /* Resource forks are always binary */
+ if (MacZip.CurrentFork == ResourceFork) z->att = BINARY;
+
+ if (noisy)
+ {
+ count_of_Zippedfiles++;
+ InformProgress(MacZip.RawCountOfItems, count_of_Zippedfiles );
+ }
+
+ /*
+ PrintFileInfo();
+ */
+ switch (MacZip.MacZipMode)
+ {
+ case JohnnyLee_EF:
+ {
+ retval = add_JLEE_ef( z );
+ if (retval != ZE_OK) return retval;
+ break;
+ }
+ case NewZipMode_EF:
+ { /* */
+#ifdef USE_EF_UT_TIME
+ retval = add_UT_ef(z, z_utim);
+ if (retval != ZE_OK) return retval;
+#endif
+
+ retval = add_MAC3_ef( z );
+ if (retval != ZE_OK) return retval;
+ break;
+ }
+ default:
+ {
+ printerr("Unknown Extrafieldmode", -1, -1, __LINE__, __FILE__, "");
+ return ZE_LOGIC; /* function should never reach this point */
+ }
+ }
+
+ /* MacStat information is now outdated and
+ must be refreshed for the next file */
+ MacZip.isMacStatValid = false;
+
+ return ZE_OK;
+}
+
+
+
+
+#ifdef USE_EF_UT_TIME
+/*
+* Build and add the Unix time extra-field. This extra field
+* will be included be default. Johnny Lee's implementation does
+* not use this kind of extra-field.
+* All datas are in Intel (=little-endian) format
+
+ Extra field info:
+ - 'UT' - UNIX time extra field
+
+ This is done the same way ../unix/unix.c stores the 'UT'/'Ux' fields
+ (full data in local header, only modification time in central header),
+ with the 'M3' field added to the end and the size of the 'M3' field
+ in the central header.
+ */
+
+static int add_UT_ef(struct zlist far *z, iztimes *z_utim)
+{
+ char *l_ef = NULL;
+ char *c_ef = NULL;
+
+ Assert_it(z, "add_UT_ef","")
+
+#ifdef IZ_CHECK_TZ
+ if (!zp_tz_is_valid)
+ return ZE_OK; /* skip silently if no valid TZ info */
+#endif
+
+ /* We can't work if there's no entry to work on. */
+ if( z == NULL ) {
+ return ZE_LOGIC;
+ }
+
+ /* Check to make sure we've got enough room in the extra fields. */
+ if( z->ext + EB_L_UT_SIZE > EXTRAFLD_MAX ||
+ z->cext + EB_C_UT_SIZE > EXTRAFLD_MAX ) {
+ return ZE_MEM;
+ }
+
+ /* Allocate memory for the local and central extra fields. */
+ if( z->extra && z->ext != 0 ) {
+ l_ef = (char *)realloc( z->extra, z->ext + EB_L_UT_SIZE );
+ } else {
+ l_ef = (char *)malloc( EB_L_UT_SIZE );
+ z->ext = 0;
+ }
+ if( l_ef == NULL ) {
+ return ZE_MEM;
+ }
+ z->extra = l_ef;
+ l_ef += z->ext;
+
+ if( z->cextra && z->cext != 0 ) {
+ c_ef = (char *)realloc( z->cextra, z->cext + EB_C_UT_SIZE );
+ } else {
+ c_ef = (char *)malloc( EB_C_UT_SIZE );
+ z->cext = 0;
+ }
+ if( c_ef == NULL ) {
+ return ZE_MEM;
+ }
+ z->cextra = c_ef;
+ c_ef += z->cext;
+
+ /* Now add the local version of the field. */
+ *l_ef++ = 'U';
+ *l_ef++ = 'T';
+ *l_ef++ = (char)(EB_UT_LEN(2)); /* length of data in local EF */
+ *l_ef++ = (char)0;
+ *l_ef++ = (char)(EB_UT_FL_MTIME | EB_UT_FL_CTIME);
+ *l_ef++ = (char)(z_utim->mtime);
+ *l_ef++ = (char)(z_utim->mtime >> 8);
+ *l_ef++ = (char)(z_utim->mtime >> 16);
+ *l_ef++ = (char)(z_utim->mtime >> 24);
+ *l_ef++ = (char)(z_utim->ctime);
+ *l_ef++ = (char)(z_utim->ctime >> 8);
+ *l_ef++ = (char)(z_utim->ctime >> 16);
+ *l_ef++ = (char)(z_utim->ctime >> 24);
+
+ z->ext += EB_L_UT_SIZE;
+
+ /* Now add the central version. */
+ memcpy(c_ef, l_ef-EB_L_UT_SIZE, EB_C_UT_SIZE);
+ c_ef[EB_LEN] = (char)(EB_UT_LEN(1)); /* length of data in central EF */
+
+ z->cext += EB_C_UT_SIZE;
+
+ return ZE_OK;
+}
+#endif /* USE_EF_UT_TIME */
+
+
+/*
+* Build and add the old 'Johnny Lee' Mac extra field
+* All native datas are in Motorola (=big-endian) format
+*/
+
+static int add_JLEE_ef( struct zlist far *z )
+{
+ char *l_ef = NULL;
+ char *c_ef = NULL;
+
+ Assert_it(z, "add_JLEE_ef","")
+
+ /* Check to make sure we've got enough room in the extra fields. */
+ if ( z->ext + EB_L_JLEE_SIZE > EXTRAFLD_MAX ||
+ z->cext + EB_C_JLEE_SIZE > EXTRAFLD_MAX ) {
+ return ZE_MEM;
+ }
+
+
+ /* Allocate memory for the local extra fields. */
+ if ( z->extra && z->ext != 0 ) {
+ l_ef = (char *)realloc( z->extra, z->ext + EB_L_JLEE_SIZE );
+ } else {
+ l_ef = (char *)malloc( EB_L_JLEE_SIZE );
+ z->ext = 0;
+ }
+ if ( l_ef == NULL ) {
+ return ZE_MEM;
+ }
+ z->extra = l_ef;
+ l_ef += z->ext;
+
+ /* Allocate memory for the central extra fields. */
+ if ( z->cextra && z->cext != 0 ) {
+ c_ef = (char *)realloc( z->cextra, z->cext + EB_C_JLEE_SIZE );
+ } else {
+ c_ef = (char *)malloc( EB_C_JLEE_SIZE );
+ z->cext = 0;
+ }
+ if ( c_ef == NULL ) {
+ return ZE_MEM;
+ }
+ z->cextra = c_ef;
+ c_ef += z->cext;
+
+
+ if ( verbose ) {
+ print_extra_info();
+ }
+
+
+ /**
+ **
+ ** Now add the local version of the field.
+ **/
+ make_extrafield_JLEE(l_ef);
+ z->ext += EB_L_JLEE_SIZE;
+
+
+ /**
+ **
+ ** Now add the central version of the field.
+ ** It's identical to the local header. I wonder why ??
+ * the first two fields are in Intel little-endian format */
+ make_extrafield_JLEE(c_ef);
+ z->cext += EB_C_JLEE_SIZE;
+
+ return ZE_OK;
+}
+
+
+
+/*
+* This is an implementation of Johnny Lee's extra field.
+* I never saw Johnny Lee's code. My code is based on the extra-field
+* definition mac (see latest appnote 1997-03-11)
+* and on some experiments with Johnny Lee's Zip-app version 1.0, 1992
+*
+* Unfortunately I cannot agree with his extra-field layout.
+* - it wasted space
+* - and holds not all mac-specific information
+*
+* I coded this extra-field only for testing purposes.
+* I don't want support this extra-field. Please use my implementation.
+*
+* This is old implementation of Johnny Lee's extra field.
+* All native datas are in Motorola (=big-endian) format
+*/
+
+static void make_extrafield_JLEE(char *ef)
+{
+
+ Assert_it(ef, "make_extrafield_JLEE","")
+
+ if (MacZip.isMacStatValid == false)
+ {
+ fprintf(stderr,"Internal Logic Error: [%d/%s] MacStat is out of sync !",
+ __LINE__,__FILE__);
+ exit(-1);
+ }
+
+
+ /* the first two fields are in Intel little-endian format */
+ *ef++ = 0xC8; /* tag for this extra block */
+ *ef++ = 0x07;
+
+ *ef++ = (char)(EB_L_JLEE_LEN); /* total data size this block */
+ *ef++ = (char)((EB_L_JLEE_LEN) >> 8);
+
+ /* the following fields are in motorola big-endian format */
+ *ef++ = 'J'; /* extra field signature: 4 Bytes */
+ *ef++ = 'L'; /* the old style extra field */
+ *ef++ = 'E';
+ *ef++ = 'E';
+
+ /* Start Macintosh Finder FInfo structure 16 Bytes overall */
+ /* Type: 4 Bytes */
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType >> 24);
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType >> 16);
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType >> 8);
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType);
+
+ /* Creator: 4 Bytes */
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdCreator >> 24);
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdCreator >> 16);
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdCreator >> 8);
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdCreator);
+
+ /* file Finder Flags: 2 Bytes */
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdFlags >> 8);
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdFlags);
+
+ /* Finders Icon position of a file*/
+ /* V/Y-Position: 2 Bytes */
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdLocation.v >> 8);
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdLocation.v);
+ /* H/X-Position: 2 Bytes */
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdLocation.h >> 8);
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdLocation.h);
+
+ /* fdFldr Folder containing file 2 Bytes */
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdFldr >> 8);
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdFldr);
+ /* End Macintosh Finder FInfo structure */
+
+
+ /* Creation-time 4 Bytes */
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlCrDat >> 24);
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlCrDat >> 16);
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlCrDat >> 8);
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlCrDat);
+
+ /* Modification-time 4 Bytes */
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlMdDat >> 24);
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlMdDat >> 16);
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlMdDat >> 8);
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlMdDat);
+
+ /* info Bits 4 Bytes */
+ *ef++ = 0x00;
+ *ef++ = 0x00;
+ *ef++ = 0x00;
+ if (MacZip.DataForkOnly)
+ { /* don't convert filename for unzipping */
+ /* 0x01 = data-fork; 0x00 = resource-fork */
+ *ef++ = (char) (MacZip.CurrentFork == DataFork) | 2;
+ }
+ else
+ {
+ *ef++ = (char) (MacZip.CurrentFork == DataFork);
+ }
+
+ /* file's location folder ID 4 Bytes */
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlParID >> 24);
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlParID >> 16);
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlParID >> 8);
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlParID);
+ /* ============ */
+ /* 40 Bytes */
+}
+
+
+
+/*
+* Build and add the new mac extra field
+* All native data are stored in Intel (=little-endian) format
+*/
+
+static int add_MAC3_ef( struct zlist far *z )
+{
+ char *l_ef = NULL;
+ char *c_ef = NULL;
+ char *attrbuff = NULL;
+ off_t attrsize = (EB_L_MAC3_FINFO_LEN + EB_MAX_OF_VARDATA);
+ char *compbuff = NULL;
+ unsigned compsize = 0;
+ unsigned m3_compr;
+ Boolean compress_data = true;
+
+ Assert_it(z, "add_MAC3_ef","")
+
+ UserStop(); /* do event handling and let the user stop */
+
+ if( verbose ) {
+ print_extra_info();
+ }
+
+ /* allocate temporary buffer to collect the Mac extra field info */
+ attrbuff = (char *)malloc( (size_t)attrsize );
+ if( attrbuff == NULL ) {
+ return ZE_MEM;
+ }
+
+ /* fill the attribute buffer, to get its (uncompressed) size */
+ attrsize = make_extrafield_MAC3(attrbuff);
+
+ if (compress_data &&
+ ((compbuff = (char *)malloc((size_t)attrsize + MEMCOMPRESS_OVERHEAD))
+ != NULL))
+ {
+ /* Try compressing the data */
+ compsize = memcompress( compbuff,
+ (size_t)attrsize + MEMCOMPRESS_OVERHEAD,
+ attrbuff,
+ (size_t)attrsize );
+#ifdef MAC_EXTRAFLD_UNCMPR
+ compsize = attrsize;
+#endif
+ }
+ else
+ {
+ compsize = attrsize;
+ }
+
+ if ((compsize) < attrsize) {
+ /* compression gained some space ... */
+ free(attrbuff); /* no longer needed ... */
+ m3_compr = EB_M3_FL_COMPRESS;
+ } else {
+ /* compression does not help, store data in uncompressed mode */
+ if (compbuff != NULL) free(compbuff);
+ compbuff = attrbuff;
+ compsize = attrsize;
+ m3_compr = EB_M3_FL_UNCMPR;
+ }
+
+ /* Check to make sure we've got enough room in the extra fields. */
+ if( z->ext + (EB_L_MAC3_SIZE + compsize) > EXTRAFLD_MAX ||
+ z->cext + EB_C_MAC3_SIZE > EXTRAFLD_MAX ) {
+ if (compbuff != NULL) free(compbuff);
+ return ZE_MEM;
+ }
+
+ /* Allocate memory for the local extra fields. */
+ if( z->extra && z->ext != 0 ) {
+ l_ef = (char *)realloc( z->extra, z->ext +
+ EB_L_MAC3_SIZE + compsize);
+ } else {
+ l_ef = (char *)malloc( EB_L_MAC3_SIZE + compsize);
+ z->ext = 0;
+ }
+ if( l_ef == NULL ) {
+ return ZE_MEM;
+ }
+ z->extra = l_ef;
+ l_ef += z->ext;
+
+ /* Allocate memory for the central extra fields. */
+ if( z->cextra && z->cext != 0 ) {
+ c_ef = (char *)realloc( z->cextra, z->cext + EB_C_MAC3_SIZE);
+ } else {
+ c_ef = (char *)malloc( EB_C_MAC3_SIZE );
+ z->cext = 0;
+ }
+ if( c_ef == NULL ) {
+ return ZE_MEM;
+ }
+ z->cextra = c_ef;
+ c_ef += z->cext;
+
+ /**
+ ** Now add the local version of the field.
+ **/
+ l_ef = make_EF_Head_MAC3(l_ef, compsize, (ulg)attrsize, m3_compr);
+ memcpy(l_ef, compbuff, (size_t)compsize);
+ l_ef += compsize;
+ z->ext += EB_L_MAC3_SIZE + compsize;
+ free(compbuff);
+ /* And the central version. */
+ c_ef = make_EF_Head_MAC3(c_ef, 0, (ulg)attrsize, m3_compr);
+ z->cext += EB_C_MAC3_SIZE;
+
+ return ZE_OK;
+}
+
+
+
+
+/*
+* Build the new mac local extra field header.
+* It's identical with the central extra field.
+* All native data are in Intel (=little-endian) format
+*/
+static char *make_EF_Head_MAC3(char *ef, unsigned compsize, ulg attrsize,
+ unsigned flag)
+{
+ unsigned info_flag = flag;
+
+ Assert_it(ef, "make_EF_Head_MAC3","")
+
+ /* the first four fields are in Intel little-endian format */
+ *ef++ = 'M'; /* tag for this extra block 2 Bytes */
+ *ef++ = '3';
+
+ /* total data size this block 2 Bytes */
+ *ef++ = (char) (EB_MAC3_HLEN + compsize);
+ *ef++ = (char)((EB_MAC3_HLEN + compsize) >> 8);
+
+ *ef++ = (char)(attrsize);
+ *ef++ = (char)(attrsize >> 8);
+ *ef++ = (char)(attrsize >> 16);
+ *ef++ = (char)(attrsize >> 24);
+
+ /* info Bits (flags) 2 Bytes */
+
+ if (MacZip.DataForkOnly) info_flag |= (EB_M3_FL_DATFRK |
+ EB_M3_FL_NOCHANGE);
+ if (MacZip.CurrentFork == DataFork) info_flag |= EB_M3_FL_DATFRK;
+ if (!MacZip.HaveGMToffset) info_flag |= EB_M3_FL_NOUTC;
+
+ *ef++ = (char)info_flag;
+ *ef++ = (char)0x00; /* reserved at the moment */
+
+ /* Note: Apple defined File-Type/-Creator as OSType ( =unsigned long,
+ see Universal Headers 3.1). However, File-Type/-Creator are a
+ unique four-character sequence. Therefore the byteorder of the
+ File-Type/-Creator are NOT changed. The native format is used. */
+
+ /* Type: 4 Bytes */
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType >> 24);
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType >> 16);
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType >> 8);
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType);
+
+ /* Creator: 4 Bytes */
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdCreator >> 24);
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdCreator >> 16);
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdCreator >> 8);
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdCreator);
+
+ return ef;
+}
+
+
+
+
+
+/*
+* Build the new mac local extra field header.
+* All native data are in Intel (=little-endian) format
+*/
+unsigned make_extrafield_MAC3(char *ef)
+{
+ char *ef_m3_begin = ef;
+ char *temp_Pathname;
+ char tmp_buffer[NAME_MAX];
+ unsigned char comment[257];
+ unsigned short FLength = 0;
+ unsigned short CLength = 0;
+ short tempFork;
+ OSErr err;
+
+ Assert_it(ef, "make_extrafield_MAC3","")
+
+ if (MacZip.isMacStatValid == false)
+ {
+ fprintf(stderr,
+ "Internal Logic Error: [%d/%s] MacStat is out of sync !",
+ __LINE__, __FILE__);
+ exit(-1);
+ }
+
+ /* Start Macintosh Finder FInfo structure except Type/Creator
+ (see make_EF_Head_MAC3()) 8 Bytes overall */
+
+ /* file Finder Flags: 2 Bytes */
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdFlags);
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdFlags >> 8);
+
+ /* Finders Icon position of a file*/
+ /* V/Y-Position: 2 Bytes */
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdLocation.v);
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdLocation.v >> 8);
+
+ /* H/X-Position: 2 Bytes */
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdLocation.h);
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdLocation.h >> 8);
+
+ /* fdFldr Folder containing file 2 Bytes */
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdFldr);
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdFldr >> 8);
+
+ /* End Macintosh Finder FInfo structure */
+
+ /* 8 Bytes so far ... */
+
+ /* Start Macintosh Finder FXInfo structure 16 Bytes overall */
+ /* Icon ID: 2 Bytes */
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlXFndrInfo.fdIconID);
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlXFndrInfo.fdIconID >> 8);
+
+ /* unused: 6 Bytes */
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlXFndrInfo.fdUnused[0]);
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlXFndrInfo.fdUnused[0] >> 8);
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlXFndrInfo.fdUnused[1]);
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlXFndrInfo.fdUnused[1] >> 8);
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlXFndrInfo.fdUnused[2]);
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlXFndrInfo.fdUnused[2] >> 8);
+ /* Script flag: 1 Byte */
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlXFndrInfo.fdScript);
+ /* More flag bits: 1 Byte */
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlXFndrInfo.fdXFlags);
+ /* Comment ID 2 Bytes */
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlXFndrInfo.fdComment);
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlXFndrInfo.fdComment >> 8);
+
+ /* Home Dir ID: 4 Bytes */
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlXFndrInfo.fdPutAway);
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlXFndrInfo.fdPutAway >> 8);
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlXFndrInfo.fdPutAway >> 16);
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlXFndrInfo.fdPutAway >> 24);
+ /* End Macintosh Finder FXInfo structure */
+
+ /* 24 Bytes so far ... */
+
+ /* file version number 1 Byte */
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFVersNum);
+
+ /* directory access rights 1 Byte */
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioACUser);
+
+ /* Creation-time 4 Bytes */
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlCrDat);
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlCrDat >> 8);
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlCrDat >> 16);
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlCrDat >> 24);
+ /* Modification-time 4 Bytes */
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlMdDat);
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlMdDat >> 8);
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlMdDat >> 16);
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlMdDat >> 24);
+ /* Backup-time 4 Bytes */
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlBkDat);
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlBkDat >> 8);
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlBkDat >> 16);
+ *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlBkDat >> 24);
+
+ /* 38 Bytes so far ... */
+#ifdef USE_EF_UT_TIME
+ if (MacZip.HaveGMToffset) {
+ /* GMT-Offset times 12 Bytes */
+ *ef++ = (char)(MacZip.Cr_UTCoffs);
+ *ef++ = (char)(MacZip.Cr_UTCoffs >> 8);
+ *ef++ = (char)(MacZip.Cr_UTCoffs >> 16);
+ *ef++ = (char)(MacZip.Cr_UTCoffs >> 24);
+ *ef++ = (char)(MacZip.Md_UTCoffs);
+ *ef++ = (char)(MacZip.Md_UTCoffs >> 8);
+ *ef++ = (char)(MacZip.Md_UTCoffs >> 16);
+ *ef++ = (char)(MacZip.Md_UTCoffs >> 24);
+ *ef++ = (char)(MacZip.Bk_UTCoffs);
+ *ef++ = (char)(MacZip.Bk_UTCoffs >> 8);
+ *ef++ = (char)(MacZip.Bk_UTCoffs >> 16);
+ *ef++ = (char)(MacZip.Bk_UTCoffs >> 24);
+ }
+ /* 50 Bytes so far ... */
+#endif
+
+ /* Text Encoding Base (charset) 2 Bytes */
+ *ef++ = (char)(MacZip.CurrTextEncodingBase);
+ *ef++ = (char)(MacZip.CurrTextEncodingBase >> 8);
+ /* 52 Bytes so far ... */
+
+ /* MacZip.CurrentFork will be changed, so we have to save it */
+ tempFork = MacZip.CurrentFork;
+ if (!MacZip.StoreFullPath) {
+ temp_Pathname = StripPartialDir(tmp_buffer, MacZip.SearchDir,
+ MacZip.FullPath);
+ } else {
+ temp_Pathname = MacZip.FullPath;
+ }
+ MacZip.CurrentFork = tempFork;
+
+ FLength = strlen(temp_Pathname) + 1;
+ memcpy( ef, temp_Pathname, (size_t)FLength );
+ ef += FLength; /* make room for the string - variable length */
+
+ err = FSpLocationFromFullPath(strlen(MacZip.FullPath), MacZip.FullPath,
+ &MacZip.fileSpec);
+ printerr("FSpLocationFromFullPath:", err, err,
+ __LINE__, __FILE__, tmp_buffer);
+
+ err = FSpDTGetComment(&MacZip.fileSpec, comment);
+ printerr("FSpDTGetComment:", (err != -5012) && (err != 0), err,
+ __LINE__, __FILE__, "");
+ PToCCpy(comment,tmp_buffer);
+
+ CLength = strlen(tmp_buffer) + 1;
+ memcpy( ef, tmp_buffer, (size_t)CLength );
+ ef += CLength; /* make room for the string - variable length */
+
+ if (verbose) printf("\n comment: [%s]", tmp_buffer);
+
+ return (unsigned)(ef - ef_m3_begin);
+}
+
+
+
+
+
+
+/*
+* Print all native data of the new mac local extra field.
+* It's for debugging purposes and disabled by default.
+*/
+
+static void PrintFileInfo(void)
+{
+DateTimeRec MacTime;
+
+printf("\n\n---------------------------------------------"\
+ "----------------------------------");
+printf("\n FullPath Name = [%s]", MacZip.FullPath);
+printf("\n File Attributes = %s 0x%x %d",
+ sBit2Str(MacZip.fpb.hFileInfo.ioFlAttrib),
+ MacZip.fpb.hFileInfo.ioFlAttrib,
+ MacZip.fpb.hFileInfo.ioFlAttrib);
+printf("\n Enclosing Folder ID# = 0x%x %d",
+ MacZip.fpb.hFileInfo.ioFlParID,
+ MacZip.fpb.hFileInfo.ioFlParID);
+
+if (!MacZip.isDirectory)
+{
+printf("\n File Type = [%c%c%c%c] 0x%lx",
+ MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType >> 24,
+ MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType >> 16,
+ MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType >> 8,
+ MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType,
+ MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType);
+
+printf("\n File Creator = [%c%c%c%c] 0x%lx",
+ MacZip.fpb.hFileInfo.ioFlFndrInfo.fdCreator >> 24,
+ MacZip.fpb.hFileInfo.ioFlFndrInfo.fdCreator >> 16,
+ MacZip.fpb.hFileInfo.ioFlFndrInfo.fdCreator >> 8,
+ MacZip.fpb.hFileInfo.ioFlFndrInfo.fdCreator,
+ MacZip.fpb.hFileInfo.ioFlFndrInfo.fdCreator);
+
+printf("\n Data Fork :" );
+printf("\n Actual (Logical) Length = %d 0x%x ",
+ MacZip.fpb.hFileInfo.ioFlLgLen,
+ MacZip.fpb.hFileInfo.ioFlLgLen);
+printf("\n Allocated (Physical) Length = %d 0x%x",
+ MacZip.fpb.hFileInfo.ioFlPyLen,
+ MacZip.fpb.hFileInfo.ioFlPyLen);
+printf("\n Resource Fork :" );
+printf("\n Actual (Logical) Length = %d 0x%x",
+ MacZip.fpb.hFileInfo.ioFlRLgLen,
+ MacZip.fpb.hFileInfo.ioFlRLgLen );
+printf("\n Allocated (Physical) Length = %d 0x%x",
+ MacZip.fpb.hFileInfo.ioFlRPyLen,
+ MacZip.fpb.hFileInfo.ioFlRPyLen );
+}
+
+printf("\n Dates : ");
+
+SecondsToDate (MacZip.CreatDate, &MacTime);
+printf("\n Created = %4d/%2d/%2d %2d:%2d:%2d ",
+ MacTime.year,
+ MacTime.month,
+ MacTime.day,
+ MacTime.hour,
+ MacTime.minute,
+ MacTime.second);
+
+SecondsToDate (MacZip.BackDate, &MacTime);
+printf("\n Backup = %4d/%2d/%2d %2d:%2d:%2d ",
+ MacTime.year,
+ MacTime.month,
+ MacTime.day,
+ MacTime.hour,
+ MacTime.minute,
+ MacTime.second);
+
+SecondsToDate (MacZip.ModDate, &MacTime);
+printf("\n Modified = %4d/%2d/%2d %2d:%2d:%2d ",
+ MacTime.year,
+ MacTime.month,
+ MacTime.day,
+ MacTime.hour,
+ MacTime.minute,
+ MacTime.second);
+
+if (!MacZip.isDirectory)
+{
+printf("\n Finder Flags : %s 0x%x %d",
+ sBit2Str(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdFlags),
+ MacZip.fpb.hFileInfo.ioFlFndrInfo.fdFlags,
+ MacZip.fpb.hFileInfo.ioFlFndrInfo.fdFlags);
+printf("\n Finder Icon Position = X: %d 0x%x ",
+ MacZip.fpb.hFileInfo.ioFlFndrInfo.fdLocation.h,
+ MacZip.fpb.hFileInfo.ioFlFndrInfo.fdLocation.h);
+printf("\n Y: %d 0x%x ",
+ MacZip.fpb.hFileInfo.ioFlFndrInfo.fdLocation.v,
+ MacZip.fpb.hFileInfo.ioFlFndrInfo.fdLocation.v);
+}
+else
+{
+printf("\n Finder Flags : %s 0x%x %d",
+ sBit2Str(MacZip.fpb.dirInfo.ioDrUsrWds.frFlags),
+ MacZip.fpb.dirInfo.ioDrUsrWds.frFlags,
+ MacZip.fpb.dirInfo.ioDrUsrWds.frFlags);
+printf("\n Finder Icon Position = X: %d 0x%x ",
+ MacZip.fpb.dirInfo.ioDrUsrWds.frLocation.h,
+ MacZip.fpb.dirInfo.ioDrUsrWds.frLocation.h);
+printf("\n Y: %d 0x%x ",
+ MacZip.fpb.dirInfo.ioDrUsrWds.frLocation.v,
+ MacZip.fpb.dirInfo.ioDrUsrWds.frLocation.v);
+}
+
+printf("\n----------------------------------------------------"\
+ "---------------------------\n");
+}
+
+
+
+/*
+* If the switch '-v' is used, print some more info.
+*/
+
+static void print_extra_info(void)
+{
+char Fork[20];
+
+if (MacZip.CurrentFork == DataFork) sstrcpy(Fork,"<DataFork>");
+else sstrcpy(Fork,"<ResourceFork>");
+
+printf("\n%16s [%c%c%c%c] [%c%c%c%c]",Fork,
+ MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType >> 24,
+ MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType >> 16,
+ MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType >> 8,
+ MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType,
+
+ MacZip.fpb.hFileInfo.ioFlFndrInfo.fdCreator >> 24,
+ MacZip.fpb.hFileInfo.ioFlFndrInfo.fdCreator >> 16,
+ MacZip.fpb.hFileInfo.ioFlFndrInfo.fdCreator >> 8,
+ MacZip.fpb.hFileInfo.ioFlFndrInfo.fdCreator);
+}
diff --git a/macos/source/getenv.c b/macos/source/getenv.c
new file mode 100644
index 0000000..586815d
--- /dev/null
+++ b/macos/source/getenv.c
@@ -0,0 +1,398 @@
+/*
+ Copyright (c) 1990-2005 Info-ZIP. All rights reserved.
+
+ See the accompanying file LICENSE, version 2004-May-22 or later
+ (the contents of which are also included in zip.h) for terms of use.
+ If, for some reason, both of these files are missing, the Info-ZIP license
+ also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*
+
+This file implements the getenv() function.
+
+# Background:
+# Under Unix: Each Process (= running Program) has a set of
+# associated variables. The variables are called enviroment
+# variables and, together, constitute the process environment.
+# These variables include the search path, the terminal type,
+# and the user's login name.
+
+# Unfortunatelly the MacOS has no equivalent. So we need
+# a file to define the environment variables.
+# Name of this file is "MacZip.Env". It can be placed
+# in the current folder of MacZip or in the
+# preference folder of the system disk.
+# If MacZip founds the "MacZip.Env" file in the current
+# the folder of MacZip the "MacZip.Env" file in the
+# preference folder will be ignored.
+
+# An environment variable has a name and a value:
+# Name=Value
+# Note: Spaces are significant:
+# ZIPOPT=-r and
+# ZIPOPT = -r are different !!!
+
+
+ */
+
+/*****************************************************************************/
+/* Includes */
+/*****************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unix.h>
+#include <Files.h>
+#include <Folders.h>
+
+#include "pathname.h"
+#include "helpers.h"
+
+/*****************************************************************************/
+/* Module level Vars */
+/*****************************************************************************/
+
+static char ListAllKeyValues = 0;
+static unsigned LineNumber = 0;
+static char CompletePath[NAME_MAX];
+Boolean IgnoreEnvironment = false; /* used by dialog.c and initfunc.c
+ of the Mainapp */
+
+/*****************************************************************************/
+/* Macros, typedefs */
+/*****************************************************************************/
+
+typedef struct _EnviromentPair {
+ char *key;
+ char *value;
+} EnviromentPair;
+
+
+#define MAX_COMMAND 1024
+
+
+/*****************************************************************************/
+/* Prototypes */
+/*****************************************************************************/
+
+
+int get_char(FILE *file);
+void unget_char(int ch,FILE *file);
+int get_string(char *string,int size, FILE *file, char *terms);
+void skip_comments(FILE *file);
+char *load_entry(FILE *file);
+char *getenv(const char *name);
+EnviromentPair *ParseLine(char *line);
+OSErr FSpFindFolder_Name(short vRefNum, OSType folderType,
+ Boolean createFolder,FSSpec *spec, unsigned char *name);
+FILE * FSp_fopen(ConstFSSpecPtr spec, const char * open_mode);
+void ShowAllKeyValues(void);
+void Set_LineNum(unsigned ln);
+
+/*****************************************************************************/
+/* Functions */
+/*****************************************************************************/
+
+
+/* get_string(str, max, file, termstr) : like fgets() but
+ * (1) has terminator string which should include \n
+ * (2) will always leave room for the null
+ * (3) uses get_char() so LineNumber will be accurate
+ * (4) returns EOF or terminating character, whichever
+ */
+int get_string(char *string, int size, FILE *file, char *terms)
+{
+ int ch;
+
+ while (EOF != (ch = get_char(file)) && !strchr(terms, ch)) {
+ if (size > 1) {
+ *string++ = (char) ch;
+ size--;
+ }
+ }
+
+ if (size > 0)
+ {
+ *string = '\0';
+ }
+
+ return ch;
+}
+
+
+
+
+void Set_LineNum(unsigned ln)
+{
+ LineNumber = ln;
+}
+
+
+
+/* get_char(file) : like getc() but increment LineNumber on newlines
+ */
+int get_char(FILE *file)
+{
+ int ch;
+
+ ch = getc(file);
+ if (ch == '\n')
+ {
+ Set_LineNum(LineNumber + 1);
+ }
+
+ return ch;
+}
+
+
+
+
+/* skip_comments(file) : read past comment (if any)
+ */
+void skip_comments(FILE *file)
+{
+ int ch;
+
+ while (EOF != (ch = get_char(file)))
+ {
+ /* ch is now the first character of a line.
+ */
+
+ while (ch == ' ' || ch == '\t')
+ {
+ ch = get_char(file);
+ }
+
+ if (ch == EOF)
+ {
+ break;
+ }
+
+ /* ch is now the first non-blank character of a line.
+ */
+
+ if (ch != '\n' && ch != '#')
+ {
+ break;
+ }
+
+ /* ch must be a newline or comment as first non-blank
+ * character on a line.
+ */
+
+ while (ch != '\n' && ch != EOF)
+ {
+ ch = get_char(file);
+ }
+
+ /* ch is now the newline of a line which we're going to
+ * ignore.
+ */
+ }
+
+ if (ch != EOF)
+ {
+ unget_char(ch, file);
+ }
+}
+
+
+
+
+/* unget_char(ch, file) : like ungetc but do LineNumber processing
+ */
+void unget_char(int ch, FILE *file)
+{
+ ungetc(ch, file);
+ if (ch == '\n')
+ {
+ Set_LineNum(LineNumber - 1);
+ }
+}
+
+
+/* this function reads one file entry -- the next -- from a file.
+* it skips any leading blank lines, ignores comments, and returns
+* NULL if for any reason the entry can't be read and parsed.
+*/
+
+char *load_entry(FILE *file)
+{
+ int ch;
+ static char cmd[MAX_COMMAND];
+
+ skip_comments(file);
+
+ ch = get_string(cmd, MAX_COMMAND, file, "\n");
+
+ if (ch == EOF)
+ {
+ return NULL;
+ }
+
+ return cmd;
+}
+
+
+
+
+
+EnviromentPair *ParseLine(char *line)
+{
+char *tmpPtr;
+static EnviromentPair *Env;
+unsigned short length = strlen(line);
+
+Env->key = "";
+Env->value = "";
+
+for (tmpPtr = line; *tmpPtr; tmpPtr++)
+ {
+ if (*tmpPtr == '=')
+ {
+ *tmpPtr = 0;
+ Env->key = line;
+ if (strlen(Env->key) < length)
+ {
+ Env->value = ++tmpPtr;
+ }
+ return Env;
+ }
+ }
+return Env;
+}
+
+
+
+
+
+char *getenv(const char *name)
+{
+FILE *fp;
+char *LineStr = NULL;
+EnviromentPair *Env1;
+FSSpec spec;
+OSErr err;
+
+if (IgnoreEnvironment)
+ return NULL; /* user wants to ignore the environment vars */
+
+if (name == NULL)
+ return NULL;
+
+GetCompletePath(CompletePath,"MacZip.Env",&spec,&err);
+
+/* try open the file in the current folder */
+fp = FSp_fopen(&spec,"r");
+if (fp == NULL)
+ { /* Okey, lets try open the file in the preference folder */
+ FSpFindFolder_Name(
+ kOnSystemDisk,
+ kPreferencesFolderType,
+ kDontCreateFolder,
+ &spec,
+ "\pMacZip.Env");
+ fp = FSp_fopen(&spec,"r");
+ if (fp == NULL)
+ {
+ return NULL; /* there is no enviroment-file */
+ }
+ }
+
+LineStr = load_entry(fp);
+while (LineStr != NULL)
+ { /* parse the file line by line */
+ Env1 = ParseLine(LineStr);
+ if (strlen(Env1->value) > 0)
+ { /* we found a key/value pair */
+ if (ListAllKeyValues)
+ printf("\n Line:%3d [%s] = [%s]",LineNumber,Env1->key,Env1->value);
+ if (stricmp(name,Env1->key) == 0)
+ { /* we found the value of a given key */
+ return Env1->value;
+ }
+ }
+ LineStr = load_entry(fp); /* read next line */
+ }
+fclose(fp);
+
+return NULL;
+}
+
+
+
+
+
+OSErr FSpFindFolder_Name(
+ short vRefNum, /* Volume reference number. */
+ OSType folderType, /* Folder type taken by FindFolder. */
+ Boolean createFolder, /* Should we create it if non-existant. */
+ FSSpec *spec, /* Pointer to resulting directory. */
+ unsigned char *name) /* Name of the file in the folder */
+{
+ short foundVRefNum;
+ long foundDirID;
+ OSErr err;
+
+ err = FindFolder(vRefNum, folderType, createFolder,
+ &foundVRefNum, &foundDirID);
+ if (err != noErr)
+ {
+ return err;
+ }
+
+ err = FSMakeFSSpec(foundVRefNum, foundDirID, name, spec);
+ return err;
+}
+
+
+
+
+void ShowAllKeyValues(void)
+{
+OSErr err;
+FSSpec spec;
+Boolean tmpIgnoreEnvironment = IgnoreEnvironment;
+
+ListAllKeyValues = 1;
+IgnoreEnvironment = false;
+
+GetCompletePath(CompletePath,"MacZip.Env",&spec,&err);
+if (err != 0)
+ { /* Okey, lets try open the file in the preference folder */
+ FSpFindFolder_Name(
+ kOnSystemDisk,
+ kPreferencesFolderType,
+ kDontCreateFolder,
+ &spec,
+ "\pMacZip.Env");
+ GetFullPathFromSpec(CompletePath,&spec, &err);
+ if (err != 0)
+ {
+ return; /* there is no enviroment-file */
+ }
+ }
+
+printf("\nLocation of the current \"MacZip.Env\" file:\n [%s]",CompletePath);
+
+printf("\n\nList of all environment variables\n");
+getenv(" ");
+printf("\n\nEnd\n\n");
+
+/* restore used variables */
+ListAllKeyValues = 0;
+LineNumber = 0;
+IgnoreEnvironment = tmpIgnoreEnvironment;
+}
+
+
+
+
+
+
+
+
+
+
diff --git a/macos/source/helpers.c b/macos/source/helpers.c
new file mode 100644
index 0000000..a7df558
--- /dev/null
+++ b/macos/source/helpers.c
@@ -0,0 +1,477 @@
+/*
+ Copyright (c) 1990-2005 Info-ZIP. All rights reserved.
+
+ See the accompanying file LICENSE, version 2004-May-22 or later
+ (the contents of which are also included in zip.h) for terms of use.
+ If, for some reason, both of these files are missing, the Info-ZIP license
+ also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*---------------------------------------------------------------------------
+
+ helpers.c
+
+ Some useful functions Used by unzip and zip.
+
+ ---------------------------------------------------------------------------*/
+
+/*****************************************************************************/
+/* Includes */
+/*****************************************************************************/
+
+#include "zip.h"
+#include <ctype.h>
+#include <time.h>
+#include <sound.h>
+
+#include "macstuff.h"
+#include "helpers.h"
+#include "pathname.h"
+
+
+/*****************************************************************************/
+/* Global Vars */
+/*****************************************************************************/
+
+
+extern int noisy;
+extern char MacPathEnd;
+extern char *zipfile; /* filename of the Zipfile */
+extern char *tempzip; /* Temporary zip file name */
+extern ZCONST unsigned char MacRoman_to_WinCP1252[128];
+
+
+static char argStr[1024];
+static char *argv[MAX_ARGS + 1];
+
+
+
+/*****************************************************************************/
+/* Functions */
+/*****************************************************************************/
+
+
+/*
+** Copy a C string to a Pascal string
+**
+*/
+unsigned char *CToPCpy(unsigned char *pstr, char *cstr)
+{
+ register char *dptr;
+ register unsigned len;
+
+ len=0;
+ dptr=(char *)pstr+1;
+ while (len<255 && (*dptr++ = *cstr++)!='\0') ++len;
+ *pstr= (unsigned char)len;
+ return pstr;
+}
+
+
+
+/*
+** Copy a Pascal string to a C string
+**
+*/
+
+char *PToCCpy(unsigned char *pstr, char *cstr)
+{
+strncpy(cstr, (char *) &pstr[1], *pstr);
+ cstr[pstr[0]] = '\0'; /* set endmarker for c-string */
+return cstr;
+}
+
+
+/*
+** strcpy() and strcat() work-alikes which allow overlapping buffers.
+*/
+
+char *sstrcpy(char *to,const char *from)
+{
+ memmove(to, from, 1+strlen(from));
+ return to;
+}
+
+char *sstrcat(char *to,const char *from)
+{
+ sstrcpy(to + strlen(to), from);
+ return to;
+}
+
+
+
+/*
+** Alloc memory and init it
+**
+*/
+char *StrCalloc(unsigned short size)
+{
+char *strPtr = NULL;
+
+if ((strPtr = calloc(size, sizeof(char))) == NULL)
+ printerr("StrCalloc failed:", -1, size, __LINE__, __FILE__, "");
+
+Assert_it(strPtr,"strPtr == NULL","")
+return strPtr;
+}
+
+
+
+/*
+** Release only non NULL pointers
+**
+*/
+char *StrFree(char *strPtr)
+{
+
+if (strPtr != NULL)
+ {
+ free(strPtr);
+ }
+
+return NULL;
+}
+
+
+
+
+/*
+** Return a value in a binary string
+**
+*/
+
+char *sBit2Str(unsigned short value)
+{
+ static char str[sizeof(value)*8];
+ int biz = 16;
+ int strwid = 16;
+ int i, j;
+ char *tempPtr = str;
+
+ j = strwid - (biz + (biz >> 2)- (biz % 4 ? 0 : 1));
+
+ for (i = 0; i < j; i++) {
+ *tempPtr++ = ' ';
+ }
+ while (--biz >= 0)
+ {
+ *tempPtr++ = ((value >> biz) & 1) + '0';
+ if (!(biz % 4) && biz) {
+ *tempPtr++ = ' ';
+ }
+ }
+ *tempPtr = '\0';
+
+ return str;
+}
+
+
+
+
+/*
+** Parse commandline style arguments
+**
+*/
+
+int ParseArguments(char *s, char ***arg)
+{
+ int n = 1, Quote = 0;
+ char *p = s, *p1, c;
+
+ argv[0] = GetAppName();
+
+ *arg = argv;
+
+ p1 = (char *) argStr;
+ while ((c = *p++) != 0) {
+ if (c==' ') continue;
+ argv[n++] = p1;
+ if (n > MAX_ARGS)
+ return (n-1);
+ do {
+ if (c=='\\' && *p++)
+ c = *p++;
+ else
+ if ((c=='"') || (c == '\'')) {
+ if (!Quote) {
+ Quote = c;
+ continue;
+ }
+ if (c == Quote) {
+ Quote = 0;
+ continue;
+ }
+ }
+ *p1++ = c;
+ } while (*p && ((c = *p++) != ' ' || Quote));
+ *p1++ = '\0';
+ }
+ return n;
+}
+
+
+
+/*
+** Print commandline style arguments
+**
+*/
+
+void PrintArguments(int argc, char **argv)
+{
+
+printf("\n Arguments:");
+printf("\n --------------------------");
+
+while(--argc >= 0)
+ printf("\n argc: %d argv: [%s]", argc, &*argv[argc]);
+
+printf("\n --------------------------\n\n");
+return;
+}
+
+
+
+/*
+** return some error-msg on file-system
+**
+*/
+
+int PrintUserHFSerr(int cond, int err, char *msg2)
+{
+char *msg;
+
+if (cond != 0)
+ {
+ switch (err)
+ {
+ case -35:
+ msg = "No such Volume";
+ break;
+
+ case -56:
+ msg = "No such Drive";
+ break;
+
+ case -37:
+ msg = "Bad Volume Name";
+ break;
+
+ case -49:
+ msg = "File is already open for writing";
+ break;
+
+ case -43:
+ msg = "Directory/File not found";
+ break;
+
+ case -120:
+ msg = "Directory/File not found or incomplete pathname";
+ break;
+
+ default: return err;
+ }
+ fprintf(stderr, "\n\n Error: %s ->%s", msg, msg2);
+ exit(err);
+ }
+
+return 0;
+}
+
+
+
+/*
+** Check mounted volumes and return number of volumes
+** with the same name.
+*/
+
+short CheckMountedVolumes(char *FullPath)
+{
+FSSpec volumes[50]; /* 50 Volumes should be enough */
+char VolumeName[257], volume[257];
+short actVolCount, volIndex = 1, VolCount = 0;
+OSErr err;
+int i;
+
+GetVolumeFromPath(FullPath, VolumeName);
+
+err = OnLine(volumes, 50, &actVolCount, &volIndex);
+printerr("OnLine:", (err != -35) && (err != 0), err, __LINE__, __FILE__, "");
+
+for (i=0; i < actVolCount; i++)
+ {
+ PToCCpy(volumes[i].name,volume);
+ if (stricmp(volume, VolumeName) == 0) VolCount++;
+ }
+printerr("OnLine: ", (VolCount == 0), VolCount, __LINE__, __FILE__, FullPath);
+
+return VolCount;
+}
+
+
+
+
+
+
+
+
+/*
+** compares strings, ignoring differences in case
+**
+*/
+
+int stricmp(const char *p1, const char *p2)
+{
+int diff;
+
+while (*p1 && *p2)
+ {
+ if (*p1 != *p2)
+ {
+ if (isalpha(*p1) && isalpha(*p2))
+ {
+ diff = toupper(*p1) - toupper(*p2);
+ if (diff) return diff;
+ }
+ else break;
+ }
+ p1++;
+ p2++;
+ }
+return *p1 - *p2;
+}
+
+
+
+/*
+** Convert the MacOS-Strings (Filenames/Findercomments) to a most compatible.
+** These strings will be stored in the public area of the zip-archive.
+** Every foreign platform (outside macos) will access these strings
+** for extraction.
+*/
+
+void MakeCompatibleString(char *MacOS_Str,
+ const char SpcChar1, const char SpcChar2,
+ const char SpcChar3, const char SpcChar4,
+ short CurrTextEncodingBase)
+{
+ char *tmpPtr;
+ register uch curch;
+
+ Assert_it(MacOS_Str,"MakeCompatibleString MacOS_Str == NULL","")
+ for (tmpPtr = MacOS_Str; (curch = *tmpPtr) != '\0'; tmpPtr++)
+ {
+ if (curch == SpcChar1)
+ *tmpPtr = SpcChar2;
+ else
+ if (curch == SpcChar3)
+ *tmpPtr = SpcChar4;
+ else /* default */
+ /* now convert from MacRoman to ISO-8859-1 */
+ /* but convert only if MacRoman is activ */
+ if ((CurrTextEncodingBase == kTextEncodingMacRoman) &&
+ (curch > 127))
+ {
+ *tmpPtr = (char)MacRoman_to_WinCP1252[curch - 128];
+ }
+ } /* end for */
+}
+
+
+
+
+Boolean CheckForSwitch(char *Switch, int argc, char **argv)
+{
+ char *p; /* steps through option arguments */
+ int i; /* arg counter, root directory flag */
+
+ for (i = 1; i < argc; i++)
+ {
+ if (argv[i][0] == '-')
+ {
+ if (argv[i][1])
+ {
+ for (p = argv[i]+1; *p; p++)
+ {
+ if (*p == Switch[0])
+ {
+ return true;
+ }
+ if ((Switch[1] != NULL) &&
+ ((*p == Switch[0]) && (*p == Switch[1])))
+ {
+ return true;
+ }
+ }
+ }
+ }
+ }
+
+return false;
+}
+
+
+
+
+
+
+
+#if (defined(USE_SIOUX) || defined(MACUNZIP_STANDALONE))
+
+/*
+** checks the condition and returns an error-msg
+** this function is for internal use only
+*/
+
+OSErr printerr(const char *msg, int cond, int err, int line, char *file,
+ const char *msg2)
+{
+
+if (cond != 0)
+ {
+ fprintf(stderr, "\nint err: %d: %s %d [%d/%s] {%s}\n", clock(), msg, err,
+ line, file, msg2);
+ }
+
+return cond;
+}
+
+
+/*
+fake-functions:
+Not Implemented for metrowerks SIOUX
+*/
+
+void leftStatusString(char *status)
+{
+status = status;
+}
+
+
+void rightStatusString(char *status)
+{
+status = status;
+}
+
+
+
+void DoWarnUserDupVol( char *FullPath )
+{
+ char VolName[257];
+ GetVolumeFromPath(FullPath, VolName);
+
+ printf("\n There are more than one volume that has the same name !!\n");
+
+ printf("\n Volume: %s\n",VolName);
+
+ printf("\n This port has one weak point:");
+ printf("\n It is based on pathnames. As you may be already know:");
+ printf("\n Pathnames are not unique on a Mac !");
+ printf("\n MacZip has problems to find the correct location of");
+ printf("\n the archive or the files.\n");
+
+ printf("\n My (Big) recommendation: Name all your volumes with an");
+ printf("\n unique name and MacZip will run without any problem.");
+}
+
+
+
+#endif
diff --git a/macos/source/helpers.h b/macos/source/helpers.h
new file mode 100644
index 0000000..86aa178
--- /dev/null
+++ b/macos/source/helpers.h
@@ -0,0 +1,57 @@
+/*
+ Copyright (c) 1990-1999 Info-ZIP. All rights reserved.
+
+ See the accompanying file LICENSE, version 1999-Oct-05 or later
+ (the contents of which are also included in zip.h) for terms of use.
+ If, for some reason, both of these files are missing, the Info-ZIP license
+ also may be found at: ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+#ifndef HELPERS_H
+#define HELPERS_H 1
+
+ /* Convert a C string to a Pascal string */
+unsigned char *CToPCpy(unsigned char *pstr, char *cstr);
+
+ /* Convert a Pascal string to a C string */
+char *PToCCpy(unsigned char *pstr, char *cstr);
+
+char *sstrcpy(char *to,const char *from);
+char *sstrcat(char *to,const char *from);
+
+char *StrCalloc(unsigned short size);
+char *StrFree(char *strPtr);
+
+char *sBit2Str(unsigned short value);
+
+void print_extra_info(void);
+
+int ParseArguments(char *s, char ***arg);
+void PrintArguments(int argc, char **argv);
+
+Boolean IsZipFile(char *name);
+OSErr printerr(const char *msg, int cond, int err, int line, char *file,
+ const char *msg2);
+int PrintUserHFSerr(int cond, int err, char *msg2);
+
+short CheckMountedVolumes(char *FullPath);
+void DoWarnUserDupVol(char *path);
+
+void PrintFileInfo(void);
+
+int stricmp(const char *p1, const char *p2);
+void leftStatusString(char *status);
+void rightStatusString(char *status);
+
+Boolean isZipFile(FSSpec *fileToOpen);
+
+unsigned long MacFileDate_to_UTime(unsigned long mactime);
+Boolean CheckForSwitch(char *Switch, int argc, char **argv);
+
+void MakeCompatibleString(char *MacOS_Str,
+ const char SpcChar1, const char SpcChar2,
+ const char SpcChar3, const char SpcChar4,
+ short CurrTextEncodingBase);
+
+#define MAX_ARGS 25
+
+#endif /* HELPERS_H */
diff --git a/macos/source/macglob.h b/macos/source/macglob.h
new file mode 100644
index 0000000..17415e1
--- /dev/null
+++ b/macos/source/macglob.h
@@ -0,0 +1,86 @@
+/*
+ Copyright (c) 1990-1999 Info-ZIP. All rights reserved.
+
+ See the accompanying file LICENSE, version 1999-Oct-05 or later
+ (the contents of which are also included in zip.h) for terms of use.
+ If, for some reason, both of these files are missing, the Info-ZIP license
+ also may be found at: ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+#ifndef _MACGLOBAL_
+#define _MACGLOBAL_
+
+#include <time.h>
+
+/*
+all my Global vars are defined here.
+*/
+
+#define ResourceFork -1
+#define DataFork 1
+#define NoFork 0
+
+/*
+all my Global vars are defined here.
+*/
+typedef struct {
+ short CurrentFork;
+ short MacZipMode;
+
+ Boolean isMacStatValid;
+ Boolean HaveGMToffset;
+
+ short CurrTextEncodingBase;
+
+ /* info about the current file */
+ Boolean isDirectory;
+ char FullPath[NAME_MAX];
+ char FileName[NAME_MAX];
+ FSSpec fileSpec;
+
+ long dirID;
+ CInfoPBRec fpb;
+
+ /* time infos about the current file */
+ time_t CreatDate;
+ time_t ModDate;
+ time_t BackDate;
+ long Cr_UTCoffs; /* offset "local time - UTC" for CreatDate */
+ long Md_UTCoffs; /* offset "local time - UTC" for ModDate */
+ long Bk_UTCoffs; /* offset "local time - UTC" for BackDate */
+
+ /* some statistics over all*/
+ unsigned long FoundFiles;
+ unsigned long FoundDirectories;
+ unsigned long RawCountOfItems;
+ unsigned long BytesOfData;
+
+ unsigned long attrsize;
+
+ /* some switches and user parameters */
+ Boolean DataForkOnly;
+ Boolean StoreFullPath;
+ Boolean StoreFoldersAlso; /* internal switch is true if '-r' is set */
+ unsigned short SearchLevels;
+ char Pattern[NAME_MAX];
+ Boolean IncludeInvisible;
+ Boolean StatingProgress;
+
+ char SearchDir[NAME_MAX];
+ char CurrentPath[NAME_MAX];
+
+ /* current zip / tempzip file info */
+ char ZipFullPath[NAME_MAX];
+
+ FSSpec ZipFileSpec;
+ unsigned long ZipFileType;
+ char TempZipFullPath[NAME_MAX];
+ FSSpec TempZipFileSpec;
+
+} MacZipGlobals;
+
+
+
+void UserStop(void);
+
+
+#endif
diff --git a/macos/source/macopen.c b/macos/source/macopen.c
new file mode 100644
index 0000000..0f65741
--- /dev/null
+++ b/macos/source/macopen.c
@@ -0,0 +1,363 @@
+/*
+ Copyright (c) 1990-2005 Info-ZIP. All rights reserved.
+
+ See the accompanying file LICENSE, version 2004-May-22 or later
+ (the contents of which are also included in zip.h) for terms of use.
+ If, for some reason, both of these files are missing, the Info-ZIP license
+ also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*** macopen.c; stuff only required for the Mac port ***/
+
+#include "zip.h"
+
+#include <string.h>
+#include <fcntl.h>
+#include <unix.h>
+#include <sound.h>
+
+#include "helpers.h"
+#include "pathname.h"
+#include "macopen.h"
+#include "macstuff.h"
+
+#ifdef MACZIP
+#include "macglob.h"
+
+extern char *zipfile; /* filename of the Zipfile */
+extern char *tempzip; /* Temporary zip file name */
+
+extern MacZipGlobals MacZip;
+
+
+/* don't include "osdep.h" otherwise we will trap into endless loop */
+#undef open
+#undef fopen
+
+
+
+FILE *MacFopen(const char *path, const char *mode)
+{
+static char TruncPath[NAME_MAX];
+OSErr err = 0;
+
+AssertStr(path,path)
+
+ /* open zipfile or tempzip */
+if (strcmp(zipfile,path) == 0)
+ {
+ GetCompletePath(MacZip.ZipFullPath,path,&MacZip.ZipFileSpec,&err);
+ err = PrintUserHFSerr((err != -43) && (err != 0), err, path);
+ printerr("GetCompletePath:",err,err,__LINE__,__FILE__,path);
+ if (CheckMountedVolumes(MacZip.ZipFullPath) > 1)
+ DoWarnUserDupVol(MacZip.ZipFullPath);
+
+ /* tempfile should appear in the same directory of the zipfile
+ -> save path of zipfile */
+ TruncFilename(TruncPath, MacZip.ZipFullPath);
+ return fopen(MacZip.ZipFullPath, mode);
+ }
+
+if (strcmp(tempzip,path) == 0)
+ { /* add path of zipfile */
+ sstrcat(TruncPath,tempzip);
+ GetCompletePath(MacZip.TempZipFullPath,TruncPath,&MacZip.TempZipFileSpec,&err);
+ err = PrintUserHFSerr((err != -43) && (err != 0), err, path);
+ printerr("GetCompletePath:",err,err,__LINE__,__FILE__,path);
+
+ return fopen(MacZip.TempZipFullPath, mode);
+ }
+
+printerr("MacFopen:",err,err,__LINE__,__FILE__,path);
+return NULL;
+}
+
+
+
+
+int MacOpen(const char *path,int oflag, ...)
+{
+char RealFname[NAME_MAX];
+
+AssertStr(path,path)
+
+RfDfFilen2Real(RealFname,path, MacZip.MacZipMode, MacZip.DataForkOnly, &MacZip.CurrentFork);
+/* convert to real fname and init global var MacZip.CurrentFork !! */
+
+switch (MacZip.CurrentFork)
+ {
+ case DataFork:
+ {
+ return my_open(RealFname, oflag);
+ break;
+ }
+ case ResourceFork:
+ {
+ return my_open( RealFname, oflag | O_RSRC);
+ break;
+ }
+ default: /* for now (Zip ver 2.3b) MacOpen should never reach this point */
+ { /* however, this may change in the future ... */
+ printerr("open: no resource / datafork ",-1,-1,__LINE__,__FILE__,path);
+ return -1;
+ }
+ }
+}
+
+
+#ifdef muell
+ /* file to delete */
+int destroy(char *path)
+{
+static char lastpath[NAME_MAX];
+char currpath[NAME_MAX];
+static Boolean FirstCall = true;
+long rc;
+
+AssertStr(path,path)
+
+RfDfFilen2Real(currpath, path, MacZip.MacZipMode, MacZip.DataForkOnly, &MacZip.CurrentFork);
+
+if (FirstCall == true)
+ {
+ FirstCall = false;
+ rc = remove(currpath);
+ }
+else if (strcmp(currpath,lastpath) == 0) return 0; /* ignore, file is already deleted */
+ else rc = remove(currpath); /* we are removeing all the files only by their
+ pathname this is dangerous on a mac but there is no other way without
+ a complete rewrite of the port */
+
+strcpy(lastpath,currpath);
+
+return rc;
+}
+#endif
+
+
+
+
+/* this function replaces the function "replace()" defined in fileio.c */
+int replace(char *new_f, char *temp_f) /* destination and source file names */
+{
+OSErr err = 0;
+char newfname[NAME_MAX];
+
+AssertStr(new_f,new_f)
+AssertStr(temp_f,temp_f)
+
+UserStop();
+
+GetFilename(newfname, new_f);
+
+/* check zipfile name and tempfile name */
+/* we are using this function only for replacing the tempfile with the zipfile */
+if ((strcmp(zipfile,new_f) == 0) || (strcmp(tempzip,temp_f) == 0))
+ {
+ remove(MacZip.ZipFullPath);
+
+ /* rename the temp file to the zip file */
+ err = rename(MacZip.TempZipFullPath,MacZip.ZipFullPath);
+ printerr("rename:",err,err,__LINE__,__FILE__,MacZip.TempZipFullPath);
+if (err != 0) return ZE_CREAT;
+ else return ZE_OK;
+ }
+else return ZE_CREAT;
+}
+
+
+
+ /* file to delete */
+ /* we are removeing all the files only by their
+ pathname this is dangerous on a mac but there is no
+ other way without a complete rewrite of the port */
+
+int destroy(char *path)
+{
+static char lastpath[NAME_MAX];
+static FSSpec trashfolder;
+static Boolean FirstCall = true;
+static char Num = 0;
+static Boolean Immediate_File_Deletion = false;
+char currpath[NAME_MAX], *envptr;
+FSSpec fileToDelete;
+OSErr err;
+
+/* init this function */
+if ((path == NULL) ||
+ (strlen(path) == 0))
+ {
+ FirstCall = true;
+ Num = 0;
+ return -1;
+ }
+
+UserStop();
+
+RfDfFilen2Real(currpath, path, MacZip.MacZipMode,
+ MacZip.DataForkOnly, &MacZip.CurrentFork);
+GetCompletePath(currpath,currpath,&fileToDelete, &err);
+
+if (FirstCall == true)
+ {
+ FirstCall = false;
+ sstrcpy(lastpath,currpath);
+ err = FSpFindFolder(fileToDelete.vRefNum, kTrashFolderType,
+ kDontCreateFolder,&trashfolder);
+ printerr("FSpFindFolder:",err,err,__LINE__,__FILE__,path);
+
+ envptr = getenv("Immediate_File_Deletion");
+ if (!(envptr == (char *)NULL || *envptr == '\0'))
+ {
+ if (stricmp(envptr,"yes") == 0)
+ Immediate_File_Deletion = true;
+ else
+ Immediate_File_Deletion = false;
+ }
+
+ if (Immediate_File_Deletion)
+ {
+ err = FSpDelete(&fileToDelete);
+ return err;
+ }
+
+ err = CatMove (fileToDelete.vRefNum, fileToDelete.parID,
+ fileToDelete.name, trashfolder.parID, trashfolder.name);
+ return err;
+ }
+
+if (strcmp(currpath,lastpath) == 0)
+ {
+ return 0; /* ignore, file is already deleted */
+ }
+else
+ {
+
+ if (Immediate_File_Deletion)
+ {
+ err = FSpDelete(&fileToDelete);
+ sstrcpy(lastpath,path);
+ return err;
+ }
+
+ err = CatMove (fileToDelete.vRefNum, fileToDelete.parID,
+ fileToDelete.name, trashfolder.parID, trashfolder.name);
+
+ /* -48 = file is already existing so we have to rename it before
+ moving the file */
+ if (err == -48)
+ {
+ Num++;
+ if (fileToDelete.name[0] >= 28) /* cut filename if to long */
+ fileToDelete.name[0] = 28;
+ P2CStr(fileToDelete.name);
+ sprintf(currpath,"%s~%d",(char *)fileToDelete.name,Num);
+ C2PStr(currpath);
+ C2PStr((char *)fileToDelete.name);
+ err = HRename (fileToDelete.vRefNum, fileToDelete.parID,
+ fileToDelete.name, (unsigned char *) currpath);
+ err = CatMove (fileToDelete.vRefNum, fileToDelete.parID,
+ (unsigned char *) currpath, trashfolder.parID,
+ trashfolder.name);
+ }
+ }
+
+sstrcpy(lastpath,currpath);
+return err;
+}
+
+
+
+#endif /* #ifdef MACZIP */
+
+
+
+
+/*
+ * int open(const char *path, int oflag)
+ *
+ * Opens a file stream.
+ */
+int my_open(char *path, int oflag)
+{
+ FSSpec spec;
+ char permission;
+ HParamBlockRec hpb;
+ OSErr err, errno;
+ Boolean targetIsFolder, wasAliased;
+
+ AssertStr(path,path)
+
+ /* Setup permission */
+ if ((oflag & 0x03) == O_RDWR)
+ permission = fsRdWrPerm;
+ else
+ permission = (oflag & O_RDONLY) ? fsRdPerm : 0 + (oflag & O_WRONLY) ? fsWrPerm : 0;
+
+ FSpLocationFromFullPath(strlen(path),path, &spec);
+ if ((oflag & (O_ALIAS | O_NRESOLVE)) == 0)
+ ResolveAliasFile(&spec, true, &targetIsFolder, &wasAliased);
+ hpb.fileParam.ioNamePtr = spec.name;
+ hpb.fileParam.ioVRefNum = spec.vRefNum;
+ hpb.fileParam.ioDirID = spec.parID;
+ hpb.ioParam.ioPermssn = permission;
+
+ if (oflag & O_RSRC) /* open the resource fork of the file */
+ err = PBHOpenRFSync(&hpb);
+ else /* open the data fork of the file */
+ err = PBHOpenDFSync(&hpb);
+
+ if ((err == fnfErr) && (oflag & O_CREAT)) {
+ hpb.fileParam.ioFlVersNum = 0;
+ err = PBHCreateSync(&hpb);
+ if (err == noErr) {
+ /* Set the finder info */
+ unsigned long secs;
+ unsigned long isbinary = oflag & O_BINARY;
+
+ hpb.fileParam.ioFlFndrInfo.fdType = '\?\?\?\?';
+ hpb.fileParam.ioFlFndrInfo.fdCreator = '\?\?\?\?';
+ hpb.fileParam.ioFlFndrInfo.fdFlags = 0;
+ if (oflag & O_ALIAS) /* set the alias bit */
+ hpb.fileParam.ioFlFndrInfo.fdFlags = kIsAlias;
+ else /* clear all flags */
+ hpb.fileParam.ioFlFndrInfo.fdFlags = 0;
+
+ GetDateTime(&secs);
+ hpb.fileParam.ioFlCrDat = hpb.fileParam.ioFlMdDat = secs;
+ PBHSetFInfoSync(&hpb);
+ }
+
+ if (err && (err != dupFNErr)) {
+ errno = err; return -1;
+ }
+
+ if (oflag & O_RSRC) /* open the resource fork of the file */
+ err = PBHOpenRFSync(&hpb);
+ else /* open the data fork of the file */
+ err = PBHOpenDFSync(&hpb);
+ }
+
+ if (err && (err != dupFNErr) && (err != opWrErr)) {
+ errno = err; return -1;
+ }
+
+ if (oflag & O_TRUNC) {
+ IOParam pb;
+
+ pb.ioRefNum = hpb.ioParam.ioRefNum;
+ pb.ioMisc = 0L;
+ err = PBSetEOFSync((ParmBlkPtr)&pb);
+ if (err != noErr) {
+ errno = err; return -1;
+ }
+ }
+
+ if (oflag & O_APPEND) lseek(hpb.ioParam.ioRefNum,0,SEEK_END);
+
+ return (hpb.ioParam.ioRefNum);
+}
+
+
+
+
+
diff --git a/macos/source/macopen.h b/macos/source/macopen.h
new file mode 100644
index 0000000..152bceb
--- /dev/null
+++ b/macos/source/macopen.h
@@ -0,0 +1,21 @@
+/*
+ Copyright (c) 1990-1999 Info-ZIP. All rights reserved.
+
+ See the accompanying file LICENSE, version 1999-Oct-05 or later
+ (the contents of which are also included in zip.h) for terms of use.
+ If, for some reason, both of these files are missing, the Info-ZIP license
+ also may be found at: ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+#ifndef __MACOPEN_H__
+#define __MACOPEN_H__
+
+#include <stdio.h>
+#include <Files.h>
+
+
+FILE *MacFopen(const char *path, const char *mode);
+int MacOpen(const char *path, int oflag, ...);
+
+int my_open(char *path, int oflag);
+
+#endif /* __MACOPEN_H__ */
diff --git a/macos/source/macos.c b/macos/source/macos.c
new file mode 100644
index 0000000..3cfee7b
--- /dev/null
+++ b/macos/source/macos.c
@@ -0,0 +1,1079 @@
+/*
+ Copyright (c) 1990-2005 Info-ZIP. All rights reserved.
+
+ See the accompanying file LICENSE, version 2004-May-22 or later
+ (the contents of which are also included in zip.h) for terms of use.
+ If, for some reason, both of these files are missing, the Info-ZIP license
+ also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*---------------------------------------------------------------------------
+
+ macos.c
+
+ Macintosh-specific routines for use with Info-ZIP's Zip 2.3 and later.
+
+ ---------------------------------------------------------------------------*/
+
+
+/*****************************************************************************/
+/* Includes */
+/*****************************************************************************/
+
+#include "zip.h"
+
+#include "revision.h"
+#include "crypt.h"
+
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sound.h>
+
+#include <unistd.h>
+
+#include <Strings.h>
+#include <setjmp.h>
+
+/* #include "charmap.h" */
+#include "helpers.h"
+#include "macstuff.h"
+#include "pathname.h"
+#include "recurse.h"
+
+
+/*****************************************************************************/
+/* Macros, typedefs */
+/*****************************************************************************/
+
+#define PATH_END MacPathEnd
+
+/*****************************************************************************/
+/* Global Vars */
+/*****************************************************************************/
+
+int error_level; /* used only in ziperr() */
+
+
+/* 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 */
+
+
+extern jmp_buf EnvForExit;
+MacZipGlobals MacZip;
+
+unsigned long count_of_Zippedfiles = 0;
+
+
+/*****************************************************************************/
+/* Module level Vars */
+/*****************************************************************************/
+
+static const char MacPathEnd = ':'; /* the Macintosh dir separator */
+
+/* Inform Progress vars */
+long estTicksToFinish;
+long createTime;
+long updateTicks;
+
+static char *Time_Est_strings[] = {
+ "Zipping Files; Items done:",
+ "More than 24 hours",
+ "More than %s hours",
+ "About %s hours, %s minutes",
+ "About an hour",
+ "Less than an hour",
+ "About %s minutes, %s seconds",
+ "About a minute",
+ "Less than a minute",
+ "About %s seconds",
+ "About a second",
+ "About 1 minute, %s seconds"};
+
+
+
+/*****************************************************************************/
+/* Prototypes */
+/*****************************************************************************/
+
+int DoCurrentDir(void);
+
+void DoAboutBox(void);
+void DoQuit(void);
+void DoEventLoop(void);
+
+void ZipInitAllVars(void);
+void UserStop(void);
+Boolean IsZipFile(char *name);
+
+static long EstimateCompletionTime(const long progressMax,
+ const long progressSoFar, unsigned char percent);
+static void UpdateTimeToComplete(void);
+
+
+
+
+#ifdef USE_SIOUX
+#include <sioux.h>
+void DoWarnUserDupVol( char *FullPath );
+
+/*****************************************************************************/
+/* Functions */
+/*****************************************************************************/
+
+/*
+** Standalone Unzip with Metrowerks SIOUX starts here
+**
+*/
+int main(int argc, char **argv)
+{
+ int return_code;
+
+ SIOUXSettings.asktosaveonclose = FALSE;
+ SIOUXSettings.showstatusline = TRUE;
+
+ SIOUXSettings.columns = 100;
+ SIOUXSettings.rows = 40;
+
+ /* 30 = MacZip Johnny Lee's; 40 = new (my) MacZip */
+ MacZip.MacZipMode = NewZipMode_EF;
+
+ argc = ccommand(&argv);
+ if (verbose) PrintArguments(argc, argv);
+
+ ZipInitAllVars();
+
+ return_code = zipmain(argc, argv);
+
+ if (verbose) printf("\n\n Finish");
+ return return_code;
+}
+
+
+
+/*
+** SIOUX needs no extra event handling
+**
+*/
+
+void UserStop(void)
+{
+};
+
+
+
+
+/*
+** Password enter function '*' printed for each char
+**
+*/
+
+int macgetch(void)
+{
+ WindowPtr whichWindow;
+ EventRecord theEvent;
+ char c; /* one-byte buffer for read() to use */
+
+ do {
+ SystemTask();
+ if (!GetNextEvent(everyEvent, &theEvent))
+ theEvent.what = nullEvent;
+ else {
+ switch (theEvent.what) {
+ case keyDown:
+ c = theEvent.message & charCodeMask;
+ break;
+ case mouseDown:
+ if (FindWindow(theEvent.where, &whichWindow) ==
+ inSysWindow)
+ SystemClick(&theEvent, whichWindow);
+ break;
+ case updateEvt:
+ break;
+ }
+ }
+ } while (theEvent.what != keyDown);
+
+ printf("*");
+ fflush(stdout);
+
+ return (int)c;
+}
+
+#endif
+
+
+
+
+/******************************/
+/* Function version_local() */
+/******************************/
+
+/*
+** Print Compilers version and compile time/date
+**
+*/
+
+void version_local()
+{
+/* prints e.g:
+Compiled with Metrowerks CodeWarrior version 2000 for PowerPC Processor
+ compile time: Feb 4 1998 17:49:49.
+*/
+
+static ZCONST char CompiledWith[] =
+ "\n\nCompiled with %s %x for %s \n %s %s %s.\n\n";
+
+ printf(CompiledWith,
+
+
+#ifdef __MWERKS__
+ " Metrowerks CodeWarrior version", __MWERKS__,
+#endif
+
+
+#ifdef __MC68K__
+ " MC68K Processor",
+#else
+ " PowerPC Processor",
+#endif
+
+#ifdef __DATE__
+ "compile time: ", __DATE__, __TIME__
+#else
+ "", "", ""
+#endif
+ );
+} /* end function version_local() */
+
+
+
+
+
+/*
+** Deletes a dir if the switch '-m' is used
+**
+*/
+
+int deletedir(char *path)
+{
+static char Num = 0;
+static FSSpec trashfolder;
+static Boolean FirstCall = true;
+static Boolean Immediate_File_Deletion = false;
+OSErr err;
+FSSpec dirToDelete;
+char currpath[NAME_MAX], *envptr;
+CInfoPBRec fpb;
+
+/* init this function */
+if ((path == NULL) ||
+ (strlen(path) == 0))
+ {
+ Num = 0;
+ FirstCall = true;
+ return -1;
+ }
+
+UserStop();
+
+GetCompletePath(currpath,path,&dirToDelete, &err);
+
+if (FirstCall == true)
+ {
+ FirstCall = false;
+ envptr = getenv("Immediate_File_Deletion");
+ if (!(envptr == (char *)NULL || *envptr == '\0'))
+ {
+ if (stricmp(envptr,"yes") == 0)
+ Immediate_File_Deletion = true;
+ else
+ Immediate_File_Deletion = false;
+ }
+ err = FSpFindFolder(dirToDelete.vRefNum, kTrashFolderType,
+ kDontCreateFolder,&trashfolder);
+ printerr("FSpFindFolder:",err,err,__LINE__,__FILE__,path);
+ }
+
+ fpb.dirInfo.ioNamePtr = dirToDelete.name;
+ fpb.dirInfo.ioVRefNum = dirToDelete.vRefNum;
+ fpb.dirInfo.ioDrDirID = dirToDelete.parID;
+ fpb.dirInfo.ioFDirIndex = 0;
+
+ err = PBGetCatInfoSync(&fpb);
+ printerr("PBGetCatInfo deletedir ", err, err,
+ __LINE__, __FILE__, "");
+
+if (fpb.dirInfo.ioDrNmFls > 0)
+ {
+ return 0; /* do not move / delete folders which are not empty */
+ }
+
+if (Immediate_File_Deletion)
+ {
+ err = FSpDelete(&dirToDelete);
+ return err;
+ }
+
+err = CatMove (dirToDelete.vRefNum, dirToDelete.parID,
+ dirToDelete.name, trashfolder.parID, trashfolder.name);
+
+/* -48 = file is already existing so we have to rename it before
+ moving the file */
+if (err == -48)
+ {
+ Num++;
+ if (dirToDelete.name[0] >= 28) /* cut foldername if to long */
+ dirToDelete.name[0] = 28;
+ P2CStr(dirToDelete.name);
+ sprintf(currpath,"%s~%d",(char *)dirToDelete.name,Num);
+ C2PStr(currpath);
+ C2PStr((char *)dirToDelete.name);
+ err = HRename (dirToDelete.vRefNum, dirToDelete.parID,
+ dirToDelete.name, (unsigned char *) currpath);
+
+ err = CatMove (dirToDelete.vRefNum, dirToDelete.parID,
+ (unsigned char *) currpath, trashfolder.parID,
+ trashfolder.name);
+ }
+
+return err;
+}
+
+
+
+
+/*
+** Set the file-type so the archive will get the correct icon, type
+** and creator code.
+*/
+
+void setfiletype(char *new_f, unsigned long Creator, unsigned long Type)
+{
+OSErr err;
+
+if (strcmp(zipfile, new_f) == 0)
+ err = FSpChangeCreatorType(&MacZip.ZipFileSpec, Creator, Type);
+printerr("FSpChangeCreatorType:", err, err, __LINE__, __FILE__, new_f);
+
+return;
+}
+
+
+
+
+
+/*
+** Convert the external (native) filename into Zip's internal Unix compatible
+** name space.
+*/
+
+char *ex2in(char *externalFilen, int isdir, int *pdosflag)
+/* char *externalFilen external file name */
+/* int isdir input: externalFilen is a directory */
+/* int *pdosflag output: force MSDOS file attributes? */
+/* Convert the external file name to a zip file name, returning the malloc'ed
+ string or NULL if not enough memory. */
+{
+ char *internalFilen; /* internal file name (malloc'ed) */
+ char *t; /* shortened name */
+ char *Pathname;
+ char buffer[NAME_MAX];
+ int dosflag;
+
+ AssertStr(externalFilen, externalFilen)
+ AssertBool(isdir,"")
+
+ dosflag = dosify; /* default for non-DOS and non-OS/2 */
+
+ /* Find starting point in name before doing malloc */
+ for (t = externalFilen; *t == PATH_END; t++)
+ ;
+
+ if (!MacZip.StoreFullPath)
+ {
+ Pathname = StripPartialDir(buffer, MacZip.SearchDir,t);
+ }
+ else
+ {
+ Pathname = t;
+ }
+
+ /* Make changes, if any, to the copied name (leave original intact) */
+ if (!pathput)
+ {
+ t = last(Pathname, PATH_END);
+ }
+ else t = Pathname;
+
+ /* Malloc space for internal name and copy it */
+ if ((internalFilen = malloc(strlen(t) + 10 + strlen(ResourceMark) )) == NULL)
+ return NULL;
+
+ sstrcpy(internalFilen, t);
+
+ /* we have to eliminate illegal chars:
+ * The name space for Mac filenames and Zip filenames (unix style names)
+ * do both include all printable extended-ASCII characters. The only
+ * difference we have to take care of is the single special character
+ * used as path delimiter:
+ * ':' on MacOS and '/' on Unix and '\' on Dos.
+ * So, to convert between Mac filenames and Unix filenames without any
+ * loss of information, we simply interchange ':' and '/'. Additionally,
+ * we try to convert the coding of the extended-ASCII characters into
+ * InfoZip's standard ISO 8859-1 codepage table.
+ */
+ MakeCompatibleString(internalFilen, ':', '/', '/', ':',
+ MacZip.CurrTextEncodingBase);
+
+ /* Returned malloc'ed name */
+ if (pdosflag)
+ *pdosflag = dosflag;
+
+ if (isdir)
+ {
+ return internalFilen; /* avoid warning on unused variable */
+ }
+
+ if (dosify)
+ {
+ msname(internalFilen);
+ printf("\n ex2in: %s",internalFilen);
+ }
+
+ return internalFilen;
+}
+
+
+
+/*
+** Collect all filenames. Go through all directories
+**
+*/
+
+int wild(char *Pathpat)
+ /* path/pattern to match */
+/* If not in exclude mode, expand the pattern based on the contents of the
+ file system. Return an error code in the ZE_ class. */
+{
+FSSpec Spec;
+char fullpath[NAME_MAX];
+OSErr err;
+
+AssertStr(Pathpat, Pathpat);
+
+if (noisy) printf("%s \n\n",GetZipVersionsInfo());
+
+if (extra_fields == 0)
+ {
+ MacZip.DataForkOnly = true;
+ }
+
+/* for switch '-R' -> '.' means current dir */
+if (strcmp(Pathpat,".") == 0) sstrcpy(Pathpat,"*");
+
+sstrcpy(MacZip.Pattern,Pathpat);
+
+if (recurse)
+ {
+ MacZip.StoreFoldersAlso = true;
+ MacZip.SearchLevels = 0; /* if 0 we aren't checking levels */
+ }
+else
+ {
+ MacZip.StoreFoldersAlso = false;
+ MacZip.SearchLevels = 1;
+ }
+
+/* make complete path */
+GetCompletePath(fullpath, MacZip.Pattern, &Spec,&err);
+err = PrintUserHFSerr((err != -43) && (err != 0), err, MacZip.Pattern);
+printerr("GetCompletePath:", err, err, __LINE__, __FILE__, fullpath);
+
+/* extract the filepattern */
+GetFilename(MacZip.Pattern, fullpath);
+
+/* extract Path and get FSSpec of search-path */
+/* get FSSpec of search-path ; we need a dir to start
+ searching for filenames */
+TruncFilename(MacZip.SearchDir, fullpath);
+GetCompletePath(MacZip.SearchDir, MacZip.SearchDir, &Spec,&err);
+
+if (noisy) {
+ if (MacZip.SearchLevels == 0)
+ {
+ printf("\nSearch Pattern: [%s] Levels: all", MacZip.Pattern);
+ }
+ else
+ {
+ printf("\nSearch Pattern: [%s] Levels: %d", MacZip.Pattern,
+ MacZip.SearchLevels);
+ }
+ printf("\nSearch Path: [%s]", MacZip.SearchDir);
+ printf("\nZip-File: [%s] \n",MacZip.ZipFullPath);
+
+}
+
+/* we are working only with pathnames;
+ * this can cause big problems on a mac ...
+ */
+if (CheckMountedVolumes(MacZip.SearchDir) > 1)
+ DoWarnUserDupVol(MacZip.SearchDir);
+
+/* start getting all filenames */
+err = FSpRecurseDirectory(&Spec, MacZip.SearchLevels);
+printerr("FSpRecurseDirectory:", err, err, __LINE__, __FILE__, "");
+
+return ZE_OK;
+}
+
+
+
+/*
+** Convert the internal filename into a external (native).
+** The user will see this modified filename.
+** For more performance:
+** I do not completly switch back to the native macos filename.
+** The user will still see directory separator '/' and the converted
+** charset.
+*/
+
+char *in2ex(char *n) /* internal file name */
+/* Convert the zip file name to an external file name, returning the malloc'ed
+ string or NULL if not enough memory. */
+{
+ char *x; /* external file name */
+
+ AssertStr(n,n)
+
+ if ((x = malloc(strlen(n) + 1)) == NULL)
+ return NULL;
+
+ RfDfFilen2Real(x, n, MacZip.MacZipMode, MacZip.DataForkOnly,
+ &MacZip.CurrentFork);
+
+ return x;
+}
+
+
+
+
+/*
+** Process on filenames. This function will be called to collect
+** the filenames.
+*/
+
+int procname(char *filename, /* name to process */
+ int caseflag) /* true to force case-sensitive match
+ (always false on a Mac) */
+/* Process a name . Return
+ an error code in the ZE_ class. */
+{
+ int rc; /* matched flag */
+
+AssertBool(caseflag,"caseflag")
+AssertStr(filename,filename)
+
+ /* add or remove name of file */
+rc = newname(filename, MacZip.isDirectory, caseflag);
+
+return rc;
+}
+
+
+
+
+ulg filetime(
+char *f, /* name of file to get info on */
+ulg *a, /* return value: file attributes */
+long *n, /* return value: file size */
+iztimes *t) /* return value: access, modific. and creation times */
+/* If file *f does not exist, return 0. Else, return the file's last
+ modified date and time as an MSDOS date and time. The date and
+ time is returned in a long with the date most significant to allow
+ unsigned integer comparison of absolute times. Also, if a is not
+ a NULL pointer, store the file attributes there, with the high two
+ bytes being the Unix attributes, and the low byte being a mapping
+ of that to DOS attributes. If n is not NULL, store the file size
+ there. If t is not NULL, the file's access, modification and creation
+ times are stored there as UNIX time_t values.
+ If f is "-", use standard input as the file. If f is a device, return
+ a file size of -1 */
+{
+ struct stat s; /* results of stat() */
+
+ AssertStr(f,f)
+
+ if (strlen(f) == 0) return 0;
+
+ if (SSTAT(f, &s) != 0)
+ /* Accept about any file kind including directories
+ * (stored with trailing : with -r option)
+ */
+ return 0;
+
+ if (a != NULL) {
+ *a = ((ulg)s.st_mode << 16) | !(s.st_mode & S_IWRITE);
+ if (MacZip.isDirectory) {
+ *a |= MSDOS_DIR_ATTR;
+ }
+ }
+ if (n != NULL)
+ *n = (s.st_mode & UNX_IFMT) == UNX_IFREG ? s.st_size : -1L;
+ if (t != NULL) {
+ t->atime = s.st_atime;
+ t->mtime = s.st_mtime;
+ t->ctime = s.st_ctime; /* on Mac, st_ctime contains creation time! */
+ }
+
+ return unix2dostime(&s.st_mtime);
+}
+
+
+
+void stamp(char *f, ulg d)
+/* char *f; name of file to change */
+/* ulg d; dos-style time to change it to */
+/* Set last updated and accessed time of file f to the DOS time d. */
+{
+ time_t u[2]; /* argument for utime() */
+
+f = f;
+
+ /* Convert DOS time to time_t format in u */
+
+ u[0] = u[1] = dos2unixtime(d);
+/* utime(f, u); */
+}
+
+
+
+
+/*
+** return only the longest part of the path:
+** second parameter: Volume:test folder:second folder:
+** third parameter: Volume:test folder:second folder:third folder:file
+** result will be: third folder:file
+** first parameter: contains string buffer that will be used to prepend
+** the "resource mark" part in front of the result when
+** a resource fork is processed in "M3" mode.
+**
+*/
+
+char *StripPartialDir(char *CompletePath,
+ const char *PartialPath, const char *FullPath)
+{
+const char *tmpPtr1 = PartialPath;
+const char *tmpPtr2 = FullPath;
+int result;
+
+Assert_it(CompletePath,"StripPartialDir","")
+AssertStrNoOverlap(FullPath,PartialPath,PartialPath)
+
+if (MacZip.DataForkOnly)
+ {
+ tmpPtr2 += strlen(tmpPtr1);
+ return (char *)tmpPtr2;
+ }
+
+switch (MacZip.MacZipMode)
+ {
+ case JohnnyLee_EF:
+ {
+ tmpPtr2 += strlen(tmpPtr1);
+ return (char *)tmpPtr2;
+ break;
+ }
+
+ case NewZipMode_EF:
+ { /* determine Fork type */
+ result = strncmp(FullPath, ResourceMark, sizeof(ResourceMark)-2);
+ if (result != 0)
+ { /* data fork */
+ MacZip.CurrentFork = DataFork;
+ tmpPtr2 += strlen(tmpPtr1);
+ return (char *)tmpPtr2;
+ }
+ else
+ { /* resource fork */
+ MacZip.CurrentFork = ResourceFork;
+ sstrcpy(CompletePath, ResourceMark);
+ tmpPtr2 += strlen(tmpPtr1);
+ tmpPtr2 += sizeof(ResourceMark);
+ sstrcat(CompletePath, tmpPtr2);
+ return (char *)CompletePath;
+ }
+ break;
+ }
+ }
+
+ return NULL; /* function should never reach this point */
+}
+
+
+
+
+/*
+** Init all global variables
+** Must be called for each zip-run
+*/
+
+void ZipInitAllVars(void)
+{
+getcwd(MacZip.CurrentPath, sizeof(MacZip.CurrentPath));
+/* MacZip.MacZipMode = JohnnyLee_EF; */
+MacZip.MacZipMode = NewZipMode_EF;
+
+MacZip.DataForkOnly = false;
+MacZip.CurrentFork = NoFork;
+
+MacZip.StoreFoldersAlso = false;
+
+MacZip.FoundFiles = 0;
+MacZip.FoundDirectories = 0;
+MacZip.RawCountOfItems = 0;
+MacZip.BytesOfData = 0;
+
+MacZip.StoreFullPath = false;
+MacZip.StatingProgress = false;
+MacZip.IncludeInvisible = false;
+
+MacZip.isMacStatValid = false;
+
+MacZip.CurrTextEncodingBase = FontScript();
+
+MacZip.HaveGMToffset = false;
+
+createTime = TickCount();
+estTicksToFinish = -1;
+updateTicks = 0;
+
+/* init some functions */
+IsZipFile(NULL);
+
+destroy(NULL);
+deletedir(NULL);
+ShowCounter(true);
+
+extra_fields = 1;
+error_level = 0;
+count_of_Zippedfiles = 0;
+}
+
+
+
+
+/*
+** Get the findercomment and store it as file-comment in the Zip-file
+**
+*/
+char *GetComment(char *filename)
+{
+OSErr err;
+static char buffer[NAME_MAX];
+char buffer2[NAME_MAX];
+char *tmpPtr;
+
+if (filename == NULL) return NULL;
+
+ /* now we can convert Unix-Path in HFS-Path */
+for (tmpPtr = filename; *tmpPtr; tmpPtr++)
+ if (*tmpPtr == '/')
+ *tmpPtr = ':';
+
+if (MacZip.StoreFullPath)
+ { /* filename is already a fullpath */
+ sstrcpy(buffer,filename);
+ }
+else
+ { /* make a fullpath */
+ sstrcpy(buffer,MacZip.SearchDir);
+ sstrcat(buffer,filename);
+ }
+
+/* make fullpath and get FSSpec */
+/* Unfortunately: I get only the converted filename here */
+/* so filenames with extended characters can not be found */
+GetCompletePath(buffer2,buffer, &MacZip.fileSpec, &err);
+printerr("GetCompletePath:",(err != -43) && (err != -120) && (err != 0) ,
+ err,__LINE__,__FILE__,buffer);
+
+err = FSpDTGetComment(&MacZip.fileSpec, (unsigned char *) buffer);
+printerr("FSpDTGetComment:", (err != -5012) && (err != 0), err,
+ __LINE__, __FILE__, filename);
+P2CStr((unsigned char *) buffer);
+if (err == -5012) return NULL; /* no finder-comments found */
+
+if (noisy) printf("\n%32s -> %s",filename, buffer);
+/*
+Beside the script change we need only to change 0x0d in 0x0a
+so the last two arguments are not needed and does nothing.
+*/
+MakeCompatibleString(buffer, 0x0d, 0x0a, ' ', ' ',
+ MacZip.CurrTextEncodingBase);
+
+return buffer;
+}
+
+
+
+
+/*
+** Print a progress indicator for stating the files
+**
+*/
+
+void PrintStatProgress(char *msg)
+{
+
+if (!noisy) return; /* do no output if noisy is false */
+
+MacZip.StatingProgress = true;
+
+if (strcmp(msg,"done") == 0)
+ {
+ MacZip.StatingProgress = false;
+ printf("\n ... done \n\n");
+ }
+else printf("\n %s",msg);
+
+}
+
+
+
+
+void InformProgress(const long progressMax, const long progressSoFar )
+{
+int curr_percent;
+char no_time[5] = "...";
+
+curr_percent = percent(progressMax, progressSoFar);
+
+if (curr_percent < 95)
+ {
+ estTicksToFinish = EstimateCompletionTime(progressMax,
+ progressSoFar, curr_percent);
+ }
+else
+ {
+ rightStatusString(no_time);
+ leftStatusString(no_time);
+ }
+
+updateTicks = TickCount() + 60;
+return;
+}
+
+
+void ShowCounter(Boolean reset)
+{
+static char statusline[100];
+static unsigned long filecount = 0;
+
+if (reset)
+ {
+ filecount = 0;
+ return;
+ }
+
+if (noisy)
+ {
+ sprintf(statusline, "%6d", filecount++);
+ rightStatusString(statusline);
+ }
+}
+
+
+static long EstimateCompletionTime(const long progressMax,
+ const long progressSoFar,
+ unsigned char curr_percent)
+{
+ long max = progressMax, value = progressSoFar;
+ static char buf[100];
+ unsigned long ticksTakenSoFar = TickCount() - createTime;
+ float currentRate = (float) ticksTakenSoFar / (float) value;
+ long newEst = (long)( currentRate * (float)( max - value ));
+
+ sprintf(buf, "%d [%d%%]",progressSoFar, curr_percent);
+ rightStatusString(buf);
+
+ estTicksToFinish = newEst;
+
+ UpdateTimeToComplete();
+
+return estTicksToFinish;
+}
+
+
+
+
+
+static void UpdateTimeToComplete(void)
+{
+ short days, hours, minutes, seconds;
+ char estStr[255];
+ Str15 xx, yy;
+ short idx = 0;
+
+ if ( estTicksToFinish == -1 )
+ return;
+
+ days = estTicksToFinish / 5184000L;
+ hours = ( estTicksToFinish - ( days * 5184000L )) / 216000L;
+ minutes = ( estTicksToFinish - ( days * 5184000L ) -
+ ( hours * 216000L )) / 3600L;
+ seconds = ( estTicksToFinish - ( days * 5184000L ) -
+ ( hours * 216000L ) - ( minutes * 3600L )) / 60L;
+
+ xx[0] = 0;
+ yy[0] = 0;
+
+ if ( days )
+ {
+ /* "more than 24 hours" */
+
+ idx = 1;
+ goto setEstTimeStr;
+ }
+
+ if ( hours >= 8 )
+ {
+ /* "more than x hours" */
+
+ NumToString( hours, xx );
+ idx = 2;
+ goto setEstTimeStr;
+ }
+
+ if ( estTicksToFinish > 252000L ) /* > 1hr, 10 minutes */
+ {
+ /* "about x hours, y minutes" */
+
+ NumToString( hours, xx );
+ NumToString( minutes, yy );
+ idx = 3;
+ goto setEstTimeStr;
+ }
+
+ if ( estTicksToFinish > 198000L ) /* > 55 minutes */
+ {
+ /* "about an hour" */
+ idx = 4;
+ goto setEstTimeStr;
+ }
+
+ if ( estTicksToFinish > 144000L ) /* > 40 minutes */
+ {
+ /* "less than an hour" */
+
+ idx = 5;
+ goto setEstTimeStr;
+ }
+
+ if ( estTicksToFinish > 4200L ) /* > 1 minute, 10 sec */
+ {
+ /* "about x minutes, y seconds */
+
+ NumToString( minutes, xx );
+ NumToString( seconds, yy );
+
+ if ( minutes == 1 )
+ idx = 11;
+ else
+ idx = 6;
+ goto setEstTimeStr;
+ }
+
+ if ( estTicksToFinish > 3000L ) /* > 50 seconds */
+ {
+ /* "about a minute" */
+
+ idx = 7;
+ goto setEstTimeStr;
+ }
+
+ if ( estTicksToFinish > 1500L ) /* > 25 seconds */
+ {
+ /* "less than a minute" */
+
+ idx = 8;
+ goto setEstTimeStr;
+ }
+
+ if ( estTicksToFinish > 120L ) /* > 2 seconds */
+ {
+ NumToString( seconds, xx );
+ idx = 9;
+ goto setEstTimeStr;
+ }
+
+ idx = 10;
+
+ setEstTimeStr:
+ sprintf(estStr,Time_Est_strings[idx],P2CStr(xx),P2CStr(yy));
+ leftStatusString((char *)estStr);
+}
+
+
+
+
+
+/*
+** Just return the zip version
+**
+*/
+
+char *GetZipVersionsInfo(void)
+{
+static char ZipVersion[100];
+
+sprintf(ZipVersion, "Zip Module\n%d.%d%d%s of %s", Z_MAJORVER, Z_MINORVER,
+ Z_PATCHLEVEL, Z_BETALEVEL, REVDATE);
+
+return ZipVersion;
+}
+
+
+
+
+#ifndef USE_SIOUX
+
+/*
+** Just return the copyright message
+**
+*/
+
+char *GetZipCopyright(void)
+{
+static char CopyR[300];
+
+sstrcpy(CopyR, copyright[0]);
+sstrcat(CopyR, copyright[1]);
+sstrcat(CopyR, "\r\rPlease send bug reports to the authors at\r"\
+ "Zip-Bugs@lists.wku.edu");
+
+return CopyR;
+}
+
+
+
+
+/*
+** Just return the compilers date/time
+**
+*/
+
+char *GetZipVersionLocal(void)
+{
+static char ZipVersionLocal[50];
+
+sprintf(ZipVersionLocal, "[%s %s]", __DATE__, __TIME__);
+
+return ZipVersionLocal;
+}
+
+#endif /* #ifndef USE_SIOUX */
+
+
+
+
diff --git a/macos/source/macstuff.c b/macos/source/macstuff.c
new file mode 100644
index 0000000..0323607
--- /dev/null
+++ b/macos/source/macstuff.c
@@ -0,0 +1,1724 @@
+/*
+These Functions were originally part of More Files version 1.4.8
+
+More Files fixes many of the broken or underfunctional
+parts of the file system.
+
+More Files
+
+A collection of File Manager and related routines
+
+by Jim Luther (Apple Macintosh Developer Technical Support Emeritus)
+with significant code contributions by Nitin Ganatra
+(Apple Macintosh Developer Technical Support Emeritus)
+Copyright 1992-1998 Apple Computer, Inc.
+Portions copyright 1995 Jim Luther
+All rights reserved.
+
+The Package "More Files" is distributed under the following
+license terms:
+
+ "You may incorporate this sample code into your
+ applications without restriction, though the
+ sample code has been provided "AS IS" and the
+ responsibility for its operation is 100% yours.
+ However, what you are not permitted to do is to
+ redistribute the source as "DSC Sample Code" after
+ having made changes. If you're going to
+ redistribute the source, we require that you make
+ it clear in the source that the code was descended
+ from Apple Sample Code, but that you've made
+ changes."
+
+
+The following changes are made by Info-ZIP:
+
+- The only changes are made by pasting the functions
+ (mostly found in MoreFilesExtras.c / MoreFiles.c)
+ directly into macstuff.c / macstuff.h and slightly
+ reformatting the text (replacement of TABs by spaces,
+ removal/replacement of non-ASCII characters).
+ The code itself is NOT changed.
+
+This file has been modified by Info-ZIP for use in MacZip.
+This file is NOT part of the original package More Files.
+
+More Files can be found on the MetroWerks CD and Developer CD from
+Apple. You can also download the latest version from:
+
+ http://members.aol.com/JumpLong/#MoreFiles
+
+Jim Luther's Home-page:
+ http://members.aol.com/JumpLong/
+
+
+*/
+
+#include <string.h>
+
+
+#include "macstuff.h"
+
+
+
+extern int errno;
+
+static OSErr GetCommentFromDesktopFile(short vRefNum,
+ long dirID,
+ ConstStr255Param name,
+ Str255 comment);
+
+static OSErr GetCommentID(short vRefNum,
+ long dirID,
+ ConstStr255Param name,
+ short *commentID);
+
+static OSErr GetDesktopFileName(short vRefNum,
+ Str255 desktopName);
+
+
+enum
+{
+ kBNDLResType = 'BNDL',
+ kFREFResType = 'FREF',
+ kIconFamResType = 'ICN#',
+ kFCMTResType = 'FCMT',
+ kAPPLResType = 'APPL'
+};
+
+
+/*****************************************************************************/
+
+/*
+** File Manager FSp calls
+*/
+
+/*****************************************************************************/
+
+pascal OSErr FSMakeFSSpecCompat(short vRefNum,
+ long dirID,
+ ConstStr255Param fileName,
+ FSSpec *spec)
+{
+ OSErr result;
+
+#if !__MACOSSEVENORLATER
+ if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
+ {
+ Boolean isDirectory;
+
+ result = GetObjectLocation(vRefNum, dirID, fileName,
+ &(spec->vRefNum), &(spec->parID), spec->name,
+ &isDirectory);
+ }
+ else
+#endif /* !__MACOSSEVENORLATER */
+ {
+ /* Let the file system create the FSSpec if it can since it does the job */
+ /* much more efficiently than I can. */
+ result = FSMakeFSSpec(vRefNum, dirID, fileName, spec);
+
+ /* Fix a bug in Macintosh PC Exchange's MakeFSSpec code where 0 is */
+ /* returned in the parID field when making an FSSpec to the volume's */
+ /* root directory by passing a full pathname in MakeFSSpec's */
+ /* fileName parameter. Fixed in Mac OS 8.1 */
+ if ( (result == noErr) && (spec->parID == 0) )
+ spec->parID = fsRtParID;
+ }
+ return ( result );
+}
+
+
+/*****************************************************************************/
+/* FSHasFSSpecCalls returns true if the file system provides FSSpec calls. */
+
+#if !__MACOSSEVENORLATER
+static Boolean FSHasFSSpecCalls(void)
+{
+ long response;
+#if !GENERATENODATA
+ static Boolean tested = false;
+ static Boolean result = false;
+#else
+ Boolean result = false;
+#endif
+
+#if !GENERATENODATA
+ if ( !tested )
+ {
+ tested = true;
+#endif
+ if ( Gestalt(gestaltFSAttr, &response) == noErr )
+ {
+ result = ((response & (1L << gestaltHasFSSpecCalls)) != 0);
+ }
+#if !GENERATENODATA
+ }
+#endif
+ return ( result );
+}
+#endif /* !__MACOSSEVENORLATER */
+
+
+
+/*****************************************************************************/
+/* QTHasFSSpecCalls returns true if QuickTime provides FSSpec calls */
+/* except for FSpExchangeFiles. */
+
+#if !__MACOSSEVENORLATER
+static Boolean QTHasFSSpecCalls(void)
+{
+ long response;
+#if !GENERATENODATA
+ static Boolean tested = false;
+ static Boolean result = false;
+#else
+ Boolean result = false;
+#endif
+
+#if !GENERATENODATA
+ if ( !tested )
+ {
+ tested = true;
+#endif
+ result = (Gestalt(gestaltQuickTimeVersion, &response) == noErr);
+#if !GENERATENODATA
+ }
+#endif
+ return ( result );
+}
+#endif /* !__MACOSSEVENORLATER */
+
+
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FSpGetDefaultDir --
+ *
+ * This function gets the current default directory.
+ *
+ * Results:
+ * The provided FSSpec is changed to point to the "default"
+ * directory. The function returns what ever errors
+ * FSMakeFSSpecCompat may encounter.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int FSpGetDefaultDir(FSSpecPtr dirSpec) /* On return the default directory. */
+{
+ OSErr err;
+ short vRefNum = 0;
+ long int dirID = 0;
+
+ err = HGetVol(NULL, &vRefNum, &dirID);
+
+ if (err == noErr) {
+ err = FSMakeFSSpecCompat(vRefNum, dirID, (ConstStr255Param) NULL,
+ dirSpec);
+ }
+
+ return err;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FSpSetDefaultDir --
+ *
+ * This function sets the default directory to the directory
+ * pointed to by the provided FSSpec.
+ *
+ * Results:
+ * The function returns what ever errors HSetVol may encounter.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int FSpSetDefaultDir(FSSpecPtr dirSpec) /* The new default directory. */
+{
+ OSErr err;
+
+ /*
+ * The following special case is needed to work around a bug
+ * in the Macintosh OS. (Acutally PC Exchange.)
+ */
+
+ if (dirSpec->parID == fsRtParID) {
+ err = HSetVol(NULL, dirSpec->vRefNum, fsRtDirID);
+ } else {
+ err = HSetVol(dirSpec->name, dirSpec->vRefNum, dirSpec->parID);
+ }
+
+ return err;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FSpFindFolder --
+ *
+ * This function is a version of the FindFolder function that
+ * returns the result as a FSSpec rather than a vRefNum and dirID.
+ *
+ * Results:
+ * Results will be simaler to that of the FindFolder function.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+OSErr
+FSpFindFolder(
+ short vRefNum, /* Volume reference number. */
+ OSType folderType, /* Folder type taken by FindFolder. */
+ Boolean createFolder, /* Should we create it if non-existant. */
+ FSSpec *spec) /* Pointer to resulting directory. */
+{
+ short foundVRefNum;
+ long foundDirID;
+ OSErr err;
+
+ err = FindFolder(vRefNum, folderType, createFolder,
+ &foundVRefNum, &foundDirID);
+ if (err != noErr) {
+ return err;
+ }
+
+ err = FSMakeFSSpecCompat(foundVRefNum, foundDirID, "\p", spec);
+ return err;
+}
+
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FSpPathFromLocation --
+ *
+ * This function obtains a full path name for a given macintosh
+ * FSSpec. Unlike the More Files function FSpGetFullPath, this
+ * function will return a C string in the Handle. It also will
+ * create paths for FSSpec that do not yet exist.
+ *
+ * Results:
+ * OSErr code.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+OSErr
+FSpPathFromLocation(
+ FSSpec *spec, /* The location we want a path for. */
+ int *length, /* Length of the resulting path. */
+ Handle *fullPath) /* Handle to path. */
+{
+ OSErr err;
+ FSSpec tempSpec;
+ CInfoPBRec pb;
+
+ *fullPath = NULL;
+
+ /*
+ * Make a copy of the input FSSpec that can be modified.
+ */
+ BlockMoveData(spec, &tempSpec, sizeof(FSSpec));
+
+ if (tempSpec.parID == fsRtParID) {
+ /*
+ * The object is a volume. Add a colon to make it a full
+ * pathname. Allocate a handle for it and we are done.
+ */
+ tempSpec.name[0] += 2;
+ tempSpec.name[tempSpec.name[0] - 1] = ':';
+ tempSpec.name[tempSpec.name[0]] = '\0';
+
+ err = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]);
+ } else {
+ /*
+ * The object isn't a volume. Is the object a file or a directory?
+ */
+ pb.dirInfo.ioNamePtr = tempSpec.name;
+ pb.dirInfo.ioVRefNum = tempSpec.vRefNum;
+ pb.dirInfo.ioDrDirID = tempSpec.parID;
+ pb.dirInfo.ioFDirIndex = 0;
+ err = PBGetCatInfoSync(&pb);
+
+ if ((err == noErr) || (err == fnfErr)) {
+ /*
+ * If the file doesn't currently exist we start over. If the
+ * directory exists everything will work just fine. Otherwise we
+ * will just fail later. If the object is a directory, append a
+ * colon so full pathname ends with colon.
+ */
+ if (err == fnfErr) {
+ BlockMoveData(spec, &tempSpec, sizeof(FSSpec));
+ } else if ( (pb.hFileInfo.ioFlAttrib & ioDirMask) != 0 ) {
+ tempSpec.name[0] += 1;
+ tempSpec.name[tempSpec.name[0]] = ':';
+ }
+
+ /*
+ * Create a new Handle for the object - make it a C string.
+ */
+ tempSpec.name[0] += 1;
+ tempSpec.name[tempSpec.name[0]] = '\0';
+ err = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]);
+ if (err == noErr) {
+ /*
+ * Get the ancestor directory names - loop until we have an
+ * error or find the root directory.
+ */
+ pb.dirInfo.ioNamePtr = tempSpec.name;
+ pb.dirInfo.ioVRefNum = tempSpec.vRefNum;
+ pb.dirInfo.ioDrParID = tempSpec.parID;
+ do {
+ pb.dirInfo.ioFDirIndex = -1;
+ pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrParID;
+ err = PBGetCatInfoSync(&pb);
+ if (err == noErr) {
+ /*
+ * Append colon to directory name and add
+ * directory name to beginning of fullPath.
+ */
+ ++tempSpec.name[0];
+ tempSpec.name[tempSpec.name[0]] = ':';
+
+ (void) Munger(*fullPath, 0, NULL, 0, &tempSpec.name[1],
+ tempSpec.name[0]);
+ err = MemError();
+ }
+ } while ( (err == noErr) &&
+ (pb.dirInfo.ioDrDirID != fsRtDirID) );
+ }
+ }
+ }
+
+ /*
+ * On error Dispose the handle, set it to NULL & return the err.
+ * Otherwise, set the length & return.
+ */
+ if (err == noErr) {
+ *length = GetHandleSize(*fullPath) - 1;
+ } else {
+ if ( *fullPath != NULL ) {
+ DisposeHandle(*fullPath);
+ }
+ *fullPath = NULL;
+ *length = 0;
+ }
+
+ return err;
+}
+
+
+
+/*****************************************************************************/
+
+pascal OSErr FSpGetDirectoryID(const FSSpec *spec,
+ long *theDirID,
+ Boolean *isDirectory)
+{
+ return ( GetDirectoryID(spec->vRefNum, spec->parID, spec->name,
+ theDirID, isDirectory) );
+}
+
+
+/*****************************************************************************/
+
+pascal OSErr GetDirectoryID(short vRefNum,
+ long dirID,
+ ConstStr255Param name,
+ long *theDirID,
+ Boolean *isDirectory)
+{
+ CInfoPBRec pb;
+ OSErr error;
+
+ error = GetCatInfoNoName(vRefNum, dirID, name, &pb);
+ if ( error == noErr )
+ {
+ *isDirectory = (pb.hFileInfo.ioFlAttrib & ioDirMask) != 0;
+ if ( *isDirectory )
+ {
+ *theDirID = pb.dirInfo.ioDrDirID;
+ }
+ else
+ {
+ *theDirID = pb.hFileInfo.ioFlParID;
+ }
+ }
+
+ return ( error );
+}
+
+
+/*****************************************************************************/
+
+pascal OSErr GetCatInfoNoName(short vRefNum,
+ long dirID,
+ ConstStr255Param name,
+ CInfoPBPtr pb)
+{
+ Str31 tempName;
+ OSErr error;
+
+ /* Protection against File Sharing problem */
+ if ( (name == NULL) || (name[0] == 0) )
+ {
+ tempName[0] = 0;
+ pb->dirInfo.ioNamePtr = tempName;
+ pb->dirInfo.ioFDirIndex = -1; /* use ioDirID */
+ }
+ else
+ {
+ pb->dirInfo.ioNamePtr = (StringPtr)name;
+ pb->dirInfo.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */
+ }
+ pb->dirInfo.ioVRefNum = vRefNum;
+ pb->dirInfo.ioDrDirID = dirID;
+ error = PBGetCatInfoSync(pb);
+ pb->dirInfo.ioNamePtr = NULL;
+ return ( error );
+}
+
+
+
+/*****************************************************************************/
+
+pascal OSErr GetObjectLocation(short vRefNum,
+ long dirID,
+ ConstStr255Param pathname,
+ short *realVRefNum,
+ long *realParID,
+ Str255 realName,
+ Boolean *isDirectory)
+{
+ OSErr error;
+ CInfoPBRec pb;
+ Str255 tempPathname;
+
+ /* clear results */
+ *realVRefNum = 0;
+ *realParID = 0;
+ realName[0] = 0;
+
+ /*
+ ** Get the real vRefNum
+ */
+ error = DetermineVRefNum(pathname, vRefNum, realVRefNum);
+ if ( error == noErr )
+ {
+ /*
+ ** Determine if the object already exists and if so,
+ ** get the real parent directory ID if it's a file
+ */
+
+ /* Protection against File Sharing problem */
+ if ( (pathname == NULL) || (pathname[0] == 0) )
+ {
+ tempPathname[0] = 0;
+ pb.hFileInfo.ioNamePtr = tempPathname;
+ pb.hFileInfo.ioFDirIndex = -1; /* use ioDirID */
+ }
+ else
+ {
+ pb.hFileInfo.ioNamePtr = (StringPtr)pathname;
+ pb.hFileInfo.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */
+ }
+ pb.hFileInfo.ioVRefNum = vRefNum;
+ pb.hFileInfo.ioDirID = dirID;
+ error = PBGetCatInfoSync(&pb);
+ if ( error == noErr )
+ {
+ /*
+ ** The file system object is present and we have the file's
+ ** real parID
+ */
+
+ /* Is it a directory or a file? */
+ *isDirectory = (pb.hFileInfo.ioFlAttrib & ioDirMask) != 0;
+ if ( *isDirectory )
+ {
+ /*
+ ** It's a directory, get its name and parent dirID, and then
+ ** we're done
+ */
+
+ pb.dirInfo.ioNamePtr = realName;
+ pb.dirInfo.ioVRefNum = *realVRefNum;
+ /* pb.dirInfo.ioDrDirID already contains the dirID of the
+ directory object */
+ pb.dirInfo.ioFDirIndex = -1; /* get information about ioDirID */
+ error = PBGetCatInfoSync(&pb);
+
+ /* get the parent ID here, because the file system can return the */
+ /* wrong parent ID from the last call. */
+ *realParID = pb.dirInfo.ioDrParID;
+ }
+ else
+ {
+ /*
+ ** It's a file - use the parent directory ID from the last call
+ ** to GetCatInfoparse, get the file name, and then we're done
+ */
+ *realParID = pb.hFileInfo.ioFlParID;
+ error = GetFilenameFromPathname(pathname, realName);
+ }
+ }
+ else if ( error == fnfErr )
+ {
+ /*
+ ** The file system object is not present - see if its parent is present
+ */
+
+ /*
+ ** Parse to get the object name from end of pathname
+ */
+ error = GetFilenameFromPathname(pathname, realName);
+
+ /* if we can't get the object name from the end, we can't continue */
+ if ( error == noErr )
+ {
+ /*
+ ** What we want now is the pathname minus the object name
+ ** for example:
+ ** if pathname is 'vol:dir:file' tempPathname becomes 'vol:dir:'
+ ** if pathname is 'vol:dir:file:' tempPathname becomes 'vol:dir:'
+ ** if pathname is ':dir:file' tempPathname becomes ':dir:'
+ ** if pathname is ':dir:file:' tempPathname becomes ':dir:'
+ ** if pathname is ':file' tempPathname becomes ':'
+ ** if pathname is 'file or file:' tempPathname becomes ''
+ */
+
+ /* get a copy of the pathname */
+ BlockMoveData(pathname, tempPathname, pathname[0] + 1);
+
+ /* remove the object name */
+ tempPathname[0] -= realName[0];
+ /* and the trailing colon (if any) */
+ if ( pathname[pathname[0]] == ':' )
+ {
+ --tempPathname[0];
+ }
+
+ /* OK, now get the parent's directory ID */
+
+ /* Protection against File Sharing problem */
+ pb.hFileInfo.ioNamePtr = (StringPtr)tempPathname;
+ if ( tempPathname[0] != 0 )
+ {
+ pb.hFileInfo.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */
+ }
+ else
+ {
+ pb.hFileInfo.ioFDirIndex = -1; /* use ioDirID */
+ }
+ pb.hFileInfo.ioVRefNum = vRefNum;
+ pb.hFileInfo.ioDirID = dirID;
+ error = PBGetCatInfoSync(&pb);
+ *realParID = pb.dirInfo.ioDrDirID;
+
+ *isDirectory = false; /* we don't know what the object is
+ really going to be */
+ }
+
+ if ( error != noErr )
+ {
+ error = dirNFErr; /* couldn't find parent directory */
+ }
+ else
+ {
+ error = fnfErr; /* we found the parent, but not the file */
+ }
+ }
+ }
+
+ return ( error );
+}
+
+
+
+/*****************************************************************************/
+
+pascal OSErr DetermineVRefNum(ConstStr255Param pathname,
+ short vRefNum,
+ short *realVRefNum)
+{
+ HParamBlockRec pb;
+ OSErr error;
+
+ error = GetVolumeInfoNoName(pathname,vRefNum, &pb);
+ if ( error == noErr )
+ {
+ *realVRefNum = pb.volumeParam.ioVRefNum;
+ }
+ return ( error );
+}
+
+
+/*****************************************************************************/
+
+pascal OSErr GetFilenameFromPathname(ConstStr255Param pathname,
+ Str255 filename)
+{
+ short index;
+ short nameEnd;
+ OSErr error;
+
+ /* default to no filename */
+ filename[0] = 0;
+
+ /* check for no pathname */
+ if ( pathname != NULL )
+ {
+ /* get string length */
+ index = pathname[0];
+
+ /* check for empty string */
+ if ( index != 0 )
+ {
+ /* skip over last trailing colon (if any) */
+ if ( pathname[index] == ':' )
+ {
+ --index;
+ }
+
+ /* save the end of the string */
+ nameEnd = index;
+
+ /* if pathname ends with multiple colons, then this pathname refers */
+ /* to a directory, not a file */
+ if ( pathname[index] != ':' )
+ {
+ /* parse backwards until we find a colon or hit the beginning
+ of the pathname */
+ while ( (index != 0) && (pathname[index] != ':') )
+ {
+ --index;
+ }
+
+ /* if we parsed to the beginning of the pathname and the
+ pathname ended */
+ /* with a colon, then pathname is a full pathname to a volume,
+ not a file */
+ if ( (index != 0) || (pathname[pathname[0]] != ':') )
+ {
+ /* get the filename and return noErr */
+ filename[0] = (char)(nameEnd - index);
+ BlockMoveData(&pathname[index+1], &filename[1], nameEnd - index);
+ error = noErr;
+ }
+ else
+ {
+ /* pathname to a volume, not a file */
+ error = notAFileErr;
+ }
+ }
+ else
+ {
+ /* directory, not a file */
+ error = notAFileErr;
+ }
+ }
+ else
+ {
+ /* empty string isn't a file */
+ error = notAFileErr;
+ }
+ }
+ else
+ {
+ /* NULL pathname isn't a file */
+ error = notAFileErr;
+ }
+
+ return ( error );
+}
+
+
+
+/*****************************************************************************/
+
+/*
+** GetVolumeInfoNoName uses pathname and vRefNum to call PBHGetVInfoSync
+** in cases where the returned volume name is not needed by the caller.
+** The pathname and vRefNum parameters are not touched, and the pb
+** parameter is initialized by PBHGetVInfoSync except that ioNamePtr in
+** the parameter block is always returned as NULL (since it might point
+** to the local tempPathname).
+**
+** I noticed using this code in several places, so here it is once.
+** This reduces the code size of MoreFiles.
+*/
+pascal OSErr GetVolumeInfoNoName(ConstStr255Param pathname,
+ short vRefNum,
+ HParmBlkPtr pb)
+{
+ Str255 tempPathname;
+ OSErr error;
+
+ /* Make sure pb parameter is not NULL */
+ if ( pb != NULL )
+ {
+ pb->volumeParam.ioVRefNum = vRefNum;
+ if ( pathname == NULL )
+ {
+ pb->volumeParam.ioNamePtr = NULL;
+ pb->volumeParam.ioVolIndex = 0; /* use ioVRefNum only */
+ }
+ else
+ { /* make a copy of the string and */
+ BlockMoveData(pathname, tempPathname, pathname[0] + 1);
+ /* use the copy so original isn't trashed */
+ pb->volumeParam.ioNamePtr = (StringPtr)tempPathname;
+ /* use ioNamePtr/ioVRefNum combination */
+ pb->volumeParam.ioVolIndex = -1;
+ }
+ error = PBHGetVInfoSync(pb);
+ pb->volumeParam.ioNamePtr = NULL; /* ioNamePtr may point to local
+ tempPathname, so don't return it */
+ }
+ else
+ {
+ error = paramErr;
+ }
+ return ( error );
+}
+
+
+
+
+/*****************************************************************************/
+
+pascal OSErr FSpGetFullPath(const FSSpec *spec,
+ short *fullPathLength,
+ Handle *fullPath)
+{
+ OSErr result;
+ OSErr realResult;
+ FSSpec tempSpec;
+ CInfoPBRec pb;
+
+ *fullPathLength = 0;
+ *fullPath = NULL;
+
+ /* Default to noErr */
+ realResult = noErr;
+
+ /* Make a copy of the input FSSpec that can be modified */
+ BlockMoveData(spec, &tempSpec, sizeof(FSSpec));
+
+ if ( tempSpec.parID == fsRtParID )
+ {
+ /* The object is a volume */
+
+ /* Add a colon to make it a full pathname */
+ ++tempSpec.name[0];
+ tempSpec.name[tempSpec.name[0]] = ':';
+
+ /* We're done */
+ result = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]);
+ }
+ else
+ {
+ /* The object isn't a volume */
+
+ /* Is the object a file or a directory? */
+ pb.dirInfo.ioNamePtr = tempSpec.name;
+ pb.dirInfo.ioVRefNum = tempSpec.vRefNum;
+ pb.dirInfo.ioDrDirID = tempSpec.parID;
+ pb.dirInfo.ioFDirIndex = 0;
+ result = PBGetCatInfoSync(&pb);
+ /* Allow file/directory name at end of path to not exist. */
+ realResult = result;
+ if ( (result == noErr) || (result == fnfErr) )
+ {
+ /* if the object is a directory, append a colon so full pathname
+ ends with colon */
+ if ( (result == noErr) && (pb.hFileInfo.ioFlAttrib & ioDirMask) != 0 )
+ {
+ ++tempSpec.name[0];
+ tempSpec.name[tempSpec.name[0]] = ':';
+ }
+
+ /* Put the object name in first */
+ result = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]);
+ if ( result == noErr )
+ {
+ /* Get the ancestor directory names */
+ pb.dirInfo.ioNamePtr = tempSpec.name;
+ pb.dirInfo.ioVRefNum = tempSpec.vRefNum;
+ pb.dirInfo.ioDrParID = tempSpec.parID;
+ do /* loop until we have an error or find the root directory */
+ {
+ pb.dirInfo.ioFDirIndex = -1;
+ pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrParID;
+ result = PBGetCatInfoSync(&pb);
+ if ( result == noErr )
+ {
+ /* Append colon to directory name */
+ ++tempSpec.name[0];
+ tempSpec.name[tempSpec.name[0]] = ':';
+
+ /* Add directory name to beginning of fullPath */
+ (void) Munger(*fullPath, 0, NULL, 0, &tempSpec.name[1],
+ tempSpec.name[0]);
+ result = MemError();
+ }
+ } while ( (result == noErr) && (pb.dirInfo.ioDrDirID != fsRtDirID) );
+ }
+ }
+ }
+ if ( result == noErr )
+ {
+ /* Return the length */
+ *fullPathLength = InlineGetHandleSize(*fullPath);
+ result = realResult; /* return realResult in case it was fnfErr */
+ }
+ else
+ {
+ /* Dispose of the handle and return NULL and zero length */
+ if ( *fullPath != NULL )
+ {
+ DisposeHandle(*fullPath);
+ }
+ *fullPath = NULL;
+ *fullPathLength = 0;
+ }
+
+ return ( result );
+}
+
+
+
+/*****************************************************************************/
+
+pascal OSErr FSpLocationFromFullPath(short fullPathLength,
+ const void *fullPath,
+ FSSpec *spec)
+{
+ AliasHandle alias;
+ OSErr result;
+ Boolean wasChanged;
+ Str32 nullString;
+
+ /* Create a minimal alias from the full pathname */
+ nullString[0] = 0; /* null string to indicate no zone or server name */
+ result = NewAliasMinimalFromFullPath(fullPathLength, fullPath, nullString,
+ nullString, &alias);
+
+ if ( result == noErr )
+ {
+ /* Let the Alias Manager resolve the alias. */
+ result = ResolveAlias(NULL, alias, spec, &wasChanged);
+
+ DisposeHandle((Handle)alias); /* Free up memory used */
+ }
+
+ return ( result );
+}
+
+
+
+/*****************************************************************************/
+
+pascal OSErr GetFullPath(short vRefNum,
+ long dirID,
+ ConstStr255Param name,
+ short *fullPathLength,
+ Handle *fullPath)
+{
+ OSErr result;
+ FSSpec spec;
+
+ *fullPathLength = 0;
+ *fullPath = NULL;
+
+ result = FSMakeFSSpecCompat(vRefNum, dirID, name, &spec);
+ if ( (result == noErr) || (result == fnfErr) )
+ {
+ result = FSpGetFullPath(&spec, fullPathLength, fullPath);
+ }
+
+ return ( result );
+}
+
+
+
+/*****************************************************************************/
+
+pascal OSErr ChangeCreatorType(short vRefNum,
+ long dirID,
+ ConstStr255Param name,
+ OSType creator,
+ OSType fileType)
+{
+ CInfoPBRec pb;
+ OSErr error;
+ short realVRefNum;
+ long parID;
+
+ pb.hFileInfo.ioNamePtr = (StringPtr)name;
+ pb.hFileInfo.ioVRefNum = vRefNum;
+ pb.hFileInfo.ioDirID = dirID;
+ pb.hFileInfo.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */
+ error = PBGetCatInfoSync(&pb);
+ if ( error == noErr )
+ {
+ if ( (pb.hFileInfo.ioFlAttrib & ioDirMask) == 0 ) /* if file */
+ { /* save parent dirID for BumpDate call */
+ parID = pb.hFileInfo.ioFlParID;
+
+ /* If creator not 0x00000000, change creator */
+ if ( creator != (OSType)0x00000000 )
+ {
+ pb.hFileInfo.ioFlFndrInfo.fdCreator = creator;
+ }
+
+ /* If fileType not 0x00000000, change fileType */
+ if ( fileType != (OSType)0x00000000 )
+ {
+ pb.hFileInfo.ioFlFndrInfo.fdType = fileType;
+ }
+
+ pb.hFileInfo.ioDirID = dirID;
+ error = PBSetCatInfoSync(&pb); /* now, save the new information
+ back to disk */
+
+ if ( (error == noErr) && (parID != fsRtParID) ) /* can't
+ bump fsRtParID */
+ {
+ /* get the real vRefNum in case a full pathname was passed */
+ error = DetermineVRefNum(name, vRefNum, &realVRefNum);
+ if ( error == noErr )
+ {
+ error = BumpDate(realVRefNum, parID, NULL);
+ /* and bump the parent directory's mod date to wake
+ up the Finder */
+ /* to the change we just made */
+ }
+ }
+ }
+ else
+ {
+ /* it was a directory, not a file */
+ error = notAFileErr;
+ }
+ }
+
+ return ( error );
+}
+
+/*****************************************************************************/
+
+pascal OSErr FSpChangeCreatorType(const FSSpec *spec,
+ OSType creator,
+ OSType fileType)
+{
+ return ( ChangeCreatorType(spec->vRefNum, spec->parID, spec->name,
+ creator, fileType) );
+}
+
+/*****************************************************************************/
+
+pascal OSErr BumpDate(short vRefNum,
+ long dirID,
+ ConstStr255Param name)
+/* Given a file or directory, change its modification date to the
+ current date/time. */
+{
+ CInfoPBRec pb;
+ Str31 tempName;
+ OSErr error;
+ unsigned long secs;
+
+ /* Protection against File Sharing problem */
+ if ( (name == NULL) || (name[0] == 0) )
+ {
+ tempName[0] = 0;
+ pb.hFileInfo.ioNamePtr = tempName;
+ pb.hFileInfo.ioFDirIndex = -1; /* use ioDirID */
+ }
+ else
+ {
+ pb.hFileInfo.ioNamePtr = (StringPtr)name;
+ pb.hFileInfo.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */
+ }
+ pb.hFileInfo.ioVRefNum = vRefNum;
+ pb.hFileInfo.ioDirID = dirID;
+ error = PBGetCatInfoSync(&pb);
+ if ( error == noErr )
+ {
+ GetDateTime(&secs);
+ /* set mod date to current date, or one second into the future
+ if mod date = current date */
+ pb.hFileInfo.ioFlMdDat =
+ (secs == pb.hFileInfo.ioFlMdDat) ? (++secs) : (secs);
+ if ( pb.dirInfo.ioNamePtr == tempName )
+ {
+ pb.hFileInfo.ioDirID = pb.hFileInfo.ioFlParID;
+ }
+ else
+ {
+ pb.hFileInfo.ioDirID = dirID;
+ }
+ error = PBSetCatInfoSync(&pb);
+ }
+
+ return ( error );
+}
+
+/*****************************************************************************/
+
+pascal OSErr FSpBumpDate(const FSSpec *spec)
+{
+ return ( BumpDate(spec->vRefNum, spec->parID, spec->name) );
+}
+
+
+/*****************************************************************************/
+
+pascal OSErr OnLine(FSSpecPtr volumes,
+ short reqVolCount,
+ short *actVolCount,
+ short *volIndex)
+{
+ HParamBlockRec pb;
+ OSErr error = noErr;
+ FSSpec *endVolArray;
+
+ if ( *volIndex > 0 )
+ {
+ *actVolCount = 0;
+ for ( endVolArray = volumes + reqVolCount;
+ (volumes < endVolArray) && (error == noErr); ++volumes )
+ {
+ pb.volumeParam.ioNamePtr = (StringPtr) & volumes->name;
+ pb.volumeParam.ioVolIndex = *volIndex;
+ error = PBHGetVInfoSync(&pb);
+ if ( error == noErr )
+ {
+ volumes->parID = fsRtParID; /* the root directory's
+ parent is 1 */
+ volumes->vRefNum = pb.volumeParam.ioVRefNum;
+ ++*volIndex;
+ ++*actVolCount;
+ }
+ }
+ }
+ else
+ {
+ error = paramErr;
+ }
+
+ return ( error );
+}
+
+
+/*****************************************************************************/
+
+pascal OSErr DTGetComment(short vRefNum,
+ long dirID,
+ ConstStr255Param name,
+ Str255 comment)
+{
+ DTPBRec pb;
+ OSErr error;
+ short dtRefNum;
+ Boolean newDTDatabase;
+
+ if (comment != NULL)
+ {
+ comment[0] = 0; /* return nothing by default */
+
+ /* attempt to open the desktop database */
+ error = DTOpen(name, vRefNum, &dtRefNum, &newDTDatabase);
+ if ( error == noErr )
+ {
+ /* There was a desktop database and it's now open */
+
+ if ( !newDTDatabase )
+ {
+ pb.ioDTRefNum = dtRefNum;
+ pb.ioNamePtr = (StringPtr)name;
+ pb.ioDirID = dirID;
+ pb.ioDTBuffer = (Ptr)&comment[1];
+ /*
+ ** IMPORTANT NOTE #1: Inside Macintosh says that comments
+ ** are up to 200 characters. While that may be correct for
+ ** the HFS file system's Desktop Manager, other file
+ ** systems (such as Apple Photo Access) return up to
+ ** 255 characters. Make sure the comment buffer is a Str255
+ ** or you'll regret it.
+ **
+ ** IMPORTANT NOTE #2: Although Inside Macintosh doesn't
+ ** mention it, ioDTReqCount is a input field to
+ ** PBDTGetCommentSync. Some file systems (like HFS) ignore
+ ** ioDTReqCount and always return the full comment --
+ ** others (like AppleShare) respect ioDTReqCount and only
+ ** return up to ioDTReqCount characters of the comment.
+ */
+ pb.ioDTReqCount = sizeof(Str255) - 1;
+ error = PBDTGetCommentSync(&pb);
+ if (error == noErr)
+ {
+ comment[0] = (unsigned char)pb.ioDTActCount;
+ }
+ }
+ }
+ else
+ {
+ /* There is no desktop database - try the Desktop file */
+ error = GetCommentFromDesktopFile(vRefNum, dirID, name, comment);
+ if ( error != noErr )
+ {
+ error = afpItemNotFound; /* return an expected error */
+ }
+ }
+ }
+ else
+ {
+ error = paramErr;
+ }
+
+ return (error);
+}
+
+/*****************************************************************************/
+
+pascal OSErr FSpDTGetComment(const FSSpec *spec,
+ Str255 comment)
+{
+ return (DTGetComment(spec->vRefNum, spec->parID, spec->name, comment));
+}
+
+
+/*****************************************************************************/
+
+pascal OSErr DTSetComment(short vRefNum,
+ long dirID,
+ ConstStr255Param name,
+ ConstStr255Param comment)
+{
+ DTPBRec pb;
+ OSErr error;
+ short dtRefNum;
+ Boolean newDTDatabase;
+
+ error = DTOpen(name, vRefNum, &dtRefNum, &newDTDatabase);
+ if ( error == noErr )
+ {
+ pb.ioDTRefNum = dtRefNum;
+ pb.ioNamePtr = (StringPtr)name;
+ pb.ioDirID = dirID;
+ pb.ioDTBuffer = (Ptr)&comment[1];
+ /* Truncate the comment to 200 characters just in case */
+ /* some file system doesn't range check */
+ if ( comment[0] <= 200 )
+ {
+ pb.ioDTReqCount = comment[0];
+ }
+ else
+ {
+ pb.ioDTReqCount = 200;
+ }
+ error = PBDTSetCommentSync(&pb);
+ }
+ return (error);
+}
+
+/*****************************************************************************/
+
+pascal OSErr FSpDTSetComment(const FSSpec *spec,
+ ConstStr255Param comment)
+{
+ return (DTSetComment(spec->vRefNum, spec->parID, spec->name, comment));
+}
+
+
+/*****************************************************************************/
+
+pascal OSErr DTOpen(ConstStr255Param volName,
+ short vRefNum,
+ short *dtRefNum,
+ Boolean *newDTDatabase)
+{
+ OSErr error;
+ GetVolParmsInfoBuffer volParmsInfo;
+ long infoSize;
+ DTPBRec pb;
+
+ /* Check for volume Desktop Manager support before calling */
+ infoSize = sizeof(GetVolParmsInfoBuffer);
+ error = HGetVolParms(volName, vRefNum, &volParmsInfo, &infoSize);
+ if ( error == noErr )
+ {
+ if ( hasDesktopMgr(volParmsInfo) )
+ {
+ pb.ioNamePtr = (StringPtr)volName;
+ pb.ioVRefNum = vRefNum;
+ error = PBDTOpenInform(&pb);
+ /* PBDTOpenInform informs us if the desktop was just created */
+ /* by leaving the low bit of ioTagInfo clear (0) */
+ *newDTDatabase = ((pb.ioTagInfo & 1L) == 0);
+ if ( error == paramErr )
+ {
+ error = PBDTGetPath(&pb);
+ /* PBDTGetPath doesn't tell us if the database is new */
+ /* so assume it is not new */
+ *newDTDatabase = false;
+ }
+ *dtRefNum = pb.ioDTRefNum;
+ }
+ else
+ {
+ error = paramErr;
+ }
+ }
+ return ( error );
+}
+
+/*****************************************************************************/
+
+/*
+** GetCommentFromDesktopFile
+**
+** Get a file or directory's Finder comment field (if any) from the
+** Desktop file's 'FCMT' resources.
+*/
+static OSErr GetCommentFromDesktopFile(short vRefNum,
+ long dirID,
+ ConstStr255Param name,
+ Str255 comment)
+{
+ OSErr error;
+ short commentID;
+ short realVRefNum;
+ Str255 desktopName;
+ short savedResFile;
+ short dfRefNum;
+ StringHandle commentHandle;
+
+ /* Get the comment ID number */
+ error = GetCommentID(vRefNum, dirID, name, &commentID);
+ if ( error == noErr )
+ {
+ if ( commentID != 0 ) /* commentID == 0 means there's no comment */
+ {
+ error = DetermineVRefNum(name, vRefNum, &realVRefNum);
+ if ( error == noErr )
+ {
+ error = GetDesktopFileName(realVRefNum, desktopName);
+ if ( error == noErr )
+ {
+ savedResFile = CurResFile();
+ /*
+ ** Open the 'Desktop' file in the root directory. (because
+ ** opening the resource file could preload unwanted resources,
+ ** bracket the call with SetResLoad(s))
+ */
+ SetResLoad(false);
+ dfRefNum = HOpenResFile(realVRefNum, fsRtDirID, desktopName,
+ fsRdPerm);
+ SetResLoad(true);
+
+ if ( dfRefNum != -1)
+ {
+ /* Get the comment resource */
+ commentHandle = (StringHandle)Get1Resource(kFCMTResType,
+ commentID);
+ if ( commentHandle != NULL )
+ {
+ if ( InlineGetHandleSize((Handle)commentHandle) > 0 )
+ {
+ BlockMoveData(*commentHandle, comment,
+ *commentHandle[0] + 1);
+ }
+ else
+ { /* no comment available */
+ error = afpItemNotFound;
+ }
+ }
+ else
+ { /* no comment available */
+ error = afpItemNotFound;
+ }
+
+ /* restore the resource chain and close
+ the Desktop file */
+ UseResFile(savedResFile);
+ CloseResFile(dfRefNum);
+ }
+ else
+ {
+ error = afpItemNotFound;
+ }
+ }
+ else
+ {
+ error = afpItemNotFound;
+ }
+ }
+ }
+ else
+ {
+ error = afpItemNotFound; /* no comment available */
+ }
+ }
+
+ return ( error );
+}
+
+/*****************************************************************************/
+
+pascal OSErr HGetVolParms(ConstStr255Param volName,
+ short vRefNum,
+ GetVolParmsInfoBuffer *volParmsInfo,
+ long *infoSize)
+{
+ HParamBlockRec pb;
+ OSErr error;
+
+ pb.ioParam.ioNamePtr = (StringPtr)volName;
+ pb.ioParam.ioVRefNum = vRefNum;
+ pb.ioParam.ioBuffer = (Ptr)volParmsInfo;
+ pb.ioParam.ioReqCount = *infoSize;
+ error = PBHGetVolParmsSync(&pb);
+ if ( error == noErr )
+ {
+ *infoSize = pb.ioParam.ioActCount;
+ }
+ return ( error );
+}
+
+/*****************************************************************************/
+/*
+** GetCommentID
+**
+** Get the comment ID number for the Desktop file's 'FCMT' resource ID from
+** the file or folders fdComment (frComment) field.
+*/
+static OSErr GetCommentID(short vRefNum,
+ long dirID,
+ ConstStr255Param name,
+ short *commentID)
+{
+ CInfoPBRec pb;
+ OSErr error;
+
+ error = GetCatInfoNoName(vRefNum, dirID, name, &pb);
+ *commentID = pb.hFileInfo.ioFlXFndrInfo.fdComment;
+ return ( error );
+}
+
+/*****************************************************************************/
+
+/*
+** GetDesktopFileName
+**
+** Get the name of the Desktop file.
+*/
+static OSErr GetDesktopFileName(short vRefNum,
+ Str255 desktopName)
+{
+ OSErr error;
+ HParamBlockRec pb;
+ short index;
+ Boolean found;
+
+ pb.fileParam.ioNamePtr = desktopName;
+ pb.fileParam.ioVRefNum = vRefNum;
+ pb.fileParam.ioFVersNum = 0;
+ index = 1;
+ found = false;
+ do
+ {
+ pb.fileParam.ioDirID = fsRtDirID;
+ pb.fileParam.ioFDirIndex = index;
+ error = PBHGetFInfoSync(&pb);
+ if ( error == noErr )
+ {
+ if ( (pb.fileParam.ioFlFndrInfo.fdType == 'FNDR') &&
+ (pb.fileParam.ioFlFndrInfo.fdCreator == 'ERIK') )
+ {
+ found = true;
+ }
+ }
+ ++index;
+ } while ( (error == noErr) && !found );
+
+ return ( error );
+}
+
+
+/*****************************************************************************/
+
+pascal OSErr XGetVInfo(short volReference,
+ StringPtr volName,
+ short *vRefNum,
+ UnsignedWide *freeBytes,
+ UnsignedWide *totalBytes)
+{
+ OSErr result;
+ long response;
+ XVolumeParam pb;
+
+ /* See if large volume support is available */
+ if ( ( Gestalt(gestaltFSAttr, &response) == noErr ) && ((response & (1L << gestaltFSSupports2TBVols)) != 0) )
+ {
+ /* Large volume support is available */
+ pb.ioVRefNum = volReference;
+ pb.ioNamePtr = volName;
+ pb.ioXVersion = 0; /* this XVolumeParam version (0) */
+ pb.ioVolIndex = 0; /* use ioVRefNum only, return volume name */
+ result = PBXGetVolInfoSync(&pb);
+ if ( result == noErr )
+ {
+ /* The volume name was returned in volName (if not NULL) and */
+ /* we have the volume's vRefNum and allocation block size */
+ *vRefNum = pb.ioVRefNum;
+
+ /* return the freeBytes and totalBytes */
+ *totalBytes = pb.ioVTotalBytes;
+ *freeBytes = pb.ioVFreeBytes;
+ }
+ }
+ else
+ {
+ /* No large volume support */
+
+ /* Use HGetVInfo to get the results */
+ result = HGetVInfo(volReference, volName, vRefNum, &freeBytes->lo, &totalBytes->lo);
+ if ( result == noErr )
+ {
+ /* zero the high longs of totalBytes and freeBytes */
+ totalBytes->hi = 0;
+ freeBytes->hi = 0;
+ }
+ }
+ return ( result );
+}
+
+
+
+/*****************************************************************************/
+
+pascal OSErr HGetVInfo(short volReference,
+ StringPtr volName,
+ short *vRefNum,
+ unsigned long *freeBytes,
+ unsigned long *totalBytes)
+{
+ HParamBlockRec pb;
+ unsigned long allocationBlockSize;
+ unsigned short numAllocationBlocks;
+ unsigned short numFreeBlocks;
+ VCB *theVCB;
+ Boolean vcbFound;
+ OSErr result;
+
+ /* Use the File Manager to get the real vRefNum */
+ pb.volumeParam.ioVRefNum = volReference;
+ pb.volumeParam.ioNamePtr = volName;
+ pb.volumeParam.ioVolIndex = 0; /* use ioVRefNum only, return volume name */
+ result = PBHGetVInfoSync(&pb);
+
+ if ( result == noErr )
+ {
+ /* The volume name was returned in volName (if not NULL) and */
+ /* we have the volume's vRefNum and allocation block size */
+ *vRefNum = pb.volumeParam.ioVRefNum;
+ allocationBlockSize = (unsigned long)pb.volumeParam.ioVAlBlkSiz;
+
+ /* System 7.5 (and beyond) pins the number of allocation blocks and */
+ /* the number of free allocation blocks returned by PBHGetVInfo to */
+ /* a value so that when multiplied by the allocation block size, */
+ /* the volume will look like it has $7fffffff bytes or less. This */
+ /* was done so older applications that use signed math or that use */
+ /* the GetVInfo function (which uses signed math) will continue to work. */
+ /* However, the unpinned numbers (which we want) are always available */
+ /* in the volume's VCB so we'll get those values from the VCB if possible. */
+
+ /* Find the volume's VCB */
+ vcbFound = false;
+ theVCB = (VCB *)(GetVCBQHdr()->qHead);
+ while ( (theVCB != NULL) && !vcbFound )
+ {
+ /* Check VCB signature before using VCB. Don't have to check for */
+ /* MFS (0xd2d7) because they can't get big enough to be pinned */
+ if ( theVCB->vcbSigWord == 0x4244 )
+ {
+ if ( theVCB->vcbVRefNum == *vRefNum )
+ {
+ vcbFound = true;
+ }
+ }
+
+ if ( !vcbFound )
+ {
+ theVCB = (VCB *)(theVCB->qLink);
+ }
+ }
+
+ if ( theVCB != NULL )
+ {
+ /* Found a VCB we can use. Get the un-pinned number of allocation blocks */
+ /* and the number of free blocks from the VCB. */
+ numAllocationBlocks = (unsigned short)theVCB->vcbNmAlBlks;
+ numFreeBlocks = (unsigned short)theVCB->vcbFreeBks;
+ }
+ else
+ {
+ /* Didn't find a VCB we can use. Return the number of allocation blocks */
+ /* and the number of free blocks returned by PBHGetVInfoSync. */
+ numAllocationBlocks = (unsigned short)pb.volumeParam.ioVNmAlBlks;
+ numFreeBlocks = (unsigned short)pb.volumeParam.ioVFrBlk;
+ }
+
+ /* Now, calculate freeBytes and totalBytes using unsigned values */
+ *freeBytes = numFreeBlocks * allocationBlockSize;
+ *totalBytes = numAllocationBlocks * allocationBlockSize;
+ }
+
+ return ( result );
+}
+
+
+/*
+** PBXGetVolInfoSync is the glue code needed to make PBXGetVolInfoSync
+** File Manager requests from CFM-based programs. At some point, Apple
+** will get around to adding this to the standard libraries you link with
+** and you'll get a duplicate symbol link error. At that time, just delete
+** this code (or comment it out).
+**
+** Non-CFM 68K programs don't needs this glue (and won't get it) because
+** they instead use the inline assembly glue found in the Files.h interface
+** file.
+*/
+
+#if __WANTPASCALELIMINATION
+#undef pascal
+#endif
+
+#if GENERATINGCFM
+pascal OSErr PBXGetVolInfoSync(XVolumeParamPtr paramBlock)
+{
+ enum
+ {
+ kXGetVolInfoSelector = 0x0012, /* Selector for XGetVolInfo */
+
+ uppFSDispatchProcInfo = kRegisterBased
+ | REGISTER_RESULT_LOCATION(kRegisterD0)
+ | RESULT_SIZE(SIZE_CODE(sizeof(OSErr)))
+ | REGISTER_ROUTINE_PARAMETER(1, kRegisterD1, SIZE_CODE(sizeof(long))) /* trap word */
+ | REGISTER_ROUTINE_PARAMETER(2, kRegisterD0, SIZE_CODE(sizeof(long))) /* selector */
+ | REGISTER_ROUTINE_PARAMETER(3, kRegisterA0, SIZE_CODE(sizeof(XVolumeParamPtr)))
+ };
+
+ return ( CallOSTrapUniversalProc(NGetTrapAddress(_FSDispatch, OSTrap),
+ uppFSDispatchProcInfo,
+ _FSDispatch,
+ kXGetVolInfoSelector,
+ paramBlock) );
+}
+#endif
+
+#if __WANTPASCALELIMINATION
+#define pascal
+#endif
+
+/*****************************************************************************/
+
+pascal OSErr GetDirName(short vRefNum,
+ long dirID,
+ Str31 name)
+{
+ CInfoPBRec pb;
+ OSErr error;
+
+ if ( name != NULL )
+ {
+ pb.dirInfo.ioNamePtr = name;
+ pb.dirInfo.ioVRefNum = vRefNum;
+ pb.dirInfo.ioDrDirID = dirID;
+ pb.dirInfo.ioFDirIndex = -1; /* get information about ioDirID */
+ error = PBGetCatInfoSync(&pb);
+ }
+ else
+ {
+ error = paramErr;
+ }
+
+ return ( error );
+}
+
+
+/*****************************************************************************/
+
+pascal OSErr GetVolFileSystemID(ConstStr255Param pathname,
+ short vRefNum,
+ short *fileSystemID)
+{
+ HParamBlockRec pb;
+ OSErr error;
+
+ error = GetVolumeInfoNoName(pathname,vRefNum, &pb);
+ if ( error == noErr )
+ {
+ *fileSystemID = pb.volumeParam.ioVFSID;
+ }
+
+ return ( error );
+}
+
+/*****************************************************************************/
+
+pascal OSErr GetDInfo(short vRefNum,
+ long dirID,
+ ConstStr255Param name,
+ DInfo *fndrInfo)
+{
+ CInfoPBRec pb;
+ OSErr error;
+
+ error = GetCatInfoNoName(vRefNum, dirID, name, &pb);
+ if ( error == noErr )
+ {
+ if ( (pb.dirInfo.ioFlAttrib & ioDirMask) != 0 )
+ {
+ /* it's a directory, return the DInfo */
+ *fndrInfo = pb.dirInfo.ioDrUsrWds;
+ }
+ else
+ {
+ /* oops, a file was passed */
+ error = dirNFErr;
+ }
+ }
+
+ return ( error );
+}
+
+/*****************************************************************************/
+
+pascal OSErr FSpGetDInfo(const FSSpec *spec,
+ DInfo *fndrInfo)
+{
+ return ( GetDInfo(spec->vRefNum, spec->parID, spec->name, fndrInfo) );
+}
+
+
diff --git a/macos/source/macstuff.h b/macos/source/macstuff.h
new file mode 100644
index 0000000..27c481d
--- /dev/null
+++ b/macos/source/macstuff.h
@@ -0,0 +1,1108 @@
+#ifndef _MACSTUFF_H
+#define _MACSTUFF_H 1
+
+/*
+These Functions were originally part of More Files version 1.4.8
+
+More Files fixes many of the broken or underfunctional
+parts of the file system.
+
+More Files
+
+A collection of File Manager and related routines
+
+by Jim Luther (Apple Macintosh Developer Technical Support Emeritus)
+with significant code contributions by Nitin Ganatra
+(Apple Macintosh Developer Technical Support Emeritus)
+Copyright 1992-1998 Apple Computer, Inc.
+Portions copyright 1995 Jim Luther
+All rights reserved.
+
+The Package "More Files" is distributed under the following
+license terms:
+
+ "You may incorporate this sample code into your
+ applications without restriction, though the
+ sample code has been provided "AS IS" and the
+ responsibility for its operation is 100% yours.
+ However, what you are not permitted to do is to
+ redistribute the source as "DSC Sample Code" after
+ having made changes. If you're going to
+ redistribute the source, we require that you make
+ it clear in the source that the code was descended
+ from Apple Sample Code, but that you've made
+ changes."
+
+
+The following changes are made by Info-ZIP:
+
+- The only changes are made by pasting the functions
+ (mostly found in MoreFilesExtras.c / MoreFiles.c)
+ directly into macstuff.c / macstuff.h and slightly
+ reformatting the text (replacement of TABs by spaces,
+ removal/replacement of non-ASCII characters).
+ The code itself is NOT changed.
+
+This file has been modified by Info-ZIP for use in MacZip.
+This file is NOT part of the original package More Files.
+
+More Files can be found on the MetroWerks CD and Developer CD from
+Apple. You can also download the latest version from:
+
+ http://members.aol.com/JumpLong/#MoreFiles
+
+Jim Luther's Home-page:
+ http://members.aol.com/JumpLong/
+
+
+*/
+
+
+#define __MACOSSEVENFIVEONEORLATER 1
+#define __MACOSSEVENFIVEORLATER 1
+#define __MACOSSEVENORLATER 1
+
+#include <Errors.h>
+#include <Files.h>
+
+
+/*
+ * Like the MoreFiles routines these fix problems in the standard
+ * Mac calls.
+ */
+
+int FSpLocationFromPath (int length,const char *path, FSSpecPtr theSpec);
+OSErr FSpPathFromLocation (FSSpecPtr theSpec,int *length, Handle *fullPath);
+
+#define hasDesktopMgr(volParms) (((volParms).vMAttrib & (1L << bHasDesktopMgr)) != 0)
+
+/*
+ * The following routines are utility functions. They are exported
+ * here because they are needed and they are not officially supported,
+ * however. The first set are from the MoreFiles package.
+ */
+int FSpGetDefaultDir (FSSpecPtr theSpec);
+int FSpSetDefaultDir (FSSpecPtr dirSpec);
+pascal OSErr FSpGetDirectoryID(const FSSpec *spec,long *theDirID,
+ Boolean *isDirectory);
+pascal short FSpOpenResFileCompat(const FSSpec *spec, SignedByte permission);
+pascal void FSpCreateResFileCompat(const FSSpec *spec,OSType creator,
+ OSType fileType,
+ ScriptCode scriptTag);
+OSErr FSpFindFolder (short vRefNum, OSType folderType,
+ Boolean createFolder,
+ FSSpec *spec);
+
+/*****************************************************************************/
+
+pascal OSErr GetVolumeInfoNoName(ConstStr255Param pathname,
+ short vRefNum,
+ HParmBlkPtr pb);
+/* Call PBHGetVInfoSync ignoring returned name.
+ GetVolumeInfoNoName uses pathname and vRefNum to call PBHGetVInfoSync
+ in cases where the returned volume name is not needed by the caller.
+ The pathname and vRefNum parameters are not touched, and the pb
+ parameter is initialized by PBHGetVInfoSync except that ioNamePtr in
+ the parameter block is always returned as NULL (since it might point
+ to GetVolumeInfoNoName's local variable tempPathname).
+
+ I noticed using this code in several places, so here it is once.
+ This reduces the code size of MoreFiles.
+
+ pathName input: Pointer to a full pathname or nil. If you pass in a
+ partial pathname, it is ignored. A full pathname to a
+ volume must end with a colon character (:).
+ vRefNum input: Volume specification (volume reference number, working
+ directory number, drive number, or 0).
+ pb input: A pointer to HParamBlockRec.
+ output: The parameter block as filled in by PBHGetVInfoSync
+ except that ioNamePtr will always be NULL.
+
+ Result Codes
+ noErr 0 No error
+ nsvErr -35 No such volume
+ paramErr -50 No default volume, or pb was NULL
+*/
+
+
+/*****************************************************************************/
+
+pascal OSErr GetFilenameFromPathname(ConstStr255Param pathname,
+ Str255 filename);
+/* Get the object name from the end of a full or partial pathname.
+ The GetFilenameFromPathname function gets the file (or directory) name
+ from the end of a full or partial pathname. Returns notAFileErr if the
+ pathname is nil, the pathname is empty, or the pathname cannot refer to
+ a filename (with a noErr result, the pathname could still refer to a
+ directory).
+
+ pathname input: A full or partial pathname.
+ filename output: The file (or directory) name.
+
+ Result Codes
+ noErr 0 No error
+ notAFileErr -1302 The pathname is nil, the pathname
+ is empty, or the pathname cannot refer
+ to a filename
+
+ __________
+
+ See also: GetObjectLocation.
+*/
+
+
+
+/*****************************************************************************/
+
+pascal OSErr FSMakeFSSpecCompat(short vRefNum, long dirID,
+ ConstStr255Param fileName,
+ FSSpec *spec);
+/* Initialize a FSSpec record.
+ The FSMakeFSSpecCompat function fills in the fields of an FSSpec record.
+ If the file system can't create the FSSpec, then the compatibility code
+ creates a FSSpec that is exactly like an FSSpec except that spec.name
+ for a file may not have the same capitalization as the file's catalog
+ entry on the disk volume. That is because fileName is parsed to get the
+ name instead of getting the name back from the file system. This works
+ fine with System 6 where FSMakeSpec isn't available.
+
+ vRefNum input: Volume specification.
+ dirID input: Directory ID.
+ fileName input: Pointer to object name, or nil when dirID specifies
+ a directory that's the object.
+ spec output: A file system specification to be filled in by
+ FSMakeFSSpecCompat.
+
+ Result Codes
+ noErr 0 No error
+ nsvErr -35 Volume doesnt exist
+ fnfErr -43 File or directory does not exist
+ (FSSpec is still valid)
+*/
+
+
+#if !SystemSevenOrLater
+static Boolean FSHasFSSpecCalls(void);
+
+static Boolean QTHasFSSpecCalls(void);
+#endif /* !SystemSevenOrLater */
+
+
+
+/*****************************************************************************/
+
+pascal OSErr GetObjectLocation(short vRefNum,
+ long dirID,
+ ConstStr255Param pathname,
+ short *realVRefNum,
+ long *realParID,
+ Str255 realName,
+ Boolean *isDirectory);
+/* Get a file system object's location.
+ The GetObjectLocation function gets a file system object's location -
+ that is, its real volume reference number, real parent directory ID,
+ and name. While we're at it, determine if the object is a file or directory.
+ If GetObjectLocation returns fnfErr, then the location information
+ returned is valid, but it describes an object that doesn't exist.
+ You can use the location information for another operation, such as
+ creating a file or directory.
+
+ vRefNum input: Volume specification.
+ dirID input: Directory ID.
+ pathname input: Pointer to object name, or nil when dirID specifies
+ a directory that's the object.
+ realVRefNum output: The real volume reference number.
+ realParID output: The parent directory ID of the specified object.
+ realName output: The name of the specified object (the case of the
+ object name may not be the same as the object's
+ catalog entry on disk - since the Macintosh file
+ system is not case sensitive, it shouldn't matter).
+ isDirectory output: True if object is a directory; false if object
+ is a file.
+
+ Result Codes
+ noErr 0 No error
+ nsvErr -35 No such volume
+ ioErr -36 I/O error
+ bdNamErr -37 Bad filename
+ fnfErr -43 File not found
+ paramErr -50 No default volume
+ dirNFErr -120 Directory not found or incomplete pathname
+ notAFileErr -1302 The pathname is nil, the pathname
+ is empty, or the pathname cannot refer
+ to a filename
+ afpAccessDenied -5000 User does not have the correct access
+ afpObjectTypeErr -5025 Directory not found or incomplete pathname
+
+ __________
+
+ See also: FSMakeFSSpecCompat
+*/
+
+pascal OSErr FSpGetDirectoryID(const FSSpec *spec, long *theDirID,
+ Boolean *isDirectory);
+
+pascal OSErr GetDirectoryID(short vRefNum,long dirID,ConstStr255Param name,
+ long *theDirID,Boolean *isDirectory);
+
+
+
+/*****************************************************************************/
+
+pascal OSErr GetCatInfoNoName(short vRefNum,
+ long dirID,
+ ConstStr255Param name,
+ CInfoPBPtr pb);
+/* Call PBGetCatInfoSync ignoring returned name.
+ GetCatInfoNoName uses vRefNum, dirID and name to call PBGetCatInfoSync
+ in cases where the returned object is not needed by the caller.
+ The vRefNum, dirID and name parameters are not touched, and the pb
+ parameter is initialized by PBGetCatInfoSync except that ioNamePtr in
+ the parameter block is always returned as NULL (since it might point
+ to GetCatInfoNoName's local variable tempName).
+
+ I noticed using this code in several places, so here it is once.
+ This reduces the code size of MoreFiles.
+
+ vRefNum input: Volume specification.
+ dirID input: Directory ID.
+ name input: Pointer to object name, or nil when dirID
+ specifies a directory that's the object.
+ pb input: A pointer to CInfoPBRec.
+ output: The parameter block as filled in by
+ PBGetCatInfoSync except that ioNamePtr will
+ always be NULL.
+
+ Result Codes
+ noErr 0 No error
+ nsvErr -35 No such volume
+ ioErr -36 I/O error
+ bdNamErr -37 Bad filename
+ fnfErr -43 File not found
+ paramErr -50 No default volume
+ dirNFErr -120 Directory not found or incomplete pathname
+ afpAccessDenied -5000 User does not have the correct access
+ afpObjectTypeErr -5025 Directory not found or incomplete pathname
+
+*/
+
+
+/*****************************************************************************/
+
+
+pascal OSErr DetermineVRefNum(ConstStr255Param pathname,
+ short vRefNum,
+ short *realVRefNum);
+/* Determine the real volume reference number.
+ The DetermineVRefNum function determines the volume reference number of
+ a volume from a pathname, a volume specification, or a combination
+ of the two.
+ WARNING: Volume names on the Macintosh are *not* unique -- Multiple
+ mounted volumes can have the same name. For this reason, the use of a
+ volume name or full pathname to identify a specific volume may not
+ produce the results you expect. If more than one volume has the same
+ name and a volume name or full pathname is used, the File Manager
+ currently uses the first volume it finds with a matching name in the
+ volume queue.
+
+ pathName input: Pointer to a full pathname or nil. If you pass in a
+ partial pathname, it is ignored. A full pathname to a
+ volume must end with a colon character (:).
+ vRefNum input: Volume specification (volume reference number, working
+ directory number, drive number, or 0).
+ realVRefNum output: The real volume reference number.
+
+ Result Codes
+ noErr 0 No error
+ nsvErr -35 No such volume
+ paramErr -50 No default volume
+*/
+
+
+/*****************************************************************************/
+
+pascal OSErr FSpGetFullPath(const FSSpec *spec,
+ short *fullPathLength,
+ Handle *fullPath);
+/* Get a full pathname to a volume, directory or file.
+ The GetFullPath function builds a full pathname to the specified
+ object. The full pathname is returned in the newly created handle
+ fullPath and the length of the full pathname is returned in
+ fullPathLength. Your program is responsible for disposing of the
+ fullPath handle.
+
+ spec input: An FSSpec record specifying the object.
+ fullPathLength output: The number of characters in the full pathname.
+ If the function fails to create a full pathname,
+ it sets fullPathLength to 0.
+ fullPath output: A handle to the newly created full pathname
+ buffer. If the function fails to create a
+ full pathname, it sets fullPath to NULL.
+
+ Result Codes
+ noErr 0 No error
+ nsvErr -35 No such volume
+ ioErr -36 I/O error
+ bdNamErr -37 Bad filename
+ fnfErr -43 File or directory does not exist
+ paramErr -50 No default volume
+ memFullErr -108 Not enough memory
+ dirNFErr -120 Directory not found or incomplete pathname
+ afpAccessDenied -5000 User does not have the correct access
+ afpObjectTypeErr -5025 Directory not found or incomplete pathname
+
+ __________
+
+ See also: GetFullPath
+*/
+
+/*****************************************************************************/
+
+pascal OSErr FSpLocationFromFullPath(short fullPathLength,
+ const void *fullPath,
+ FSSpec *spec);
+/* Get a FSSpec from a full pathname.
+ The FSpLocationFromFullPath function returns a FSSpec to the object
+ specified by full pathname. This function requires the Alias Manager.
+
+ fullPathLength input: The number of characters in the full pathname
+ of the target.
+ fullPath input: A pointer to a buffer that contains the full
+ pathname of the target. The full pathname
+ starts with the name of the volume, includes
+ all of the directory names in the path to the
+ target, and ends with the target name.
+ spec output: An FSSpec record specifying the object.
+
+ Result Codes
+ noErr 0 No error
+ nsvErr -35 The volume is not mounted
+ fnfErr -43 Target not found, but volume and parent
+ directory found
+ paramErr -50 Parameter error
+ usrCanceledErr -128 The user canceled the operation
+
+ __________
+
+ See also: LocationFromFullPath
+*/
+
+
+/*****************************************************************************/
+
+pascal OSErr GetFullPath(short vRefNum,
+ long dirID,
+ ConstStr255Param name,
+ short *fullPathLength,
+ Handle *fullPath);
+/* Get a full pathname to a volume, directory or file.
+ The GetFullPath function builds a full pathname to the specified
+ object. The full pathname is returned in the newly created handle
+ fullPath and the length of the full pathname is returned in
+ fullPathLength. Your program is responsible for disposing of the
+ fullPath handle.
+
+ Note that a full pathname can be made to a file/directory that does not
+ yet exist if all directories up to that file/directory exist. In this case,
+ GetFullPath will return a fnfErr.
+
+ vRefNum input: Volume specification.
+ dirID input: Directory ID.
+ name input: Pointer to object name, or nil when dirID
+ specifies a directory that's the object.
+ fullPathLength output: The number of characters in the full pathname.
+ If the function fails to create a full
+ pathname, it sets fullPathLength to 0.
+ fullPath output: A handle to the newly created full pathname
+ buffer. If the function fails to create a
+ full pathname, it sets fullPath to NULL.
+
+ Result Codes
+ noErr 0 No error
+ nsvErr -35 No such volume
+ ioErr -36 I/O error
+ bdNamErr -37 Bad filename
+ fnfErr -43 File or directory does not exist (fullPath
+ and fullPathLength are still valid)
+ paramErr -50 No default volume
+ memFullErr -108 Not enough memory
+ dirNFErr -120 Directory not found or incomplete pathname
+ afpAccessDenied -5000 User does not have the correct access
+ afpObjectTypeErr -5025 Directory not found or incomplete pathname
+
+ __________
+
+ See also: FSpGetFullPath
+*/
+
+
+
+/*****************************************************************************/
+
+pascal OSErr ChangeCreatorType(short vRefNum,
+ long dirID,
+ ConstStr255Param name,
+ OSType creator,
+ OSType fileType);
+/* Change the creator or file type of a file.
+ The ChangeCreatorType function changes the creator or file type of a file.
+
+ vRefNum input: Volume specification.
+ dirID input: Directory ID.
+ name input: The name of the file.
+ creator input: The new creator type or 0x00000000 to leave
+ the creator type alone.
+ fileType input: The new file type or 0x00000000 to leave the
+ file type alone.
+
+ Result Codes
+ noErr 0 No error
+ nsvErr -35 No such volume
+ ioErr -36 I/O error
+ bdNamErr -37 Bad filename
+ fnfErr -43 File not found
+ fLckdErr -45 File is locked
+ vLckdErr -46 Volume is locked or read-only
+ paramErr -50 No default volume
+ dirNFErr -120 Directory not found or incomplete pathname
+ notAFileErr -1302 Name was not a file
+ afpAccessDenied -5000 User does not have the correct access
+ afpObjectTypeErr -5025 Directory not found or incomplete pathname
+
+ __________
+
+ See also: FSpChangeCreatorType
+*/
+
+/*****************************************************************************/
+
+pascal OSErr FSpChangeCreatorType(const FSSpec *spec,
+ OSType creator,
+ OSType fileType);
+/* Change the creator or file type of a file.
+ The FSpChangeCreatorType function changes the creator or file type of a file.
+
+ spec input: An FSSpec record specifying the file.
+ creator input: The new creator type or 0x00000000 to leave
+ the creator type alone.
+ fileType input: The new file type or 0x00000000 to leave the
+ file type alone.
+
+ Result Codes
+ noErr 0 No error
+ nsvErr -35 No such volume
+ ioErr -36 I/O error
+ bdNamErr -37 Bad filename
+ fnfErr -43 File not found
+ fLckdErr -45 File is locked
+ vLckdErr -46 Volume is locked or read-only
+ paramErr -50 No default volume
+ dirNFErr -120 Directory not found or incomplete pathname
+ notAFileErr -1302 Name was not a file
+ afpAccessDenied -5000 User does not have the correct access
+ afpObjectTypeErr -5025 Directory not found or incomplete pathname
+
+ __________
+
+ See also: ChangeCreatorType
+*/
+
+
+/*****************************************************************************/
+
+pascal OSErr BumpDate(short vRefNum,
+ long dirID,
+ ConstStr255Param name);
+/* Update the modification date of a file or directory.
+ The BumpDate function changes the modification date of a file or
+ directory to the current date/time. If the modification date is already
+ equal to the current date/time, then add one second to the
+ modification date.
+
+ vRefNum input: Volume specification.
+ dirID input: Directory ID.
+ name input: Pointer to object name, or nil when dirID specifies
+ a directory that's the object.
+
+ Result Codes
+ noErr 0 No error
+ nsvErr -35 No such volume
+ ioErr -36 I/O error
+ bdNamErr -37 Bad filename
+ fnfErr -43 File not found
+ fLckdErr -45 File is locked
+ vLckdErr -46 Volume is locked or read-only
+ paramErr -50 No default volume
+ dirNFErr -120 Directory not found or incomplete pathname
+ afpAccessDenied -5000 User does not have the correct access
+ afpObjectTypeErr -5025 Directory not found or incomplete pathname
+
+ __________
+
+ See also: FSpBumpDate
+*/
+
+/*****************************************************************************/
+
+pascal OSErr FSpBumpDate(const FSSpec *spec);
+/* Update the modification date of a file or directory.
+ The FSpBumpDate function changes the modification date of a file or
+ directory to the current date/time. If the modification date is already
+ equal to the current date/time, then add one second to the
+ modification date.
+
+ spec input: An FSSpec record specifying the object.
+
+ Result Codes
+ noErr 0 No error
+ nsvErr -35 No such volume
+ ioErr -36 I/O error
+ bdNamErr -37 Bad filename
+ fnfErr -43 File not found
+ fLckdErr -45 File is locked
+ vLckdErr -46 Volume is locked or read-only
+ paramErr -50 No default volume
+ dirNFErr -120 Directory not found or incomplete pathname
+ afpAccessDenied -5000 User does not have the correct access
+ afpObjectTypeErr -5025 Directory not found or incomplete pathname
+
+ __________
+
+ See also: BumpDate
+*/
+
+/*****************************************************************************/
+
+pascal OSErr OnLine(FSSpecPtr volumes,
+ short reqVolCount,
+ short *actVolCount,
+ short *volIndex);
+/* Return the list of volumes currently mounted.
+ The OnLine function returns the list of volumes currently mounted in
+ an array of FSSpec records.
+
+ A noErr result indicates that the volumes array was filled
+ (actVolCount == reqVolCount) and there may be additional volumes
+ mounted. A nsvErr result indicates that the end of the volume list
+ was found and actVolCount volumes were actually found this time.
+
+ volumes input: Pointer to array of FSSpec where the volume list
+ is returned.
+ reqVolCount input: Maximum number of volumes to return (the number of
+ elements in the volumes array).
+ actVolCount output: The number of volumes actually returned.
+ volIndex input: The current volume index position. Set to 1 to
+ start with the first volume.
+ output: The volume index position to get the next volume.
+ Pass this value the next time you call OnLine to
+ start where you left off.
+
+ Result Codes
+ noErr 0 No error, but there are more volumes
+ to list
+ nsvErr -35 No more volumes to be listed
+ paramErr -50 volIndex was <= 0
+*/
+
+/*****************************************************************************/
+
+pascal OSErr DTGetComment(short vRefNum,
+ long dirID,
+ ConstStr255Param name,
+ Str255 comment);
+/* Get a file or directory's Finder comment field (if any).
+ The DTGetComment function gets a file or directory's Finder comment
+ field (if any) from the Desktop Manager or if the Desktop Manager is
+ not available, from the Finder's Desktop file.
+
+ IMPORTANT NOTE: Inside Macintosh says that comments are up to
+ 200 characters. While that may be correct for the HFS file system's
+ Desktop Manager, other file systems (such as Apple Photo Access) return
+ up to 255 characters. Make sure the comment buffer is a Str255 or you'll
+ regret it.
+
+ vRefNum input: Volume specification.
+ dirID input: Directory ID.
+ name input: Pointer to object name, or nil when dirID
+ specifies a directory that's the object.
+ comment output: A Str255 where the comment is to be returned.
+
+ Result Codes
+ noErr 0 No error
+ nsvErr -35 Volume not found
+ ioErr -36 I/O error
+ fnfErr -43 File not found
+ paramErr -50 Volume doesn't support this function
+ rfNumErr -51 Reference number invalid
+ extFSErr -58 External file system error - no file
+ system claimed this call.
+ desktopDamagedErr -1305 The desktop database has become corrupted -
+ the Finder will fix this, but if your
+ application is not running with the
+ Finder, use PBDTReset or PBDTDelete
+ afpItemNotFound -5012 Information not found
+
+ __________
+
+ Also see: DTCopyComment, FSpDTCopyComment, DTSetComment, FSpDTSetComment,
+ FSpDTGetComment
+*/
+
+/*****************************************************************************/
+
+pascal OSErr FSpDTGetComment(const FSSpec *spec,
+ Str255 comment);
+/* Get a file or directory's Finder comment field (if any).
+ The FSpDTGetComment function gets a file or directory's Finder comment
+ field (if any) from the Desktop Manager or if the Desktop Manager is
+ not available, from the Finder's Desktop file.
+
+ IMPORTANT NOTE: Inside Macintosh says that comments are up to
+ 200 characters. While that may be correct for the HFS file system's
+ Desktop Manager, other file systems (such as Apple Photo Access) return
+ up to 255 characters. Make sure the comment buffer is a Str255 or you'll
+ regret it.
+
+ spec input: An FSSpec record specifying the file or directory.
+ comment output: A Str255 where the comment is to be returned.
+
+ Result Codes
+ noErr 0 No error
+ nsvErr -35 Volume not found
+ ioErr -36 I/O error
+ fnfErr -43 File not found
+ paramErr -50 Volume doesn't support this function
+ rfNumErr -51 Reference number invalid
+ extFSErr -58 External file system error - no file
+ system claimed this call.
+ desktopDamagedErr -1305 The desktop database has become corrupted -
+ the Finder will fix this, but if your
+ application is not running with the
+ Finder, use PBDTReset or PBDTDelete
+ afpItemNotFound -5012 Information not found
+
+ __________
+
+ Also see: DTCopyComment, FSpDTCopyComment, DTSetComment, FSpDTSetComment,
+ DTGetComment
+*/
+
+/*****************************************************************************/
+
+pascal OSErr DTOpen(ConstStr255Param volName,
+ short vRefNum,
+ short *dtRefNum,
+ Boolean *newDTDatabase);
+/* Open a volume's desktop database and return the desktop database refNum.
+ The DTOpen function opens a volume's desktop database. It returns
+ the reference number of the desktop database and indicates if the
+ desktop database was created as a result of this call (if it was created,
+ then it is empty).
+
+ volName input: A pointer to the name of a mounted volume
+ or nil.
+ vRefNum input: Volume specification.
+ dtRefNum output: The reference number of Desktop Manager's
+ desktop database on the specified volume.
+ newDTDatabase output: true if the desktop database was created as a
+ result of this call and thus empty.
+ false if the desktop database was already created,
+ or if it could not be determined if it was already
+ created.
+
+ Result Codes
+ noErr 0 No error
+ nsvErr -35 Volume not found
+ ioErr -36 I/O error
+ paramErr -50 Volume doesn't support this function
+ extFSErr -58 External file system error - no file
+ system claimed this call.
+ desktopDamagedErr -1305 The desktop database has become corrupted -
+ the Finder will fix this, but if your
+ application is not running with the
+ Finder, use PBDTReset or PBDTDelete
+*/
+
+/*****************************************************************************/
+
+pascal OSErr HGetVolParms(ConstStr255Param volName,
+ short vRefNum,
+ GetVolParmsInfoBuffer *volParmsInfo,
+ long *infoSize);
+/* Determine the characteristics of a volume.
+ The HGetVolParms function returns information about the characteristics
+ of a volume. A result of paramErr usually just means the volume doesn't
+ support PBHGetVolParms and the feature you were going to check
+ for isn't available.
+
+ volName input: A pointer to the name of a mounted volume
+ or nil.
+ vRefNum input: Volume specification.
+ volParmsInfo input: Pointer to GetVolParmsInfoBuffer where the
+ volume attributes information is returned.
+ output: Atributes information.
+ infoSize input: Size of buffer pointed to by volParmsInfo.
+ output: Size of data actually returned.
+
+ Result Codes
+ noErr 0 No error
+ nsvErr -35 Volume not found
+ paramErr -50 Volume doesn't support this function
+
+ __________
+
+ Also see the macros for checking attribute bits in MoreFilesExtras.h
+*/
+
+/*****************************************************************************/
+
+pascal OSErr DeleteDirectoryContents(short vRefNum,
+ long dirID,
+ ConstStr255Param name);
+/* Delete the contents of a directory.
+ The DeleteDirectoryContents function deletes the contents of a directory.
+ All files and subdirectories in the specified directory are deleted.
+ If a locked file or directory is encountered, it is unlocked and then
+ deleted. If any unexpected errors are encountered,
+ DeleteDirectoryContents quits and returns to the caller.
+
+ vRefNum input: Volume specification.
+ dirID input: Directory ID.
+ name input: Pointer to directory name, or nil when dirID specifies
+ a directory that's the object.
+
+ Result Codes
+ noErr 0 No error
+ nsvErr -35 No such volume
+ ioErr -36 I/O error
+ bdNamErr -37 Bad filename
+ fnfErr -43 File not found
+ wPrErr -44 Hardware volume lock
+ fLckdErr -45 File is locked
+ vLckdErr -46 Software volume lock
+ fBsyErr -47 File busy, directory not empty, or working
+ directory control block open
+ paramErr -50 No default volume
+ dirNFErr -120 Directory not found or incomplete pathname
+ afpAccessDenied -5000 User does not have the correct access
+ afpObjectTypeErr -5025 Directory not found or incomplete pathname
+
+ __________
+
+ Also see: DeleteDirectory
+*/
+
+/*****************************************************************************/
+
+pascal OSErr DeleteDirectory(short vRefNum,
+ long dirID,
+ ConstStr255Param name);
+/* Delete a directory and its contents.
+ The DeleteDirectory function deletes a directory and its contents.
+ All files and subdirectories in the specified directory are deleted.
+ If a locked file or directory is encountered, it is unlocked and then
+ deleted. After deleting the directories contents, the directory is
+ deleted. If any unexpected errors are encountered, DeleteDirectory
+ quits and returns to the caller.
+
+ vRefNum input: Volume specification.
+ dirID input: Directory ID.
+ name input: Pointer to directory name, or nil when dirID specifies
+ a directory that's the object.
+
+ Result Codes
+ noErr 0 No error
+ nsvErr -35 No such volume
+ ioErr -36 I/O error
+ bdNamErr -37 Bad filename
+ fnfErr -43 File not found
+ wPrErr -44 Hardware volume lock
+ fLckdErr -45 File is locked
+ vLckdErr -46 Software volume lock
+ fBsyErr -47 File busy, directory not empty, or working
+ directory control block open
+ paramErr -50 No default volume
+ dirNFErr -120 Directory not found or incomplete pathname
+ afpAccessDenied -5000 User does not have the correct access
+ afpObjectTypeErr -5025 Directory not found or incomplete pathname
+
+ __________
+
+ Also see: DeleteDirectoryContents
+*/
+
+/*****************************************************************************/
+
+pascal OSErr DTSetComment(short vRefNum,
+ long dirID,
+ ConstStr255Param name,
+ ConstStr255Param comment);
+/* Set a file or directory's Finder comment field.
+ The DTSetComment function sets a file or directory's Finder comment
+ field. The volume must support the Desktop Manager because you only
+ have read access to the Desktop file.
+
+ vRefNum input: Volume specification.
+ dirID input: Directory ID.
+ name input: Pointer to object name, or nil when dirID
+ specifies a directory that's the object.
+ comment input: The comment to add. Comments are limited to 200 characters;
+ longer comments are truncated.
+
+ Result Codes
+ noErr 0 No error
+ nsvErr -35 Volume not found
+ ioErr -36 I/O error
+ fnfErr -43 File or directory doesnt exist
+ paramErr -50 Volume doesn't support this function
+ wPrErr -44 Volume is locked through hardware
+ vLckdErr -46 Volume is locked through software
+ rfNumErr -51 Reference number invalid
+ extFSErr -58 External file system error - no file
+ system claimed this call.
+ desktopDamagedErr -1305 The desktop database has become corrupted -
+ the Finder will fix this, but if your
+ application is not running with the
+ Finder, use PBDTReset or PBDTDelete
+
+ __________
+
+ Also see: DTCopyComment, FSpDTCopyComment, FSpDTSetComment, DTGetComment,
+ FSpDTGetComment
+*/
+
+/*****************************************************************************/
+
+pascal OSErr FSpDTSetComment(const FSSpec *spec,
+ ConstStr255Param comment);
+/* Set a file or directory's Finder comment field.
+ The FSpDTSetComment function sets a file or directory's Finder comment
+ field. The volume must support the Desktop Manager because you only
+ have read access to the Desktop file.
+
+ spec input: An FSSpec record specifying the file or directory.
+ comment input: The comment to add. Comments are limited to 200 characters;
+ longer comments are truncated.
+
+ Result Codes
+ noErr 0 No error
+ nsvErr -35 Volume not found
+ ioErr -36 I/O error
+ fnfErr -43 File or directory doesnt exist
+ wPrErr -44 Volume is locked through hardware
+ vLckdErr -46 Volume is locked through software
+ rfNumErr -51 Reference number invalid
+ paramErr -50 Volume doesn't support this function
+ extFSErr -58 External file system error - no file
+ system claimed this call.
+ desktopDamagedErr -1305 The desktop database has become corrupted -
+ the Finder will fix this, but if your
+ application is not running with the
+ Finder, use PBDTReset or PBDTDelete
+
+ __________
+
+ Also see: DTCopyComment, FSpDTCopyComment, DTSetComment, DTGetComment,
+ FSpDTGetComment
+*/
+
+/*****************************************************************************/
+
+pascal OSErr XGetVInfo(short volReference,
+ StringPtr volName,
+ short *vRefNum,
+ UnsignedWide *freeBytes,
+ UnsignedWide *totalBytes);
+/* Get extended information about a mounted volume.
+ The XGetVInfo function returns the name, volume reference number,
+ available space (in bytes), and total space (in bytes) for the
+ specified volume. You can specify the volume by providing its drive
+ number, volume reference number, or 0 for the default volume.
+ This routine is compatible with volumes up to 2 terabytes.
+
+ volReference input: The drive number, volume reference number,
+ or 0 for the default volume.
+ volName input: A pointer to a buffer (minimum Str27) where
+ the volume name is to be returned or must
+ be nil.
+ output: The volume name.
+ vRefNum output: The volume reference number.
+ freeBytes output: The number of free bytes on the volume.
+ freeBytes is an UnsignedWide value.
+ totalBytes output: The total number of bytes on the volume.
+ totalBytes is an UnsignedWide value.
+
+ Result Codes
+ noErr 0 No error
+ nsvErr -35 No such volume
+ paramErr -50 No default volume
+
+ __________
+
+ Also see: HGetVInfo
+*/
+
+/*****************************************************************************/
+
+pascal OSErr HGetVInfo(short volReference,
+ StringPtr volName,
+ short *vRefNum,
+ unsigned long *freeBytes,
+ unsigned long *totalBytes);
+/* Get information about a mounted volume.
+ The HGetVInfo function returns the name, volume reference number,
+ available space (in bytes), and total space (in bytes) for the
+ specified volume. You can specify the volume by providing its drive
+ number, volume reference number, or 0 for the default volume.
+ This routine is compatible with volumes up to 4 gigabytes.
+
+ volReference input: The drive number, volume reference number,
+ or 0 for the default volume.
+ volName input: A pointer to a buffer (minimum Str27) where
+ the volume name is to be returned or must
+ be nil.
+ output: The volume name.
+ vRefNum output: The volume reference number.
+ freeBytes output: The number of free bytes on the volume.
+ freeBytes is an unsigned long value.
+ totalBytes output: The total number of bytes on the volume.
+ totalBytes is an unsigned long value.
+
+ Result Codes
+ noErr 0 No error
+ nsvErr -35 No such volume
+ paramErr -50 No default volume
+
+ __________
+
+ Also see: XGetVInfo
+*/
+
+/*****************************************************************************/
+
+pascal OSErr GetDirName(short vRefNum,
+ long dirID,
+ Str31 name);
+/* Get the name of a directory from its directory ID.
+ The GetDirName function gets the name of a directory from its
+ directory ID.
+
+ vRefNum input: Volume specification.
+ dirID input: Directory ID.
+ name output: Points to a Str31 where the directory name is to be
+ returned.
+
+ Result Codes
+ noErr 0 No error
+ nsvErr -35 No such volume
+ ioErr -36 I/O error
+ bdNamErr -37 Bad filename
+ fnfErr -43 File not found
+ paramErr -50 No default volume or
+ name parameter was NULL
+ dirNFErr -120 Directory not found or incomplete pathname
+ afpAccessDenied -5000 User does not have the correct access
+ afpObjectTypeErr -5025 Directory not found or incomplete pathname
+*/
+
+
+/*****************************************************************************/
+
+pascal OSErr GetVolFileSystemID(ConstStr255Param pathname,
+ short vRefNum,
+ short *fileSystemID);
+/* Get a volume's file system ID.
+ The GetVolFileSystemID function returned the file system ID of
+ a mounted volume. The file system ID identifies the file system
+ that handles requests to a particular volume. Here's a partial list
+ of file system ID numbers (only Apple's file systems are listed):
+ FSID File System
+ ----- -----------------------------------------------------
+ $0000 Macintosh HFS or MFS
+ $0100 ProDOS File System
+ $0101 PowerTalk Mail Enclosures
+ $4147 ISO 9660 File Access (through Foreign File Access)
+ $4242 High Sierra File Access (through Foreign File Access)
+ $464D QuickTake File System (through Foreign File Access)
+ $4953 Macintosh PC Exchange (MS-DOS)
+ $4A48 Audio CD Access (through Foreign File Access)
+ $4D4B Apple Photo Access (through Foreign File Access)
+
+ See the Technical Note "FL 35 - Determining Which File System
+ Is Active" and the "Guide to the File System Manager" for more
+ information.
+
+ pathName input: Pointer to a full pathname or nil. If you pass
+ in a partial pathname, it is ignored. A full
+ pathname to a volume must contain at least
+ one colon character (:) and must not start with
+ a colon character.
+ vRefNum input: Volume specification (volume reference number,
+ working directory number, drive number, or 0).
+ fileSystemID output: The volume's file system ID.
+
+ Result Codes
+ noErr 0 No error
+ nsvErr -35 No such volume
+ paramErr -50 No default volume, or pb was NULL
+*/
+
+/*****************************************************************************/
+
+pascal OSErr GetDInfo(short vRefNum,
+ long dirID,
+ ConstStr255Param name,
+ DInfo *fndrInfo);
+/* Get the finder information for a directory.
+ The GetDInfo function gets the finder information for a directory.
+
+ vRefNum input: Volume specification.
+ dirID input: Directory ID.
+ name input: Pointer to object name, or nil when dirID
+ specifies a directory that's the object.
+ fndrInfo output: If the object is a directory, then its DInfo.
+
+ Result Codes
+ noErr 0 No error
+ nsvErr -35 No such volume
+ ioErr -36 I/O error
+ bdNamErr -37 Bad filename
+ fnfErr -43 File not found
+ paramErr -50 No default volume
+ dirNFErr -120 Directory not found or incomplete pathname
+ afpAccessDenied -5000 User does not have the correct access
+ afpObjectTypeErr -5025 Directory not found or incomplete pathname
+
+ __________
+
+ Also see: FSpGetDInfo, FSpGetFInfoCompat
+*/
+
+/*****************************************************************************/
+
+pascal OSErr FSpGetDInfo(const FSSpec *spec,
+ DInfo *fndrInfo);
+/* Get the finder information for a directory.
+ The FSpGetDInfo function gets the finder information for a directory.
+
+ spec input: An FSSpec record specifying the directory.
+ fndrInfo output: If the object is a directory, then its DInfo.
+
+ Result Codes
+ noErr 0 No error
+ nsvErr -35 No such volume
+ ioErr -36 I/O error
+ bdNamErr -37 Bad filename
+ fnfErr -43 File not found
+ paramErr -50 No default volume
+ dirNFErr -120 Directory not found or incomplete pathname
+ afpAccessDenied -5000 User does not have the correct access
+ afpObjectTypeErr -5025 Directory not found or incomplete pathname
+
+ __________
+
+ Also see: FSpGetFInfoCompat, GetDInfo
+*/
+
+
+#endif /* _MACSTUFF_H */
diff --git a/macos/source/mactime.c b/macos/source/mactime.c
new file mode 100644
index 0000000..fcdd440
--- /dev/null
+++ b/macos/source/mactime.c
@@ -0,0 +1,451 @@
+/*
+ Copyright (c) 1990-2005 Info-ZIP. All rights reserved.
+
+ See the accompanying file LICENSE, version 2004-May-22 or later
+ (the contents of which are also included in zip.h) for terms of use.
+ If, for some reason, both of these files are missing, the Info-ZIP license
+ also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.htmlhtml
+*/
+/* -----------------------------------------------------------------------------
+
+The original functions (Metrowerks Codewarrior pro 3.0) gmtime, localtime,
+mktime and time do not work correctly. The supplied link library mactime.c
+contains replacement functions for them.
+
+ * Caveat: On a Mac, we only know the GMT and DST offsets for
+ * the current time, not for the time in question.
+ * Mac has no support for DST handling.
+ * DST changeover is all manually set by the user.
+
+
+------------------------------------------------------------------------------*/
+
+/*****************************************************************************/
+/* Includes */
+/*****************************************************************************/
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <OSUtils.h>
+
+#include "mactime.h"
+
+
+/*
+The MacOS function GetDateTime returns the
+number of seconds elapsed since midnight, January 1, 1904.
+*/
+const unsigned long MacOS_2_Unix = 2082844800L;
+
+
+/*****************************************************************************/
+/* Macros, typedefs */
+/*****************************************************************************/
+
+
+#ifndef TEST_TIME_LIB
+#define my_gmtime gmtime
+#define my_localtime localtime
+#define my_mktime mktime
+#define my_time time
+#endif
+
+
+/*****************************************************************************/
+/* Prototypes */
+/*****************************************************************************/
+/* internal prototypes */
+static void clear_tm(struct tm * tm);
+static long GMTDelta(void);
+static Boolean DaylightSaving(void);
+static time_t GetTimeMac(void);
+static time_t Mactime(time_t *timer);
+static void normalize(int *i,int *j,int norm);
+static struct tm *time2tm(const time_t *timer);
+static time_t tm2time(struct tm *tp);
+
+/* Because serial port and SLIP conflict with ReadXPram calls,
+ we cache the call here so we don't hang on calling ReadLocation() */
+static void myReadLocation(MachineLocation * loc);
+
+
+/* prototypes for STD lib replacement functions */
+struct tm *my_gmtime(const time_t *t);
+struct tm *my_localtime(const time_t *t);
+time_t my_mktime(struct tm *tp);
+time_t my_time(time_t *t);
+
+
+/*****************************************************************************/
+/* Functions */
+/*****************************************************************************/
+
+ /*
+ * Mac file times are based on 1904 Jan 1 00:00 local time,
+ * not 1970 Jan 1 00:00 UTC.
+ * So we have to convert the time stamps into UNIX UTC
+ * compatible values.
+ */
+time_t MacFtime2UnixFtime(unsigned long macftime)
+{
+ long UTCoffset;
+
+ GetGMToffsetMac(macftime, &UTCoffset);
+ MACOS_TO_UNIX(macftime);
+ macftime -= UTCoffset;
+
+ return macftime;
+}
+
+
+ /*
+ * Mac file times are based on 1904 Jan 1 00:00 local time,
+ * not 1970 Jan 1 00:00 UTC.
+ * So we have to convert the time stamps into MacOS local
+ * compatible values.
+ */
+unsigned long UnixFtime2MacFtime(time_t unxftime)
+{
+ long UTCoffset;
+ unsigned long macftime = unxftime;
+
+ UNIX_TO_MACOS(macftime);
+ GetGMToffsetMac(macftime, &UTCoffset);
+ macftime += UTCoffset;
+
+ return macftime;
+}
+
+
+
+
+
+/*
+* This function convert a file-localtime to an another
+* file-localtime.
+*/
+time_t AdjustForTZmoveMac(unsigned long macloctim, long s_gmtoffs)
+{
+ time_t MacGMTTime;
+ long UTCoffset;
+
+ /* convert macloctim into corresponding UTC value */
+ MacGMTTime = macloctim - s_gmtoffs;
+ GetGMToffsetMac(macloctim, &UTCoffset);
+
+ return (MacGMTTime + UTCoffset);
+} /* AdjustForTZmove() */
+
+
+
+
+/*
+ * This function calculates the difference between the supplied Mac
+ * ftime value (local time) and the corresponding UTC time in seconds.
+ */
+Boolean GetGMToffsetMac(unsigned long mactime, long *UTCoffset)
+{
+
+mactime = mactime;
+/*
+ * Caveat: On a Mac, we only know the GMT and DST offsets for
+ * the current time, not for the time in question.
+ * Mac has no support for DST handling.
+ * DST changeover is all manually set by the user.
+
+ May be later I can include a support of GMT offset calculation for the
+ time in question here.
+*/
+ *UTCoffset = GMTDelta();
+
+ return true;
+}
+
+
+
+
+
+
+
+/*****************************************************************************
+ * Standard Library Replacement Functions
+ * gmtime(), mktime(), localtime(), time()
+ *
+ * The unix epoch is used here.
+ * These functions gmtime(), mktime(), localtime() and time()
+ * expects and returns unix times.
+ *
+ * At midnight Jan. 1, 1970 GMT, the local time was
+ * midnight Jan. 1, 1970 + GMTDelta().
+ *
+ *
+ *****************************************************************************/
+
+
+struct tm *my_gmtime(const time_t *timer)
+{
+ return time2tm(timer);
+}
+
+
+
+
+struct tm *my_localtime(const time_t *timer)
+{
+ time_t maclocal;
+
+ maclocal = *timer;
+ maclocal += GMTDelta();
+
+ return time2tm(&maclocal);
+}
+
+
+
+
+time_t my_mktime(struct tm *tp)
+{
+ time_t maclocal;
+
+ maclocal = tm2time(tp);
+ maclocal -= GMTDelta();
+
+ return maclocal;
+}
+
+
+
+
+
+
+time_t my_time(time_t *time)
+{
+time_t tmp_time;
+
+GetDateTime(&tmp_time);
+
+MACOS_TO_UNIX(tmp_time);
+
+if (time)
+ {
+ *time = tmp_time;
+ }
+
+return tmp_time;
+}
+
+
+
+/*****************************************************************************/
+/* static module level functions
+/*****************************************************************************/
+
+
+/*
+ * The geographic location and time zone information of a Mac
+ * are stored in extended parameter RAM. The ReadLocation
+ * produdure uses the geographic location record, MachineLocation,
+ * to read the geographic location and time zone information in
+ * extended parameter RAM.
+ *
+ * Because serial port and SLIP conflict with ReadXPram calls,
+ * we cache the call here.
+ *
+ * Caveat: this caching will give the wrong result if a session
+ * extend across the DST changeover time, but
+ * this function resets itself every 2 hours.
+ */
+static void myReadLocation(MachineLocation * loc)
+{
+ static MachineLocation storedLoc; /* InsideMac, OSUtilities, page 4-20 */
+ static time_t first_call = 0, last_call = 86400;
+
+ if ((last_call - first_call) > 7200)
+ {
+ GetDateTime(&first_call);
+ ReadLocation(&storedLoc);
+ }
+
+ GetDateTime(&last_call);
+ *loc = storedLoc;
+}
+
+
+
+
+static Boolean DaylightSaving(void)
+{
+ MachineLocation loc;
+ unsigned char dlsDelta;
+
+ myReadLocation(&loc);
+ dlsDelta = loc.u.dlsDelta;
+
+ return (dlsDelta != 0);
+}
+
+
+
+
+/* current local time = GMTDelta() + GMT
+ GMT = local time - GMTDelta() */
+static long GMTDelta(void)
+{
+ MachineLocation loc;
+ long gmtDelta;
+
+ myReadLocation(&loc);
+
+ /*
+ * On a Mac, the GMT value is in seconds east of GMT. For example,
+ * San Francisco is at -28,800 seconds (8 hours * 3600 seconds per hour)
+ * east of GMT. The gmtDelta field is a 3-byte value contained in a
+ * long word, so you must take care to get it properly.
+ */
+ gmtDelta = loc.u.gmtDelta & 0x00FFFFFF;
+ if ((gmtDelta & 0x00800000) != 0)
+ {
+ gmtDelta |= 0xFF000000;
+ }
+
+ return gmtDelta;
+}
+
+
+
+/* This routine simulates stdclib time(), time in seconds since 1.1.1970
+ The time is in GMT */
+static time_t GetTimeMac(void)
+{
+ unsigned long maclocal;
+
+
+ /*
+ * Get the current time expressed as the number of seconds
+ * elapsed since the Mac epoch, midnight, Jan. 1, 1904 (local time).
+ * On a Mac, current time accuracy is up to a second.
+ */
+
+ GetDateTime(&maclocal); /* Get Mac local time */
+ maclocal -= GMTDelta(); /* Get Mac GMT */
+ MACOS_TO_UNIX(maclocal);
+
+ return maclocal; /* return unix GMT */
+}
+
+
+
+
+/*
+ * clear_tm - sets a broken-down time to the equivalent of 1970/1/1 00:00:00
+ */
+
+static void clear_tm(struct tm * tm)
+{
+ tm->tm_sec = 0;
+ tm->tm_min = 0;
+ tm->tm_hour = 0;
+ tm->tm_mday = 1;
+ tm->tm_mon = 0;
+ tm->tm_year = 0;
+ tm->tm_wday = 1;
+ tm->tm_yday = 0;
+ tm->tm_isdst = -1;
+}
+
+
+static void normalize(int *i,int *j,int norm)
+{
+ while(*i < 0)
+ {
+ *i += norm;
+ (*j)--;
+ }
+
+ while(*i >= norm)
+ {
+ *i -= norm;
+ (*j)++;
+ }
+}
+
+
+
+/* Returns the GMT times */
+static time_t Mactime(time_t *timer)
+{
+ time_t t = GetTimeMac();
+
+ if (timer != NULL)
+ *timer = t;
+
+ return t;
+}
+
+
+
+
+static struct tm *time2tm(const time_t *timer)
+{
+ DateTimeRec dtr;
+ MachineLocation loc;
+ time_t macLocal = *timer;
+
+ static struct tm statictime;
+ static const short monthday[12] =
+ {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
+
+ UNIX_TO_MACOS(macLocal);
+ SecondsToDate(macLocal, &dtr);
+
+ statictime.tm_sec = dtr.second; /* second, from 0 to 59 */
+ statictime.tm_min = dtr.minute; /* minute, from 0 to 59 */
+ statictime.tm_hour = dtr.hour; /* hour, from 0 to 23 */
+ statictime.tm_mday = dtr.day; /* day of the month, from 1 to 31 */
+ statictime.tm_mon = dtr.month - 1; /* month, 1= January and 12 = December */
+ statictime.tm_year = dtr.year - 1900; /* year, ranging from 1904 to 2040 */
+ statictime.tm_wday = dtr.dayOfWeek - 1; /* day of the week, 1 = Sun, 7 = Sat */
+
+ statictime.tm_yday = monthday[statictime.tm_mon]
+ + statictime.tm_mday - 1;
+
+ if (2 < statictime.tm_mon && !(statictime.tm_year & 3))
+ {
+ ++statictime.tm_yday;
+ }
+
+ myReadLocation(&loc);
+ statictime.tm_isdst = DaylightSaving();
+
+ return(&statictime);
+}
+
+
+
+
+
+static time_t tm2time(struct tm *tp)
+{
+time_t intMacTime;
+DateTimeRec dtr;
+
+ normalize(&tp->tm_sec, &tp->tm_min, 60);
+ normalize(&tp->tm_min, &tp->tm_hour,60);
+ normalize(&tp->tm_hour,&tp->tm_mday,24);
+ normalize(&tp->tm_mon, &tp->tm_year,12);
+
+ dtr.year = tp->tm_year + 1900; /* years since 1900 */
+ dtr.month = tp->tm_mon + 1; /* month, 0 = January and 11 = December */
+ dtr.day = tp->tm_mday; /* day of the month, from 1 to 31 */
+ dtr.hour = tp->tm_hour; /* hour, from 0 to 23 */
+ dtr.minute = tp->tm_min; /* minute, from 0 to 59 */
+ dtr.second = tp->tm_sec; /* second, from 0 to 59 */
+
+ DateToSeconds(&dtr, &intMacTime);
+
+ MACOS_TO_UNIX(intMacTime);
+
+ return intMacTime;
+}
diff --git a/macos/source/mactime.h b/macos/source/mactime.h
new file mode 100644
index 0000000..fa70c7f
--- /dev/null
+++ b/macos/source/mactime.h
@@ -0,0 +1,61 @@
+/*
+ Copyright (c) 1990-1999 Info-ZIP. All rights reserved.
+
+ See the accompanying file LICENSE, version 1999-Oct-05 or later
+ (the contents of which are also included in zip.h) for terms of use.
+ If, for some reason, both of these files are missing, the Info-ZIP license
+ also may be found at: ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+#ifndef _MACTIME_H_
+#define _MACTIME_H_
+/* -----------------------------------------------------------------------------
+
+The original functions (Metrowerks Codewarrior pro 3.0) gmtime, localtime,
+mktime and time do not work correctly. The supplied link library mactime.c
+contains replacement functions for them.
+
+ * Caveat: On a Mac, we only know the GMT and DST offsets for
+ * the current time, not for the time in question.
+ * Mac has no support for DST handling.
+ * DST changeover is all manually set by the user.
+
+
+------------------------------------------------------------------------------*/
+
+#include <time.h>
+#include <mactypes.h>
+
+/*****************************************************************************/
+/* Macros, typedefs */
+/*****************************************************************************/
+
+
+ /*
+ * ARGH. Mac times are based on 1904 Jan 1 00:00, not 1970 Jan 1 00:00.
+ * So we have to diddle time_t's appropriately: add or subtract 66 years'
+ * worth of seconds == number of days times 86400 == (66*365 regular days +
+ * 17 leap days ) * 86400 == (24090 + 17) * 86400 == 2082844800L seconds.
+ * We hope time_t is an unsigned long (ulg) on the Macintosh...
+ */
+/*
+This Offset is only used by MacFileDate_to_UTime()
+*/
+
+#define MACOS_TO_UNIX(x) (x) -= (unsigned long)MacOS_2_Unix
+#define UNIX_TO_MACOS(x) (x) += (unsigned long)MacOS_2_Unix
+
+/*
+The MacOS function GetDateTime returns the
+number of seconds elapsed since midnight, January 1, 1904.
+*/
+extern const unsigned long MacOS_2_Unix;
+
+
+/* prototypes for public utility functions */
+time_t MacFtime2UnixFtime(unsigned long macftime);
+unsigned long UnixFtime2MacFtime(time_t unxftime);
+time_t AdjustForTZmoveMac(unsigned long macloctim, long s_gmtoffs);
+Boolean GetGMToffsetMac(unsigned long macftime, long *UTCoffset);
+
+
+#endif
diff --git a/macos/source/pathname.c b/macos/source/pathname.c
new file mode 100644
index 0000000..166d872
--- /dev/null
+++ b/macos/source/pathname.c
@@ -0,0 +1,665 @@
+/*
+ Copyright (c) 1990-2005 Info-ZIP. All rights reserved.
+
+ See the accompanying file LICENSE, version 2004-May-22 or later
+ (the contents of which are also included in zip.h) for terms of use.
+ If, for some reason, both of these files are missing, the Info-ZIP license
+ also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.htmlhtml
+*/
+/*---------------------------------------------------------------------------
+
+ pathname.c
+
+ Function dealing with the pathname. Mostly C-string work.
+
+ ---------------------------------------------------------------------------*/
+
+/*****************************************************************************/
+/* Includes */
+/*****************************************************************************/
+
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sound.h>
+
+#include "pathname.h"
+#include "helpers.h"
+#include "macstuff.h"
+
+
+/*****************************************************************************/
+/* Global Vars */
+/*****************************************************************************/
+
+const char ResourceMark[] = "XtraStuf.mac:"; /* see also macos.c */
+
+
+#include "zip.h"
+
+
+
+
+/*****************************************************************************/
+/* Functions */
+/*****************************************************************************/
+
+
+
+
+/*
+** return volumename from pathname
+**
+*/
+
+unsigned short GetVolumeFromPath(const char *FullPath, char *VolumeName)
+{
+const char *VolEnd, *tmpPtr1;
+char *tmpPtr2 = VolumeName;
+
+AssertStr(FullPath,"GetVolumeFromPath")
+
+for (VolEnd = FullPath; *VolEnd != '\0' && *VolEnd != ':'; VolEnd++)
+ ;
+if (*VolEnd == '\0') return 0;
+
+for (tmpPtr1 = FullPath; tmpPtr1 != VolEnd;)
+ {
+ *tmpPtr2++ = *tmpPtr1++;
+ }
+
+*tmpPtr2 = '\0';
+
+return (unsigned short) strlen(VolumeName);
+}
+
+
+
+/***********************************/
+/* Function FindNewExtractFolder() */
+/***********************************/
+
+char *FindNewExtractFolder(char *ExtractPath)
+{
+char buffer[NAME_MAX], *tmpPtr, *namePtr;
+short count = 0, folderCount = 0;
+OSErr err;
+FSSpec Spec;
+long theDirID;
+Boolean isDirectory;
+unsigned short namelen, pathlen = strlen(ExtractPath);
+
+AssertStr(ExtractPath,"FindNewExtractFolder ExtractPath == NULL")
+
+for (tmpPtr = ExtractPath; *tmpPtr; tmpPtr++)
+ if (*tmpPtr == ':')
+ {
+ folderCount++;
+ namePtr = tmpPtr;
+ }
+
+if (folderCount > 1)
+ namelen = strlen(namePtr);
+else
+ namelen = strlen(ExtractPath);
+
+for (count = 0; count < 99; count++)
+ {
+ memset(buffer,0,sizeof(buffer));
+
+ if (namelen >= 28)
+ ExtractPath[pathlen-2] = 0x0;
+ else
+ ExtractPath[pathlen-1] = 0x0;
+
+ sprintf(buffer,"%s%d",ExtractPath,count);
+ GetCompletePath(ExtractPath, buffer, &Spec,&err);
+ err = FSpGetDirectoryID(&Spec, &theDirID, &isDirectory);
+ if (err == -43) break;
+ }
+
+/* Foldernames must always end with a colon */
+sstrcat(ExtractPath,":");
+return ExtractPath;
+}
+
+
+
+/*
+** creates an archive file name
+**
+*/
+
+void createArchiveName(char *thePath)
+{
+char *tmpPtr, *namePtr;
+short folderCount = 0;
+unsigned short namelen, pathlen = strlen(thePath);
+
+if (thePath[pathlen-1] == ':') thePath[pathlen-1] = 0x0;
+
+for (tmpPtr = thePath; *tmpPtr; tmpPtr++)
+ if (*tmpPtr == ':')
+ {
+ folderCount++;
+ namePtr = tmpPtr;
+ }
+
+namelen = strlen(namePtr);
+
+ /* we have to eliminate illegal chars:
+ * The name space for Mac filenames and Zip filenames (unix style names)
+ * do both include all printable extended-ASCII characters. The only
+ * difference we have to take care of is the single special character
+ * used as path delimiter:
+ * ':' on MacOS and '/' on Unix and '\' on Dos.
+ * So, to convert between Mac filenames and Unix filenames without any
+ * loss of information, we simply interchange ':' and '/'. Additionally,
+ * we try to convert the coding of the extended-ASCII characters into
+ * InfoZip's standard ISO 8859-1 codepage table.
+ */
+ MakeCompatibleString(namePtr, '/', '_', '.', '-', -1);
+
+ /* Avoid filenames like: "Archive..zip" */
+if (thePath[pathlen-1] == '.')
+ {
+ thePath[pathlen-1] = 0;
+ }
+
+if (folderCount >= 1)
+ { /* path contains at least one folder */
+
+ if (namelen >= 28)
+ {
+ pathlen = pathlen-4;
+ }
+
+ thePath[pathlen] = '.';
+ thePath[pathlen+1] = 'z';
+ thePath[pathlen+2] = 'i';
+ thePath[pathlen+3] = 'p';
+ thePath[pathlen+4] = 0x0;
+ return;
+ }
+else
+ { /* path contains no folder */
+ FindDesktopFolder(thePath);
+ createArchiveName(thePath);
+ }
+}
+
+
+
+/*
+** finds the desktop-folder on a volume with
+** largest amount of free-space.
+*/
+
+void FindDesktopFolder(char *Path)
+{
+char buffer[255];
+FSSpec volumes[50]; /* 50 Volumes should be enough */
+short actVolCount, volIndex = 1, VolCount = 0;
+OSErr err;
+short i, foundVRefNum;
+FSSpec spec;
+UnsignedWide freeBytes;
+UnsignedWide totalBytes;
+UnsignedWide MaxFreeBytes;
+
+err = OnLine(volumes, 50, &actVolCount, &volIndex);
+printerr("OnLine:", (err != -35) && (err != 0), err, __LINE__, __FILE__, "");
+
+MaxFreeBytes.hi = 0;
+MaxFreeBytes.lo = 0;
+
+for (i=0; i < actVolCount; i++)
+ {
+ XGetVInfo(volumes[i].vRefNum,
+ volumes[i].name,
+ &volumes[i].vRefNum,
+ &freeBytes,
+ &totalBytes);
+
+ if (MaxFreeBytes.hi < freeBytes.hi) {
+ MaxFreeBytes.hi = freeBytes.hi;
+ MaxFreeBytes.lo = freeBytes.lo;
+ foundVRefNum = volumes[i].vRefNum;
+ }
+
+ if ((freeBytes.hi == 0) && (MaxFreeBytes.lo < freeBytes.lo)) {
+ MaxFreeBytes.hi = freeBytes.hi;
+ MaxFreeBytes.lo = freeBytes.lo;
+ foundVRefNum = volumes[i].vRefNum;
+ }
+
+}
+
+ FSpFindFolder(foundVRefNum, kDesktopFolderType,
+ kDontCreateFolder,&spec);
+
+ GetFullPathFromSpec(buffer, &spec , &err);
+ sstrcat(buffer,Path);
+ sstrcpy(Path,buffer);
+}
+
+
+/*
+** return the path without the filename
+**
+*/
+
+char *TruncFilename(char *DirPath, const char *FilePath)
+{
+char *tmpPtr;
+char *dirPtr = NULL;
+
+AssertStr(DirPath,"TruncFilename")
+Assert_it(Spec,"TruncFilename","")
+
+sstrcpy(DirPath, FilePath);
+
+for (tmpPtr = DirPath; *tmpPtr; tmpPtr++)
+ if (*tmpPtr == ':')
+ dirPtr = tmpPtr;
+
+if (dirPtr)
+ *++dirPtr = '\0';
+else
+ printerr("TruncFilename: FilePath has no Folders", -1,
+ -1, __LINE__, __FILE__, FilePath);
+
+return DirPath;
+}
+
+
+
+/*
+** return only filename
+**
+*/
+
+char *GetFilename(char *FileName, const char *FilePath)
+{
+const char *tmpPtr;
+const char *dirPtr = NULL;
+
+Assert_it(FileName,"GetFilename","")
+Assert_it(FilePath,"GetFilename","")
+
+for (tmpPtr = FilePath; *tmpPtr; tmpPtr++)
+ {
+ if (*tmpPtr == ':')
+ {
+ dirPtr = tmpPtr;
+ }
+ }
+
+if (dirPtr)
+ {
+ ++dirPtr; /* jump over the ':' */
+ }
+else
+ {
+ return strcpy(FileName, FilePath); /* FilePath has no Folders */
+ }
+
+return strcpy(FileName, dirPtr);
+}
+
+
+
+/*
+** return fullpathname from folder/dir-id
+**
+*/
+
+char *GetFullPathFromID(char *CompletePath, short vRefNum, long dirID,
+ ConstStr255Param name, OSErr *err)
+{
+FSSpec spec;
+
+ *err = FSMakeFSSpecCompat(vRefNum, dirID, name, &spec);
+ printerr("FSMakeFSSpecCompat:", (*err != -43) && (*err != 0), *err,
+ __LINE__, __FILE__, "");
+ if ( (*err == noErr) || (*err == fnfErr) )
+ {
+ return GetFullPathFromSpec(CompletePath, &spec, err);
+ }
+
+return NULL;
+}
+
+
+
+/*
+** convert real-filename to archive-filename
+**
+*/
+
+char *Real2RfDfFilen(char *RfDfFilen, const char *RealPath,
+ short CurrentFork, short MacZipMode, Boolean DataForkOnly)
+{
+
+AssertStr(RealPath,"Real2RfDfFilen")
+AssertStr(RfDfFilen,"Real2RfDfFilen")
+
+if (DataForkOnly) /* make no changes */
+ {
+ return sstrcpy(RfDfFilen, RealPath);
+ }
+
+switch (MacZipMode)
+ {
+ case JohnnyLee_EF:
+ {
+ sstrcpy(RfDfFilen, RealPath);
+ if (CurrentFork == DataFork) /* data-fork */
+ return sstrcat(RfDfFilen, "d");
+ if (CurrentFork == ResourceFork) /* resource-fork */
+ return sstrcat(RfDfFilen, "r");
+ break;
+ }
+
+ case NewZipMode_EF:
+ {
+ switch (CurrentFork)
+ {
+ case DataFork:
+ {
+ sstrcpy(RfDfFilen, RealPath);
+ return RfDfFilen; /* data-fork */
+ break;
+ }
+ case ResourceFork:
+ {
+ sstrcpy(RfDfFilen, ResourceMark);
+ sstrcat(RfDfFilen, RealPath); /* resource-fork */
+ return RfDfFilen;
+ break;
+ }
+ default:
+ {
+ printerr("Real2RfDfFilen:", -1, -1,
+ __LINE__, __FILE__, RealPath);
+ return NULL; /* function should never reach this point */
+ }
+ }
+ break;
+ }
+ default:
+ {
+ printerr("Real2RfDfFilen:", -1, -1, __LINE__, __FILE__, RealPath);
+ return NULL; /* function should never reach this point */
+ }
+ }
+
+printerr("Real2RfDfFilen:", -1, -1, __LINE__, __FILE__, RealPath);
+return NULL; /* function should never come reach this point */
+}
+
+
+
+/*
+** convert archive-filename into a real filename
+**
+*/
+
+char *RfDfFilen2Real(char *RealFn, const char *RfDfFilen, short MacZipMode,
+ Boolean DataForkOnly, short *CurrentFork)
+{
+short length;
+int result;
+
+AssertStr(RfDfFilen,"RfDfFilen2Real")
+
+if (DataForkOnly ||
+ (MacZipMode == UnKnown_EF) ||
+ (MacZipMode < JohnnyLee_EF))
+ {
+ *CurrentFork = DataFork;
+ return sstrcpy(RealFn,RfDfFilen);
+ }
+
+result = strncmp(RfDfFilen, ResourceMark, sizeof(ResourceMark)-2);
+if (result == 0)
+ {
+ MacZipMode = NewZipMode_EF;
+ }
+
+switch (MacZipMode)
+ {
+ case JohnnyLee_EF:
+ {
+ sstrcpy(RealFn, RfDfFilen);
+ length = strlen(RealFn); /* determine Fork type */
+ if (RealFn[length-1] == 'd') *CurrentFork = DataFork;
+ else *CurrentFork = ResourceFork;
+ RealFn[length-1] = '\0'; /* simply cut one char */
+ return RealFn;
+ break;
+ }
+
+ case NewZipMode_EF:
+ { /* determine Fork type */
+ result = strncmp(RfDfFilen, ResourceMark, sizeof(ResourceMark)-2);
+ if (result != 0)
+ {
+ *CurrentFork = DataFork;
+ sstrcpy(RealFn, RfDfFilen);
+ return RealFn; /* data-fork */
+ }
+ else
+ {
+ *CurrentFork = ResourceFork;
+ if (strlen(RfDfFilen) > (sizeof(ResourceMark) - 1))
+ {
+ sstrcpy(RealFn, &RfDfFilen[sizeof(ResourceMark)-1]);
+ }
+ else RealFn[0] = '\0';
+ return RealFn; /* resource-fork */
+ }
+ break;
+ }
+ default:
+ {
+ *CurrentFork = NoFork;
+ printerr("RfDfFilen2Real():", -1, MacZipMode,
+ __LINE__, __FILE__, RfDfFilen);
+ return NULL; /* function should never reach this point */
+ }
+ }
+
+printerr("RfDfFilen2Real():", -1, MacZipMode, __LINE__, __FILE__, RfDfFilen);
+return NULL; /* function should never reach this point */
+}
+
+
+
+/*
+** return the applications name (argv[0])
+**
+*/
+
+char *GetAppName(void)
+{
+ProcessSerialNumber psn;
+static Str255 AppName;
+ProcessInfoRec pinfo;
+OSErr err;
+
+GetCurrentProcess(&psn);
+pinfo.processName = AppName;
+pinfo.processInfoLength = sizeof(pinfo);
+pinfo.processAppSpec = NULL;
+
+err = GetProcessInformation(&psn,&pinfo);
+AppName[AppName[0]+1] = 0x00;
+
+return (char *)&AppName[1];
+}
+
+
+
+/*
+** return fullpathname from FSSpec
+**
+*/
+
+char *GetFullPathFromSpec(char *FullPath, FSSpec *Spec, OSErr *err)
+{
+Handle hFullPath;
+short len;
+
+Assert_it(Spec,"GetFullPathFromSpec","")
+
+*err = FSpGetFullPath(Spec, &len, &hFullPath);
+printerr("FSpGetFullPath:", (*err != -43) && (*err != 0), *err,
+ __LINE__, __FILE__, "");
+
+memmove(FullPath, (Handle) *hFullPath, len);
+FullPath[len] = '\0'; /* make c-string */
+
+DisposeHandle((Handle)hFullPath); /* we don't need it any more */
+
+printerr("Warning path length exceeds limit: ", len >= NAME_MAX, len,
+ __LINE__, __FILE__, " chars ");
+
+return FullPath;
+}
+
+
+
+
+/*
+* This function expands a given partial path to a complete path.
+* Path expansions are relative to the running app.
+* This function follows the notation:
+* 1. relative path:
+* a: ":subfolder:filename" -> ":current folder:subfolder:filename"
+* b: "::folder2:filename" -> folder2 is beside the current
+* folder on the same level
+* c: "filename" -> in current folder
+*
+* An absolute path will be returned.
+
+The following characteristics of Macintosh pathnames should be noted:
+
+ A full pathname never begins with a colon, but must contain at
+ least one colon.
+ A partial pathname always begins with a colon separator except in
+ the case where the file partial pathname is a simple file or
+ directory name.
+ Single trailing separator colons in full or partial pathnames are
+ ignored except in the case of full pathnames to volumes.
+ In full pathnames to volumes, the trailing separator colon is required.
+ Consecutive separator colons can be used to ascend a level from a
+ directory to its parent directory. Two consecutive separator colons
+ will ascend one level, three consecutive separator colons will ascend
+ two levels, and so on. Ascending can only occur from a directory;
+ not a file.
+*/
+
+char *GetCompletePath(char *CompletePath, const char *name, FSSpec *Spec,
+ OSErr *err)
+{
+Boolean hasDirName = false;
+char currentdir[NAME_MAX];
+char *tmpPtr;
+unsigned short pathlen;
+
+AssertStr(name,"GetCompletePath")
+Assert_it(Spec,"GetCompletePath","")
+Assert_it((CompletePath != name),"GetCompletePath","")
+
+for (tmpPtr = name; *tmpPtr; tmpPtr++)
+ if (*tmpPtr == ':') hasDirName = true;
+
+if (name[0] != ':') /* case c: path including volume name or only filename */
+ {
+ if (hasDirName)
+ { /* okey, starts with volume name, so it must be a complete path */
+ sstrcpy(CompletePath, name);
+ }
+ else
+ { /* only filename: add cwd and return */
+ getcwd(currentdir, NAME_MAX);
+ sstrcat(currentdir, name);
+ sstrcpy(CompletePath, currentdir);
+ }
+ }
+else if (name[1] == ':') /* it's case b: "::folder2:filename" */
+ {
+ printerr("GetCompletePath ", -1, *err, __LINE__, __FILE__, "not implemented");
+ /* it's not yet implemented; do we really need this case ?*/
+ return NULL;
+ }
+else /* it's case a: ":subfolder:filename" */
+ {
+ getcwd(CompletePath, NAME_MAX); /* we don't need a second colon */
+ CompletePath[strlen(CompletePath)-1] = '\0';
+ sstrcat(CompletePath, name);
+ }
+
+pathlen = strlen(CompletePath);
+*err = FSpLocationFromFullPath(pathlen, CompletePath, Spec);
+
+return CompletePath;
+}
+
+
+
+char *MakeFilenameShorter(const char *LongFilename)
+{
+static char filename[35]; /* contents should be never longer than 32 chars */
+static unsigned char Num = 0; /* change the number for every call */
+ /* this var will rollover without a problem */
+char tempLongFilename[1024], charnum[5];
+char *last_dotpos = tempLongFilename;
+unsigned long full_length = strlen(LongFilename);
+unsigned long ext_length = 0;
+unsigned long num_to_cut = 0;
+long firstpart_length;
+char *tmpPtr;
+short MaxLength = 31;
+
+if (full_length <= MaxLength) /* filename is not long */
+ {
+ return strcpy(filename,LongFilename);
+ }
+
+Num++;
+strcpy(tempLongFilename,LongFilename);
+
+/* Look for the last extension pos */
+for (tmpPtr = tempLongFilename; *tmpPtr; tmpPtr++)
+ if (*tmpPtr == '.') last_dotpos = tmpPtr;
+
+ext_length = strlen(last_dotpos);
+firstpart_length = last_dotpos - tempLongFilename;
+
+if (ext_length > 6) /* up to 5 chars are treated as a */
+ { /* normal extension like ".html" or ".class" */
+ firstpart_length = 0;
+ }
+
+num_to_cut = full_length - MaxLength;
+
+/* number the files to make the names unique */
+sprintf(charnum,"~%x", Num);
+num_to_cut += strlen(charnum);
+
+if (firstpart_length == 0)
+ {
+ firstpart_length = full_length;
+ tempLongFilename[firstpart_length - num_to_cut] = 0;
+ sprintf(filename,"%s%s", tempLongFilename, charnum);
+ }
+else
+ {
+ tempLongFilename[firstpart_length - num_to_cut] = 0;
+ sprintf(filename,"%s%s%s", tempLongFilename, charnum, last_dotpos);
+ }
+
+return filename;
+}
diff --git a/macos/source/pathname.h b/macos/source/pathname.h
new file mode 100644
index 0000000..05a9078
--- /dev/null
+++ b/macos/source/pathname.h
@@ -0,0 +1,59 @@
+/*
+ Copyright (c) 1990-1999 Info-ZIP. All rights reserved.
+
+ See the accompanying file LICENSE, version 1999-Oct-05 or later
+ (the contents of which are also included in zip.h) for terms of use.
+ If, for some reason, both of these files are missing, the Info-ZIP license
+ also may be found at: ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+#ifndef PATHNAME_H
+#define PATHNAME_H 1
+
+
+char *StripPartialDir(char *CompletePath,
+ const char *PartialPath, const char *FullPath);
+
+char *Real2RfDfFilen(char *RfDfFilen, const char *RealPath, short CurrentFork,
+ short MacZipMode, Boolean DataForkOnly);
+char *RfDfFilen2Real(char *RealFn, const char *RfDfFilen, short MacZipMode,
+ Boolean DataForkOnly, short *CurrentFork);
+
+unsigned short GetVolumeFromPath(const char *FullPath, char *VolumeName);
+char *GetCompletePath(char *CompletePath, const char *name, FSSpec *Spec,
+ OSErr *err);
+char *TruncFilename(char *DirPath, const char *FilePath);
+char *GetFilename(char *CompletePath, const char *name);
+char *GetFullPathFromSpec(char *CompletePath, FSSpec *Spec, OSErr *err);
+char *GetFullPathFromID(char *CompletePath, short vRefNum, long dirID,
+ ConstStr255Param name, OSErr *err);
+
+char *GetAppName(void);
+void createArchiveName(char *Path);
+void FindDesktopFolder(char *Path);
+char *FindNewExtractFolder(char *ExtractPath);
+
+char *MakeFilenameShorter(const char *LongFilename);
+
+/*
+Rule: UnKnown_EF should always be zero.
+ JohnnyLee_EF, NewZipMode_EF should always greater than all
+ other definitions
+*/
+#define UnKnown_EF 0
+#define TomBrownZipIt1_EF 10
+#define TomBrownZipIt2_EF 20
+#define JohnnyLee_EF 30
+#define NewZipMode_EF 40
+
+
+
+#define ResourceFork -1
+#define DataFork 1
+#define NoFork 0
+
+
+#ifndef NAME_MAX
+#define NAME_MAX 1024
+#endif
+
+#endif /* PATHNAME_H */
diff --git a/macos/source/recurse.c b/macos/source/recurse.c
new file mode 100644
index 0000000..e87db3c
--- /dev/null
+++ b/macos/source/recurse.c
@@ -0,0 +1,442 @@
+/*
+These functions are based on Jim Luther's IterateDirectory() found in MoreFiles
+However, it's heavily modified by Dirk Haase
+*/
+
+/*
+** IterateDirectory: File Manager directory iterator routines.
+**
+** by Jim Luther
+**
+** File: IterateDirectory.c
+**
+** Copyright (c) 1995-1998 Jim Luther and Apple Computer, Inc.
+** All rights reserved.
+**
+** You may incorporate this sample code into your applications without
+** restriction, though the sample code has been provided "AS IS" and the
+** responsibility for its operation is 100% yours.
+**
+** IterateDirectory is designed to drop into the MoreFiles sample code
+** library I wrote while in Apple Developer Technical Support
+*/
+
+/*****************************************************************************/
+/* Includes */
+/*****************************************************************************/
+
+#include <Types.h>
+#include <Errors.h>
+#include <Files.h>
+#include <stdio.h>
+#include <string.h>
+
+
+#include "zip.h"
+#include "macstuff.h"
+#include "helpers.h"
+#include "recurse.h"
+#include "macglob.h"
+#include "pathname.h"
+
+
+
+
+/*****************************************************************************/
+/* Macros, typedefs */
+/*****************************************************************************/
+
+/* The RecurseGlobals structure is used to minimize the amount of
+** stack space used when recursively calling RecurseDirectoryLevel
+** and to hold global information that might be needed at any time.
+*/
+struct RecurseGlobals
+{
+ short vRefNum;
+ CInfoPBRec cPB; /* the parameter block used for
+ PBGetCatInfo calls */
+ unsigned char *itemName; /* the name of the current item */
+ char *FullPath;
+ short FullPathLen;
+ OSErr result; /* temporary holder of results -
+ saves 2 bytes of stack each level */
+ Boolean quitFlag; /* set to true if filter wants to
+ kill interation */
+ unsigned short maxLevels; /* Maximum levels to
+ iterate through */
+ unsigned short currentLevel; /* The current level
+ IterateLevel is on */
+};
+
+typedef struct RecurseGlobals RecurseGlobals;
+typedef RecurseGlobals *RecurseGlobalsPtr;
+
+
+/*****************************************************************************/
+/* Global Vars */
+/*****************************************************************************/
+
+extern MacZipGlobals MacZip;
+extern const char ResourceMark[13]; /* "XtraStuf.mac:" var is initialized in file pathname.c */
+extern int extra_fields; /* do not create extra fields if false */
+
+static RecurseGlobals theGlobals;
+
+static unsigned long DirLevels = 0;
+static char *buffer;
+extern int verbose; /* 1=report oddities in zip file structure */
+
+/*****************************************************************************/
+/* Prototypes */
+/*****************************************************************************/
+
+int procname(char *filename, int caseflag);
+int MatchWild( char *pPat, char *pStr, int case_sens);
+Boolean IsZipFile(char *name);
+
+static void RecurseDirectoryLevel(long DirID, RecurseGlobals *Globals);
+static Boolean isRegularItem( RecurseGlobals *Globals);
+static void ProcessFiles(RecurseGlobals *Globals,
+ Boolean hasDataFork, Boolean hasResourceFork);
+static void ProcessDirectory(RecurseGlobals *Globals,
+ Boolean IncludeItem, long DirID);
+static void ProcessItem(RecurseGlobals *Globals, long DirID);
+
+/*****************************************************************************/
+/* Functions */
+/*****************************************************************************/
+
+static void RecurseDirectoryLevel(long DirID, RecurseGlobals *Globals)
+{
+char buffer2[23];
+
+ /* if maxLevels is zero, we aren't checking levels */
+ if ( (Globals->maxLevels == 0) ||
+ /* if currentLevel < maxLevels, look at this level */
+ (Globals->currentLevel < Globals->maxLevels) )
+ {
+ short index = 1;
+
+ ++Globals->currentLevel; /* go to next level */
+ if (DirLevels < Globals->currentLevel) DirLevels = Globals->currentLevel;
+ sprintf(buffer2,"Globals->currentLevel: %d",Globals->currentLevel);
+
+ do
+ { /* Isn't C great... What I'd give for a "WITH
+ theGlobals DO" about now... */
+
+ /* Get next source item at the current directory level */
+ Globals->cPB.dirInfo.ioFDirIndex = index;
+ Globals->cPB.dirInfo.ioDrDirID = DirID;
+ Globals->result = PBGetCatInfoSync((CInfoPBPtr)&Globals->cPB);
+
+ ShowCounter(false);
+
+ if ( Globals->result == noErr )
+ {
+ ProcessItem(Globals, DirID);
+ } /* if ( Globals->result == noErr ) */
+
+ ++index; /* prepare to get next item */
+ /* time to fall back a level? */
+ } while ( (Globals->result == noErr) && (!Globals->quitFlag) );
+
+ if ( (Globals->result == fnfErr) || /* fnfErr is OK -
+ it only means we hit
+ the end of this level */
+ (Globals->result == afpAccessDenied) ) /* afpAccessDenied is OK,
+ too - it only means we cannot see inside a directory */
+ {
+ Globals->result = noErr;
+ }
+
+ --Globals->currentLevel; /* return to previous level as we leave */
+ }
+}
+
+
+
+/*****************************************************************************/
+
+pascal OSErr RecurseDirectory(short vRefNum,
+ long thedirID,
+ ConstStr255Param name,
+ unsigned short maxLevels)
+{
+ OSErr result;
+ short theVRefNum;
+ Boolean isDirectory;
+ long DirID;
+
+ /* Get the real directory ID and make sure it is a directory */
+ result = GetDirectoryID(vRefNum, thedirID, name, &DirID, &isDirectory);
+ if ( result == noErr )
+ {
+ if ( isDirectory == true )
+ {
+ /* Get the real vRefNum */
+ result = DetermineVRefNum(name, vRefNum, &theVRefNum);
+ if ( result == noErr )
+ {
+ /* Set up the globals we need to access from
+ the recursive routine. */
+ theGlobals.cPB.hFileInfo.ioNamePtr = theGlobals.itemName;
+ theGlobals.cPB.hFileInfo.ioVRefNum = theVRefNum;
+ theGlobals.itemName[0] = 0;
+ theGlobals.result = noErr;
+ theGlobals.quitFlag = false;
+ theGlobals.maxLevels = maxLevels;
+ theGlobals.currentLevel = 0; /* start at level 0 */
+
+ /* Here we go into recursion land... */
+ RecurseDirectoryLevel(DirID, &theGlobals);
+
+ result = theGlobals.result; /* set the result */
+ }
+ }
+ else
+ {
+ result = dirNFErr; /* a file was passed instead
+ of a directory */
+ }
+ }
+
+ return ( result );
+}
+
+
+
+/*****************************************************************************/
+
+pascal OSErr FSpRecurseDirectory(const FSSpec *spec,
+ unsigned short maxLevels)
+{
+ OSErr rc;
+
+ theGlobals.vRefNum = spec->vRefNum;
+
+ /* make room for pathnames */
+ theGlobals.itemName = (unsigned char *) StrCalloc(NAME_MAX);
+ theGlobals.FullPath = StrCalloc(NAME_MAX);
+ buffer = StrCalloc(NAME_MAX);
+
+
+ if ((noisy) && (MacZip.DataForkOnly))
+ printf("\n Warning: Datafork only \n");
+
+ /* reset the count to zero */
+ ShowCounter(true);
+
+ if (noisy) leftStatusString("Build File List; Items done:");
+ if (noisy) printf("\n Collecting Filenames ...");
+ rc = RecurseDirectory(spec->vRefNum, spec->parID, spec->name,maxLevels);
+ printerr("RecurseDirectory:",rc,rc,__LINE__,__FILE__,"");
+
+ if (noisy) printf("\n... done \n\n %6d matched files found \n",
+ MacZip.FoundFiles);
+ if (noisy) printf(" %6d folders found in %d Levels \n",
+ MacZip.FoundDirectories,DirLevels);
+
+ if (MacZip.BytesOfData > (1024*1024))
+ if (noisy) printf(" %4.3f MBytes unzipped size\n\n",
+ (float) MacZip.BytesOfData/(1024*1024));
+ else
+ if (noisy) printf(" %4.3f KBytes unzipped size\n\n",
+ (float) MacZip.BytesOfData/1024);
+
+ /* free all memory of pathnames */
+ theGlobals.itemName = (unsigned char *) StrFree((char *)theGlobals.itemName);
+ theGlobals.FullPath = StrFree(theGlobals.FullPath);
+ buffer = StrFree(buffer);
+
+ return rc;
+}
+
+
+
+
+/*
+* Return true if filename == zipfile
+* After the first match no further check will be done !
+*
+*/
+Boolean IsZipFile(char *filen)
+{
+static firstMatch = false;
+
+if (filen == NULL)
+ firstMatch = false;
+
+if (!firstMatch)
+ {
+ if (stricmp(filen, MacZip.ZipFullPath) == 0)
+ {
+ firstMatch = true;
+ return true;
+ }
+ }
+
+return false;
+}
+
+
+
+static Boolean isRegularItem( RecurseGlobals *Globals)
+{
+Boolean isInvisible = false,
+ isAlias = false,
+ isSystem = false;
+
+isSystem = !((Globals->cPB.hFileInfo.ioFlFndrInfo.fdFlags &
+ (1 << 12)) == 0 );
+isInvisible = !((Globals->cPB.hFileInfo.ioFlFndrInfo.fdFlags &
+ (1 << 14)) == 0 );
+isAlias = !((Globals->cPB.hFileInfo.ioFlFndrInfo.fdFlags &
+ (1 << 15)) == 0);
+
+if (isAlias == true)
+ {
+ return false;
+ }
+
+if (MacZip.IncludeInvisible == true)
+ {
+ return true;
+ }
+
+if ((isSystem == true) ||
+ (isInvisible == true))
+ {
+ return false;
+ }
+
+return true;
+}
+
+
+
+
+static void ProcessFiles(RecurseGlobals *Globals,
+ Boolean hasDataFork, Boolean hasResourceFork)
+{
+ /* some file statistics */
+MacZip.FoundFiles++;
+
+if (hasDataFork == true)
+ {
+ MacZip.BytesOfData =
+ Globals->cPB.hFileInfo.ioFlLgLen +
+ MacZip.BytesOfData;
+ MacZip.CurrentFork = DataFork;
+ MacZip.RawCountOfItems++;
+
+ if (MacZip.DataForkOnly == true)
+ {
+ procname(Globals->FullPath, false);
+ hasResourceFork = false;
+ }
+ else
+ {
+ procname(Real2RfDfFilen(buffer,Globals->FullPath,
+ DataFork, MacZip.MacZipMode,
+ MacZip.DataForkOnly), false);
+ }
+ }
+
+if (hasResourceFork == true)
+ {
+ MacZip.BytesOfData =
+ Globals->cPB.hFileInfo.ioFlRLgLen +
+ MacZip.BytesOfData;
+ MacZip.CurrentFork = ResourceFork;
+ MacZip.RawCountOfItems++;
+
+ procname(Real2RfDfFilen(buffer, Globals->FullPath,
+ ResourceFork, MacZip.MacZipMode,
+ MacZip.DataForkOnly), false);
+ }
+}
+
+
+
+
+static void ProcessDirectory(RecurseGlobals *Globals,
+ Boolean IncludeItem, long DirID)
+{
+OSErr rc;
+
+MacZip.isDirectory = true;
+
+GetFullPathFromID(Globals->FullPath,Globals->vRefNum, DirID,
+ Globals->itemName, &rc);
+
+MacZip.RawCountOfItems++;
+MacZip.FoundDirectories++;
+
+if (MacZip.StoreFoldersAlso)
+ {
+ procname(Globals->FullPath, false);
+ }
+
+ /* We have a directory */
+ if ( !Globals->quitFlag && IncludeItem)
+ {
+ /* Dive again if the IterateFilterProc didn't say "quit" and dir is
+ not an alias */
+ RecurseDirectoryLevel(Globals->cPB.dirInfo.ioDrDirID,
+ Globals);
+ }
+}
+
+
+
+static void ProcessItem(RecurseGlobals *Globals, long DirID)
+{
+OSErr rc;
+Boolean IncludeItem = false, hasDataFork = false;
+Boolean hasResourceFork = false;
+
+IncludeItem = isRegularItem(Globals);
+
+/* Is it a File? */
+if ( (Globals->cPB.hFileInfo.ioFlAttrib & ioDirMask) == 0 )
+ {
+ PToCCpy(Globals->itemName,MacZip.FileName);
+ MacZip.isDirectory = false;
+
+ hasDataFork = (Globals->cPB.hFileInfo.ioFlLgLen != 0);
+ hasResourceFork = (Globals->cPB.hFileInfo.ioFlRLgLen != 0);
+
+ /* include also files with zero recource- and data-fork */
+ if ((hasDataFork == 0) && (hasResourceFork == 0))
+ hasDataFork = true;
+
+ if ((hasDataFork == 0) &&
+ (hasResourceFork != 0) &&
+ (extra_fields == false))
+ {
+ IncludeItem = false;
+ }
+
+ GetFullPathFromID(Globals->FullPath,Globals->vRefNum,
+ DirID, Globals->itemName, &rc);
+ printerr("GetFullPathFromID:",rc,rc,__LINE__,
+ __FILE__,MacZip.FileName);
+
+ if (IncludeItem && /* don't include the zipfile itself */
+ (!IsZipFile(Globals->FullPath)) )
+ {
+ if (MATCH(MacZip.Pattern, MacZip.FileName, false) == true)
+ {
+ ProcessFiles(Globals, hasDataFork, hasResourceFork);
+ } /* if (MatchWild( MacZip.FileName,MacZip.Pattern ) ==
+ true) */
+ } /* if (!IsZipFile(Globals->FullPath)) */
+ } /* Is it a File? */
+
+/* Is it a directory? */
+if ( (Globals->cPB.hFileInfo.ioFlAttrib & ioDirMask) != 0 )
+ {
+ ProcessDirectory(Globals,IncludeItem, DirID);
+ } /* Is it a directory? */
+}
diff --git a/macos/source/recurse.h b/macos/source/recurse.h
new file mode 100644
index 0000000..cfbc4b0
--- /dev/null
+++ b/macos/source/recurse.h
@@ -0,0 +1,129 @@
+/*
+** IterateDirectory: File Manager directory iterator routines.
+**
+** by Jim Luther
+**
+** File: IterateDirectory.h
+**
+** Copyright (c) 1995-1998 Jim Luther and Apple Computer, Inc.
+** All rights reserved.
+**
+** You may incorporate this sample code into your applications without
+** restriction, though the sample code has been provided "AS IS" and the
+** responsibility for its operation is 100% yours.
+**
+** IterateDirectory is designed to drop into the MoreFiles sample code
+** library I wrote while in Apple Developer Technical Support
+*/
+
+#ifndef __RECURSEDIRECTORY__
+#define __RECURSEDIRECTORY__
+
+#include <Types.h>
+#include <Files.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*****************************************************************************/
+
+pascal OSErr RecurseDirectory(short vRefNum,
+ long dirID,
+ ConstStr255Param name,
+ unsigned short maxLevels );
+/* Iterate (scan) through a directory's content.
+ The IterateDirectory function performs a recursive iteration (scan) of
+ the specified directory and calls your IterateFilterProc function once
+ for each file and directory found.
+
+ The maxLevels parameter lets you control how deep the recursion goes.
+ If maxLevels is 1, IterateDirectory only scans the specified directory;
+ if maxLevels is 2, IterateDirectory scans the specified directory and
+ one subdirectory below the specified directory; etc. Set maxLevels to
+ zero to scan all levels.
+
+ The yourDataPtr parameter can point to whatever data structure you might
+ want to access from within the IterateFilterProc.
+
+ vRefNum input: Volume specification.
+ dirID input: Directory ID.
+ name input: Pointer to object name, or nil when dirID
+ specifies a directory that's the object.
+ maxLevels input: Maximum number of directory levels to scan or
+ zero to scan all directory levels.
+ iterateFilter input: A pointer to the routine you want called once
+ for each file and directory found by
+ IterateDirectory.
+ yourDataPtr input: A pointer to whatever data structure you might
+ want to access from within the IterateFilterProc.
+
+ Result Codes
+ noErr 0 No error
+ nsvErr -35 No such volume
+ ioErr -36 I/O error
+ bdNamErr -37 Bad filename
+ fnfErr -43 File not found
+ paramErr -50 No default volume or iterateFilter was NULL
+ dirNFErr -120 Directory not found or incomplete pathname
+ or a file was passed instead of a directory
+ afpAccessDenied -5000 User does not have the correct access
+ afpObjectTypeErr -5025 Directory not found or incomplete pathname
+
+ __________
+
+ See also: RecurseFilterProcPtr, FSpRecurseDirectory
+*/
+
+/*****************************************************************************/
+
+pascal OSErr FSpRecurseDirectory(const FSSpec *spec,
+ unsigned short maxLevels);
+/* Iterate (scan) through a directory's content.
+ The FSpIterateDirectory function performs a recursive iteration (scan)
+ of the specified directory and calls your IterateFilterProc function once
+ for each file and directory found.
+
+ The maxLevels parameter lets you control how deep the recursion goes.
+ If maxLevels is 1, FSpIterateDirectory only scans the specified directory;
+ if maxLevels is 2, FSpIterateDirectory scans the specified directory and
+ one subdirectory below the specified directory; etc. Set maxLevels to
+ zero to scan all levels.
+
+ The yourDataPtr parameter can point to whatever data structure you might
+ want to access from within the IterateFilterProc.
+
+ spec input: An FSSpec record specifying the directory to scan.
+ maxLevels input: Maximum number of directory levels to scan or
+ zero to scan all directory levels.
+ iterateFilter input: A pointer to the routine you want called once
+ for each file and directory found by
+ FSpIterateDirectory.
+ yourDataPtr input: A pointer to whatever data structure you might
+ want to access from within the IterateFilterProc.
+
+ Result Codes
+ noErr 0 No error
+ nsvErr -35 No such volume
+ ioErr -36 I/O error
+ bdNamErr -37 Bad filename
+ fnfErr -43 File not found
+ paramErr -50 No default volume or iterateFilter was NULL
+ dirNFErr -120 Directory not found or incomplete pathname
+ afpAccessDenied -5000 User does not have the correct access
+ afpObjectTypeErr -5025 Directory not found or incomplete pathname
+
+ __________
+
+ See also: RecurseFilterProcPtr, RecurseDirectory
+*/
+
+
+
+/*****************************************************************************/
+
+
+
+#endif /* __RECURSEDIRECTORY__ */
diff --git a/macos/source/unixlike.c b/macos/source/unixlike.c
new file mode 100644
index 0000000..017d3fa
--- /dev/null
+++ b/macos/source/unixlike.c
@@ -0,0 +1,313 @@
+/*
+ Copyright (c) 1990-2005 Info-ZIP. All rights reserved.
+
+ See the accompanying file LICENSE, version 2004-May-22 or later
+ (the contents of which are also included in zip.h) for terms of use.
+ If, for some reason, both of these files are missing, the Info-ZIP license
+ also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*---------------------------------------------------------------------------
+
+ unixlike.c
+
+ Macintosh-specific routines to emulate unixfunctions.
+
+ ---------------------------------------------------------------------------*/
+
+/*****************************************************************************/
+/* Includes */
+/*****************************************************************************/
+
+#include "zip.h"
+
+#include <string.h>
+#include <stdio.h>
+#include <sound.h>
+
+#include "unixlike.h"
+#include "helpers.h"
+#include "pathname.h"
+#include "macstuff.h"
+#include "macglob.h"
+#include "mactime.h"
+
+/*****************************************************************************/
+/* Global Vars */
+/*****************************************************************************/
+
+extern MacZipGlobals MacZip;
+extern int errno;
+
+
+/*****************************************************************************/
+/* Prototypes */
+/*****************************************************************************/
+
+
+/*****************************************************************************/
+/* Functions */
+/*****************************************************************************/
+
+
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MacStat --
+ *
+ * This function replaces the library version of stat. The stat
+ * function provided by most Mac compiliers is rather broken and
+ * incomplete.
+ *
+ * Results:
+ * See stat documentation.
+ *
+ * Side effects:
+ * See stat documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int Zmacstat(const char *Fname, struct stat *buf)
+{
+ OSErr err, rc;
+ short fullPathLength;
+ Handle hFullPath;
+ char path[NAME_MAX], path2[NAME_MAX];
+ HVolumeParam vpb;
+ static unsigned long count_of_files = 0;
+
+ AssertStr(Fname,Fname)
+ Assert_it(buf,"","")
+
+ UserStop();
+
+ memset(buf, 0, sizeof(buf)); /* zero out all fields */
+
+ RfDfFilen2Real(path2, Fname, MacZip.MacZipMode, MacZip.DataForkOnly,
+ &MacZip.CurrentFork);
+ GetCompletePath(path, path2, &MacZip.fileSpec, &err);
+ err = PrintUserHFSerr((err != -43) && (err != 0), err, path);
+ printerr("GetCompletePath:", err, err, __LINE__, __FILE__, path);
+
+ if (err != noErr) {
+ errno = err;
+ return -1;
+ }
+
+ /* Collect here some more information, it's not related to Macstat.
+ (note: filespec gets changed later in this function) */
+ /* clear string-buffer */
+ memset(MacZip.FullPath, 0x00, sizeof(MacZip.FullPath));
+ rc = FSpGetFullPath(&MacZip.fileSpec, &fullPathLength, &hFullPath);
+ strncpy(MacZip.FullPath, *hFullPath, fullPathLength);
+ DisposeHandle(hFullPath); /* we don't need it any more */
+ /* Collect some more information not related to Macstat */
+
+
+ /*
+ * Fill the fpb & vpb struct up with info about file or directory.
+ */
+
+ FSpGetDirectoryID(&MacZip.fileSpec, &MacZip.dirID, &MacZip.isDirectory);
+ vpb.ioVRefNum = MacZip.fpb.hFileInfo.ioVRefNum = MacZip.fileSpec.vRefNum;
+ vpb.ioNamePtr = MacZip.fpb.hFileInfo.ioNamePtr = MacZip.fileSpec.name;
+
+ if (MacZip.isDirectory) {
+ MacZip.fpb.hFileInfo.ioDirID = MacZip.fileSpec.parID;
+ /*
+ * Directories are executable by everyone.
+ */
+ buf->st_mode |= UNX_IXUSR | UNX_IXGRP | UNX_IXOTH | UNX_IFDIR;
+ } else {
+ MacZip.fpb.hFileInfo.ioDirID = MacZip.dirID;
+ }
+
+ MacZip.fpb.hFileInfo.ioFDirIndex = 0;
+ err = PBGetCatInfoSync((CInfoPBPtr)&MacZip.fpb);
+
+ if (err == noErr) {
+ vpb.ioVolIndex = 0;
+ err = PBHGetVInfoSync((HParmBlkPtr)&vpb);
+ if (err == noErr && buf != NULL) {
+ /*
+ * Files are always readable by everyone.
+ */
+ buf->st_mode |= UNX_IRUSR | UNX_IRGRP | UNX_IROTH;
+
+ /*
+ * Use the Volume Info & File Info to fill out stat buf.
+ */
+ if (MacZip.fpb.hFileInfo.ioFlAttrib & 0x10) {
+ buf->st_mode |= UNX_IFDIR;
+ buf->st_nlink = 2;
+ } else {
+ buf->st_nlink = 1;
+ if (MacZip.fpb.hFileInfo.ioFlFndrInfo.fdFlags & 0x8000) {
+ buf->st_mode |= UNX_IFLNK;
+ } else {
+ buf->st_mode |= UNX_IFREG;
+ }
+ }
+
+ if (MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType == 'APPL') {
+ /*
+ * Applications are executable by everyone.
+ */
+ buf->st_mode |= UNX_IXUSR | UNX_IXGRP | UNX_IXOTH;
+ }
+ if ((MacZip.fpb.hFileInfo.ioFlAttrib & 0x01) == 0){
+ /*
+ * If not locked, then everyone has write acces.
+ */
+ buf->st_mode |= UNX_IWUSR | UNX_IWGRP | UNX_IWOTH;
+ }
+
+ buf->st_ino = MacZip.fpb.hFileInfo.ioDirID;
+ buf->st_dev = MacZip.fpb.hFileInfo.ioVRefNum;
+ buf->st_uid = -1;
+ buf->st_gid = -1;
+ buf->st_rdev = 0;
+
+ if (MacZip.CurrentFork == ResourceFork)
+ buf->st_size = MacZip.fpb.hFileInfo.ioFlRLgLen;
+ else
+ buf->st_size = MacZip.fpb.hFileInfo.ioFlLgLen;
+
+ buf->st_blksize = vpb.ioVAlBlkSiz;
+ buf->st_blocks = (buf->st_size + buf->st_blksize - 1)
+ / buf->st_blksize;
+
+ /*
+ * The times returned by the Mac file system are in the
+ * local time zone. We convert them to GMT so that the
+ * epoch starts from GMT. This is also consistent with
+ * what is returned from "clock seconds".
+ */
+ if (!MacZip.isDirectory) {
+ MacZip.CreatDate = MacZip.fpb.hFileInfo.ioFlCrDat;
+ MacZip.ModDate = MacZip.fpb.hFileInfo.ioFlMdDat;
+ MacZip.BackDate = MacZip.fpb.hFileInfo.ioFlBkDat;
+ } else {
+ MacZip.CreatDate = MacZip.fpb.dirInfo.ioDrCrDat;
+ MacZip.ModDate = MacZip.fpb.dirInfo.ioDrMdDat;
+ MacZip.BackDate = MacZip.fpb.dirInfo.ioDrBkDat;
+ }
+
+#ifdef IZ_CHECK_TZ
+ if (!zp_tz_is_valid)
+ {
+ MacZip.HaveGMToffset = false;
+ MacZip.Md_UTCoffs = 0L;
+ MacZip.Cr_UTCoffs = 0L;
+ MacZip.Bk_UTCoffs = 0L;
+ }
+ else
+#endif
+ {
+ /* Do not use GMT offsets when Md_UTCoffs calculation
+ * fails, since this time stamp is used for time
+ * comparisons in Zip and UnZip operations.
+ * We do not bother when GMT offset calculation fails for
+ * any other time stamp value. Instead we simply assume
+ * a default value of 0.
+ */
+ MacZip.HaveGMToffset =
+ GetGMToffsetMac(MacZip.ModDate, &MacZip.Md_UTCoffs);
+ if (MacZip.HaveGMToffset) {
+ GetGMToffsetMac(MacZip.CreatDate, &MacZip.Cr_UTCoffs);
+ GetGMToffsetMac(MacZip.BackDate, &MacZip.Bk_UTCoffs);
+ } else {
+ MacZip.Cr_UTCoffs = 0L;
+ MacZip.Bk_UTCoffs = 0L;
+ }
+ }
+#ifdef DEBUG_TIME
+ {
+ printf("\nZmacstat: MacZip.HaveGMToffset: %d",
+ MacZip.HaveGMToffset);
+ printf("\nZmacstat: Mac modif: %lu local -> UTOffset: %d",
+ MacZip.ModDate, MacZip.Md_UTCoffs);
+ printf("\nZmacstat: Mac creat: %lu local -> UTOffset: %d",
+ MacZip.CreatDate, MacZip.Cr_UTCoffs);
+ printf("\nZmacstat: Mac back: %lu local -> UTOffset: %d",
+ MacZip.BackDate, MacZip.Bk_UTCoffs);
+ }
+#endif /* DEBUG_TIME */
+
+
+ buf->st_mtime = MacFtime2UnixFtime(MacZip.ModDate);
+ buf->st_ctime = MacFtime2UnixFtime(MacZip.CreatDate);
+ buf->st_atime = buf->st_mtime;
+
+#ifdef DEBUG_TIME
+ {
+ printf("\nZmacstat: Unix modif: %lu UTC; Mac: %lu local",
+ buf->st_mtime, MacZip.ModDate);
+ printf("\nZmacstat: Unix creat: %lu UTC; Mac: %lu local\n",
+ buf->st_ctime, MacZip.CreatDate);
+ }
+#endif /* DEBUG_TIME */
+
+ if (noisy)
+ {
+ if (MacZip.StatingProgress)
+ {
+ count_of_files++;
+ InformProgress(MacZip.RawCountOfItems, count_of_files );
+ }
+ else
+ count_of_files = 0;
+ }
+ }
+ }
+
+ if (err != noErr) {
+ errno = err;
+ }
+
+ MacZip.isMacStatValid = true;
+ return (err == noErr ? 0 : -1);
+}
+
+
+
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * chmod --
+ *
+ * Results:
+ * See chmod documentation.
+ *
+ * Side effects:
+ * See chmod documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int chmod(char *path, int mode)
+{
+ HParamBlockRec hpb;
+ OSErr err;
+
+ hpb.fileParam.ioNamePtr = C2PStr(path);
+ hpb.fileParam.ioVRefNum = 0;
+ hpb.fileParam.ioDirID = 0;
+
+ if (mode & 0200) {
+ err = PBHRstFLockSync(&hpb);
+ } else {
+ err = PBHSetFLockSync(&hpb);
+ }
+
+ if (err != noErr) {
+ errno = err;
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/macos/source/unixlike.h b/macos/source/unixlike.h
new file mode 100644
index 0000000..e61a354
--- /dev/null
+++ b/macos/source/unixlike.h
@@ -0,0 +1,86 @@
+/*
+ Copyright (c) 1990-1999 Info-ZIP. All rights reserved.
+
+ See the accompanying file LICENSE, version 1999-Oct-05 or later
+ (the contents of which are also included in zip.h) for terms of use.
+ If, for some reason, both of these files are missing, the Info-ZIP license
+ also may be found at: ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+/*
+ * Directory Operations for Mac based on BSD 4.3 <macdir.h>
+ * By Jason Linhart, January 1997
+ */
+
+#ifndef _UNIXLIKE_H
+#define _UNIXLIKE_H 1
+
+#include <stat.h>
+
+#ifndef NAME_MAX
+#define NAME_MAX 2048
+#endif
+
+#define UNX_IFMT 0170000 /* Unix file type mask */
+#define UNX_IFSOCK 0140000 /* Unix socket (BSD, not SysV or Amiga) */
+#define UNX_IFLNK 0120000 /* Unix symbolic link (not SysV, Amiga) */
+#define UNX_IFREG 0100000 /* Unix regular file */
+#define UNX_IFBLK 0060000 /* Unix block special (not Amiga) */
+#define UNX_IFDIR 0040000 /* Unix directory */
+#define UNX_IFCHR 0020000 /* Unix character special (not Amiga) */
+#define UNX_IFIFO 0010000 /* Unix fifo (BCC, not MSC or Amiga) */
+
+#define UNX_ISUID 04000 /* Unix set user id on execution */
+#define UNX_ISGID 02000 /* Unix set group id on execution */
+#define UNX_ISVTX 01000 /* Unix directory permissions control */
+#define UNX_ENFMT UNX_ISGID /* Unix record locking enforcement flag */
+
+#define UNX_IRWXU 00700 /* Unix read, write, execute: owner */
+#define UNX_IRUSR 00400 /* Unix read permission: owner */
+#define UNX_IWUSR 00200 /* Unix write permission: owner */
+#define UNX_IXUSR 00100 /* Unix execute permission: owner */
+
+#define UNX_IRWXG 00070 /* Unix read, write, execute: group */
+#define UNX_IRGRP 00040 /* Unix read permission: group */
+#define UNX_IWGRP 00020 /* Unix write permission: group */
+#define UNX_IXGRP 00010 /* Unix execute permission: group */
+
+#define UNX_IRWXO 00007 /* Unix read, write, execute: other */
+#define UNX_IROTH 00004 /* Unix read permission: other */
+#define UNX_IWOTH 00002 /* Unix write permission: other */
+#define UNX_IXOTH 00001 /* Unix execute permission: other */
+
+/* historical file modes */
+#define S_IREAD 0x100
+#define S_IWRITE 0x80
+#define S_IEXEC 0x40
+
+
+#define isatty(arg) 1
+
+
+#define EINVAL 22 /* Invalid argument */
+#define ENAMETOOLONG 63 /* File name too long */
+
+
+struct dirent {
+ char d_name[NAME_MAX];
+};
+
+/*
+ * The following definitions are usually found in fcntl.h.
+ * However, MetroWerks has screwed that file up a couple of times
+ * and all we need are the defines.
+ */
+#define O_APPEND 0x0100 /* open the file in append mode */
+#define O_CREAT 0x0200 /* create the file if it doesn't exist */
+#define O_EXCL 0x0400 /* if the file exists don't create it again */
+#define O_TRUNC 0x0800 /* truncate the file after opening it */
+
+
+int Zmacstat (const char *path, struct stat *buf);
+int chmod(char *path, int mode);
+
+
+#include "macstuff.h"
+
+#endif /* _UNIXLIKE_H */
diff --git a/macos/source/zip_rc.hqx b/macos/source/zip_rc.hqx
new file mode 100644
index 0000000..99e0d25
--- /dev/null
+++ b/macos/source/zip_rc.hqx
@@ -0,0 +1,43 @@
+(This file must be converted with BinHex 4.0)
+:#RTTF#jbBbjcDA3!8dP84&0*9#%!N!3([`#3"&(E8dP8)3!"!!!([h*-BA8#Q3#
+3!aDCQ3d!"RTTF#jbB`!!&[Bi"2[rG!"-5QS!N!1!!*!%"32,j+m2!*!Drj!%8P0
+53e*6483"",#mXHDaqlGG!!!GmJ#3"JFj!*!%6Mi!N!MGc!`!P@6pq1R*k4&+Z,d
+p"5$(b(-Upcc#j%EiHCfjPTq%8h+X8d)MR$`rF[b9Vh`pTLc2jqZ9r'RNq9VN1'&
+'MMmj6Sk6#5HFc0J4lN8iHFU2--,*K%Z1NIR+#1XNR("#bE-)2I+FF$*G@H6BL+`
+*!&6IV1ml1d+22#-$4UEm*#01"T`m*4`Ji(03ThM'$-EBilf-V8-e6Q8bXEVD@Xi
+2bilcmGEY"lV6QGjZrK)I1CKZ$BfR4pSbLD'f`F'qVPKb+*(-*V2CPLfaGj1CE+a
+Z+-$kpr4hpHrCf@d%f66E!A2P-rA6phmUj)QrdYP4r[6)H+cZF"hRV``NHSG5`b!
+F6-0YBZ$!JH&%#frIb,2TmH4`LVGN4c1(%U1Q8#cf)P44dU"#-`D)I($H4I5qc[j
+NJLI5)qpN5)Ic[S(-`-&1H(U2L*U'-H`1Y1p&qc#*YVk4(RNUbp(ae(#'R,B[d%B
+(Nd40$id1C`FhmUlKNBmbkAf$Sra8qpDYcm0,H%GIhbiej(!EESbmC+a*'3dqdlC
+j)%*H#+!,D!K4#J#3!$9H-J)mB*6L!50R"%"&hi6DD*61[-qq22%f1hkXPq@r)'`
+(1hjQJ19cKP'bY0#60RQ3!&kd,r))mj-X,LBCCa&CeiX#f`ibZ$9##+[1HUJ34G5
+584+#&@p9i[UDj-&PD2rAi0qYdMpMQ""M8FLBT`#FUMje-i6rVXl2qI`jK@XY#eH
++%JH[5(`6,qEcH@K,(FfA4rZDNG,4mp60fALH@TT,SC!!5Sf0$HHP31&mP"AfKN)
+K-!N[&XjM@##`1I,(a"V"#L%@#U9'*'lT-5CaU8GqpLTFkUP"%klmfMLJ1QpH5r2
+djNdfhIXJFIqqN!!&1QHe$jUlHF`jZ2I41X8k$@ZbKF1C2"Cq6YZaF(Z+5Yra&63
+"alCh62Vm6N(RqR90&)#m`cE3mILqV`@qBmcQkf0"9Ei%#**RRRpcS0DmV!N6DB-
+&#R112Ym4-1d)GJ(R0,i,0!TEJ!%$#Mj$SFqp80)XU4&"+j!!DmFJk)S2*[(KNMR
+mHApd)4Im@I2aqEBrpd,EVi3ehd@qETI[eprhmmlp0UGjqhe`q#[[Ljk#GDclAll
+[P91j$d[[ir`4X1LcbmVcI$8cCd49rY*`E2l+F1l-Uk0CV,edY8%d('d@pD*qVRk
+L@64FE9KlU9Q%E`3$i@+cD"BSp)'26f,8K%[iL[#3!$-h&aDPY5L2CJBBpF5Kh5k
++ASJVqckQ9kG`*C95rEka+29B5U+f"eYIqF&ZC()P-%GbHXQ44)a!l[Z9q3[c5Z!
+aN!!pGHT"X#q,IJ$8lG#i224dkNXMhd,#3I"ap4JkEk@YlrKEp1r14erRqIYVJY@
+RbX4G0GVTc4A5A20`[E`GcX60GGI#0@$KHMqfFB9BIV4&%kr6+kH*J`(FR3lKcJj
+pNqpN!JiZ-`'&1jQ!a*e-31RCQB$%R8c!dY1CJ19(C`+@AjGIa[qCCq8qH,K8FA%
+LH$LpGbZiFpp0ehUR[lZTL-[HU3T8q*FVkd5&AaDBjrX##ha2S$UImK6,r-Z9MDM
+#PaVqNfUH+VqmXplAGpG!G`k,I&I!i[ZC`J,Iba3@rEQC`J,Iba5@rFQGIhNq5h`
+r-lM2ArAJIYjp(jEjYX!5he+i`cIhZRrjYq)%rjNh@"K4Ej!!V8&p!,8@0C*$l3L
+bk#`f"%i9DMaRk,i*YC&aj0dFH6G(hXf4Gh2Nh4ajYp5aY(5[I@a#hBBDeh9E'*X
+Kq3q,)QS*99$0SCj&R68Va[9Ie6lJ9444KDk%dDE9%CrPQhJ,hbD#)RJ8936RJK1
+bjb%HMTILXr&#r&Um++SIZ#*1fAP1hM-c'CG*VekG*BkGApkj'DZA13GkPA1JPcN
+(iC4c%*m@1&[2l0@LLCK%pFUBG%kj4M@2,@pY&UjA+*Y2#Zil5%pF&GI[LBAVh-2
+$3I"aCG,5ekC[qL[MlZ1QRP32Ga5YQFY`Cf-[rZ!JX+GrCir-1R)J6J!jdY[ekRU
+IXFT6',*jNmH[B69Hq&&6$N-NlS3K8Xm03mM2+VTKb253!iSqNDRHIKqNq$hqV6$
+%pVF8KPMc@68N$0Q#[KXH1UJL$1P'',*PpB``C"5M'eXG)JbTfDal(BB!AfdN$-'
+cjq2P-%6bli8Kq,pej"NCErJr%NGk[[Pkpa44M+pBl4Mq$SC![ij'pZ[3j20d)N[
+i$qR%J5hSI`01r3hJcl+!m54`kMY9f'+N1PrYaRqe4SCq@E8Hr)$%dK,,5@`LdR2
+b$cBKPr+"5-q*AH`)BBm-4AUqlG-DHk"a9QQ`Yi"0+Beefb-pTlj6'Z(2`,ZS0"j
++!KY9'SpQ-0f,5U2Q'(Lr+Sd(h`3fV65DpX2VT0+)[!EHKdUMS4ABTdVMX4IJG8T
+T'*pJ6K'P8IXk0+iTMFB8I'L[i9r!Qp6c`!dlH9,2idGJTp9PD'b(MjH9AZ0cQ02
+TqYdI$#8c2*2-$Kr+**,r!`#3!dm4!!!: