Carbonize AppleSingle decoder, fileMacAlias() XPInstall API, and

gestalt() XPInstall API to restore XPInstall to full working
functionality on Mach-O builds.
b=202772; r=ssu, ccarlen, sr=sfraser; a=asa


git-svn-id: svn://10.0.0.236/trunk@142673 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
sgehani%netscape.com 2003-05-21 00:53:35 +00:00
parent a4bd0b269f
commit 2d9b362f53
5 changed files with 743 additions and 776 deletions

View File

@ -109,6 +109,19 @@ CPPSRCS += \
OS_LIBS += $(call EXPAND_LIBNAME,ole32 version uuid)
endif
# Support AppleSingle decoding on Mac OS X
ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
REQUIRES += macmorefiles
CPPSRCS += \
nsAppleSingleDecoder.cpp \
$(NULL)
LIBS += \
$(DEPTH)/dist/lib/libmacmorefiles_s.a \
$(NULL)
endif
LOCAL_INCLUDES = -I$(srcdir)/../public
EXTRA_DSO_LDOPTS = \

File diff suppressed because it is too large Load Diff

View File

@ -23,13 +23,9 @@
/*----------------------------------------------------------------------*
* Implements a simple AppleSingle decoder, as described in RFC1740
* http://andrew2.andrew.cmu.edu/rfc/rfc1740.html
* http://andrew2.andrew.cmu.edu/rfc/rfc1740.html
*----------------------------------------------------------------------*/
#ifndef macintosh
#error Sorry! This is Mac only functionality!
#endif
#pragma options align=mac68k
#ifndef _NS_APPLESINGLEDECODER_H_
@ -37,48 +33,50 @@
#include <stdlib.h>
#include <string.h>
#include <Files.h>
#include <Errors.h>
#include <Carbon/Carbon.h>
/*----------------------------------------------------------------------*
* Struct definitions from RFC1740
*----------------------------------------------------------------------*/
#define APPLESINGLE_MAGIC 0x00051600L
#define APPLESINGLE_VERSION 0x00020000L
typedef struct ASHeader /* header portion of AppleSingle */
{
/* AppleSingle = 0x00051600; AppleDouble = 0x00051607 */
UInt32 magicNum; /* internal file type tag */
UInt32 versionNum; /* format version: 2 = 0x00020000 */
UInt8 filler[16]; /* filler, currently all bits 0 */
UInt16 numEntries; /* number of entries which follow */
/* AppleSingle = 0x00051600; AppleDouble = 0x00051607 */
UInt32 magicNum; /* internal file type tag */
UInt32 versionNum; /* format version: 2 = 0x00020000 */
UInt8 filler[16]; /* filler, currently all bits 0 */
UInt16 numEntries; /* number of entries which follow */
} ASHeader ; /* ASHeader */
typedef struct ASEntry /* one AppleSingle entry descriptor */
{
UInt32 entryID; /* entry type: see list, 0 invalid */
UInt32 entryOffset; /* offset, in octets, from beginning */
/* of file to this entry's data */
UInt32 entryLength; /* length of data in octets */
UInt32 entryID; /* entry type: see list, 0 invalid */
UInt32 entryOffset; /* offset, in octets, from beginning */
/* of file to this entry's data */
UInt32 entryLength; /* length of data in octets */
} ASEntry; /* ASEntry */
typedef struct ASFinderInfo
{
FInfo ioFlFndrInfo; /* PBGetFileInfo() or PBGetCatInfo() */
FXInfo ioFlXFndrInfo; /* PBGetCatInfo() (HFS only) */
FInfo ioFlFndrInfo; /* PBGetFileInfo() or PBGetCatInfo() */
FXInfo ioFlXFndrInfo; /* PBGetCatInfo() (HFS only) */
} ASFinderInfo; /* ASFinderInfo */
typedef struct ASMacInfo /* entry ID 10, Macintosh file information */
typedef struct ASMacInfo /* entry ID 10, Macintosh file information */
{
UInt8 filler[3]; /* filler, currently all bits 0 */
UInt8 ioFlAttrib; /* PBGetFileInfo() or PBGetCatInfo() */
UInt8 filler[3]; /* filler, currently all bits 0 */
UInt8 ioFlAttrib; /* PBGetFileInfo() or PBGetCatInfo() */
} ASMacInfo;
typedef struct ASFileDates /* entry ID 8, file dates info */
typedef struct ASFileDates /* entry ID 8, file dates info */
{
SInt32 create; /* file creation date/time */
SInt32 modify; /* last modification date/time */
SInt32 backup; /* last backup date/time */
SInt32 access; /* last access date/time */
SInt32 create; /* file creation date/time */
SInt32 modify; /* last modification date/time */
SInt32 backup; /* last backup date/time */
SInt32 access; /* last access date/time */
} ASFileDates; /* ASFileDates */
/* entryID list */
@ -88,7 +86,7 @@ typedef struct ASFileDates /* entry ID 8, file dates info */
#define AS_COMMENT 4 /* standard Mac comment */
#define AS_ICONBW 5 /* Mac black & white icon */
#define AS_ICONCOLOR 6 /* Mac color icon */
/* 7 /* not used */
/* 7 not used */
#define AS_FILEDATES 8 /* file dates; create, modify, etc */
#define AS_FINDERINFO 9 /* Mac Finder info & extended info */
#define AS_MACINFO 10 /* Mac file info, attributes, etc */
@ -103,118 +101,115 @@ typedef struct ASFileDates /* entry ID 8, file dates info */
/*----------------------------------------------------------------------*
* Macros
*----------------------------------------------------------------------*/
#define MAC_ERR_CHECK(_funcCall) \
err = _funcCall; \
if (err!=noErr) \
return err;
#define MAC_ERR_CHECK(_funcCall) \
err = _funcCall; \
if (err!=noErr) \
return err;
class nsAppleSingleDecoder
{
public:
nsAppleSingleDecoder(FSSpec *inSpec, FSSpec *outSpec);
nsAppleSingleDecoder();
~nsAppleSingleDecoder();
/**
* Decode
*
* Takes an "in" FSSpec for the source file in AppleSingle
* format to decode and write out to an "out" FSSpec.
* This form is used when the Decode(void) method has already
* been invoked once and this object is reused to decode
* another AppleSingled file: useful in iteration to avoid
* nsAppleSingleDecoder object instantiation per file.
*
* @param inSpec the AppleSingled file to decode
* @param outSpec the destination file in which the decoded
* data was written out (empty when passed in
* and filled on return)
* @return err a standard MacOS OSErr where noErr means OK
*/
OSErr Decode(FSSpec *inSpec, FSSpec *outSpec);
/**
* Decode
*
* Decodes the AppleSingled file passed in to the constructor
* and writes out the decoded data to the outSpec passed to the
* constructor.
*
* @return err a standard MacOS OSErr where noErr = OK
*/
OSErr Decode();
/**
* DecodeFolder
*
* Traverses arbitrarily nested subdirs decoding any files
* in AppleSingle format and leaving other files alone.
*
* @param aFolder the folder whose contents to decode
* @return err a standard MacOS err (dirNFErr if invalid dir, noErr = OK)
*/
OSErr DecodeFolder(FSSpec *aFolder);
nsAppleSingleDecoder(const FSRef *inRef, FSRef *outRef);
nsAppleSingleDecoder();
~nsAppleSingleDecoder();
/**
* Decode
*
* Takes an "in" FSSpec for the source file in AppleSingle
* format to decode and write out to an "out" FSSpec.
* This form is used when the Decode(void) method has already
* been invoked once and this object is reused to decode
* another AppleSingled file: useful in iteration to avoid
* nsAppleSingleDecoder object instantiation per file.
*
* @param inRef the AppleSingled file to decode
* @param outRef the destination file in which the decoded
* data was written out (empty when passed in
* and filled on return)
* @return err a standard MacOS OSErr where noErr means OK
*/
OSErr Decode(const FSRef *inRef, FSRef *outRef);
/**
* Decode
*
* Decodes the AppleSingled file passed in to the constructor
* and writes out the decoded data to the outSpec passed to the
* constructor.
*
* @return err a standard MacOS OSErr where noErr = OK
*/
OSErr Decode();
/**
* DecodeFolder
*
* Traverses arbitrarily nested subdirs decoding any files
* in AppleSingle format and leaving other files alone.
*
* @param aFolder the folder whose contents to decode
* @return err a standard MacOS err
* (dirNFErr if invalid dir, noErr = OK)
*/
OSErr DecodeFolder(const FSRef *aFolder);
/**
* IsAppleSingleFile
*
* Checks the file header to see whether this is an AppleSingle
* version 2 file by matching the magicNum field in the header.
*
* @param inSpec the file to check
* @return bAppleSingle a Boolean where true indicates this is
* in fact an AppleSingle file
*/
static Boolean IsAppleSingleFile(FSSpec *inSpec);
/**
* String utilities to ensure building standalone
* since Mozilla doesn't use PLStringFuncs.
*/
static StringPtr PLstrncpy(StringPtr dst, ConstStr255Param src, short max);
static StringPtr PLstrncat(StringPtr dst, ConstStr255Param src, short max);
static Boolean PLstrcmp(StringPtr str1, StringPtr str2);
/**
* ltoa -- long to ascii
*
* Converts a long to a C string. We allocate
* a string of the appropriate size and the caller
* should assume ownership of the returned pointer.
*/
static char *ltoa(long n);
private:
FSSpec *mInSpec;
FSSpec *mOutSpec;
short mInRefNum; // cache since it's used through the life of one Decode cycle
Boolean mRenameReqd;
OSType mCreator;
OSType mType;
OSErr ProcessASEntry(ASEntry inEntry);
OSErr ProcessDataFork(ASEntry inEntry);
OSErr ProcessResourceFork(ASEntry inEntry);
OSErr ProcessRealName(ASEntry inEntry);
OSErr ProcessFileDates(ASEntry inEntry);
OSErr ProcessFinderInfo(ASEntry inEntry);
OSErr ProcessMacInfo(ASEntry inEntry);
OSErr EntryToMacFile(ASEntry inEntry, UInt16 inTargetSpecRefNum);
OSErr DTSetAPPL(Str255 volName, short vRefNum, OSType creator,
long applParID, Str255 applName);
/**
* IsAppleSingleFile
*
* Checks the file header to see whether this is an AppleSingle
* version 2 file by matching the magicNum field in the header.
*
* @param inRef the file to check
* @return bAppleSingle a Boolean where true indicates this is
* in fact an AppleSingle file
*/
static Boolean IsAppleSingleFile(const FSRef *inRef);
/**
* IsDirectory
*
* Check whether the supplied FSSpec points to a directory.
*
* @param inRef the file/directory spec
* @return bDir true iff this spec is a valid directory
*/
static Boolean IsDirectory(const FSRef *inRef);
OSErr FSMakeUnique(FSSpec *ioSpec);
/**
* String utility wrapper to compare to Unicode filenames.
*/
static Boolean UCstrcmp(const HFSUniStr255 *str1, const HFSUniStr255 *str2);
private:
const FSRef *mInRef;
FSRef *mOutRef;
// cache since it's used through the life of one Decode cycle:
SInt16 mInRefNum;
Boolean mRenameReqd;
OSErr ProcessASEntry(ASEntry inEntry);
OSErr ProcessDataFork(ASEntry inEntry);
OSErr ProcessResourceFork(ASEntry inEntry);
OSErr ProcessRealName(ASEntry inEntry);
OSErr ProcessFileDates(ASEntry inEntry);
OSErr ProcessFinderInfo(ASEntry inEntry);
OSErr EntryToMacFile(ASEntry inEntry, UInt16 inTargetSpecRefNum);
OSErr FSMakeUnique(const FSRef *inParentRef, FSRef *outRef);
};
#ifdef __cplusplus
extern "C" {
#endif
pascal void
DecodeDirIterateFilter(const CInfoPBRec * const cpbPtr, Boolean *quitFlag, void *yourDataPtr);
Boolean
DecodeDirIterateFilter(Boolean containerChanged, ItemCount currentLevel,
const FSCatalogInfo *catalogInfo, const FSRef *ref,
const FSSpec *spec, const HFSUniStr255 *name, void *yourDataPtr);
#ifdef __cplusplus
}
@ -222,4 +217,4 @@ DecodeDirIterateFilter(const CInfoPBRec * const cpbPtr, Boolean *quitFlag, void
#pragma options align=reset
#endif /* _NS_APPLESINGLEDECODER_H_ */
#endif /* _NS_APPLESINGLEDECODER_H_ */

View File

@ -23,6 +23,7 @@
* Douglas Turner <dougt@netscape.com>
* Pierre Phaneuf <pp@ludusdesign.com>
* Sean Su <ssu@netscape.com>
* Samir Gehani <sgehani@netscape.com>
*/
@ -75,8 +76,8 @@
#include "nsInstallFileOpEnums.h"
#include "nsInstallFileOpItem.h"
#ifdef XP_MAC
#include "Gestalt.h"
#if defined(XP_MAC) || defined(XP_MACOSX)
#include <Gestalt.h>
#include "nsAppleSingleDecoder.h"
#include "nsILocalFileMac.h"
#endif
@ -328,7 +329,7 @@ nsInstall::GetInstallPlatform(nsCString& aPlatform)
mInstallPlatform += ' ';
mInstallPlatform += (char*)name.machine;
}
#elif defined (XP_MAC)
#elif defined (XP_MAC) || defined (XP_MACOSX)
mInstallPlatform += "PPC";
#elif defined(XP_OS2)
ULONG os2ver = 0;
@ -902,12 +903,12 @@ nsInstall::FinalizeInstall(PRInt32* aReturn)
return NS_OK;
}
#ifdef XP_MAC
#if defined(XP_MAC) || defined(XP_MACOSX)
#define GESTALT_CHAR_CODE(x) (((unsigned long) ((x[0]) & 0x000000FF)) << 24) \
| (((unsigned long) ((x[1]) & 0x000000FF)) << 16) \
| (((unsigned long) ((x[2]) & 0x000000FF)) << 8) \
| (((unsigned long) ((x[3]) & 0x000000FF)))
#endif /* XP_MAC */
#endif /* XP_MACOS || XP_MACOSX */
PRInt32
nsInstall::Gestalt(const nsString& aSelector, PRInt32* aReturn)
@ -921,7 +922,7 @@ nsInstall::Gestalt(const nsString& aSelector, PRInt32* aReturn)
*aReturn = SaveError( result );
return NS_OK;
}
#ifdef XP_MAC
#if defined(XP_MAC) || defined(XP_MACOSX)
long response = 0;
char selectorChars[4];
@ -945,7 +946,7 @@ nsInstall::Gestalt(const nsString& aSelector, PRInt32* aReturn)
else
*aReturn = response;
#endif
#endif /* XP_MAC || XP_MACOSX */
return NS_OK;
}
@ -2159,7 +2160,8 @@ nsInstall::FileOpFileMacAlias(nsIFile *aSourceFile, nsIFile *aAliasFile, PRInt32
*aReturn = nsInstall::SUCCESS;
#ifdef XP_MAC
#if defined(XP_MAC) || defined(XP_MACOSX)
nsInstallFileOpItem* ifop = new nsInstallFileOpItem(this, NS_FOP_MAC_ALIAS, aSourceFile, aAliasFile, aReturn);
if (!ifop)
{
@ -2186,7 +2188,8 @@ nsInstall::FileOpFileMacAlias(nsIFile *aSourceFile, nsIFile *aAliasFile, PRInt32
}
SaveError(*aReturn);
#endif
#endif /* XP_MAC || XP_MACOSX */
return NS_OK;
}
@ -2667,16 +2670,17 @@ nsInstall::ExtractFileFromJar(const nsString& aJarfile, nsIFile* aSuggestedName,
}
}
#ifdef XP_MAC
FSSpec finalSpec, extractedSpec;
#if defined(XP_MAC) || defined(XP_MACOSX)
FSRef finalRef, extractedRef;
nsCOMPtr<nsILocalFileMac> tempExtractHereSpec;
tempExtractHereSpec = do_QueryInterface(extractHereSpec, &rv);
tempExtractHereSpec->GetFSSpec(&extractedSpec);
tempExtractHereSpec->GetFSRef(&extractedRef);
if ( nsAppleSingleDecoder::IsAppleSingleFile(&extractedSpec) )
if ( nsAppleSingleDecoder::IsAppleSingleFile(&extractedRef) )
{
nsAppleSingleDecoder *asd = new nsAppleSingleDecoder(&extractedSpec, &finalSpec);
nsAppleSingleDecoder *asd =
new nsAppleSingleDecoder(&extractedRef, &finalRef);
OSErr decodeErr = fnfErr;
if (asd)
@ -2689,22 +2693,20 @@ nsInstall::ExtractFileFromJar(const nsString& aJarfile, nsIFile* aSuggestedName,
return EXTRACTION_FAILED;
}
if ( !(extractedSpec.vRefNum == finalSpec.vRefNum) ||
!(extractedSpec.parID == finalSpec.parID) ||
!(nsAppleSingleDecoder::PLstrcmp(extractedSpec.name, finalSpec.name)) )
if (noErr != FSCompareFSRefs(&extractedRef, &finalRef))
{
// delete the unique extracted file that got renamed in AS decoding
FSpDelete(&extractedSpec);
FSDeleteObject(&extractedRef);
// "real name" in AppleSingle entry may cause file rename
tempExtractHereSpec->InitWithFSSpec(&finalSpec);
tempExtractHereSpec->InitWithFSRef(&finalRef);
extractHereSpec = do_QueryInterface(tempExtractHereSpec, &rv);
}
}
#endif
#endif /* XP_MAC || XP_MACOSX */
extractHereSpec->Clone(aRealName);
return nsInstall::SUCCESS;
}

