diff options
Diffstat (limited to 'macos/source')
-rw-r--r-- | macos/source/VolWarn.h | 69 | ||||
-rw-r--r-- | macos/source/charmap.h | 380 | ||||
-rw-r--r-- | macos/source/extrafld.c | 920 | ||||
-rw-r--r-- | macos/source/getenv.c | 398 | ||||
-rw-r--r-- | macos/source/helpers.c | 477 | ||||
-rw-r--r-- | macos/source/helpers.h | 57 | ||||
-rw-r--r-- | macos/source/macglob.h | 86 | ||||
-rw-r--r-- | macos/source/macopen.c | 363 | ||||
-rw-r--r-- | macos/source/macopen.h | 21 | ||||
-rw-r--r-- | macos/source/macos.c | 1079 | ||||
-rw-r--r-- | macos/source/macstuff.c | 1724 | ||||
-rw-r--r-- | macos/source/macstuff.h | 1108 | ||||
-rw-r--r-- | macos/source/mactime.c | 451 | ||||
-rw-r--r-- | macos/source/mactime.h | 61 | ||||
-rw-r--r-- | macos/source/pathname.c | 665 | ||||
-rw-r--r-- | macos/source/pathname.h | 59 | ||||
-rw-r--r-- | macos/source/recurse.c | 442 | ||||
-rw-r--r-- | macos/source/recurse.h | 129 | ||||
-rw-r--r-- | macos/source/unixlike.c | 313 | ||||
-rw-r--r-- | macos/source/unixlike.h | 86 | ||||
-rw-r--r-- | macos/source/zip_rc.hqx | 43 |
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!!!: |