From 8023b08ebc917330174af8549e4d20743c99601c Mon Sep 17 00:00:00 2001 From: "sfraser%netscape.com" Date: Mon, 11 Oct 1999 21:19:06 +0000 Subject: [PATCH] Fix for bugs 15795 and 16090 -- fix startup crash which was due to an uninitialized nsFileSpec trashing the stack. Also no longer set mError on CreateDirectory if the dir already exists, prevent += "foo" when mError is set, and add assertions XP to catch calls with NULL strings. reviewed by dougt and (in part) sspitzer. a=leaf. git-svn-id: svn://10.0.0.236/trunk@50360 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/xpcom/io/nsFileSpec.cpp | 96 +- mozilla/xpcom/io/nsFileSpec.h | 127 +- mozilla/xpcom/io/nsFileSpecMac.cpp | 1749 +++++++++++----------- mozilla/xpcom/io/nsFileSpecStreaming.cpp | 18 + mozilla/xpcom/io/nsFileSpecUnix.cpp | 4 + mozilla/xpcom/io/nsFileSpecWin.cpp | 5 + mozilla/xpcom/io/nsIFileStream.cpp | 401 ++--- 7 files changed, 1298 insertions(+), 1102 deletions(-) diff --git a/mozilla/xpcom/io/nsFileSpec.cpp b/mozilla/xpcom/io/nsFileSpec.cpp index 49f45daa44e..4c24797e2de 100644 --- a/mozilla/xpcom/io/nsFileSpec.cpp +++ b/mozilla/xpcom/io/nsFileSpec.cpp @@ -30,6 +30,11 @@ #include #include +#ifdef XP_MAC +#include +#include +#endif + //======================================================================================== // class nsSimpleCharString //======================================================================================== @@ -252,6 +257,7 @@ void nsSimpleCharString::ReallocData(PRUint32 inLength) mData->mLength = inLength; } // nsSimpleCharString::ReleaseData + //======================================================================================== NS_NAMESPACE nsFileSpecHelpers //======================================================================================== @@ -362,6 +368,11 @@ char* nsSimpleCharString::GetLeaf(char inSeparator) const return result; } // nsSimpleCharString::GetLeaf + +#ifdef XP_MAC +#pragma mark - +#endif + #if defined(XP_UNIX) || defined(XP_PC) || defined(XP_BEOS) //---------------------------------------------------------------------------------------- @@ -437,10 +448,15 @@ void nsFileSpecHelpers::MakeAllDirectories(const char* inPath, int mode) #endif // XP_PC || XP_UNIX +#ifdef XP_MAC +#pragma mark - +#endif + #if defined(XP_PC) #include "nsFileSpecWin.cpp" // Windows-specific implementations #elif defined(XP_MAC) -#include "nsFileSpecMac.cpp" // Macintosh-specific implementations +//#include "nsFileSpecMac.cpp" // Macintosh-specific implementations +// we include the .cpp file in the project now. #elif defined(XP_BEOS) #include "nsFileSpecBeOS.cpp" // BeOS-specific implementations #elif defined(XP_UNIX) @@ -602,6 +618,10 @@ void nsFileURL::operator = (const nsFileSpec& inOther) } // nsFileURL::operator = #endif +#ifdef XP_MAC +#pragma mark - +#endif + //======================================================================================== // nsFilePath implementation //======================================================================================== @@ -741,6 +761,8 @@ void nsFilePath::operator = (const nsFilePath& inOther) void nsFilePath::operator +=(const char* inRelativeUnixPath) //---------------------------------------------------------------------------------------- { + NS_ASSERTION(inRelativeUnixPath, "Attempt append relative path with null path"); + char* escapedPath = nsEscape(inRelativeUnixPath, url_Path); mPath += escapedPath; nsCRT::free(escapedPath); @@ -753,11 +775,18 @@ void nsFilePath::operator +=(const char* inRelativeUnixPath) nsFilePath nsFilePath::operator +(const char* inRelativeUnixPath) const //---------------------------------------------------------------------------------------- { - nsFilePath result(*this); - result += inRelativeUnixPath; - return result; + NS_ASSERTION(inRelativeUnixPath, "Attempt append relative path with null path"); + + nsFilePath resultPath(*this); + resultPath += inRelativeUnixPath; + return resultPath; } // nsFilePath::operator + + +#ifdef XP_MAC +#pragma mark - +#endif + //======================================================================================== // nsFileSpec implementation //======================================================================================== @@ -766,11 +795,27 @@ nsFilePath nsFilePath::operator +(const char* inRelativeUnixPath) const //---------------------------------------------------------------------------------------- nsFileSpec::nsFileSpec() //---------------------------------------------------------------------------------------- -: mError(NS_OK) +: mError(NS_OK) // XXX shouldn't this be NS_ERROR_NOT_INITIALIZED? { } + +//---------------------------------------------------------------------------------------- +void nsFileSpec::Clear() +//---------------------------------------------------------------------------------------- +{ + mPath.SetToEmpty(); + mError = NS_ERROR_NOT_INITIALIZED; +} + #endif +//---------------------------------------------------------------------------------------- +nsFileSpec::~nsFileSpec() +//---------------------------------------------------------------------------------------- +{ + // mPath cleans itself up +} + //---------------------------------------------------------------------------------------- nsFileSpec::nsFileSpec(const nsPersistentFileDescriptor& inDescriptor) //---------------------------------------------------------------------------------------- @@ -876,9 +921,7 @@ nsFileSpec::nsFileSpec(const nsFilePath& inPath) , mError(NS_OK) { } -#endif // XP_UNIX -#if defined XP_UNIX || defined XP_BEOS //---------------------------------------------------------------------------------------- void nsFileSpec::operator = (const nsFilePath& inPath) //---------------------------------------------------------------------------------------- @@ -896,9 +939,7 @@ nsFileSpec::nsFileSpec(const nsFileSpec& inSpec) , mError(NS_OK) { } -#endif //XP_UNIX -#if defined(XP_UNIX) || defined(XP_PC) || defined(XP_BEOS) //---------------------------------------------------------------------------------------- nsFileSpec::nsFileSpec(const char* inString, PRBool inCreateDirs) //---------------------------------------------------------------------------------------- @@ -908,9 +949,7 @@ nsFileSpec::nsFileSpec(const char* inString, PRBool inCreateDirs) // Make canonical and absolute. nsFileSpecHelpers::Canonify(mPath, inCreateDirs); } -#endif //XP_UNIX,PC -#if defined(XP_UNIX) || defined(XP_PC) || defined(XP_BEOS) //---------------------------------------------------------------------------------------- nsFileSpec::nsFileSpec(const nsString& inString, PRBool inCreateDirs) //---------------------------------------------------------------------------------------- @@ -920,15 +959,7 @@ nsFileSpec::nsFileSpec(const nsString& inString, PRBool inCreateDirs) // Make canonical and absolute. nsFileSpecHelpers::Canonify(mPath, inCreateDirs); } -#endif //XP_UNIX,PC -//---------------------------------------------------------------------------------------- -nsFileSpec::~nsFileSpec() -//---------------------------------------------------------------------------------------- -{ -} - -#if defined(XP_UNIX) || defined(XP_PC) || defined(XP_BEOS) //---------------------------------------------------------------------------------------- void nsFileSpec::operator = (const nsFileSpec& inSpec) //---------------------------------------------------------------------------------------- @@ -936,10 +967,7 @@ void nsFileSpec::operator = (const nsFileSpec& inSpec) mPath = inSpec.mPath; mError = inSpec.Error(); } -#endif //XP_UNIX - -#if defined(XP_UNIX) || defined(XP_PC) || defined(XP_BEOS) //---------------------------------------------------------------------------------------- void nsFileSpec::operator = (const char* inString) //---------------------------------------------------------------------------------------- @@ -949,15 +977,17 @@ void nsFileSpec::operator = (const char* inString) nsFileSpecHelpers::Canonify(mPath, PR_FALSE /* XXX? */); mError = NS_OK; } -#endif //XP_UNIX +#endif //XP_UNIX,PC,XP_BEOS //---------------------------------------------------------------------------------------- nsFileSpec nsFileSpec::operator + (const char* inRelativePath) const //---------------------------------------------------------------------------------------- { - nsFileSpec result = *this; - result += inRelativePath; - return result; + NS_ASSERTION(inRelativePath, "Attempt to append name with a null string"); + + nsFileSpec resultSpec = *this; + resultSpec += inRelativePath; + return resultSpec; } // nsFileSpec::operator + //---------------------------------------------------------------------------------------- @@ -1015,22 +1045,23 @@ PRBool nsFileSpec::operator != (const nsFileSpec& inOther) const #ifndef XP_MAC //---------------------------------------------------------------------------------------- -const char* nsFileSpec::GetCString() const // This is the only automatic conversion to const char* // that is provided, and it allows the // path to be "passed" to NSPR file routines. This practice // is VERY EVIL and should only be used to support legacy // code. Using it guarantees bugs on Macintosh. The path is NOT allocated, so do // not even think of deleting (or freeing) it. +const char* nsFileSpec::GetCString() const //---------------------------------------------------------------------------------------- { return mPath; } #endif -/* Is our spec a child of the provided parent? */ -PRBool -nsFileSpec::IsChildOf(nsFileSpec &possibleParent) +//---------------------------------------------------------------------------------------- +// Is our spec a child of the provided parent? +PRBool nsFileSpec::IsChildOf(nsFileSpec &possibleParent) +//---------------------------------------------------------------------------------------- { nsFileSpec iter = *this, parent; #ifdef DEBUG @@ -1059,10 +1090,13 @@ nsFileSpec::IsChildOf(nsFileSpec &possibleParent) #endif } - /* not reached, but I bet some compiler will whine */ + // not reached, but I bet some compiler will whine return PR_FALSE; } +#ifdef XP_MAC +#pragma mark - +#endif //======================================================================================== // class nsPersistentFileDescriptor diff --git a/mozilla/xpcom/io/nsFileSpec.h b/mozilla/xpcom/io/nsFileSpec.h index ea3c1a8b58a..22aa2d01f53 100644 --- a/mozilla/xpcom/io/nsFileSpec.h +++ b/mozilla/xpcom/io/nsFileSpec.h @@ -328,22 +328,27 @@ class NS_COM nsFileSpec PRBool operator ==(const nsFileSpec& inOther) const; PRBool operator !=(const nsFileSpec& inOther) const; - operator const char* () const { return GetCString(); } - // Same as GetCString (please read the comments). - // Do not try to free this! - const char* GetNativePathCString() const { return GetCString(); } - // Same as GetCString (please read the comments). - // Do not try to free this! + + // Returns a native path, and allows the + // path to be "passed" to legacy code. This practice + // is VERY EVIL and should only be used to support legacy + // code. Using it guarantees bugs on Macintosh. + // The path is cached and freed by the nsFileSpec destructor + // so do not delete (or free) it. See also nsNSPRPath below, + // if you really must pass a string to PR_OpenFile(). + // Doing so will introduce two automatic bugs. const char* GetCString() const; - // Returns a native path, and allows the - // path to be "passed" to legacy code. This practice - // is VERY EVIL and should only be used to support legacy - // code. Using it guarantees bugs on Macintosh. - // The path is cached and freed by the nsFileSpec destructor - // so do not delete (or free) it. See also nsNSPRPath below, - // if you really must pass a string to PR_OpenFile(). - // Doing so will introduce two automatic bugs. - PRBool IsChildOf(nsFileSpec &possibleParent); + + // Same as GetCString (please read the comments). + // Do not try to free this! + operator const char* () const { return GetCString(); } + + // Same as GetCString (please read the comments). + // Do not try to free this! + const char* GetNativePathCString() const { return GetCString(); } + + + PRBool IsChildOf(nsFileSpec &possibleParent); #ifdef XP_MAC // For Macintosh people, this is meant to be useful in its own right as a C++ version @@ -372,10 +377,10 @@ class NS_COM nsFileSpec ConstStr255Param GetLeafPName() const { return mSpec.name; } OSErr GetCatInfo(CInfoPBRec& outInfo) const; -#if DOUGT_UNTESTED + OSErr SetFileTypeAndCreator(OSType type, OSType creator); OSErr GetFileTypeAndCreator(OSType* type, OSType* creator); -#endif + #endif // end of Macintosh utility methods. PRBool Valid() const { return NS_SUCCEEDED(Error()); } @@ -394,33 +399,46 @@ class NS_COM nsFileSpec //-------------------------------------------------- char* GetLeafName() const; // Allocated. Use nsCRT::free(). + +#if 0 +// needs implementing + // copy the leaf name into the supplied buffer, thus + // getting a copy without allocation. Buffer should be + // 64 chars big. + void GetLeafNameCopy(char* destBuffer, PRInt32 bufferSize) const; +#endif + // inLeafName can be a relative path, so this allows + // one kind of concatenation of "paths". void SetLeafName(const char* inLeafName); - // inLeafName can be a relative path, so this allows - // one kind of concatenation of "paths". void SetLeafName(const nsString& inLeafName) { const nsAutoCString leafName(inLeafName); SetLeafName(leafName); } - void GetParent(nsFileSpec& outSpec) const; - // Return the filespec of the parent directory. Used - // in conjunction with GetLeafName(), this lets you - // parse a path into a list of node names. Beware, - // however, that the top node is still not a name, - // but a spec. Volumes on Macintosh can have identical - // names. Perhaps could be used for an operator --() ? - typedef PRUint32 TimeStamp; // ie nsFileSpec::TimeStamp. This is 32 bits now, - // but might change, eg, to a 64-bit class. So use the - // typedef, and use a streaming operator to convert - // to a string, so that your code won't break. It's - // none of your business what the number means. Don't - // rely on the implementation. + // Return the filespec of the parent directory. Used + // in conjunction with GetLeafName(), this lets you + // parse a path into a list of node names. Beware, + // however, that the top node is still not a name, + // but a spec. Volumes on Macintosh can have identical + // names. Perhaps could be used for an operator --() ? + void GetParent(nsFileSpec& outSpec) const; + + + // ie nsFileSpec::TimeStamp. This is 32 bits now, + // but might change, eg, to a 64-bit class. So use the + // typedef, and use a streaming operator to convert + // to a string, so that your code won't break. It's + // none of your business what the number means. Don't + // rely on the implementation. + typedef PRUint32 TimeStamp; + + // This will return different values on different + // platforms, even for the same file (eg, on a server). + // But if the platform is constant, it will increase after + // every file modification. void GetModDate(TimeStamp& outStamp) const; - // This will return different values on different - // platforms, even for the same file (eg, on a server). - // But if the platform is constant, it will increase after - // every file modification. + PRBool ModDateChanged(const TimeStamp& oldStamp) const { TimeStamp newStamp; @@ -438,15 +456,17 @@ class NS_COM nsFileSpec relativePath(inRelativeUnixPath); return *this + relativePath; } + + // Concatenate the relative path to this directory. + // Used for constructing the filespec of a descendant. + // This must be a directory for this to work. This differs + // from SetLeafName(), since the latter will work + // starting with a sibling of the directory and throws + // away its leaf information, whereas this one assumes + // this is a directory, and the relative path starts + // "below" this. void operator += (const char* inRelativeUnixPath); - // Concatenate the relative path to this directory. - // Used for constructing the filespec of a descendant. - // This must be a directory for this to work. This differs - // from SetLeafName(), since the latter will work - // starting with a sibling of the directory and throws - // away its leaf information, whereas this one assumes - // this is a directory, and the relative path starts - // "below" this. + void operator += (const nsString& inRelativeUnixPath) { const nsAutoCString relativePath(inRelativeUnixPath); @@ -461,22 +481,22 @@ class NS_COM nsFileSpec MakeUnique(suggestedLeafName); } - PRBool IsDirectory() const; - // More stringent than Exists() - PRBool IsFile() const; - // More stringent than Exists() + + PRBool IsDirectory() const; // More stringent than Exists() + PRBool IsFile() const; // More stringent than Exists() PRBool Exists() const; PRBool IsHidden() const; PRBool IsSymlink() const; + //-------------------------------------------------- // Creation and deletion of objects. These can modify the disk. //-------------------------------------------------- + // Called for the spec of an alias. Modifies the spec to + // point to the original. Sets mError. nsresult ResolveSymlink(PRBool& wasSymlink); - // Called for the spec of an alias. Modifies the spec to - // point to the original. Sets mError. void CreateDirectory(int mode = 0700 /* for unix */); void CreateDir(int mode = 0700) { CreateDirectory(mode); } @@ -498,11 +518,17 @@ class NS_COM nsFileSpec const nsAutoCString argsString(args); return Execute(argsString); } + //-------------------------------------------------- // Data //-------------------------------------------------- protected: + + // Clear the nsFileSpec contents, resetting it + // to the uninitialized state; + void Clear(); + friend class nsFilePath; friend class nsFileURL; friend class nsDirectoryIterator; @@ -511,6 +537,7 @@ class NS_COM nsFileSpec #endif nsSimpleCharString mPath; nsresult mError; + }; // class nsFileSpec // FOR HISTORICAL REASONS: diff --git a/mozilla/xpcom/io/nsFileSpecMac.cpp b/mozilla/xpcom/io/nsFileSpecMac.cpp index 0b2253f79cb..964d8788157 100644 --- a/mozilla/xpcom/io/nsFileSpecMac.cpp +++ b/mozilla/xpcom/io/nsFileSpecMac.cpp @@ -2,7 +2,7 @@ * * The contents of this file are subject to the Netscape Public License * Version 1.0 (the "NPL"); you may not use this file except in - * compliance with the NPL. You may obtain a copy of the NPL at + * compliance with the NPL. You may obtain a copy of the NPL at * http://www.mozilla.org/NPL/ * * Software distributed under the NPL is distributed on an "AS IS" basis, @@ -11,13 +11,19 @@ * NPL. * * The Initial Developer of this code under the NPL is Netscape - * Communications Corporation. Portions created by Netscape are - * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights * Reserved. */ -// This file is included by nsFile.cp, and includes the Macintosh-specific -// implementations. +// This file is included by nsFile.cp, and includes the Macintosh-specific +// implementations. + + +#include + +#include "prtypes.h" +#include "nscore.h" #include "FullPath.h" #include "FileCopy.h" @@ -30,84 +36,88 @@ #include #include // ULONG_MAX +#include "nsFileSpec.h" +#include "nsEscape.h" + + const unsigned char* kAliasHavenFolderName = "\pnsAliasHaven"; //======================================================================================== namespace MacFileHelpers //======================================================================================== { - inline void PLstrcpy(Str255 dst, ConstStr255Param src) - { - memcpy(dst, src, 1 + src[0]); - } + inline void PLstrcpy(Str255 dst, ConstStr255Param src) + { + memcpy(dst, src, 1 + src[0]); + } - void PLstrcpy(Str255 dst, const char* src, int inMaxLen=255); - void PLstrncpy(Str255 dst, const char* src, int inMaxLen); + void PLstrcpy(Str255 dst, const char* src, int inMaxLen=255); + void PLstrncpy(Str255 dst, const char* src, int inMaxLen); - void SwapSlashColon(char * s); - OSErr FSSpecFromUnixPath( - const char * unixPath, - FSSpec& ioSpec, - Boolean hexDecode, - Boolean resolveAlias, - Boolean allowPartial = false, - Boolean createDirs = false); - char* MacPathFromUnixPath( - const char* unixPath, - Boolean hexDecode); - char* EncodeMacPath( - char* inPath, // NOT const - gets clobbered - Boolean prependSlash, - Boolean doEscape ); - OSErr FSSpecFromPathname( - const char* inPathNamePtr, - FSSpec& ioSpec, - Boolean inCreateDirs); - char* PathNameFromFSSpec( - const FSSpec& inSpec, - Boolean wantLeafName ); - OSErr CreateFolderInFolder( - short refNum, // Parent directory/volume - long dirID, - ConstStr255Param folderName, // Name of the new folder - short& outRefNum, // Volume of the created folder - long& outDirID); // + void SwapSlashColon(char * s); + OSErr FSSpecFromUnixPath( + const char * unixPath, + FSSpec& ioSpec, + Boolean hexDecode, + Boolean resolveAlias, + Boolean allowPartial = false, + Boolean createDirs = false); + char* MacPathFromUnixPath( + const char* unixPath, + Boolean hexDecode); + char* EncodeMacPath( + char* inPath, // NOT const - gets clobbered + Boolean prependSlash, + Boolean doEscape ); + OSErr FSSpecFromPathname( + const char* inPathNamePtr, + FSSpec& ioSpec, + Boolean inCreateDirs); + char* PathNameFromFSSpec( + const FSSpec& inSpec, + Boolean wantLeafName ); + OSErr CreateFolderInFolder( + short refNum, // Parent directory/volume + long dirID, + ConstStr255Param folderName, // Name of the new folder + short& outRefNum, // Volume of the created folder + long& outDirID); // - // Some routines to support an "alias haven" directory. Aliases in this directory - // are never resolved. There is a ResolveAlias here that respects that. This is - // to support attaching of aliases in mail. - void EnsureAliasHaven(); - void SetNoResolve(Boolean inResolve); - PRBool IsAliasSafe(const FSSpec& inSpec); - OSErr MakeAliasSafe(FSSpec& inOutSpec); - OSErr ResolveAliasFile(FSSpec& inOutSpec, Boolean& wasAliased); + // Some routines to support an "alias haven" directory. Aliases in this directory + // are never resolved. There is a ResolveAlias here that respects that. This is + // to support attaching of aliases in mail. + void EnsureAliasHaven(); + void SetNoResolve(Boolean inResolve); + PRBool IsAliasSafe(const FSSpec& inSpec); + OSErr MakeAliasSafe(FSSpec& inOutSpec); + OSErr ResolveAliasFile(FSSpec& inOutSpec, Boolean& wasAliased); - Boolean sNoResolve = false; - long sAliasHavenDirID = 0; - short sAliasHavenVRefNum = 0; + Boolean sNoResolve = false; + long sAliasHavenDirID = 0; + short sAliasHavenVRefNum = 0; } // namespace MacFileHelpers //---------------------------------------------------------------------------------------- void MacFileHelpers::PLstrcpy(Str255 dst, const char* src, int inMax) //---------------------------------------------------------------------------------------- { - int srcLength = strlen(src); - NS_ASSERTION(srcLength <= inMax, "Oops, string is too long!"); - if (srcLength > inMax) - srcLength = inMax; - dst[0] = srcLength; - memcpy(&dst[1], src, srcLength); + int srcLength = strlen(src); + NS_ASSERTION(srcLength <= inMax, "Oops, string is too long!"); + if (srcLength > inMax) + srcLength = inMax; + dst[0] = srcLength; + memcpy(&dst[1], src, srcLength); } //---------------------------------------------------------------------------------------- void MacFileHelpers::PLstrncpy(Str255 dst, const char* src, int inMax) //---------------------------------------------------------------------------------------- { - int srcLength = strlen(src); - if (srcLength > inMax) - srcLength = inMax; - dst[0] = srcLength; - memcpy(&dst[1], src, srcLength); + int srcLength = strlen(src); + if (srcLength > inMax) + srcLength = inMax; + dst[0] = srcLength; + memcpy(&dst[1], src, srcLength); } //----------------------------------- @@ -115,74 +125,74 @@ void MacFileHelpers::SwapSlashColon(char * s) //----------------------------------- { - while (*s) - { - if (*s == '/') - *s++ = ':'; - else if (*s == ':') - *s++ = '/'; - else - *s++; - } + while (*s) + { + if (*s == '/') + *s++ = ':'; + else if (*s == ':') + *s++ = '/'; + else + *s++; + } } // MacFileHelpers::SwapSlashColon //----------------------------------- char* MacFileHelpers::EncodeMacPath( - char* inPath, // NOT const, gets clobbered - Boolean prependSlash, - Boolean doEscape ) -// Transforms Macintosh style path into Unix one -// Method: Swap ':' and '/', hex escape the result + char* inPath, // NOT const, gets clobbered + Boolean prependSlash, + Boolean doEscape ) +// Transforms Macintosh style path into Unix one +// Method: Swap ':' and '/', hex escape the result //----------------------------------- { - if (inPath == nsnull) - return nsnull; - int pathSize = strlen(inPath); - - // XP code sometimes chokes if there's a final slash in the unix path. - // Since correct mac paths to folders and volumes will end in ':', strip this - // first. - char* c = inPath + pathSize - 1; - if (*c == ':') - { - *c = 0; - pathSize--; - } + if (inPath == nsnull) + return nsnull; + int pathSize = strlen(inPath); + + // XP code sometimes chokes if there's a final slash in the unix path. + // Since correct mac paths to folders and volumes will end in ':', strip this + // first. + char* c = inPath + pathSize - 1; + if (*c == ':') + { + *c = 0; + pathSize--; + } - char * newPath = nsnull; - char * finalPath = nsnull; - - if (prependSlash) - { - newPath = new char[pathSize + 2]; - newPath[0] = ':'; // It will be converted to '/' - memcpy(&newPath[1], inPath, pathSize + 1); - } - else - { - newPath = new char[pathSize + 1]; - strcpy(newPath, inPath); - } - if (newPath) - { - SwapSlashColon( newPath ); - if (doEscape) - { - finalPath = nsEscape(newPath, url_Path); - delete [] newPath; - } - else - finalPath = newPath; - } - delete [] inPath; - return finalPath; + char * newPath = nsnull; + char * finalPath = nsnull; + + if (prependSlash) + { + newPath = new char[pathSize + 2]; + newPath[0] = ':'; // It will be converted to '/' + memcpy(&newPath[1], inPath, pathSize + 1); + } + else + { + newPath = new char[pathSize + 1]; + strcpy(newPath, inPath); + } + if (newPath) + { + SwapSlashColon( newPath ); + if (doEscape) + { + finalPath = nsEscape(newPath, url_Path); + delete [] newPath; + } + else + finalPath = newPath; + } + delete [] inPath; + return finalPath; } // MacFileHelpers::EncodeMacPath //---------------------------------------------------------------------------------------- inline void MacFileHelpers::SetNoResolve(Boolean inResolve) //---------------------------------------------------------------------------------------- { - sNoResolve = inResolve; + sNoResolve = inResolve; } // MacFileHelpers::SetNoResolve //---------------------------------------------------------------------------------------- @@ -191,252 +201,252 @@ OSErr MacFileHelpers::MakeAliasSafe(FSSpec& inOutSpec) // returns the spec of the copy to the caller //---------------------------------------------------------------------------------------- { - EnsureAliasHaven(); - nsFileSpec dstDirSpec(sAliasHavenVRefNum, sAliasHavenDirID, "\p"); + EnsureAliasHaven(); + nsFileSpec dstDirSpec(sAliasHavenVRefNum, sAliasHavenDirID, "\p"); - // Make sure its name is unique - nsFileSpec havenSpec(sAliasHavenVRefNum, sAliasHavenDirID, "\pG'day"); - if (havenSpec.Valid()) - havenSpec.MakeUnique(inOutSpec.name); - // Copy the file into the haven directory - if (havenSpec.Valid()) - { - OSErr err = ::FSpFileCopy( - &inOutSpec, - dstDirSpec, - havenSpec.GetLeafPName(), - nil, 0, true); - // Return the spec of the copy to the caller. - if (err != noErr) - return err; - inOutSpec = havenSpec; - } - return noErr; + // Make sure its name is unique + nsFileSpec havenSpec(sAliasHavenVRefNum, sAliasHavenDirID, "\pG'day"); + if (havenSpec.Valid()) + havenSpec.MakeUnique(inOutSpec.name); + // Copy the file into the haven directory + if (havenSpec.Valid()) + { + OSErr err = ::FSpFileCopy( + &inOutSpec, + dstDirSpec, + havenSpec.GetLeafPName(), + nil, 0, true); + // Return the spec of the copy to the caller. + if (err != noErr) + return err; + inOutSpec = havenSpec; + } + return noErr; } // MacFileHelpers::MakeAliasSafe //---------------------------------------------------------------------------------------- char* MacFileHelpers::MacPathFromUnixPath(const char* unixPath, Boolean hexDecode) //---------------------------------------------------------------------------------------- { - // Relying on the fact that the unix path is always longer than the mac path: - size_t len = strlen(unixPath); - char* result = new char[len + 2]; // ... but allow for the initial colon in a partial name - // REMEMBER: at the end we call SwapSlashColon, so bear that in mind when you see - // this code using '/' as a separator in what is supposed to be a Macintosh path! - if (result) - { - char* dst = result; - const char* src = unixPath; - if (*src == '/') // * full path - src++; - else if (strchr(src, '/') && *src != '.') - { - // * partial path, and not just a leaf name. The '.' test is there because - // the loop below will add sufficient colons in that case. - *dst++ = '/'; - } - // Copy src to dst, but watch out for .. and . - char c = '/'; - do - { - char cprev = c; // remember the previous char (initially /) - c = *src++; - if (c == '.' && cprev == '/') - { - char* dstSaved = dst; - // Special cases: "." and "..". Convert to ':' and '::' - *dst++ = '/'; // . becomes : - c = *src++; - if (c == '.') - { - *dst++ = '/'; // .. becomes :: - c = *src++; - } - if (c == '/') - { - // ../ becomes :: so just skip the slash - // ./ becomes : " " " " " - src++; - } - else if (c) - { - // Oh. A file called ".foo" or "..foo" - // Back up and just do the normal thing. - src -= (dst - dstSaved); - dst = dstSaved; - // Since c is not '/', we won't do this stuff on the - // next iteration. - } - continue; - } - else if (c == '/' && cprev == '/') - { - // Hmm. A 'run on' path with two slashes right next to each other. - // This is an illegal path, but, hey, we'll be tough and try to - // deal with it (especially since '::' has loaded semantics in - // a Mac path) - continue; - } - *dst++ = c; - } while (c); - if (hexDecode) - nsUnescape(result); // Hex Decode - MacFileHelpers::SwapSlashColon(result); - } - return result; + // Relying on the fact that the unix path is always longer than the mac path: + size_t len = strlen(unixPath); + char* result = new char[len + 2]; // ... but allow for the initial colon in a partial name + // REMEMBER: at the end we call SwapSlashColon, so bear that in mind when you see + // this code using '/' as a separator in what is supposed to be a Macintosh path! + if (result) + { + char* dst = result; + const char* src = unixPath; + if (*src == '/') // * full path + src++; + else if (strchr(src, '/') && *src != '.') + { + // * partial path, and not just a leaf name. The '.' test is there because + // the loop below will add sufficient colons in that case. + *dst++ = '/'; + } + // Copy src to dst, but watch out for .. and . + char c = '/'; + do + { + char cprev = c; // remember the previous char (initially /) + c = *src++; + if (c == '.' && cprev == '/') + { + char* dstSaved = dst; + // Special cases: "." and "..". Convert to ':' and '::' + *dst++ = '/'; // . becomes : + c = *src++; + if (c == '.') + { + *dst++ = '/'; // .. becomes :: + c = *src++; + } + if (c == '/') + { + // ../ becomes :: so just skip the slash + // ./ becomes : " " " " " + src++; + } + else if (c) + { + // Oh. A file called ".foo" or "..foo" + // Back up and just do the normal thing. + src -= (dst - dstSaved); + dst = dstSaved; + // Since c is not '/', we won't do this stuff on the + // next iteration. + } + continue; + } + else if (c == '/' && cprev == '/') + { + // Hmm. A 'run on' path with two slashes right next to each other. + // This is an illegal path, but, hey, we'll be tough and try to + // deal with it (especially since '::' has loaded semantics in + // a Mac path) + continue; + } + *dst++ = c; + } while (c); + if (hexDecode) + nsUnescape(result); // Hex Decode + MacFileHelpers::SwapSlashColon(result); + } + return result; } // MacFileHelpers::MacPathFromUnixPath //---------------------------------------------------------------------------------------- OSErr MacFileHelpers::FSSpecFromPathname( - const char* inPathNamePtr, - FSSpec& ioSpec, // used as in-parameter for a relative path. - Boolean inCreateDirs) + const char* inPathNamePtr, + FSSpec& ioSpec, // used as in-parameter for a relative path. + Boolean inCreateDirs) // FSSpecFromPathname reverses PathNameFromFSSpec. // It returns a FSSpec given a c string which is a mac pathname. //---------------------------------------------------------------------------------------- { - OSErr err; - // Simplify this routine to use FSMakeFSSpec if length < 255. Otherwise use the MoreFiles - // routine FSpLocationFromFullPath, which allocates memory, to handle longer pathnames. - - short inVRefNum = ioSpec.vRefNum; - long inParID = ioSpec.parID; - - size_t inLength = strlen(inPathNamePtr); - bool isRelative = (strchr(inPathNamePtr, ':') == 0 || *inPathNamePtr == ':'); + OSErr err; + // Simplify this routine to use FSMakeFSSpec if length < 255. Otherwise use the MoreFiles + // routine FSpLocationFromFullPath, which allocates memory, to handle longer pathnames. + + short inVRefNum = ioSpec.vRefNum; + long inParID = ioSpec.parID; + + size_t inLength = strlen(inPathNamePtr); + bool isRelative = (strchr(inPathNamePtr, ':') == 0 || *inPathNamePtr == ':'); #ifdef NS_DEBUG - // Attempt to catch people sending unix paths in to routines that expect native ones. - NS_ASSERTION(strchr(inPathNamePtr, '/') == 0, - "Possible unix path where native path is required"); + // Attempt to catch people sending unix paths in to routines that expect native ones. + NS_ASSERTION(strchr(inPathNamePtr, '/') == 0, + "Possible unix path where native path is required"); #endif - if (inLength < 255) - { - Str255 pascalpath; - MacFileHelpers::PLstrcpy(pascalpath, inPathNamePtr); - if (isRelative) - err = ::FSMakeFSSpec(inVRefNum, inParID, pascalpath, &ioSpec); - else - err = ::FSMakeFSSpec(0, 0, pascalpath, &ioSpec); - } - else if (!isRelative) - err = FSpLocationFromFullPath(inLength, inPathNamePtr, &ioSpec); - else - err = bdNamErr; + if (inLength < 255) + { + Str255 pascalpath; + MacFileHelpers::PLstrcpy(pascalpath, inPathNamePtr); + if (isRelative) + err = ::FSMakeFSSpec(inVRefNum, inParID, pascalpath, &ioSpec); + else + err = ::FSMakeFSSpec(0, 0, pascalpath, &ioSpec); + } + else if (!isRelative) + err = FSpLocationFromFullPath(inLength, inPathNamePtr, &ioSpec); + else + err = bdNamErr; - if ((err == dirNFErr || err == bdNamErr) && inCreateDirs) - { - const char* path = inPathNamePtr; - if (isRelative) - { - ioSpec.vRefNum = inVRefNum; - ioSpec.parID = inParID; - } - else - { - ioSpec.vRefNum = 0; - ioSpec.parID = 0; - } - do { - // Locate the colon that terminates the node. - // But if we've a partial path (starting with a colon), find the second one. - const char* nextColon = strchr(path + (*path == ':'), ':'); - // Well, if there are no more colons, point to the end of the string. - if (!nextColon) - nextColon = path + strlen(path); + if ((err == dirNFErr || err == bdNamErr) && inCreateDirs) + { + const char* path = inPathNamePtr; + if (isRelative) + { + ioSpec.vRefNum = inVRefNum; + ioSpec.parID = inParID; + } + else + { + ioSpec.vRefNum = 0; + ioSpec.parID = 0; + } + do { + // Locate the colon that terminates the node. + // But if we've a partial path (starting with a colon), find the second one. + const char* nextColon = strchr(path + (*path == ':'), ':'); + // Well, if there are no more colons, point to the end of the string. + if (!nextColon) + nextColon = path + strlen(path); - // Make a pascal string out of this node. Include initial - // and final colon, if any! - Str255 ppath; - MacFileHelpers::PLstrncpy(ppath, path, nextColon - path + 1); - - // Use this string as a relative path using the directory created - // on the previous round (or directory 0,0 on the first round). - err = ::FSMakeFSSpec(ioSpec.vRefNum, ioSpec.parID, ppath, &ioSpec); + // Make a pascal string out of this node. Include initial + // and final colon, if any! + Str255 ppath; + MacFileHelpers::PLstrncpy(ppath, path, nextColon - path + 1); + + // Use this string as a relative path using the directory created + // on the previous round (or directory 0,0 on the first round). + err = ::FSMakeFSSpec(ioSpec.vRefNum, ioSpec.parID, ppath, &ioSpec); - // If this was the leaf node, then we are done. - if (!*nextColon) - break; + // If this was the leaf node, then we are done. + if (!*nextColon) + break; - // Since there's more to go, we have to get the directory ID, which becomes - // the parID for the next round. - if (err == noErr) - { - // The directory (or perhaps a file) exists. Find its dirID. - long dirID; - Boolean isDirectory; - err = ::FSpGetDirectoryID(&ioSpec, &dirID, &isDirectory); - if (!isDirectory) - return dupFNErr; // oops! a file exists with that name. - if (err) - return err; - ioSpec.parID = dirID; - } - else if (err == fnfErr) - { - // If we got "file not found", then - // we need to create a directory. - err = ::FSpDirCreate(&ioSpec, smCurrentScript, &ioSpec.parID); - // For some reason, this usually returns fnfErr, even though it works. - if (err == fnfErr) - err = noErr; - } - if (err != noErr) - return err; - path = nextColon; // next round - } while (1); - } - return err; + // Since there's more to go, we have to get the directory ID, which becomes + // the parID for the next round. + if (err == noErr) + { + // The directory (or perhaps a file) exists. Find its dirID. + long dirID; + Boolean isDirectory; + err = ::FSpGetDirectoryID(&ioSpec, &dirID, &isDirectory); + if (!isDirectory) + return dupFNErr; // oops! a file exists with that name. + if (err) + return err; + ioSpec.parID = dirID; + } + else if (err == fnfErr) + { + // If we got "file not found", then + // we need to create a directory. + err = ::FSpDirCreate(&ioSpec, smCurrentScript, &ioSpec.parID); + // For some reason, this usually returns fnfErr, even though it works. + if (err == fnfErr) + err = noErr; + } + if (err != noErr) + return err; + path = nextColon; // next round + } while (1); + } + return err; } // MacFileHelpers::FSSpecFromPathname //---------------------------------------------------------------------------------------- OSErr MacFileHelpers::CreateFolderInFolder( - short refNum, // Parent directory/volume - long dirID, - ConstStr255Param folderName, // Name of the new folder - short& outRefNum, // Volume of the created folder - long& outDirID) // + short refNum, // Parent directory/volume + long dirID, + ConstStr255Param folderName, // Name of the new folder + short& outRefNum, // Volume of the created folder + long& outDirID) // // Creates a folder named 'folderName' inside a folder. // The errors returned are same as PBDirCreate //---------------------------------------------------------------------------------------- { - HFileParam hpb; - hpb.ioVRefNum = refNum; - hpb.ioDirID = dirID; - hpb.ioNamePtr = (StringPtr)&folderName; + HFileParam hpb; + hpb.ioVRefNum = refNum; + hpb.ioDirID = dirID; + hpb.ioNamePtr = (StringPtr)&folderName; - OSErr err = PBDirCreateSync((HParmBlkPtr)&hpb); - if (err == noErr) - { - outRefNum = hpb.ioVRefNum; - outDirID = hpb.ioDirID; - } - else - { - outRefNum = 0; - outDirID = 0; - } - return err; + OSErr err = PBDirCreateSync((HParmBlkPtr)&hpb); + if (err == noErr) + { + outRefNum = hpb.ioVRefNum; + outDirID = hpb.ioDirID; + } + else + { + outRefNum = 0; + outDirID = 0; + } + return err; } // MacFileHelpers::CreateFolderInFolder //---------------------------------------------------------------------------------------- void MacFileHelpers::EnsureAliasHaven() //---------------------------------------------------------------------------------------- { - // Alias Haven is a directory in which we never resolve aliases. - if (sAliasHavenVRefNum != 0) - return; + // Alias Haven is a directory in which we never resolve aliases. + if (sAliasHavenVRefNum != 0) + return; - - FSSpec temp; - if (FindFolder(0, kTemporaryFolderType, true, & temp.vRefNum, &temp.parID) == noErr) - { - CreateFolderInFolder( - temp.vRefNum, // Parent directory/volume - temp.parID, - kAliasHavenFolderName, // Name of the new folder - sAliasHavenVRefNum, // Volume of the created folder - sAliasHavenDirID); - } + + FSSpec temp; + if (FindFolder(0, kTemporaryFolderType, true, & temp.vRefNum, &temp.parID) == noErr) + { + CreateFolderInFolder( + temp.vRefNum, // Parent directory/volume + temp.parID, + kAliasHavenFolderName, // Name of the new folder + sAliasHavenVRefNum, // Volume of the created folder + sAliasHavenDirID); + } } // MacFileHelpers::EnsureAliasHaven //---------------------------------------------------------------------------------------- @@ -445,55 +455,55 @@ PRBool MacFileHelpers::IsAliasSafe(const FSSpec& inSpec) // has been turned off. //---------------------------------------------------------------------------------------- { - return sNoResolve - || (inSpec.parID == sAliasHavenDirID && inSpec.vRefNum == sAliasHavenVRefNum); + return sNoResolve + || (inSpec.parID == sAliasHavenDirID && inSpec.vRefNum == sAliasHavenVRefNum); } // MacFileHelpers::IsAliasSafe //---------------------------------------------------------------------------------------- OSErr MacFileHelpers::ResolveAliasFile(FSSpec& inOutSpec, Boolean& wasAliased) //---------------------------------------------------------------------------------------- { - wasAliased = false; - if (IsAliasSafe(inOutSpec)) - return noErr; - Boolean dummy; - return ::ResolveAliasFile(&inOutSpec, TRUE, &dummy, &wasAliased); + wasAliased = false; + if (IsAliasSafe(inOutSpec)) + return noErr; + Boolean dummy; + return ::ResolveAliasFile(&inOutSpec, TRUE, &dummy, &wasAliased); } // MacFileHelpers::ResolveAliasFile //----------------------------------- OSErr MacFileHelpers::FSSpecFromUnixPath( - const char * unixPath, - FSSpec& ioSpec, - Boolean hexDecode, - Boolean resolveAlias, - Boolean allowPartial, - Boolean createDirs) + const char * unixPath, + FSSpec& ioSpec, + Boolean hexDecode, + Boolean resolveAlias, + Boolean allowPartial, + Boolean createDirs) // File spec from URL. Reverses GetURLFromFileSpec // Its input is only the part of the URL // JRM 97/01/08 changed this so that if it's a partial path (doesn't start with '/'), // then it is combined with inOutSpec's vRefNum and parID to form a new spec. //----------------------------------- { - if (unixPath == nsnull) - return badFidErr; - char* macPath = MacPathFromUnixPath(unixPath, hexDecode); - if (!macPath) - return memFullErr; + if (unixPath == nsnull) + return badFidErr; + char* macPath = MacPathFromUnixPath(unixPath, hexDecode); + if (!macPath) + return memFullErr; - OSErr err = noErr; - if (!allowPartial) - { - NS_ASSERTION(*unixPath == '/' /*full path*/, "Not a full Unix path!"); - } - err = FSSpecFromPathname(macPath, ioSpec, createDirs); - if (err == fnfErr) - err = noErr; - Boolean dummy; - if (err == noErr && resolveAlias) // Added - err = MacFileHelpers::ResolveAliasFile(ioSpec, dummy); - delete [] macPath; - NS_ASSERTION(err==noErr||err==fnfErr||err==dirNFErr||err==nsvErr, "Not a path!"); - return err; + OSErr err = noErr; + if (!allowPartial) + { + NS_ASSERTION(*unixPath == '/' /*full path*/, "Not a full Unix path!"); + } + err = FSSpecFromPathname(macPath, ioSpec, createDirs); + if (err == fnfErr) + err = noErr; + Boolean dummy; + if (err == noErr && resolveAlias) // Added + err = MacFileHelpers::ResolveAliasFile(ioSpec, dummy); + delete [] macPath; + NS_ASSERTION(err==noErr||err==fnfErr||err==dirNFErr||err==nsvErr, "Not a path!"); + return err; } // MacFileHelpers::FSSpecFromLocalUnixPath //----------------------------------- @@ -504,106 +514,107 @@ char* MacFileHelpers::PathNameFromFSSpec( const FSSpec& inSpec, Boolean wantLeaf // fnfErr. //----------------------------------- { - char* result = nil; - OSErr err = noErr; - - short fullPathLength = 0; - Handle fullPath = nsnull; - - FSSpec tempSpec = inSpec; - if ( tempSpec.parID == fsRtParID ) - { - /* The object is a volume */ - - /* Add a colon to make it a full pathname */ - tempSpec.name[++tempSpec.name[0]] = ':'; - - /* We're done */ - err = PtrToHand(&tempSpec.name[1], &fullPath, tempSpec.name[0]); - } - else - { - /* The object isn't a volume */ - - CInfoPBRec pb = { 0 }; - Str63 dummyFileName; - MacFileHelpers::PLstrcpy(dummyFileName, "\pG'day!"); + char* result = nil; + OSErr err = noErr; + + short fullPathLength = 0; + Handle fullPath = nsnull; + + FSSpec tempSpec = inSpec; + if ( tempSpec.parID == fsRtParID ) + { + /* The object is a volume */ + + /* Add a colon to make it a full pathname */ + tempSpec.name[++tempSpec.name[0]] = ':'; + + /* We're done */ + err = PtrToHand(&tempSpec.name[1], &fullPath, tempSpec.name[0]); + } + else + { + /* The object isn't a volume */ + + CInfoPBRec pb = { 0 }; + Str63 dummyFileName; + MacFileHelpers::PLstrcpy(dummyFileName, "\pG'day!"); - /* Is the object a file or a directory? */ - pb.dirInfo.ioNamePtr = (! tempSpec.name[0]) ? (StringPtr)dummyFileName : 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 object is a directory, append a colon so full pathname ends with colon - // Beware of the "illegal spec" case that Netscape uses (empty name string). In - // this case, we don't want the colon. - if ( err == noErr && tempSpec.name[0] && (pb.hFileInfo.ioFlAttrib & ioDirMask) != 0 ) - { - ++tempSpec.name[0]; - tempSpec.name[tempSpec.name[0]] = ':'; - } - - /* Put the object name in first */ - err = PtrToHand(&tempSpec.name[1], &fullPath, tempSpec.name[0]); - if ( err == 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; - err = PBGetCatInfoSync(&pb); - if ( err == 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, nsnull, 0, &tempSpec.name[1], tempSpec.name[0]); - err = MemError(); - } - } while ( err == noErr && pb.dirInfo.ioDrDirID != fsRtDirID ); - } - } - } - if ( err != noErr && err != fnfErr) - goto Clean; + /* Is the object a file or a directory? */ + pb.dirInfo.ioNamePtr = (! tempSpec.name[0]) ? (StringPtr)dummyFileName : 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 object is a directory, append a colon so full pathname ends with colon + // Beware of the "illegal spec" case that Netscape uses (empty name string). In + // this case, we don't want the colon. + if ( err == noErr && tempSpec.name[0] && (pb.hFileInfo.ioFlAttrib & ioDirMask) != 0 ) + { + ++tempSpec.name[0]; + tempSpec.name[tempSpec.name[0]] = ':'; + } + + /* Put the object name in first */ + err = PtrToHand(&tempSpec.name[1], &fullPath, tempSpec.name[0]); + if ( err == 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; + err = PBGetCatInfoSync(&pb); + if ( err == 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, nsnull, 0, &tempSpec.name[1], tempSpec.name[0]); + err = MemError(); + } + } while ( err == noErr && pb.dirInfo.ioDrDirID != fsRtDirID ); + } + } + } + if ( err != noErr && err != fnfErr) + goto Clean; - fullPathLength = GetHandleSize(fullPath); - err = noErr; - int allocSize = 1 + fullPathLength; - // We only want the leaf name if it's the root directory or wantLeafName is true. - if (inSpec.parID != fsRtParID && !wantLeafName) - allocSize -= inSpec.name[0]; - result = new char[allocSize]; - if (!result) - goto Clean; - memcpy(result, *fullPath, allocSize - 1); - result[ allocSize - 1 ] = 0; + fullPathLength = GetHandleSize(fullPath); + err = noErr; + int allocSize = 1 + fullPathLength; + // We only want the leaf name if it's the root directory or wantLeafName is true. + if (inSpec.parID != fsRtParID && !wantLeafName) + allocSize -= inSpec.name[0]; + result = new char[allocSize]; + if (!result) + goto Clean; + memcpy(result, *fullPath, allocSize - 1); + result[ allocSize - 1 ] = 0; Clean: - if (fullPath) - DisposeHandle(fullPath); - NS_ASSERTION(result, "Out of memory"); // OOPS! very bad. - return result; + if (fullPath) + DisposeHandle(fullPath); + NS_ASSERTION(result, "Out of memory"); // OOPS! very bad. + return result; } // MacFileHelpers::PathNameFromFSSpec +#pragma mark - + //======================================================================================== -// Macintosh nsFileSpec implementation +// Macintosh nsFileSpec implementation //======================================================================================== //---------------------------------------------------------------------------------------- nsFileSpec::nsFileSpec() //---------------------------------------------------------------------------------------- -: mError(NS_ERROR_NOT_INITIALIZED) { - mSpec.name[0] = '\0'; + Clear(); } //---------------------------------------------------------------------------------------- @@ -612,11 +623,11 @@ nsFileSpec::nsFileSpec(const FSSpec& inSpec, PRBool resolveAlias) : mSpec(inSpec) , mError(NS_OK) { - if (resolveAlias) - { - PRBool dummy; - ResolveSymlink(dummy); - } + if (resolveAlias) + { + PRBool dummy; + ResolveSymlink(dummy); + } } //---------------------------------------------------------------------------------------- @@ -630,8 +641,8 @@ void nsFileSpec::operator = (const FSSpec& inSpec) //---------------------------------------------------------------------------------------- nsFileSpec::nsFileSpec(const nsFileSpec& inSpec) //---------------------------------------------------------------------------------------- -: mSpec(inSpec.mSpec) -, mError(inSpec.Error()) +: mSpec(inSpec.mSpec) +, mError(inSpec.Error()) { } @@ -639,20 +650,15 @@ nsFileSpec::nsFileSpec(const nsFileSpec& inSpec) nsFileSpec::nsFileSpec(const char* inNativePathString, PRBool inCreateDirs) //---------------------------------------------------------------------------------------- { - mSpec.vRefNum = 0; - mSpec.parID = 0; + Clear(); // this sets mError to NS_ERROR_NOT_INITIALIZED - if (inNativePathString) - { - mError = NS_FILE_RESULT(MacFileHelpers::FSSpecFromPathname( - inNativePathString, mSpec, inCreateDirs)); - if (mError == NS_FILE_RESULT(fnfErr)) - mError = NS_OK; - } - else - { - mError = NS_ERROR_NOT_INITIALIZED; - } + if (inNativePathString) + { + mError = NS_FILE_RESULT(MacFileHelpers::FSSpecFromPathname( + inNativePathString, mSpec, inCreateDirs)); + if (mError == NS_FILE_RESULT(fnfErr)) + mError = NS_OK; + } } // nsFileSpec::nsFileSpec @@ -660,107 +666,110 @@ nsFileSpec::nsFileSpec(const char* inNativePathString, PRBool inCreateDirs) nsFileSpec::nsFileSpec(const nsString& inNativePathString, PRBool inCreateDirs) //---------------------------------------------------------------------------------------- { - mSpec.vRefNum = 0; - mSpec.parID = 0; + Clear(); // this sets mError to NS_ERROR_NOT_INITIALIZED - mError = NS_FILE_RESULT( - MacFileHelpers::FSSpecFromPathname( - nsAutoCString(inNativePathString), - mSpec, inCreateDirs)); - if (mError == NS_FILE_RESULT(fnfErr)) - mError = NS_OK; + mError = NS_FILE_RESULT( + MacFileHelpers::FSSpecFromPathname( + nsAutoCString(inNativePathString), + mSpec, inCreateDirs)); + if (mError == NS_FILE_RESULT(fnfErr)) + mError = NS_OK; } // nsFileSpec::nsFileSpec //---------------------------------------------------------------------------------------- -nsFileSpec::nsFileSpec(short vRefNum, long parID, ConstStr255Param name, PRBool resolveAlias) +nsFileSpec::nsFileSpec(short vRefNum, long parID, ConstStr255Param fileName, PRBool resolveAlias) //---------------------------------------------------------------------------------------- { - mError = NS_FILE_RESULT(::FSMakeFSSpec(vRefNum, parID, name, &mSpec)); - if (mError == NS_FILE_RESULT(fnfErr)) - mError = NS_OK; + mError = NS_FILE_RESULT(::FSMakeFSSpec(vRefNum, parID, fileName, &mSpec)); + if (mError == NS_FILE_RESULT(fnfErr)) + mError = NS_OK; - if (resolveAlias) - { - PRBool dummy; - ResolveSymlink(dummy); - } + if (resolveAlias) + { + PRBool dummy; + ResolveSymlink(dummy); + } } //---------------------------------------------------------------------------------------- nsFileSpec::nsFileSpec(const nsFilePath& inPath) //---------------------------------------------------------------------------------------- { - *this = inPath.GetFileSpec(); + *this = inPath.GetFileSpec(); } //---------------------------------------------------------------------------------------- void nsFileSpec::operator = (const char* inString) //---------------------------------------------------------------------------------------- { - mPath.SetToEmpty(); + Clear(); // this sets mError to NS_ERROR_NOT_INITIALIZED - mSpec.vRefNum = 0; - mSpec.parID = 0; - - if (inString) - { - mError = NS_FILE_RESULT(MacFileHelpers::FSSpecFromPathname(inString, mSpec, true)); - if (mError == NS_FILE_RESULT(fnfErr)) - mError = NS_OK; - } - else - { - mError = NS_ERROR_NOT_INITIALIZED; - } - + if (inString) + { + mError = NS_FILE_RESULT(MacFileHelpers::FSSpecFromPathname(inString, mSpec, true)); + if (mError == NS_FILE_RESULT(fnfErr)) + mError = NS_OK; + } + } // nsFileSpec::operator = //---------------------------------------------------------------------------------------- void nsFileSpec::operator = (const nsFileSpec& inSpec) //---------------------------------------------------------------------------------------- { - mPath.SetToEmpty(); - mSpec.vRefNum = inSpec.mSpec.vRefNum; - mSpec.parID = inSpec.mSpec.parID; - memcpy(mSpec.name, inSpec.mSpec.name, inSpec.mSpec.name[0] + 1); - mError = inSpec.Error(); + mPath.SetToEmpty(); + mSpec.vRefNum = inSpec.mSpec.vRefNum; + mSpec.parID = inSpec.mSpec.parID; + memcpy(mSpec.name, inSpec.mSpec.name, inSpec.mSpec.name[0] + 1); + mError = inSpec.Error(); // note that the error is propagated } // nsFileSpec::operator = //---------------------------------------------------------------------------------------- void nsFileSpec::operator = (const nsFilePath& inPath) //---------------------------------------------------------------------------------------- { - *this = inPath.GetFileSpec(); + *this = inPath.GetFileSpec(); } // nsFileSpec::operator = +//---------------------------------------------------------------------------------------- +inline void nsFileSpec::Clear() +//---------------------------------------------------------------------------------------- +{ + mPath.SetToEmpty(); + mSpec.vRefNum = 0; + mSpec.parID = 0; + mSpec.name[0] = 0; + mError = NS_ERROR_NOT_INITIALIZED; +} + //---------------------------------------------------------------------------------------- PRBool nsFileSpec::Exists() const //---------------------------------------------------------------------------------------- { - FSSpec temp; - return ::FSMakeFSSpec(mSpec.vRefNum, mSpec.parID, mSpec.name, &temp) == noErr; + FSSpec temp; + return ::FSMakeFSSpec(mSpec.vRefNum, mSpec.parID, mSpec.name, &temp) == noErr; } // nsFileSpec::Exists() //---------------------------------------------------------------------------------------- void nsFileSpec::GetModDate(TimeStamp& outStamp) const //---------------------------------------------------------------------------------------- { - CInfoPBRec pb; - if (GetCatInfo(pb) == noErr) - outStamp = ((DirInfo*)&pb)->ioDrMdDat; // The mod date is in the same spot for files and dirs. - else - outStamp = 0; + CInfoPBRec pb; + if (GetCatInfo(pb) == noErr) + outStamp = ((DirInfo*)&pb)->ioDrMdDat; // The mod date is in the same spot for files and dirs. + else + outStamp = 0; } // nsFileSpec::GetModDate //---------------------------------------------------------------------------------------- PRUint32 nsFileSpec::GetFileSize() const //---------------------------------------------------------------------------------------- { - CInfoPBRec pb; - if (noErr == GetCatInfo(pb)) - return (PRUint32)((HFileInfo*)&pb)->ioFlLgLen; - return 0; + CInfoPBRec pb; + if (noErr == GetCatInfo(pb)) + return (PRUint32)((HFileInfo*)&pb)->ioFlLgLen; + return 0; } // nsFileSpec::GetFileSize //---------------------------------------------------------------------------------------- @@ -768,15 +777,21 @@ void nsFileSpec::SetLeafName(const char* inLeafName) // In leaf name can actually be a partial path... //---------------------------------------------------------------------------------------- { - mPath.SetToEmpty(); + NS_ASSERTION(inLeafName, "Attempt to set leaf name with a null string"); + + mPath.SetToEmpty(); - // what about long relative paths? Hmm? We don't have a routine for this anywhere. - Str255 partialPath; - MacFileHelpers::PLstrcpy(partialPath, inLeafName); - mError = NS_FILE_RESULT( - ::FSMakeFSSpec(mSpec.vRefNum, mSpec.parID, partialPath, &mSpec)); - if (mError == NS_FILE_RESULT(fnfErr)) - mError = NS_OK; + if (inLeafName) + { + // what about long relative paths? Hmm? We don't have a routine for this anywhere. + Str255 partialPath; + MacFileHelpers::PLstrcpy(partialPath, inLeafName); + mError = NS_FILE_RESULT( + ::FSMakeFSSpec(mSpec.vRefNum, mSpec.parID, partialPath, &mSpec)); + if (mError == NS_FILE_RESULT(fnfErr)) + mError = NS_OK; + } + } // nsFileSpec::SetLeafName //---------------------------------------------------------------------------------------- @@ -784,82 +799,82 @@ char* nsFileSpec::GetLeafName() const // Result needs to be nsCRT::free()ed. //---------------------------------------------------------------------------------------- { - char leaf[64]; - memcpy(leaf, &mSpec.name[1], mSpec.name[0]); - leaf[mSpec.name[0]] = '\0'; - return nsCRT::strdup(leaf); + char leaf[64]; + memcpy(leaf, &mSpec.name[1], mSpec.name[0]); + leaf[mSpec.name[0]] = '\0'; + return nsCRT::strdup(leaf); } // nsFileSpec::GetLeafName //---------------------------------------------------------------------------------------- void nsFileSpec::MakeAliasSafe() //---------------------------------------------------------------------------------------- { - mPath.SetToEmpty(); - mError = NS_FILE_RESULT(MacFileHelpers::MakeAliasSafe(mSpec)); + mPath.SetToEmpty(); + mError = NS_FILE_RESULT(MacFileHelpers::MakeAliasSafe(mSpec)); } // nsFileSpec::MakeAliasSafe //---------------------------------------------------------------------------------------- void nsFileSpec::MakeUnique(ConstStr255Param inSuggestedLeafName) //---------------------------------------------------------------------------------------- { - mPath.SetToEmpty(); - if (inSuggestedLeafName[0] > 0) - MacFileHelpers::PLstrcpy(mSpec.name, inSuggestedLeafName); + mPath.SetToEmpty(); + if (inSuggestedLeafName[0] > 0) + MacFileHelpers::PLstrcpy(mSpec.name, inSuggestedLeafName); - MakeUnique(); + MakeUnique(); } // nsFileSpec::MakeUnique //---------------------------------------------------------------------------------------- PRBool nsFileSpec::IsFile() const //---------------------------------------------------------------------------------------- { - long dirID; - Boolean isDirectory; - return (noErr == FSpGetDirectoryID(&mSpec, &dirID, &isDirectory) && !isDirectory); + long dirID; + Boolean isDirectory; + return (noErr == ::FSpGetDirectoryID(&mSpec, &dirID, &isDirectory) && !isDirectory); } // nsFileSpec::IsFile //---------------------------------------------------------------------------------------- PRBool nsFileSpec::IsDirectory() const //---------------------------------------------------------------------------------------- { - long dirID; - Boolean isDirectory; - return (noErr == FSpGetDirectoryID(&mSpec, &dirID, &isDirectory) && isDirectory); + long dirID; + Boolean isDirectory; + return (noErr == ::FSpGetDirectoryID(&mSpec, &dirID, &isDirectory) && isDirectory); } // nsFileSpec::IsDirectory //---------------------------------------------------------------------------------------- PRBool nsFileSpec::IsHidden() const //---------------------------------------------------------------------------------------- { - CInfoPBRec cInfo; - PRBool hidden = PR_FALSE; + CInfoPBRec cInfo; + PRBool hidden = PR_FALSE; - if (noErr == GetCatInfo(cInfo)) - if (cInfo.hFileInfo.ioFlFndrInfo.fdFlags & kIsInvisible) - hidden = PR_TRUE; - - return hidden; + if (noErr == GetCatInfo(cInfo)) + if (cInfo.hFileInfo.ioFlFndrInfo.fdFlags & kIsInvisible) + hidden = PR_TRUE; + + return hidden; } // nsFileSpec::IsHidden //---------------------------------------------------------------------------------------- PRBool nsFileSpec::IsSymlink() const //---------------------------------------------------------------------------------------- { - CInfoPBRec cInfo; - PRBool hidden = PR_FALSE; + CInfoPBRec cInfo; + PRBool hidden = PR_FALSE; - if (noErr == GetCatInfo(cInfo)) - if (cInfo.hFileInfo.ioFlFndrInfo.fdFlags & kIsAlias) - hidden = PR_TRUE; - - return hidden; + if (noErr == GetCatInfo(cInfo)) + if (cInfo.hFileInfo.ioFlFndrInfo.fdFlags & kIsAlias) + hidden = PR_TRUE; + + return hidden; } // nsFileSpec::IsSymlink //---------------------------------------------------------------------------------------- nsresult nsFileSpec::ResolveSymlink(PRBool& wasAliased) //---------------------------------------------------------------------------------------- { - Boolean wasAliased2; // Type conversion Boolean <--> PRBool + Boolean wasAliased2; // Type conversion Boolean <--> PRBool OSErr err = MacFileHelpers::ResolveAliasFile(mSpec, wasAliased2); if (wasAliased2) { @@ -869,67 +884,78 @@ nsresult nsFileSpec::ResolveSymlink(PRBool& wasAliased) else wasAliased = PR_FALSE; - return mError; + return mError; } // nsFileSpec::ResolveSymlink //---------------------------------------------------------------------------------------- void nsFileSpec::GetParent(nsFileSpec& outSpec) const //---------------------------------------------------------------------------------------- { - if (NS_SUCCEEDED(mError)) - outSpec.mError - = NS_FILE_RESULT(::FSMakeFSSpec(mSpec.vRefNum, mSpec.parID, nsnull, outSpec)); + if (NS_SUCCEEDED(mError)) + outSpec.mError = NS_FILE_RESULT(::FSMakeFSSpec(mSpec.vRefNum, mSpec.parID, nsnull, outSpec)); } // nsFileSpec::GetParent //---------------------------------------------------------------------------------------- void nsFileSpec::operator += (const char* inRelativePath) //---------------------------------------------------------------------------------------- { - // Invalidate the path cache string, since we're changing ourselves. - mPath.SetToEmpty(); - // Find the dirID of the directory described by this spec - long dirID; - Boolean isDirectory; - mError = NS_FILE_RESULT(::FSpGetDirectoryID(&mSpec, &dirID, &isDirectory)); - if (NS_FAILED(mError) || !isDirectory || !inRelativePath) - return; - // mSpec.vRefNum is already correct. - mSpec.parID = dirID; + NS_ASSERTION(inRelativePath, "Attempt to append relative path with null path"); - // Next, determine if it is a UNIX or Mac style path. Now, Macintosh relative paths - // are either leaf names (in which the distinction between unix and macintosh - // relative paths disappears) or they start with a colon. If we find an initial colon, - // then assume it's a macintosh path. - // If it is a UNIX path (including just a leaf name), we will also look for ':' and - // assert if we find one. - if (*inRelativePath != ':') - { - // Looks like a UNIX path (including possibly just a leaf name) - NS_ASSERTION(strchr(inRelativePath, ':') == nsnull, - "Can not determine path type"); - // Convert unix path (which is unencoded) to a spec - mError = NS_FILE_RESULT( - MacFileHelpers::FSSpecFromUnixPath( - inRelativePath, mSpec, false, false, true, true)); - } - else - { - // We must be a mac path! - mError = - NS_FILE_RESULT( - MacFileHelpers::FSSpecFromPathname(inRelativePath, mSpec, true)); - } - if (mError == NS_FILE_RESULT(fnfErr)) - mError = NS_OK; - + // Invalidate the path cache string, since we're changing ourselves. + mPath.SetToEmpty(); + + // if we are already bad, don't allow appendage + if (NS_FAILED(Error())) + { + NS_WARNING("trying to append to a bad nsFileSpec"); + return; + } + + // Find the dirID of the directory described by this spec + long dirID; + Boolean isDirectory; + mError = NS_FILE_RESULT(::FSpGetDirectoryID(&mSpec, &dirID, &isDirectory)); + if (NS_FAILED(mError) || !isDirectory || !inRelativePath) + return; + // mSpec.vRefNum is already correct. + mSpec.parID = dirID; + + // Next, determine if it is a UNIX or Mac style path. Now, Macintosh relative paths + // are either leaf names (in which the distinction between unix and macintosh + // relative paths disappears) or they start with a colon. If we find an initial colon, + // then assume it's a macintosh path. + // If it is a UNIX path (including just a leaf name), we will also look for ':' and + // assert if we find one. + if (*inRelativePath != ':') + { + // Looks like a UNIX path (including possibly just a leaf name) + NS_ASSERTION(strchr(inRelativePath, ':') == nsnull, "Can not determine path type"); + // Convert unix path (which is unencoded) to a spec + mError = NS_FILE_RESULT( + MacFileHelpers::FSSpecFromUnixPath(inRelativePath, mSpec, false, false, true, true)); + } + else + { + // We must be a mac path! + mError = NS_FILE_RESULT(MacFileHelpers::FSSpecFromPathname(inRelativePath, mSpec, true)); + } + if (mError == NS_FILE_RESULT(fnfErr)) + mError = NS_OK; + } // nsFileSpec::operator += //---------------------------------------------------------------------------------------- void nsFileSpec::CreateDirectory(int /* unix mode */) //---------------------------------------------------------------------------------------- { - long ignoredDirID; - mError = NS_FILE_RESULT(FSpDirCreate(&mSpec, smCurrentScript, &ignoredDirID)); + long ignoredDirID; + OSErr err = ::FSpDirCreate(&mSpec, smCurrentScript, &ignoredDirID); + // it's OK if the dir already exists + if (err != noErr && IsDirectory()) + err = noErr; + + mError = NS_FILE_RESULT(err); + } // nsFileSpec::CreateDirectory //---------------------------------------------------------------------------------------- @@ -938,21 +964,22 @@ void nsFileSpec::Delete(PRBool inRecursive) const { OSErr anErr; - nsresult& mutableError = const_cast(this)->mError; - if (inRecursive) - { - // MoreFilesExtras - anErr = ::DeleteDirectory( - mSpec.vRefNum, - mSpec.parID, - const_cast(mSpec.name)); - } - else - anErr = ::FSpDelete(&mSpec); - - if (anErr == fnfErr) // deleting a file that doesn't exist isn't an error! - anErr = noErr; - mutableError = NS_FILE_RESULT(anErr); + nsresult& mutableError = const_cast(this)->mError; + if (inRecursive) + { + // MoreFilesExtras + anErr = ::DeleteDirectory( + mSpec.vRefNum, + mSpec.parID, + const_cast(mSpec.name)); + } + else + anErr = ::FSpDelete(&mSpec); + + if (anErr == fnfErr) // deleting a file that doesn't exist isn't an error! + anErr = noErr; + + mutableError = NS_FILE_RESULT(anErr); } // nsFileSpec::Delete @@ -960,8 +987,8 @@ void nsFileSpec::Delete(PRBool inRecursive) const void nsFileSpec::RecursiveCopy(nsFileSpec newDir) const //---------------------------------------------------------------------------------------- { - if (IsDirectory()) - { + if (IsDirectory()) + { if (!(newDir.Exists())) { newDir.CreateDirectory(); @@ -983,12 +1010,12 @@ void nsFileSpec::RecursiveCopy(nsFileSpec newDir) const } else { - child.RecursiveCopy(newDir); + child.RecursiveCopy(newDir); } } - } - else - { + } + else + { nsFileSpec& filePath = (nsFileSpec&) *this; if (!(newDir.Exists())) @@ -996,8 +1023,8 @@ void nsFileSpec::RecursiveCopy(nsFileSpec newDir) const newDir.CreateDirectory(); } - filePath.Copy(newDir); - } + filePath.Copy(newDir); + } } // nsFileSpec::RecursiveCopy @@ -1005,34 +1032,36 @@ void nsFileSpec::RecursiveCopy(nsFileSpec newDir) const nsresult nsFileSpec::Rename(const char* inNewName) //---------------------------------------------------------------------------------------- { - if (strchr(inNewName, '/')) - return -1; // no relative paths here! - Str255 pName; - MacFileHelpers::PLstrcpy(pName, inNewName); - if (FSpRename(&mSpec, pName) != noErr) - return -1; - SetLeafName(inNewName); - return 0; + NS_ASSERTION(inNewName, "Attempt to rename with null new name"); + + if (strchr(inNewName, '/')) + return NS_FILE_FAILURE; // no relative paths here! + + Str255 pName; + MacFileHelpers::PLstrcpy(pName, inNewName); + if (::FSpRename(&mSpec, pName) != noErr) + return NS_FILE_FAILURE; + SetLeafName(inNewName); + return NS_OK; } // nsFileSpec::Rename //---------------------------------------------------------------------------------------- nsresult nsFileSpec::Copy(const nsFileSpec& newParentDir) const //---------------------------------------------------------------------------------------- { - // We can only copy into a directory, and (for now) can not copy entire directories + // We can only copy into a directory, and (for now) can not copy entire directories - if (!newParentDir.IsDirectory() || (IsDirectory() ) ) - return NS_FILE_FAILURE; + if (!newParentDir.IsDirectory() || (IsDirectory() ) ) + return NS_FILE_FAILURE; + + nsresult rv = NS_FILE_RESULT(::FSpFileCopy(&mSpec, + &newParentDir.mSpec, + const_cast(GetLeafPName()), + nsnull, + 0, + true)); - - nsresult result = NS_FILE_RESULT(::FSpFileCopy( &mSpec, - &newParentDir.mSpec, - const_cast(GetLeafPName()), - nsnull, - 0, - true)); - - return result; + return rv; } // nsFileSpec::Copy @@ -1040,43 +1069,43 @@ nsresult nsFileSpec::Copy(const nsFileSpec& newParentDir) const nsresult nsFileSpec::Move(const nsFileSpec& newParentDir) //---------------------------------------------------------------------------------------- { - // We can only move into a directory - - if (!newParentDir.IsDirectory()) - return NS_FILE_FAILURE; + // We can only move into a directory + + if (!newParentDir.IsDirectory()) + return NS_FILE_FAILURE; - nsresult result = NS_FILE_RESULT(::FSpMoveRenameCompat(&mSpec, - &newParentDir.mSpec, - const_cast(GetLeafPName()))); + nsresult result = NS_FILE_RESULT(::FSpMoveRenameCompat(&mSpec, + &newParentDir.mSpec, + const_cast(GetLeafPName()))); - if ( NS_SUCCEEDED(result) ) - { - char* leafName = GetLeafName(); - *this = newParentDir + leafName; - nsCRT::free(leafName); - } - return result; + if ( NS_SUCCEEDED(result) ) + { + char* leafName = GetLeafName(); + *this = newParentDir + leafName; + nsCRT::free(leafName); + } + return result; } // nsFileSpec::Move //---------------------------------------------------------------------------------------- nsresult nsFileSpec::Execute(const char* /*args - how can this be cross-platform? problem! */ ) const //---------------------------------------------------------------------------------------- { - if (IsDirectory()) - return NS_FILE_FAILURE; + if (IsDirectory()) + return NS_FILE_FAILURE; - LaunchParamBlockRec launchThis; - launchThis.launchAppSpec = const_cast(&mSpec); - launchThis.launchAppParameters = nsnull; // args; - /* launch the thing */ - launchThis.launchBlockID = extendedBlock; - launchThis.launchEPBLength = extendedBlockLen; - launchThis.launchFileFlags = nsnull; - launchThis.launchControlFlags = launchContinue + launchNoFileFlags + launchUseMinimum; - launchThis.launchControlFlags += launchDontSwitch; + LaunchParamBlockRec launchThis; + launchThis.launchAppSpec = const_cast(&mSpec); + launchThis.launchAppParameters = nsnull; // args; + /* launch the thing */ + launchThis.launchBlockID = extendedBlock; + launchThis.launchEPBLength = extendedBlockLen; + launchThis.launchFileFlags = nsnull; + launchThis.launchControlFlags = launchContinue + launchNoFileFlags + launchUseMinimum; + launchThis.launchControlFlags += launchDontSwitch; - nsresult result = NS_FILE_RESULT(::LaunchApplication(&launchThis)); - return result; + nsresult result = NS_FILE_RESULT(::LaunchApplication(&launchThis)); + return result; } // nsFileSpec::Execute @@ -1084,351 +1113,363 @@ nsresult nsFileSpec::Execute(const char* /*args - how can this be cross-platform OSErr nsFileSpec::GetCatInfo(CInfoPBRec& outInfo) const //---------------------------------------------------------------------------------------- { - DirInfo *dipb=(DirInfo *)&outInfo; - dipb->ioCompletion = nsnull; - dipb->ioFDirIndex = 0; // use dirID and name - dipb->ioVRefNum = mSpec.vRefNum; - dipb->ioDrDirID = mSpec.parID; - dipb->ioNamePtr = const_cast(this)->mSpec.name; - return PBGetCatInfoSync(&outInfo); + DirInfo *dipb=(DirInfo *)&outInfo; + dipb->ioCompletion = nsnull; + dipb->ioFDirIndex = 0; // use dirID and name + dipb->ioVRefNum = mSpec.vRefNum; + dipb->ioDrDirID = mSpec.parID; + dipb->ioNamePtr = const_cast(this)->mSpec.name; + return PBGetCatInfoSync(&outInfo); } // nsFileSpec::GetCatInfo() -#if DOUGT_UNTESTED + //---------------------------------------------------------------------------------------- OSErr nsFileSpec::SetFileTypeAndCreator(OSType type, OSType creator) //---------------------------------------------------------------------------------------- { - FInfo info; - OSErr err = ::FSpGetFInfo (mSpec, &info); + FInfo info; + OSErr err = ::FSpGetFInfo(&mSpec, &info); if (err != noErr) return err; info.fdType = type; - info.fdCreator = creator; - err = ::FSpSetFInfo (mSpec, &info); + info.fdCreator = creator; + err = ::FSpSetFInfo(&mSpec, &info); return err; } - //---------------------------------------------------------------------------------------- OSErr nsFileSpec::GetFileTypeAndCreator(OSType* type, OSType* creator) //---------------------------------------------------------------------------------------- { - FInfo info; - OSErr err = ::FSpGetFInfo (mSpec, &info); + FInfo info; + OSErr err = ::FSpGetFInfo(&mSpec, &info); if (err != noErr) return err; *type = info.fdType; - *creator = info.fdCreator; - return noErr; + *creator = info.fdCreator; + return noErr; } -#endif - //---------------------------------------------------------------------------------------- PRInt64 nsFileSpec::GetDiskSpaceAvailable() const //---------------------------------------------------------------------------------------- { - PRInt64 int64; + PRInt64 space64Bits; - LL_I2L(int64 , LONG_MAX); + LL_I2L(space64Bits , LONG_MAX); - HVolumeParam pb; - pb.ioCompletion = nsnull; - pb.ioVolIndex = 0; - pb.ioNamePtr = nsnull; - pb.ioVRefNum = mSpec.vRefNum; - - OSErr err = PBHGetVInfoSync( (HParmBlkPtr)&pb ); - - if ( err == noErr ) - LL_I2L(int64 , (pb.ioVFrBlk * pb.ioVAlBlkSiz)); - - return int64; + XVolumeParam pb; + pb.ioCompletion = nsnull; + pb.ioVolIndex = 0; + pb.ioNamePtr = nsnull; + pb.ioVRefNum = mSpec.vRefNum; + + // PBXGetVolInfoSync works on HFS+ volumes too! + OSErr err = ::PBXGetVolInfoSync(&pb); + + if (err == noErr) + { + space64Bits.lo = pb.ioVFreeBytes.lo; + space64Bits.hi = pb.ioVFreeBytes.hi; + } + + return space64Bits; } // nsFileSpec::GetDiskSpace() //---------------------------------------------------------------------------------------- const char* nsFileSpec::GetCString() const // This is the only conversion to const char* that is provided, and it allows the // path to be "passed" to NSPR file routines. This practice is VERY EVIL and should only -// be used to support legacy code. Using it guarantees bugs on Macintosh. The string is +// be used to support legacy code. Using it guarantees bugs on Macintosh. The string is // cached and freed by the nsFileSpec destructor, so do not delete (or free) it. //---------------------------------------------------------------------------------------- { - if (mPath.IsEmpty()) - { - char* path = MacFileHelpers::PathNameFromFSSpec(mSpec, true); - if (path != NULL) { - const_cast(this)->mPath = path; // operator =() copies the string!!! - delete[] path; - } else { - const_cast(this)->mError = NS_ERROR_OUT_OF_MEMORY; - } - } - return mPath; + if (mPath.IsEmpty()) + { + char* path = MacFileHelpers::PathNameFromFSSpec(mSpec, true); + if (path != NULL) { + const_cast(this)->mPath = path; // operator =() copies the string!!! + delete[] path; + } else { + const_cast(this)->mError = NS_ERROR_OUT_OF_MEMORY; + } + } + return mPath; } +#pragma mark - + //======================================================================================== -// Macintosh nsFilePath implementation +// Macintosh nsFilePath implementation //======================================================================================== //---------------------------------------------------------------------------------------- static void AssignFromPath(nsFilePath& ioPath, const char* inString, PRBool inCreateDirs) //---------------------------------------------------------------------------------------- { - NS_ASSERTION(strstr(inString, kFileURLPrefix) != inString, "URL passed as path"); - FSSpec spec; - spec.vRefNum = 0; - spec.parID = 0; - MacFileHelpers::FSSpecFromUnixPath( - inString, - spec, - false, - true, // resolve alias - true, - inCreateDirs); - // Now we have a spec, - // Invoke operator = (const nsFileSpec&) to do the rest. - // Why didn't we just say mPath = inString to get the path? Well, we want it to be - // canonical and absolute. - ioPath = spec; + NS_ASSERTION(inString, "AssignFromPath called with null inString"); + NS_ASSERTION(strstr(inString, kFileURLPrefix) != inString, "URL passed as path"); + + FSSpec spec; + spec.vRefNum = 0; + spec.parID = 0; + MacFileHelpers::FSSpecFromUnixPath( + inString, + spec, + false, + true, // resolve alias + true, + inCreateDirs); + // Now we have a spec, + // Invoke operator = (const nsFileSpec&) to do the rest. + // Why didn't we just say mPath = inString to get the path? Well, we want it to be + // canonical and absolute. + ioPath = spec; } //---------------------------------------------------------------------------------------- nsFilePath::nsFilePath(const char* inString, PRBool inCreateDirs) //---------------------------------------------------------------------------------------- { - AssignFromPath(*this, inString, inCreateDirs); + AssignFromPath(*this, inString, inCreateDirs); } //nsFilePath::nsFilePath //---------------------------------------------------------------------------------------- nsFilePath::nsFilePath(const nsString& inString, PRBool inCreateDirs) //---------------------------------------------------------------------------------------- { - AssignFromPath(*this, nsAutoCString(inString), inCreateDirs); + AssignFromPath(*this, nsAutoCString(inString), inCreateDirs); } //---------------------------------------------------------------------------------------- void nsFilePath::operator = (const char* inString) //---------------------------------------------------------------------------------------- { - AssignFromPath(*this, nsAutoCString(inString), PR_FALSE); + AssignFromPath(*this, nsAutoCString(inString), PR_FALSE); } //---------------------------------------------------------------------------------------- nsFilePath::nsFilePath(const nsFileSpec& inSpec) //---------------------------------------------------------------------------------------- { - *this = inSpec; + *this = inSpec; } //---------------------------------------------------------------------------------------- nsFilePath::nsFilePath(const nsFileURL& inOther) //---------------------------------------------------------------------------------------- { - *this = inOther; + *this = inOther; } //---------------------------------------------------------------------------------------- void nsFilePath::operator = (const nsFileSpec& inSpec) //---------------------------------------------------------------------------------------- { - char * path = MacFileHelpers::PathNameFromFSSpec(inSpec, true); - path = MacFileHelpers::EncodeMacPath(path, true, false); - mPath = path; - nsCRT::free(path); - mFileSpec = inSpec; + char * path = MacFileHelpers::PathNameFromFSSpec(inSpec, true); + path = MacFileHelpers::EncodeMacPath(path, true, false); + mPath = path; + nsCRT::free(path); + mFileSpec = inSpec; } // nsFilePath::operator = //---------------------------------------------------------------------------------------- void nsFilePath::operator = (const nsFileURL& inOther) //---------------------------------------------------------------------------------------- { - char * path = MacFileHelpers::PathNameFromFSSpec(inOther.mFileSpec, true); - path = MacFileHelpers::EncodeMacPath(path, true, false); - mPath = path; - nsCRT::free(path); - mFileSpec = inOther.GetFileSpec(); + char * path = MacFileHelpers::PathNameFromFSSpec(inOther.mFileSpec, true); + path = MacFileHelpers::EncodeMacPath(path, true, false); + mPath = path; + nsCRT::free(path); + mFileSpec = inOther.GetFileSpec(); } +#pragma mark - + //======================================================================================== -// nsFileURL implementation +// nsFileURL implementation //======================================================================================== //---------------------------------------------------------------------------------------- nsFileURL::nsFileURL(const char* inString, PRBool inCreateDirs) //---------------------------------------------------------------------------------------- -: mURL(inString) -{ - NS_ASSERTION(strstr(inString, kFileURLPrefix) == inString, "Not a URL!"); - mFileSpec.mError = NS_FILE_RESULT(MacFileHelpers::FSSpecFromUnixPath( - inString + kFileURLPrefixLength, - mFileSpec.mSpec, - true, // need to decode - false, // resolve alias - false, // must be a full path - inCreateDirs)); - if (mFileSpec.mError == NS_FILE_RESULT(fnfErr)) - mFileSpec.mError = NS_OK; +: mURL(inString) +{ + NS_ASSERTION(inString, "nsFileURL constructed with null inString"); + NS_ASSERTION(strstr(inString, kFileURLPrefix) == inString, "Not a URL!"); + mFileSpec.mError = NS_FILE_RESULT(MacFileHelpers::FSSpecFromUnixPath( + inString + kFileURLPrefixLength, + mFileSpec.mSpec, + true, // need to decode + false, // resolve alias + false, // must be a full path + inCreateDirs)); + if (mFileSpec.mError == NS_FILE_RESULT(fnfErr)) + mFileSpec.mError = NS_OK; } // nsFileURL::nsFileURL //---------------------------------------------------------------------------------------- nsFileURL::nsFileURL(const nsString& inString, PRBool inCreateDirs) //---------------------------------------------------------------------------------------- -: mURL(nsnull) +: mURL(nsnull) { - nsAutoCString autostring(inString); - const char* cstring = (const char*)autostring; - mURL = cstring; - NS_ASSERTION(strstr(cstring, kFileURLPrefix) == cstring, "Not a URL!"); - mFileSpec.mError = NS_FILE_RESULT(MacFileHelpers::FSSpecFromUnixPath( - cstring + kFileURLPrefixLength, - mFileSpec.mSpec, - true, // need to decode - false, // resolve alias - false, // must be a full path - inCreateDirs)); - if (mFileSpec.mError == NS_FILE_RESULT(fnfErr)) - mFileSpec.mError = NS_OK; + nsAutoCString autostring(inString); + const char* cstring = (const char*)autostring; + mURL = cstring; + NS_ASSERTION(strstr(cstring, kFileURLPrefix) == cstring, "Not a URL!"); + mFileSpec.mError = NS_FILE_RESULT(MacFileHelpers::FSSpecFromUnixPath( + cstring + kFileURLPrefixLength, + mFileSpec.mSpec, + true, // need to decode + false, // resolve alias + false, // must be a full path + inCreateDirs)); + if (mFileSpec.mError == NS_FILE_RESULT(fnfErr)) + mFileSpec.mError = NS_OK; } // nsFileURL::nsFileURL //---------------------------------------------------------------------------------------- nsFileURL::nsFileURL(const nsFilePath& inOther) //---------------------------------------------------------------------------------------- { - *this = inOther.GetFileSpec(); + *this = inOther.GetFileSpec(); } // nsFileURL::nsFileURL //---------------------------------------------------------------------------------------- nsFileURL::nsFileURL(const nsFileSpec& inOther) //---------------------------------------------------------------------------------------- { - *this = inOther; + *this = inOther; } // nsFileURL::nsFileURL //---------------------------------------------------------------------------------------- void nsFileURL::operator = (const nsFilePath& inOther) //---------------------------------------------------------------------------------------- { - *this = inOther.GetFileSpec(); + *this = inOther.GetFileSpec(); } // nsFileURL::operator = //---------------------------------------------------------------------------------------- void nsFileURL::operator = (const nsFileSpec& inOther) //---------------------------------------------------------------------------------------- { - mFileSpec = inOther; - char* path = MacFileHelpers::PathNameFromFSSpec( mFileSpec, true ); - char* encodedPath = MacFileHelpers::EncodeMacPath(path, true, true); - nsSimpleCharString encodedURL(kFileURLPrefix); - encodedURL += encodedPath; - nsCRT::free(encodedPath); - mURL = encodedURL; - if (encodedURL[encodedURL.Length() - 1] != '/' && inOther.IsDirectory()) - mURL += "/"; + mFileSpec = inOther; + char* path = MacFileHelpers::PathNameFromFSSpec( mFileSpec, true ); + char* encodedPath = MacFileHelpers::EncodeMacPath(path, true, true); + nsSimpleCharString encodedURL(kFileURLPrefix); + encodedURL += encodedPath; + nsCRT::free(encodedPath); + mURL = encodedURL; + if (encodedURL[encodedURL.Length() - 1] != '/' && inOther.IsDirectory()) + mURL += "/"; } // nsFileURL::operator = //---------------------------------------------------------------------------------------- void nsFileURL::operator = (const char* inString) //---------------------------------------------------------------------------------------- { - mURL = inString; - NS_ASSERTION(strstr(inString, kFileURLPrefix) == inString, "Not a URL!"); - mFileSpec.mError = NS_FILE_RESULT(MacFileHelpers::FSSpecFromUnixPath( - inString + kFileURLPrefixLength, - mFileSpec.mSpec, - true, // need to decode - true, // resolve alias - false, // must be a full path - false)); // don't create dirs. - if (mFileSpec.mError == NS_FILE_RESULT(fnfErr)) - mFileSpec.mError = NS_OK; + NS_ASSERTION(inString, "nsFileURL operator= constructed with null inString"); + + mURL = inString; + NS_ASSERTION(strstr(inString, kFileURLPrefix) == inString, "Not a URL!"); + mFileSpec.mError = NS_FILE_RESULT(MacFileHelpers::FSSpecFromUnixPath( + inString + kFileURLPrefixLength, + mFileSpec.mSpec, + true, // need to decode + true, // resolve alias + false, // must be a full path + false)); // don't create dirs. + if (mFileSpec.mError == NS_FILE_RESULT(fnfErr)) + mFileSpec.mError = NS_OK; } // nsFileURL::operator = +#pragma mark - + //======================================================================================== -// nsDirectoryIterator +// nsDirectoryIterator //======================================================================================== //---------------------------------------------------------------------------------------- nsDirectoryIterator::nsDirectoryIterator( - const nsFileSpec& inDirectory -, PRBool resolveSymLinks) + const nsFileSpec& inDirectory +, PRBool resolveSymLinks) //---------------------------------------------------------------------------------------- - : mCurrent(inDirectory) - , mExists(false) - , mIndex(-1) - , mResoveSymLinks(resolveSymLinks) + : mCurrent(inDirectory) + , mExists(false) + , mIndex(-1) + , mResoveSymLinks(resolveSymLinks) { - CInfoPBRec pb; - OSErr err = inDirectory.GetCatInfo(pb); - - // test that we have got a directory back, not a file - DirInfo* dipb = (DirInfo*)&pb; - if (err != noErr || !( dipb->ioFlAttrib & 0x0010)) - return; - // Sorry about this, there seems to be a bug in CWPro 4: - FSSpec& currentSpec = mCurrent.nsFileSpec::operator FSSpec&(); - mVRefNum = currentSpec.vRefNum; - mParID = dipb->ioDrDirID; - mMaxIndex = pb.dirInfo.ioDrNmFls; - mIndex = 0; // ready to increment - ++(*this); // the pre-increment operator - + CInfoPBRec pb; + OSErr err = inDirectory.GetCatInfo(pb); + + // test that we have got a directory back, not a file + DirInfo* dipb = (DirInfo*)&pb; + if (err != noErr || !( dipb->ioFlAttrib & 0x0010)) + return; + // Sorry about this, there seems to be a bug in CWPro 4: + FSSpec& currentSpec = mCurrent.nsFileSpec::operator FSSpec&(); + mVRefNum = currentSpec.vRefNum; + mParID = dipb->ioDrDirID; + mMaxIndex = pb.dirInfo.ioDrNmFls; + mIndex = 0; // ready to increment + ++(*this); // the pre-increment operator + } // nsDirectoryIterator::nsDirectoryIterator //---------------------------------------------------------------------------------------- OSErr nsDirectoryIterator::SetToIndex() //---------------------------------------------------------------------------------------- { - CInfoPBRec cipb; - DirInfo *dipb=(DirInfo *)&cipb; - Str255 objectName; - dipb->ioCompletion = nsnull; - dipb->ioFDirIndex = mIndex; - // Sorry about this, there seems to be a bug in CWPro 4: - FSSpec& currentSpec = mCurrent.nsFileSpec::operator FSSpec&(); - dipb->ioVRefNum = mVRefNum; /* Might need to use vRefNum, not sure*/ - dipb->ioDrDirID = mParID; - dipb->ioNamePtr = objectName; - OSErr err = PBGetCatInfoSync(&cipb); - FSSpec temp; - if (err == noErr) - err = FSMakeFSSpec(mVRefNum, mParID, objectName, &temp); - mCurrent = temp; // use the operator: it clears the string cache. - mExists = err == noErr; + CInfoPBRec cipb; + DirInfo *dipb=(DirInfo *)&cipb; + Str255 objectName; + dipb->ioCompletion = nsnull; + dipb->ioFDirIndex = mIndex; + // Sorry about this, there seems to be a bug in CWPro 4: + FSSpec& currentSpec = mCurrent.nsFileSpec::operator FSSpec&(); + dipb->ioVRefNum = mVRefNum; /* Might need to use vRefNum, not sure*/ + dipb->ioDrDirID = mParID; + dipb->ioNamePtr = objectName; + OSErr err = PBGetCatInfoSync(&cipb); + FSSpec temp; + if (err == noErr) + err = FSMakeFSSpec(mVRefNum, mParID, objectName, &temp); + mCurrent = temp; // use the operator: it clears the string cache. + mExists = err == noErr; - if (mExists && mResoveSymLinks) - { - PRBool ignore; - mCurrent.ResolveSymlink(ignore); - } - return err; + if (mExists && mResoveSymLinks) + { + PRBool ignore; + mCurrent.ResolveSymlink(ignore); + } + return err; } // nsDirectoryIterator::SetToIndex() //---------------------------------------------------------------------------------------- nsDirectoryIterator& nsDirectoryIterator::operator -- () //---------------------------------------------------------------------------------------- { - mExists = false; - while (--mIndex > 0) - { - OSErr err = SetToIndex(); - if (err == noErr) - break; - } - return *this; + mExists = false; + while (--mIndex > 0) + { + OSErr err = SetToIndex(); + if (err == noErr) + break; + } + return *this; } // nsDirectoryIterator::operator -- //---------------------------------------------------------------------------------------- nsDirectoryIterator& nsDirectoryIterator::operator ++ () //---------------------------------------------------------------------------------------- { - mExists = false; - if (mIndex >= 0) // probably trying to use a file as a directory! - while (++mIndex <= mMaxIndex) - { - OSErr err = SetToIndex(); - if (err == noErr) - break; - } - return *this; + mExists = false; + if (mIndex >= 0) // probably trying to use a file as a directory! + while (++mIndex <= mMaxIndex) + { + OSErr err = SetToIndex(); + if (err == noErr) + break; + } + return *this; } // nsDirectoryIterator::operator ++ diff --git a/mozilla/xpcom/io/nsFileSpecStreaming.cpp b/mozilla/xpcom/io/nsFileSpecStreaming.cpp index 408ab12f6de..c9f235d4d8c 100644 --- a/mozilla/xpcom/io/nsFileSpecStreaming.cpp +++ b/mozilla/xpcom/io/nsFileSpecStreaming.cpp @@ -1,3 +1,21 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ + #include "nsFileSpecStreaming.h" #include "nsIInputStream.h" diff --git a/mozilla/xpcom/io/nsFileSpecUnix.cpp b/mozilla/xpcom/io/nsFileSpecUnix.cpp index b568c8ea026..56f1643b245 100644 --- a/mozilla/xpcom/io/nsFileSpecUnix.cpp +++ b/mozilla/xpcom/io/nsFileSpecUnix.cpp @@ -248,6 +248,8 @@ void nsFileSpec::GetParent(nsFileSpec& outSpec) const void nsFileSpec::operator += (const char* inRelativePath) //---------------------------------------------------------------------------------------- { + NS_ASSERTION(inRelativePath, "Attempt to do += with a null string"); + if (!inRelativePath || mPath.IsEmpty()) return; @@ -339,6 +341,8 @@ void nsFileSpec::RecursiveCopy(nsFileSpec newDir) const nsresult nsFileSpec::Rename(const char* inNewName) //---------------------------------------------------------------------------------------- { + NS_ASSERTION(inNewName, "Attempt to Rename with a null string"); + // This function should not be used to move a file on disk. if (mPath.IsEmpty() || strchr(inNewName, '/')) return NS_FILE_FAILURE; diff --git a/mozilla/xpcom/io/nsFileSpecWin.cpp b/mozilla/xpcom/io/nsFileSpecWin.cpp index 5b8c9b7963b..b2ec603963e 100644 --- a/mozilla/xpcom/io/nsFileSpecWin.cpp +++ b/mozilla/xpcom/io/nsFileSpecWin.cpp @@ -175,6 +175,7 @@ void nsFilePath::operator = (const nsFileSpec& inSpec) void nsFileSpec::SetLeafName(const char* inLeafName) //---------------------------------------------------------------------------------------- { + NS_ASSERTION(inLeafName, "Attempt to SetLeafName with a null string"); mPath.LeafReplace('\\', inLeafName); } // nsFileSpec::SetLeafName @@ -374,6 +375,8 @@ void nsFileSpec::GetParent(nsFileSpec& outSpec) const void nsFileSpec::operator += (const char* inRelativePath) //---------------------------------------------------------------------------------------- { + NS_ASSERTION(inRelativePath, "Attempt to do += with a null string"); + if (!inRelativePath || mPath.IsEmpty()) return; @@ -468,6 +471,8 @@ void nsFileSpec::RecursiveCopy(nsFileSpec newDir) const nsresult nsFileSpec::Rename(const char* inNewName) //---------------------------------------------------------------------------------------- { + NS_ASSERTION(inNewName, "Attempt to Rename with a null string"); + // This function should not be used to move a file on disk. if (strchr(inNewName, '/')) return NS_FILE_FAILURE; diff --git a/mozilla/xpcom/io/nsIFileStream.cpp b/mozilla/xpcom/io/nsIFileStream.cpp index d3834100aaa..9ecd770d954 100644 --- a/mozilla/xpcom/io/nsIFileStream.cpp +++ b/mozilla/xpcom/io/nsIFileStream.cpp @@ -44,185 +44,46 @@ class FileImpl //======================================================================================== { public: - FileImpl(PRFileDesc* inDesc) - : mFileDesc(inDesc) - , mNSPRMode(0) - , mFailed(PR_FALSE) - , mEOF(PR_FALSE) - , mLength(-1) - { - NS_INIT_REFCNT(); + FileImpl(PRFileDesc* inDesc); + FileImpl(const nsFileSpec& inFile, int nsprMode, PRIntn accessMode); - nsresult rv = mOutBuffer.Init(4096, 4096); - if (NS_FAILED(rv)) mFailed = PR_TRUE; - - mWriteCursor = nsnull; - mWriteLimit = nsnull; - - } - FileImpl( - const nsFileSpec& inFile, - int nsprMode, - PRIntn accessMode) - : mFileDesc(nsnull) - , mNSPRMode(-1) - , mFailed(PR_FALSE) - , mEOF(PR_FALSE) - , mLength(-1) - { - NS_INIT_REFCNT(); - - nsresult rv = mOutBuffer.Init(4096, 4096); - if (NS_FAILED(rv)) mFailed = PR_TRUE; - - mWriteCursor = nsnull; - mWriteLimit = nsnull; - - rv = Open(inFile, nsprMode, accessMode); -/// NS_ASSERTION(NS_SUCCEEDED(rv), "Open failed"); - } - virtual ~FileImpl() - { - Close(); - } - + virtual ~FileImpl(); // nsISupports interface NS_DECL_ISUPPORTS - // nsIOpenFile interface - NS_IMETHOD Open( - const nsFileSpec& inFile, - int nsprMode, - PRIntn accessMode); + // nsIOpenFile interface + NS_IMETHOD Open(const nsFileSpec& inFile, int nsprMode, PRIntn accessMode); NS_IMETHOD Close(); NS_IMETHOD Seek(PRSeekWhence whence, PRInt32 offset); - - NS_IMETHOD GetIsOpen(PRBool* outOpen) - { - *outOpen = (mFileDesc != nsnull); - return NS_OK; - } + NS_IMETHOD GetIsOpen(PRBool* outOpen); NS_IMETHOD Tell(PRIntn* outWhere); - // nsIInputStream interface - NS_IMETHOD Available(PRUint32 *aLength) - { - NS_PRECONDITION(aLength != nsnull, "null ptr"); - if (!aLength) - return NS_ERROR_NULL_POINTER; - if (mLength < 0) - return NS_ERROR_UNEXPECTED; - *aLength = mLength; - return NS_OK; - } - NS_IMETHOD Read(char* aBuf, - PRUint32 aCount, - PRUint32 *aReadCount) - { - NS_PRECONDITION(aBuf != nsnull, "null ptr"); - if (!aBuf) - return NS_ERROR_NULL_POINTER; - NS_PRECONDITION(aReadCount != nsnull, "null ptr"); - if (!aReadCount) - return NS_ERROR_NULL_POINTER; - if (!mFileDesc) - return NS_FILE_RESULT(PR_BAD_DESCRIPTOR_ERROR); - if (mFailed) - return NS_ERROR_FAILURE; - PRInt32 bytesRead = PR_Read(mFileDesc, aBuf, aCount); - if (bytesRead < 0) - { - *aReadCount = 0; - mFailed = PR_TRUE; - return NS_FILE_RESULT(PR_GetError()); - } - else if (bytesRead == 0) { - mEOF = PR_TRUE; - } - *aReadCount = bytesRead; - return NS_OK; - } - // nsIOutputStream interface - NS_IMETHOD Write(const char* aBuf, - PRUint32 aCount, - PRUint32 *aWriteCount) - { - NS_PRECONDITION(aBuf != nsnull, "null ptr"); - NS_PRECONDITION(aWriteCount != nsnull, "null ptr"); - - *aWriteCount = 0; + // nsIInputStream interface + NS_IMETHOD Available(PRUint32 *aLength); + NS_IMETHOD Read(char* aBuf, PRUint32 aCount, PRUint32 *aReadCount); - #ifdef XP_MAC - // Calling PR_Write on stdout is sure suicide. - if (mFileDesc == PR_STDOUT || mFileDesc == PR_STDERR) - { - cout.write(aBuf, aCount); - *aWriteCount = aCount; - return NS_OK; - } - #endif - if (!mFileDesc) - return NS_FILE_RESULT(PR_BAD_DESCRIPTOR_ERROR); - if (mFailed) - return NS_ERROR_FAILURE; - - PRUint32 bufOffset = 0; - PRUint32 currentWrite = 0; - while (aCount > 0) - { - if (mWriteCursor == nsnull || mWriteCursor == mWriteLimit) - { - char* seg = mOutBuffer.AppendNewSegment(); - if (seg == nsnull) - { - // buffer is full, try again - Flush(); - seg = mOutBuffer.AppendNewSegment(); - if (seg == nsnull) - return NS_ERROR_OUT_OF_MEMORY; - } - mWriteCursor = seg; - mWriteLimit = seg + mOutBuffer.GetSegmentSize(); - } - - // move - - currentWrite = mWriteLimit - mWriteCursor; - - if (aCount < currentWrite) - currentWrite = aCount; - - memcpy(mWriteCursor, (aBuf + bufOffset), currentWrite); - - mWriteCursor += currentWrite; - - aCount -= currentWrite; - bufOffset += currentWrite; - *aWriteCount += currentWrite; - } - return NS_OK; - } + // nsIOutputStream interface + NS_IMETHOD Write(const char* aBuf, PRUint32 aCount, PRUint32 *aWriteCount); NS_IMETHOD Flush(); - - NS_IMETHOD GetAtEOF(PRBool* outAtEOF) - { - *outAtEOF = mEOF; - return NS_OK; - } - NS_IMETHOD SetAtEOF(PRBool inAtEOF) - { - mEOF = inAtEOF; - return NS_OK; - } + NS_IMETHOD GetAtEOF(PRBool* outAtEOF); + NS_IMETHOD SetAtEOF(PRBool inAtEOF); protected: + enum { + kOuputBufferSegmentSize = 4096, + kOuputBufferMaxSize = 4096 + }; + + nsresult AllocateBuffers(PRUint32 segmentSize, PRUint32 maxSize); + PRFileDesc* mFileDesc; int mNSPRMode; PRBool mFailed; PRBool mEOF; PRInt32 mLength; + PRBool mGotBuffers; nsSegmentedBuffer mOutBuffer; char* mWriteCursor; char* mWriteLimit; @@ -245,6 +106,60 @@ NS_IMPL_QUERY_HEAD(FileImpl) NS_IMPL_QUERY_TAIL(nsIOutputStream) +//---------------------------------------------------------------------------------------- +FileImpl::FileImpl(PRFileDesc* inDesc) +//---------------------------------------------------------------------------------------- +: mFileDesc(inDesc) +, mNSPRMode(0) +, mFailed(PR_FALSE) +, mEOF(PR_FALSE) +, mLength(-1) +, mGotBuffers(PR_FALSE) +{ + NS_INIT_REFCNT(); + + mWriteCursor = nsnull; + mWriteLimit = nsnull; +} + + +//---------------------------------------------------------------------------------------- +FileImpl::FileImpl(const nsFileSpec& inFile, int nsprMode, PRIntn accessMode) +//---------------------------------------------------------------------------------------- +: mFileDesc(nsnull) +, mNSPRMode(-1) +, mFailed(PR_FALSE) +, mEOF(PR_FALSE) +, mLength(-1) +, mGotBuffers(PR_FALSE) +{ + NS_INIT_REFCNT(); + + mWriteCursor = nsnull; + mWriteLimit = nsnull; + + nsresult rv = Open(inFile, nsprMode, accessMode); // this sets nsprMode + + if (NS_FAILED(rv)) + { +#if DEBUG + char *fileName = inFile.GetLeafName(); + printf("Opening file %s failed\n", fileName); + nsCRT::free(fileName); +#endif + } + +} + +//---------------------------------------------------------------------------------------- +FileImpl::~FileImpl() +//---------------------------------------------------------------------------------------- +{ + nsresult rv = Close(); + NS_ASSERTION(NS_SUCCEEDED(rv), "Close failed"); +} + + //---------------------------------------------------------------------------------------- NS_IMETHODIMP FileImpl::Open( const nsFileSpec& inFile, @@ -286,8 +201,8 @@ NS_IMETHODIMP FileImpl::Open( mFileDesc = 0; OSErr err = inFile.Error(); if (err != noErr) - if (err != fnfErr || !(nsprMode & PR_CREATE_FILE)) - return NS_FILE_RESULT(inFile.Error()); + if (err != fnfErr || !(nsprMode & PR_CREATE_FILE)) + return NS_FILE_RESULT(inFile.Error()); err = noErr; #if DEBUG const OSType kCreator = 'CWIE'; @@ -338,6 +253,28 @@ NS_IMETHODIMP FileImpl::Open( return NS_OK; } // FileImpl::Open + +//---------------------------------------------------------------------------------------- +NS_IMETHODIMP FileImpl::Available(PRUint32 *aLength) +//---------------------------------------------------------------------------------------- +{ + NS_PRECONDITION(aLength != nsnull, "null ptr"); + if (!aLength) + return NS_ERROR_NULL_POINTER; + if (mLength < 0) + return NS_ERROR_UNEXPECTED; + *aLength = mLength; + return NS_OK; +} + +//---------------------------------------------------------------------------------------- +NS_IMETHODIMP FileImpl::GetIsOpen(PRBool* outOpen) +//---------------------------------------------------------------------------------------- +{ + *outOpen = (mFileDesc != nsnull); + return NS_OK; +} + //---------------------------------------------------------------------------------------- NS_IMETHODIMP FileImpl::Seek(PRSeekWhence whence, PRInt32 offset) //---------------------------------------------------------------------------------------- @@ -371,6 +308,105 @@ NS_IMETHODIMP FileImpl::Seek(PRSeekWhence whence, PRInt32 offset) return NS_OK; } // FileImpl::Seek + +//---------------------------------------------------------------------------------------- +NS_IMETHODIMP FileImpl::Read(char* aBuf, PRUint32 aCount, PRUint32 *aReadCount) +//---------------------------------------------------------------------------------------- +{ + NS_PRECONDITION(aBuf != nsnull, "null ptr"); + if (!aBuf) + return NS_ERROR_NULL_POINTER; + NS_PRECONDITION(aReadCount != nsnull, "null ptr"); + if (!aReadCount) + return NS_ERROR_NULL_POINTER; + if (!mFileDesc) + return NS_FILE_RESULT(PR_BAD_DESCRIPTOR_ERROR); + if (mFailed) + return NS_ERROR_FAILURE; + PRInt32 bytesRead = PR_Read(mFileDesc, aBuf, aCount); + if (bytesRead < 0) + { + *aReadCount = 0; + mFailed = PR_TRUE; + return NS_FILE_RESULT(PR_GetError()); + } + else if (bytesRead == 0) + { + mEOF = PR_TRUE; + } + *aReadCount = bytesRead; + return NS_OK; +} + + +//---------------------------------------------------------------------------------------- +NS_IMETHODIMP FileImpl::Write(const char* aBuf, PRUint32 aCount, PRUint32 *aWriteCount) +//---------------------------------------------------------------------------------------- +{ + NS_PRECONDITION(aBuf != nsnull, "null ptr"); + NS_PRECONDITION(aWriteCount != nsnull, "null ptr"); + + *aWriteCount = 0; + +#ifdef XP_MAC + // Calling PR_Write on stdout is sure suicide. + if (mFileDesc == PR_STDOUT || mFileDesc == PR_STDERR) + { + cout.write(aBuf, aCount); + *aWriteCount = aCount; + return NS_OK; + } +#endif + if (!mFileDesc) + return NS_FILE_RESULT(PR_BAD_DESCRIPTOR_ERROR); + if (mFailed) + return NS_ERROR_FAILURE; + + if (!mGotBuffers) + { + nsresult rv = AllocateBuffers(kOuputBufferSegmentSize, kOuputBufferMaxSize); + if (NS_FAILED(rv)) + return rv; // try to write non-buffered? + } + + PRUint32 bufOffset = 0; + PRUint32 currentWrite = 0; + while (aCount > 0) + { + if (mWriteCursor == nsnull || mWriteCursor == mWriteLimit) + { + char* seg = mOutBuffer.AppendNewSegment(); + if (seg == nsnull) + { + // buffer is full, try again + Flush(); + seg = mOutBuffer.AppendNewSegment(); + if (seg == nsnull) + return NS_ERROR_OUT_OF_MEMORY; + } + mWriteCursor = seg; + mWriteLimit = seg + mOutBuffer.GetSegmentSize(); + } + + // move + currentWrite = mWriteLimit - mWriteCursor; + + if (aCount < currentWrite) + currentWrite = aCount; + + memcpy(mWriteCursor, (aBuf + bufOffset), currentWrite); + + mWriteCursor += currentWrite; + + aCount -= currentWrite; + bufOffset += currentWrite; + *aWriteCount += currentWrite; + } + + return NS_OK; +} + + //---------------------------------------------------------------------------------------- NS_IMETHODIMP FileImpl::Tell(PRIntn* outWhere) //---------------------------------------------------------------------------------------- @@ -385,7 +421,8 @@ NS_IMETHODIMP FileImpl::Tell(PRIntn* outWhere) NS_IMETHODIMP FileImpl::Close() //---------------------------------------------------------------------------------------- { - Flush(); + if ((mNSPRMode & PR_RDONLY) == 0) + Flush(); if (mFileDesc==PR_STDIN || mFileDesc==PR_STDOUT || mFileDesc==PR_STDERR || !mFileDesc) return NS_OK; @@ -423,10 +460,10 @@ NS_IMETHODIMP FileImpl::Flush() PRInt32 bytesWrit = PR_Write(mFileDesc, seg, segSize); if (bytesWrit != (PRInt32)segSize) - { - mFailed = PR_TRUE; - return NS_FILE_RESULT(PR_GetError()); - } + { + mFailed = PR_TRUE; + return NS_FILE_RESULT(PR_GetError()); + } } mOutBuffer.Empty(); @@ -442,6 +479,36 @@ NS_IMETHODIMP FileImpl::Flush() return NS_OK; } // FileImpl::flush + +//---------------------------------------------------------------------------------------- +NS_IMETHODIMP FileImpl::GetAtEOF(PRBool* outAtEOF) +//---------------------------------------------------------------------------------------- +{ + *outAtEOF = mEOF; + return NS_OK; +} + + +//---------------------------------------------------------------------------------------- +NS_IMETHODIMP FileImpl::SetAtEOF(PRBool inAtEOF) +//---------------------------------------------------------------------------------------- +{ + mEOF = inAtEOF; + return NS_OK; +} + +//---------------------------------------------------------------------------------------- +nsresult FileImpl::AllocateBuffers(PRUint32 segmentSize, PRUint32 maxBufSize) +//---------------------------------------------------------------------------------------- +{ + nsresult rv = mOutBuffer.Init(segmentSize, maxBufSize); + if (NS_SUCCEEDED(rv)) + mGotBuffers = PR_TRUE; + + return rv; +} + + //---------------------------------------------------------------------------------------- NS_COM nsresult NS_NewTypicalInputFileStream( nsISupports** aResult,