View File

@ -42,6 +42,7 @@
#include "ScheduledTasks.h"
#include "nsProcess.h"
#include "nsNativeCharsetUtils.h"
#include "nsReadableUtils.h"
#include "nsInstallExecute.h"
#ifdef _WINDOWS
@ -49,13 +50,12 @@
#include "nsWinShortcut.h"
#endif
#ifdef XP_MAC
#include "Aliases.h"
#include "Gestalt.h"
#include "Resources.h"
#include "TextUtils.h"
#include "script.h"
#include "MoreFilesExtras.h"
#if defined(XP_MAC) || defined(XP_MACOSX)
#include <Aliases.h>
#include <Gestalt.h>
#include <Resources.h>
#include <TextUtils.h>
#include "MoreFilesX.h"
#include "nsILocalFileMac.h"
#endif
@ -1322,7 +1322,7 @@ PRInt32
nsInstallFileOpItem::NativeFileOpMacAliasPrepare()
{
#ifdef XP_MAC
#if defined(XP_MAC) || defined(XP_MACOSX)
nsCOMPtr<nsILocalFileMac> targetFile = do_QueryInterface(mTarget);
nsCOMPtr<nsILocalFileMac> sourceFile = do_QueryInterface(mSrc);
@ -1346,7 +1346,7 @@ nsInstallFileOpItem::NativeFileOpMacAliasPrepare()
if (NS_FAILED(rv))
return nsInstall::FILENAME_ALREADY_USED;
}
#endif /* XP_MAC */
#endif /* XP_MAC || XP_MACOSX */
return nsInstall::SUCCESS;
}
@ -1355,16 +1355,16 @@ PRInt32
nsInstallFileOpItem::NativeFileOpMacAliasComplete()
{
#ifdef XP_MAC
#if defined(XP_MAC) || defined(XP_MACOSX)
// XXX gestalt to see if alias manager is around
nsCOMPtr<nsILocalFileMac> localFileMacTarget = do_QueryInterface(mTarget);
nsCOMPtr<nsILocalFileMac> localFileMacSrc = do_QueryInterface(mSrc);
FSSpec fsSource, fsAlias;
FSRef sourceRef, aliasRef, aliasParentRef;
HFSUniStr255 aliasName;
PRBool exists;
AliasHandle aliasH;
FInfo info;
OSErr err = noErr;
nsresult rv = NS_OK;
@ -1386,23 +1386,43 @@ nsInstallFileOpItem::NativeFileOpMacAliasComplete()
return nsInstall::FILENAME_ALREADY_USED;
}
rv = localFileMacSrc->GetFSSpec(&fsSource);
if (!NS_SUCCEEDED(rv)) return rv;
rv = localFileMacTarget->GetFSSpec(&fsAlias);
if (!NS_SUCCEEDED(rv)) return rv;
rv = localFileMacSrc->GetFSRef(&sourceRef);
if (NS_FAILED(rv)) return rv;
err = NewAliasMinimal( &fsSource, &aliasH );
// get alias parent
nsCOMPtr<nsIFile> aliasParentIFile;
rv = localFileMacTarget->GetParent(getter_AddRefs(aliasParentIFile));
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsILocalFileMac> macDaddy(do_QueryInterface(aliasParentIFile));
rv = macDaddy->GetFSRef(&aliasParentRef);
if (NS_FAILED(rv)) return rv;
// get alias leaf name
nsAutoString leafName;
rv = localFileMacTarget->GetLeafName(leafName);
if (NS_FAILED(rv)) return rv;
aliasName.length = leafName.Length();
CopyUnicodeTo(leafName, 0, aliasName.unicode, aliasName.length);
err = FSNewAliasMinimal( &sourceRef, &aliasH );
if (err != noErr) // bubble up Alias Manager error
return err;
// create the alias file
FSpGetFInfo(&fsSource, &info);
FSpCreateResFile(&fsAlias, info.fdCreator, info.fdType, smRoman);
short refNum = FSpOpenResFile(&fsAlias, fsRdWrPerm);
FSCatalogInfo catInfo;
FSGetCatalogInfo(&sourceRef, kFSCatInfoFinderInfo, &catInfo,
NULL, NULL, NULL);
// mark newly created file as an alias file
FInfo *fInfo = (FInfo *) catInfo.finderInfo;
fInfo->fdFlags |= kIsAlias;
FSCreateResFile(&aliasParentRef, aliasName.length, aliasName.unicode,
kFSCatInfoFinderInfo, &catInfo, &aliasRef, NULL);
SInt16 refNum = FSOpenResFile(&aliasRef, fsRdWrPerm);
if (refNum != -1)
{
UseResFile(refNum);
AddResource((Handle)aliasH, rAliasType, 0, fsAlias.name);
AddResource((Handle)aliasH, rAliasType, 0, "\pAlias");
ReleaseResource((Handle)aliasH);
UpdateResFile(refNum);
CloseResFile(refNum);
@ -1410,11 +1430,7 @@ nsInstallFileOpItem::NativeFileOpMacAliasComplete()
else
return nsInstall::SUCCESS; // non-fatal so prevent internal abort
// mark newly created file as an alias file
FSpGetFInfo(&fsAlias, &info);
info.fdFlags |= kIsAlias;
FSpSetFInfo(&fsAlias, &info);
#endif
#endif /* XP_MAC || XP_MACOSX */
return nsInstall::SUCCESS;
}
@ -1422,7 +1438,7 @@ nsInstallFileOpItem::NativeFileOpMacAliasComplete()
PRInt32
nsInstallFileOpItem::NativeFileOpMacAliasAbort()
{
#ifdef XP_MAC
#if defined(XP_MAC) || defined(XP_MACOSX)
NativeFileOpFileDeleteComplete(mTarget);
#endif