diff --git a/base/public/Makefile.in b/base/public/Makefile.in index 30b60781ab30..9e67e90bd42e 100644 --- a/base/public/Makefile.in +++ b/base/public/Makefile.in @@ -37,6 +37,7 @@ EXPORTS = \ nsFileStream.h \ nsIFileStream.h \ nsIStringStream.h \ + nsFileSpecStreaming.h \ nsSpecialSystemDirectory.h \ nsIObserverService.h \ nsIObserverList.h \ diff --git a/base/public/makefile.win b/base/public/makefile.win index 27a20bfe1603..75567c716c91 100644 --- a/base/public/makefile.win +++ b/base/public/makefile.win @@ -29,6 +29,7 @@ EXPORTS = \ nsISizeOfHandler.h \ nsEscape.h \ nsFileSpec.h \ + nsFileSpecStreaming.h \ nsFileStream.h \ nsIFileStream.h \ nsIString.h \ diff --git a/base/public/nsFileSpec.h b/base/public/nsFileSpec.h index 21c3d32bbe03..936e2f2fb929 100644 --- a/base/public/nsFileSpec.h +++ b/base/public/nsFileSpec.h @@ -53,7 +53,7 @@ // // nsFilePath myPath("/Development/iotest.txt"); // -// nsOutputFileStream testStream(myPath); +// nsOutputFileStream testStream(nsFileSpec(myPath)); // testStream << "Hello World" << nsEndl; // // 4. Handy methods for manipulating file specifiers safely, e.g. MakeUnique(), @@ -63,35 +63,35 @@ // // Examples: // -// Initialize a URL from a string without suffix +// Initialize a URL from a string // // nsFileURL fileURL("file:///Development/MPW/MPW%20Shell"); // -// Initialize a Unix path from a URL +// Initialize a Unix-style path from a URL // // nsFilePath filePath(fileURL); // -// Initialize a native file spec from a URL +// Initialize a file spec from a URL // // nsFileSpec fileSpec(fileURL); // -// Make the spec unique (this one has no suffix). +// Make the spec unique. // // fileSpec.MakeUnique(); // -// Assign the spec to a URL +// Assign the spec to a URL (causing conversion) // // fileURL = fileSpec; // -// Assign a unix path using a string with a suffix. +// Assign a unix path using a string // // filePath = "/Development/MPW/SysErrs.err"; // -// Assign to a file spec using a unix path. +// Assign to a file spec using a unix path (causing conversion). // // fileSpec = filePath; // -// Make this unique (this one has a suffix). +// Make this unique. // // fileSpec.MakeUnique(); // @@ -103,10 +103,6 @@ // is solved by holding a "private" native file spec inside the // nsFilePath and nsFileURL classes, which is used when appropriate. // -// Not yet done: -// -// Equality operators... much more. -// //======================================================================================== #ifndef _FILESPEC_H_ @@ -153,8 +149,9 @@ //======================================================================================== class nsFileSpec; // Preferred. For i/o use nsInputFileStream, nsOutputFileStream -class nsFilePath; // This can be passed to NSPR file I/O routines, if you must. +class nsFilePath; class nsFileURL; +class nsNSPRPath; // This can be passed to NSPR file I/O routines, if you must. class nsPersistentFileDescriptor; // Used for storage across program launches. #define kFileURLPrefix "file://" @@ -167,6 +164,7 @@ class nsIInputStream; class nsOutputFileStream; class nsInputFileStream; class nsOutputConsoleStream; + class nsString; //======================================================================================== @@ -269,8 +267,12 @@ protected: void ReleaseData(); void ReallocData(PRUint32 inLength); -// DATA + //-------------------------------------------------- + // Data + //-------------------------------------------------- + protected: + struct Data { int mRefCount; PRUint32 mLength; @@ -289,8 +291,8 @@ class NS_BASE nsFileSpec nsFileSpec(); // These two meathods take *native* file paths. - NS_EXPLICIT nsFileSpec(const char* inString, PRBool inCreateDirs = PR_FALSE); - NS_EXPLICIT nsFileSpec(const nsString& inString, PRBool inCreateDirs = PR_FALSE); + NS_EXPLICIT nsFileSpec(const char* inNativePath, PRBool inCreateDirs = PR_FALSE); + NS_EXPLICIT nsFileSpec(const nsString& inNativePath, PRBool inCreateDirs = PR_FALSE); NS_EXPLICIT nsFileSpec(const nsFilePath& inPath); @@ -300,10 +302,10 @@ class NS_BASE nsFileSpec virtual ~nsFileSpec(); // These two operands take *native* file paths. - void operator = (const char* inPath); - void operator = (const nsString& inPath) + void operator = (const char* inNativePath); + void operator = (const nsString& inNativePath) { - const nsAutoCString path(inPath); + const nsAutoCString path(inNativePath); *this = path; } @@ -317,14 +319,19 @@ class NS_BASE nsFileSpec 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! const char* GetCString() const; - // This is the only conversion to const char* - // that is provided, and it allows the + // 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. + // 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. #ifdef XP_MAC // For Macintosh people, this is meant to be useful in its own right as a C++ version @@ -367,22 +374,15 @@ class NS_BASE nsFileSpec { #ifndef XP_MAC if (mPath.IsEmpty() && NS_SUCCEEDED(mError)) - ((nsFileSpec*)this)->mError = NS_FILE_FAILURE; + ((nsFileSpec*)this)->mError = NS_ERROR_NOT_INITIALIZED; #endif return mError; } PRBool Failed() const { return (PRBool)NS_FAILED(Error()); } - - friend NS_BASE nsOutputStream& operator << ( - nsOutputStream& s, - const nsFileSpec& spec); // THIS IS FOR DEBUGGING ONLY. - // see PersistentFileDescriptor for the real deal. - - - //-------------------------------------------------- - // Queries and path algebra. These do not modify the disk. - //-------------------------------------------------- + //-------------------------------------------------- + // Queries and path algebra. These do not modify the disk. + //-------------------------------------------------- char* GetLeafName() const; // Allocated. Use nsCRT::free(). void SetLeafName(const char* inLeafName); @@ -422,14 +422,14 @@ class NS_BASE nsFileSpec PRUint32 GetFileSize() const; PRUint32 GetDiskSpaceAvailable() const; - nsFileSpec operator + (const char* inRelativePath) const; - nsFileSpec operator + (const nsString& inRelativePath) const + nsFileSpec operator + (const char* inRelativeUnixPath) const; + nsFileSpec operator + (const nsString& inRelativeUnixPath) const { const nsAutoCString - relativePath(inRelativePath); + relativePath(inRelativeUnixPath); return *this + relativePath; } - void operator += (const char* inRelativePath); + 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 @@ -438,9 +438,9 @@ class NS_BASE nsFileSpec // away its leaf information, whereas this one assumes // this is a directory, and the relative path starts // "below" this. - void operator += (const nsString& inRelativePath) + void operator += (const nsString& inRelativeUnixPath) { - const nsAutoCString relativePath(inRelativePath); + const nsAutoCString relativePath(inRelativeUnixPath); *this += relativePath; } @@ -458,9 +458,9 @@ class NS_BASE nsFileSpec // More stringent than Exists() PRBool Exists() const; - //-------------------------------------------------- - // Creation and deletion of objects. These can modify the disk. - //-------------------------------------------------- + //-------------------------------------------------- + // Creation and deletion of objects. These can modify the disk. + //-------------------------------------------------- void CreateDirectory(int mode = 0700 /* for unix */); void CreateDir(int mode = 0700) { CreateDirectory(mode); } @@ -481,9 +481,9 @@ class NS_BASE nsFileSpec const nsAutoCString argsString(args); return Execute(argsString); } - //-------------------------------------------------- - // Data - //-------------------------------------------------- + //-------------------------------------------------- + // Data + //-------------------------------------------------- protected: friend class nsFilePath; @@ -509,8 +509,8 @@ class NS_BASE nsFileURL { public: nsFileURL(const nsFileURL& inURL); - NS_EXPLICIT nsFileURL(const char* inString, PRBool inCreateDirs = PR_FALSE); - NS_EXPLICIT nsFileURL(const nsString& inString, PRBool inCreateDirs = PR_FALSE); + NS_EXPLICIT nsFileURL(const char* inURLString, PRBool inCreateDirs = PR_FALSE); + NS_EXPLICIT nsFileURL(const nsString& inURLString, PRBool inCreateDirs = PR_FALSE); NS_EXPLICIT nsFileURL(const nsFilePath& inPath); NS_EXPLICIT nsFileURL(const nsFileSpec& inPath); virtual ~nsFileURL(); @@ -520,10 +520,10 @@ class NS_BASE nsFileURL // but should not provide a conversion constructor. void operator = (const nsFileURL& inURL); - void operator = (const char* inString); - void operator = (const nsString& inString) + void operator = (const char* inURLString); + void operator = (const nsString& inURLString) { - const nsAutoCString string(inString); + const nsAutoCString string(inURLString); *this = string; } void operator = (const nsFilePath& inOther); @@ -532,16 +532,20 @@ class NS_BASE nsFileURL void operator +=(const char* inRelativeUnixPath); nsFileURL operator +(const char* inRelativeUnixPath) const; operator const char* () const { return (const char*)mURL; } // deprecated. + const char* GetURLString() const { return (const char*)mURL; } + // Not allocated, so don't free it. const char* GetAsString() const { return (const char*)mURL; } - - friend NS_BASE nsOutputStream& operator << ( - nsOutputStream& s, const nsFileURL& spec); + // Not allocated, so don't free it. #ifdef XP_MAC // Accessor to allow quick assignment to a mFileSpec const nsFileSpec& GetFileSpec() const { return mFileSpec; } #endif + //-------------------------------------------------- + // Data + //-------------------------------------------------- + protected: friend class nsFilePath; // to allow construction of nsFilePath nsSimpleCharString mURL; @@ -562,8 +566,8 @@ class NS_BASE nsFilePath { public: nsFilePath(const nsFilePath& inPath); - NS_EXPLICIT nsFilePath(const char* inString, PRBool inCreateDirs = PR_FALSE); - NS_EXPLICIT nsFilePath(const nsString& inString, PRBool inCreateDirs = PR_FALSE); + NS_EXPLICIT nsFilePath(const char* inUnixPathString, PRBool inCreateDirs = PR_FALSE); + NS_EXPLICIT nsFilePath(const nsString& inUnixPathString, PRBool inCreateDirs = PR_FALSE); NS_EXPLICIT nsFilePath(const nsFileURL& inURL); NS_EXPLICIT nsFilePath(const nsFileSpec& inPath); virtual ~nsFilePath(); @@ -572,13 +576,13 @@ class NS_BASE nsFilePath operator const char* () const { return mPath; } // This will return a UNIX string. If you // need a string that can be passed into - // NSPR, take a look at the nsprPath class. + // NSPR, take a look at the nsNSPRPath class. void operator = (const nsFilePath& inPath); - void operator = (const char* inString); - void operator = (const nsString& inString) + void operator = (const char* inUnixPathString); + void operator = (const nsString& inUnixPathString) { - const nsAutoCString string(inString); + const nsAutoCString string(inUnixPathString); *this = string; } void operator = (const nsFileURL& inURL); @@ -593,6 +597,10 @@ class NS_BASE nsFilePath const nsFileSpec& GetFileSpec() const { return mFileSpec; } #endif + //-------------------------------------------------- + // Data + //-------------------------------------------------- + private: nsSimpleCharString mPath; @@ -622,8 +630,11 @@ class NS_BASE nsPersistentFileDescriptor NS_EXPLICIT nsPersistentFileDescriptor(const nsFileSpec& inPath); void operator = (const nsFileSpec& inPath); - nsresult Read(nsIInputStream* aStream); - nsresult Write(nsIOutputStream* aStream); + // The following four functions are declared here (as friends). Their implementations + // are in mozilla/base/src/nsFileSpecStreaming.cpp. + + friend nsresult Read(nsIInputStream* aStream, nsPersistentFileDescriptor&); + friend nsresult Write(nsIOutputStream* aStream, const nsPersistentFileDescriptor&); // writes the data to a file friend NS_BASE nsInputStream& operator >> (nsInputStream&, nsPersistentFileDescriptor&); // reads the data from a file @@ -631,11 +642,15 @@ class NS_BASE nsPersistentFileDescriptor // writes the data to a file friend class nsFileSpec; - private: - + void GetData(nsSimpleCharString& outData) const; + void SetData(const nsSimpleCharString& inData); void GetData(nsSimpleCharString& outData, PRInt32& outSize) const; void SetData(const nsSimpleCharString& inData, PRInt32 inSize); + //-------------------------------------------------- + // Data + //-------------------------------------------------- + protected: nsSimpleCharString mDescriptorString; @@ -654,7 +669,7 @@ class NS_BASE nsDirectoryIterator // // or: // -// for (nsDirectoryIterator i(parentDir, PR_FALSE); i.Exists(); i--) +// for (nsDirectoryIterator i(parentDir, -1); i.Exists(); i--) // { // // do something with i.Spec() // } @@ -681,6 +696,17 @@ class NS_BASE nsDirectoryIterator nsFileSpec& Spec() { return mCurrent; } private: + +#if defined(XP_MAC) + OSErr SetToIndex(); +#endif + + //-------------------------------------------------- + // Data + //-------------------------------------------------- + + private: + nsFileSpec mCurrent; PRBool mExists; @@ -689,35 +715,44 @@ class NS_BASE nsDirectoryIterator #elif defined(XP_PC) PRDir* mDir; // XXX why not use PRDir for Unix too? #elif defined(XP_MAC) - OSErr SetToIndex(); short mIndex; short mMaxIndex; #endif }; // class nsDirectoryIterator //======================================================================================== -class NS_BASE nsprPath +class NS_BASE nsNSPRPath // This class will allow you to pass any one of the nsFile* classes directly into NSPR // without the need to worry about whether you have the right kind of filepath or not. // It will also take care of cleaning up any allocated memory. //======================================================================================== { public: - NS_EXPLICIT nsprPath(const nsFileSpec& other) - : mFilePath(other), modifiedNSPRPath(nsnull) {} - NS_EXPLICIT nsprPath(const nsFileURL& other) - : mFilePath(other), modifiedNSPRPath(nsnull) {} - NS_EXPLICIT nsprPath(const nsFilePath& other) - : mFilePath(other), modifiedNSPRPath(nsnull) {} + NS_EXPLICIT nsNSPRPath(const nsFileSpec& inSpec) + : mFilePath(inSpec), modifiedNSPRPath(nsnull) {} + NS_EXPLICIT nsNSPRPath(const nsFileURL& inURL) + : mFilePath(inURL), modifiedNSPRPath(nsnull) {} + NS_EXPLICIT nsNSPRPath(const nsFilePath& inUnixPath) + : mFilePath(inUnixPath), modifiedNSPRPath(nsnull) {} - virtual ~nsprPath(); + virtual ~nsNSPRPath(); operator const char*() const; - // actually, can modify modifiedNSPRPath, but - // that's really just "mutable". + // Returns the path + // that NSPR file routines expect on each platform. + // Concerning constness, this can modify + // modifiedNSPRPath, but it's really just "mutable". + + //-------------------------------------------------- + // Data + //-------------------------------------------------- + private: - nsFilePath mFilePath; - char* modifiedNSPRPath; // Currently used only on XP_PC -}; // class nsprPath + + nsFilePath mFilePath; + char* modifiedNSPRPath; // Currently used only on XP_PC +}; // class nsNSPRPath + +typedef nsNSPRPath nsprPath; // old name. #endif // _FILESPEC_H_ diff --git a/base/src/Makefile.in b/base/src/Makefile.in index 825bc6fa2aae..190672177b07 100644 --- a/base/src/Makefile.in +++ b/base/src/Makefile.in @@ -40,6 +40,7 @@ CPPSRCS = \ nsDeque.cpp \ nsEscape.cpp \ nsFileSpec.cpp \ + nsFileSpecStreaming.cpp \ nsFileStream.cpp \ nsIFileStream.cpp \ nsIStringStream.cpp \ diff --git a/base/src/mac/nsFileSpecMac.cpp b/base/src/mac/nsFileSpecMac.cpp index d6f2bf3294c0..41398b1b2185 100644 --- a/base/src/mac/nsFileSpecMac.cpp +++ b/base/src/mac/nsFileSpecMac.cpp @@ -16,8 +16,8 @@ * 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 "FullPath.h" #include "FileCopy.h" @@ -35,78 +35,78 @@ 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); } //----------------------------------- @@ -114,74 +114,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 //---------------------------------------------------------------------------------------- @@ -190,208 +190,244 @@ 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 - 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; - } - *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; + } + *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. - - size_t inLength = strlen(inPathNamePtr); - bool isRelative = (strchr(inPathNamePtr, ':') == 0 || *inPathNamePtr == ':'); - if (inLength < 255) - { - Str255 ppath; - MacFileHelpers::PLstrcpy(ppath, inPathNamePtr); - if (isRelative) - err = ::FSMakeFSSpec(ioSpec.vRefNum, ioSpec.parID, ppath, &ioSpec); - else - err = ::FSMakeFSSpec(0, 0, ppath, &ioSpec); - } - else if (!isRelative) - err = FSpLocationFromFullPath(inLength, inPathNamePtr, &ioSpec); + 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"); +#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 ((err == dirNFErr || err == bdNamErr) && inCreateDirs) - { - const char* path = inPathNamePtr; - 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; - // If we got "file not found", then - // we need to create a directory. - if (err == fnfErr && *nextColon) - err = FSpDirCreate(&ioSpec, smCurrentScript, &ioSpec.parID); - // For some reason, this usually returns fnfErr, even though it works. - if (err != noErr && err != fnfErr) - 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 //---------------------------------------------------------------------------------------- @@ -400,55 +436,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 //----------------------------------- @@ -459,223 +495,208 @@ 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 //======================================================================================== -// Macintosh nsFileSpec implementation +// Macintosh nsFileSpec implementation //======================================================================================== //---------------------------------------------------------------------------------------- nsFileSpec::nsFileSpec() //---------------------------------------------------------------------------------------- -: mError(NS_OK) +: mError(NS_ERROR_NOT_INITIALIZED) { - mSpec.name[0] = '\0'; + mSpec.name[0] = '\0'; } //---------------------------------------------------------------------------------------- nsFileSpec::nsFileSpec(const nsFileSpec& inSpec) //---------------------------------------------------------------------------------------- -: mSpec(inSpec.mSpec) -, mError(inSpec.Error()) +: mSpec(inSpec.mSpec) +, mError(inSpec.Error()) { } //---------------------------------------------------------------------------------------- -nsFileSpec::nsFileSpec(const char* inString, PRBool inCreateDirs) +nsFileSpec::nsFileSpec(const char* inNativePathString, PRBool inCreateDirs) //---------------------------------------------------------------------------------------- { - mSpec.vRefNum = 0; - mSpec.parID = 0; - // Convert unix (non-encoded) path to a spec. - mError = NS_FILE_RESULT( - MacFileHelpers::FSSpecFromUnixPath( - inString, - mSpec, false, false, true, inCreateDirs)); - if (mError == NS_FILE_RESULT(fnfErr)) - mError = NS_OK; + mSpec.vRefNum = 0; + mSpec.parID = 0; + + mError = NS_FILE_RESULT( + MacFileHelpers::FSSpecFromPathname( + inNativePathString, + mSpec, inCreateDirs)); + if (mError == NS_FILE_RESULT(fnfErr)) + mError = NS_OK; } // nsFileSpec::nsFileSpec //---------------------------------------------------------------------------------------- -nsFileSpec::nsFileSpec(const nsString& inString, PRBool inCreateDirs) +nsFileSpec::nsFileSpec(const nsString& inNativePathString, PRBool inCreateDirs) //---------------------------------------------------------------------------------------- { - mSpec.vRefNum = 0; - mSpec.parID = 0; - // Convert unix (non-encoded) path to a spec. - mError = NS_FILE_RESULT( - MacFileHelpers::FSSpecFromUnixPath( - nsAutoCString(inString), - mSpec, false, false, true, inCreateDirs)); - if (mError == NS_FILE_RESULT(fnfErr)) - mError = NS_OK; + mSpec.vRefNum = 0; + mSpec.parID = 0; + + 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) //---------------------------------------------------------------------------------------- { - 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, name, &mSpec)); + if (mError == NS_FILE_RESULT(fnfErr)) + mError = NS_OK; } //---------------------------------------------------------------------------------------- nsFileSpec::nsFileSpec(const nsFilePath& inPath) //---------------------------------------------------------------------------------------- { - *this = inPath.GetFileSpec(); + *this = inPath.GetFileSpec(); } //---------------------------------------------------------------------------------------- void nsFileSpec::operator = (const char* inString) //---------------------------------------------------------------------------------------- { - mPath.SetToEmpty(); + mPath.SetToEmpty(); - mSpec.vRefNum = 0; - mSpec.parID = 0; - // Convert unix (non-encoded) path to a spec. - mError = NS_FILE_RESULT( - MacFileHelpers::FSSpecFromUnixPath(inString, mSpec, false, false, true)); - if (mError == NS_FILE_RESULT(fnfErr)) - mError = NS_OK; + mSpec.vRefNum = 0; + mSpec.parID = 0; + + 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(); } // nsFileSpec::operator = //---------------------------------------------------------------------------------------- void nsFileSpec::operator = (const nsFilePath& inPath) //---------------------------------------------------------------------------------------- { - *this = inPath.GetFileSpec(); + *this = inPath.GetFileSpec(); } // nsFileSpec::operator = -#if DEBUG -//---------------------------------------------------------------------------------------- -nsOutputStream& operator << (nsOutputStream& s, const nsFileSpec& spec) -//---------------------------------------------------------------------------------------- -{ -#if 0 - s << spec.mSpec.vRefNum << ", " << spec.mSpec.parID << ", \""; - s.write((const char*)&spec.mSpec.name[1], spec.mSpec.name[0]); - return s << "\""; -#else - return s << "\"" << spec.GetCString() << "\""; -#endif -} // nsOutputStream& operator << (nsOutputStream&, const nsFileSpec&) -#endif - //---------------------------------------------------------------------------------------- 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; + CInfoPBRec pb; if (GetCatInfo(pb) == noErr) outStamp = ((DirInfo*)&pb)->ioDrMdDat; // The mod date is in the same spot for files and dirs. else @@ -686,7 +707,7 @@ void nsFileSpec::GetModDate(TimeStamp& outStamp) const PRUint32 nsFileSpec::GetFileSize() const //---------------------------------------------------------------------------------------- { - CInfoPBRec pb; + CInfoPBRec pb; if (noErr == GetCatInfo(pb)) return (PRUint32)((HFileInfo*)&pb)->ioFlLgLen; return 0; @@ -697,15 +718,15 @@ void nsFileSpec::SetLeafName(const char* inLeafName) // In leaf name can actually be a partial path... //---------------------------------------------------------------------------------------- { - mPath.SetToEmpty(); + 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; + // 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 //---------------------------------------------------------------------------------------- @@ -713,111 +734,132 @@ 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 //---------------------------------------------------------------------------------------- void nsFileSpec::ResolveAlias(PRBool& wasAliased) //---------------------------------------------------------------------------------------- { - Boolean wasAliased2; - mError = NS_FILE_RESULT(MacFileHelpers::ResolveAliasFile(mSpec, wasAliased2)); - wasAliased = (wasAliased2 != false); + Boolean wasAliased2; + mError = NS_FILE_RESULT(MacFileHelpers::ResolveAliasFile(mSpec, wasAliased2)); + wasAliased = (wasAliased2 != false); } // nsFileSpec::ResolveAlias //---------------------------------------------------------------------------------------- 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 //---------------------------------------------------------------------------------------- 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) //---------------------------------------------------------------------------------------- { - mPath.SetToEmpty(); - long dirID; - Boolean isDirectory; - mError = NS_FILE_RESULT(::FSpGetDirectoryID(&mSpec, &dirID, &isDirectory)); - if (NS_SUCCEEDED(mError) && isDirectory) - { - mSpec.parID = dirID; - // mSpec.vRefNum is already correct. - // Convert unix path (which is unencoded) to a spec + // 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; + + // 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)); - if (mError == NS_FILE_RESULT(fnfErr)) - mError = NS_OK; - } + 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; + mError = NS_FILE_RESULT(FSpDirCreate(&mSpec, smCurrentScript, &ignoredDirID)); } // nsFileSpec::CreateDirectory //---------------------------------------------------------------------------------------- void nsFileSpec::Delete(PRBool inRecursive) const //---------------------------------------------------------------------------------------- { - nsresult& mutableError = const_cast(this)->mError; - if (inRecursive) - { - // MoreFilesExtras - mutableError = NS_FILE_RESULT(::DeleteDirectory( - mSpec.vRefNum, - mSpec.parID, - const_cast(mSpec.name))); - } - else - mutableError = NS_FILE_RESULT(FSpDelete(&mSpec)); + nsresult& mutableError = const_cast(this)->mError; + if (inRecursive) + { + // MoreFilesExtras + mutableError = NS_FILE_RESULT(::DeleteDirectory( + mSpec.vRefNum, + mSpec.parID, + const_cast(mSpec.name))); + } + else + mutableError = NS_FILE_RESULT(FSpDelete(&mSpec)); } // nsFileSpec::Delete //---------------------------------------------------------------------------------------- @@ -862,7 +904,7 @@ nsresult nsFileSpec::Move(const nsFileSpec& newParentDir) // We can only move into a directory if (!newParentDir.IsDirectory()) - return NS_FILE_FAILURE; + return NS_FILE_FAILURE; nsresult result = NS_FILE_RESULT(::FSpMoveRenameCompat(&mSpec, &newParentDir.mSpec, @@ -903,30 +945,30 @@ nsresult nsFileSpec::Execute(const char* /*args - how can this be cross-platform OSErr nsFileSpec::GetCatInfo(CInfoPBRec& outInfo) const //---------------------------------------------------------------------------------------- { - DirInfo *dipb=(DirInfo *)&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); + 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() //---------------------------------------------------------------------------------------- PRUint32 nsFileSpec::GetDiskSpaceAvailable() const //---------------------------------------------------------------------------------------- { - HVolumeParam pb; - pb.ioCompletion = NULL; - pb.ioVolIndex = 0; - pb.ioNamePtr = NULL; - pb.ioVRefNum = mSpec.vRefNum; - - OSErr err = PBHGetVInfoSync( (HParmBlkPtr)&pb ); - - if ( err == noErr ) - return pb.ioVFrBlk * pb.ioVAlBlkSiz; - return ULONG_MAX; + HVolumeParam pb; + pb.ioCompletion = nsnull; + pb.ioVolIndex = 0; + pb.ioNamePtr = nsnull; + pb.ioVRefNum = mSpec.vRefNum; + + OSErr err = PBHGetVInfoSync( (HParmBlkPtr)&pb ); + + if ( err == noErr ) + return pb.ioVFrBlk * pb.ioVAlBlkSiz; + return ULONG_MAX; } // nsFileSpec::GetDiskSpace() //---------------------------------------------------------------------------------------- @@ -948,66 +990,85 @@ const char* nsFileSpec::GetCString() const } //======================================================================================== -// 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, + false, + 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) //---------------------------------------------------------------------------------------- -: mFileSpec(inString, inCreateDirs) { - // Make canonical and absolute. - char * path = MacFileHelpers::PathNameFromFSSpec( mFileSpec, true ); - path = MacFileHelpers::EncodeMacPath(path, true, false); - mPath = path; - delete [] path; -} + AssignFromPath(*this, inString, inCreateDirs); +} //nsFilePath::nsFilePath //---------------------------------------------------------------------------------------- nsFilePath::nsFilePath(const nsString& inString, PRBool inCreateDirs) //---------------------------------------------------------------------------------------- -: mFileSpec(nsAutoCString(inString), inCreateDirs) { - // Make canonical and absolute. - char * path = MacFileHelpers::PathNameFromFSSpec( mFileSpec, true ); - path = MacFileHelpers::EncodeMacPath(path, true, false); - mPath = path; - delete [] path; + AssignFromPath(*this, nsAutoCString(inString), inCreateDirs); +} + +//---------------------------------------------------------------------------------------- +void nsFilePath::operator = (const char* inString) +//---------------------------------------------------------------------------------------- +{ + 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; - delete [] path; - mFileSpec = inSpec; + char * path = MacFileHelpers::PathNameFromFSSpec(inSpec, true); + path = MacFileHelpers::EncodeMacPath(path, true, false); + mPath = path; + delete [] 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; - delete [] path; + char * path = MacFileHelpers::PathNameFromFSSpec(inOther.mFileSpec, true); + path = MacFileHelpers::EncodeMacPath(path, true, false); + mPath = path; + delete [] path; mFileSpec = inOther.GetFileSpec(); } @@ -1022,12 +1083,12 @@ nsFileURL::nsFileURL(const char* inString, PRBool inCreateDirs) { 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, // don't resolve alias - false, // must be a full path - inCreateDirs)); + inString + kFileURLPrefixLength, + mFileSpec.mSpec, + true, // need to decode + false, // don't resolve alias + false, // must be a full path + inCreateDirs)); if (mFileSpec.mError == NS_FILE_RESULT(fnfErr)) mFileSpec.mError = NS_OK; } // nsFileURL::nsFileURL @@ -1042,12 +1103,12 @@ nsFileURL::nsFileURL(const nsString& inString, PRBool inCreateDirs) 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, // don't resolve alias - false, // must be a full path - inCreateDirs)); + cstring + kFileURLPrefixLength, + mFileSpec.mSpec, + true, // need to decode + false, // don't resolve alias + false, // must be a full path + inCreateDirs)); if (mFileSpec.mError == NS_FILE_RESULT(fnfErr)) mFileSpec.mError = NS_OK; } // nsFileURL::nsFileURL @@ -1056,14 +1117,14 @@ nsFileURL::nsFileURL(const nsString& inString, PRBool inCreateDirs) nsFileURL::nsFileURL(const nsFilePath& inOther) //---------------------------------------------------------------------------------------- { - *this = inOther.GetFileSpec(); + *this = inOther.GetFileSpec(); } // nsFileURL::nsFileURL //---------------------------------------------------------------------------------------- nsFileURL::nsFileURL(const nsFileSpec& inOther) //---------------------------------------------------------------------------------------- { - *this = inOther; + *this = inOther; } // nsFileURL::nsFileURL //---------------------------------------------------------------------------------------- @@ -1078,14 +1139,14 @@ 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; - delete [] encodedPath; + char* path = MacFileHelpers::PathNameFromFSSpec( mFileSpec, true ); + char* encodedPath = MacFileHelpers::EncodeMacPath(path, true, true); + nsSimpleCharString encodedURL(kFileURLPrefix); + encodedURL += encodedPath; + delete [] encodedPath; mURL = encodedURL; - if (encodedURL[encodedURL.Length() - 1] != '/' && inOther.IsDirectory()) - mURL += "/"; + if (encodedURL[encodedURL.Length() - 1] != '/' && inOther.IsDirectory()) + mURL += "/"; } // nsFileURL::operator = //---------------------------------------------------------------------------------------- @@ -1095,102 +1156,102 @@ 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 - false, // don't resolve alias - false, // must be a full path - false)); // don't create dirs. + inString + kFileURLPrefixLength, + mFileSpec.mSpec, + true, // need to decode + false, // don't 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 = //======================================================================================== -// nsDirectoryIterator +// nsDirectoryIterator //======================================================================================== //---------------------------------------------------------------------------------------- nsDirectoryIterator::nsDirectoryIterator( - const nsFileSpec& inDirectory -, int inIterateDirection) + const nsFileSpec& inDirectory +, int inIterateDirection) //---------------------------------------------------------------------------------------- - : mCurrent(inDirectory) - , mExists(false) - , mIndex(-1) + : mCurrent(inDirectory) + , mExists(false) + , mIndex(-1) { - CInfoPBRec pb; + 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&(); - currentSpec.vRefNum = currentSpec.vRefNum; - currentSpec.parID = dipb->ioDrDirID; - mMaxIndex = pb.dirInfo.ioDrNmFls; - if (inIterateDirection > 0) - { - mIndex = 0; // ready to increment - ++(*this); // the pre-increment operator - } - else - { - mIndex = mMaxIndex + 1; // ready to decrement - --(*this); // the pre-decrement operator - } + // 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&(); + currentSpec.vRefNum = currentSpec.vRefNum; + currentSpec.parID = dipb->ioDrDirID; + mMaxIndex = pb.dirInfo.ioDrNmFls; + if (inIterateDirection > 0) + { + mIndex = 0; // ready to increment + ++(*this); // the pre-increment operator + } + else + { + mIndex = mMaxIndex + 1; // ready to decrement + --(*this); // the pre-decrement 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 = currentSpec.vRefNum; /* Might need to use vRefNum, not sure*/ - dipb->ioDrDirID = currentSpec.parID; - dipb->ioNamePtr = objectName; - OSErr err = PBGetCatInfoSync(&cipb); - FSSpec temp; - if (err == noErr) - err = FSMakeFSSpec(currentSpec.vRefNum, currentSpec.parID, objectName, &temp); - currentSpec = temp; // use the operator: it clears the string cache etc. - mExists = err == noErr; - return err; + 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 = currentSpec.vRefNum; /* Might need to use vRefNum, not sure*/ + dipb->ioDrDirID = currentSpec.parID; + dipb->ioNamePtr = objectName; + OSErr err = PBGetCatInfoSync(&cipb); + FSSpec temp; + if (err == noErr) + err = FSMakeFSSpec(currentSpec.vRefNum, currentSpec.parID, objectName, &temp); + currentSpec = temp; // use the operator: it clears the string cache etc. + mExists = err == noErr; + 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/base/src/makefile.win b/base/src/makefile.win index 0eed1387f4a7..893d0dfe49b9 100644 --- a/base/src/makefile.win +++ b/base/src/makefile.win @@ -78,6 +78,7 @@ CPP_OBJS = \ .\$(OBJDIR)\nsUnicharInputStream.obj \ .\$(OBJDIR)\nsVoidArray.obj \ .\$(OBJDIR)\nsFileSpec.obj \ + .\$(OBJDIR)\nsFileSpecStreaming.obj \ .\$(OBJDIR)\nsFileStream.obj \ .\$(OBJDIR)\nsEscape.obj \ .\$(OBJDIR)\nsIFileStream.obj \ diff --git a/base/src/nsFileSpec.cpp b/base/src/nsFileSpec.cpp index ed861acd2c67..9170bc1b958c 100644 --- a/base/src/nsFileSpec.cpp +++ b/base/src/nsFileSpec.cpp @@ -18,7 +18,6 @@ #include "nsFileSpec.h" -#include "nsFileStream.h" #include "nsDebug.h" #include "nsEscape.h" @@ -596,13 +595,6 @@ void nsFileURL::operator = (const nsFileSpec& inOther) } // nsFileURL::operator = #endif -//---------------------------------------------------------------------------------------- -nsOutputStream& operator << (nsOutputStream& s, const nsFileURL& url) -//---------------------------------------------------------------------------------------- -{ - return (s << url.mURL); -} - //======================================================================================== // nsFilePath implementation //======================================================================================== @@ -691,15 +683,12 @@ void nsFilePath::operator = (const nsFileSpec& inOther) } #endif // XP_UNIX +#ifndef XP_MAC //---------------------------------------------------------------------------------------- void nsFilePath::operator = (const char* inString) //---------------------------------------------------------------------------------------- { NS_ASSERTION(strstr(inString, kFileURLPrefix) != inString, "URL passed as path"); -#ifdef XP_MAC - mFileSpec = inString; - mPath = (const char*)nsFilePath(mFileSpec); -#else mPath = inString; #ifdef XP_PC nsFileSpecHelpers::UnixToNative(mPath); @@ -709,8 +698,8 @@ void nsFilePath::operator = (const char* inString) #ifdef XP_PC nsFileSpecHelpers::NativeToUnix(mPath); #endif -#endif // XP_MAC } +#endif // XP_MAC #ifndef XP_MAC //---------------------------------------------------------------------------------------- @@ -945,23 +934,6 @@ void nsFileSpec::operator = (const char* inString) } #endif //XP_UNIX -#if (defined(XP_UNIX) || defined(XP_PC)) -//---------------------------------------------------------------------------------------- -nsOutputStream& operator << (nsOutputStream& s, const nsFileSpec& spec) -//---------------------------------------------------------------------------------------- -{ -#ifdef NS_DEBUG - static PRBool warnedOnce = PR_FALSE; - if (!warnedOnce) - { - NS_WARNING("This is for debugging only. Do not call this in shipped version!"); - warnedOnce = PR_TRUE; - } -#endif // NS_DEBUG - return (s << spec.GetCString()); -} -#endif // DEBUG ONLY! - //---------------------------------------------------------------------------------------- nsFileSpec nsFileSpec::operator + (const char* inRelativePath) const //---------------------------------------------------------------------------------------- @@ -1077,6 +1049,20 @@ nsPersistentFileDescriptor::~nsPersistentFileDescriptor() { } // nsPersistentFileDescriptor::~nsPersistentFileDescriptor +//---------------------------------------------------------------------------------------- +void nsPersistentFileDescriptor::GetData(nsSimpleCharString& outData) const +//---------------------------------------------------------------------------------------- +{ + outData = mDescriptorString; +} + +//---------------------------------------------------------------------------------------- +void nsPersistentFileDescriptor::SetData(const nsSimpleCharString& inData) +//---------------------------------------------------------------------------------------- +{ + SetData(inData, inData.Length()); +} + //---------------------------------------------------------------------------------------- void nsPersistentFileDescriptor::GetData(nsSimpleCharString& outData, PRInt32& outSize) const //---------------------------------------------------------------------------------------- @@ -1092,70 +1078,6 @@ void nsPersistentFileDescriptor::SetData(const nsSimpleCharString& inData, PRInt mDescriptorString.CopyFrom((const char*)inData, inSize); } -#define MAX_PERSISTENT_DATA_SIZE 1000 - -//---------------------------------------------------------------------------------------- -nsresult nsPersistentFileDescriptor::Read(nsIInputStream* aStream) -//---------------------------------------------------------------------------------------- -{ - nsInputStream inputStream(aStream); - inputStream >> *this; - return NS_OK; -} - -//---------------------------------------------------------------------------------------- -nsresult nsPersistentFileDescriptor::Write(nsIOutputStream* aStream) -//---------------------------------------------------------------------------------------- -{ - nsOutputStream outputStream(aStream); - outputStream << *this; - return NS_OK; -} - -//---------------------------------------------------------------------------------------- -nsInputStream& operator >> (nsInputStream& s, nsPersistentFileDescriptor& d) -// reads the data from a file -//---------------------------------------------------------------------------------------- -{ - char bigBuffer[MAX_PERSISTENT_DATA_SIZE + 1]; - // The first 8 bytes of the data should be a hex version of the data size to follow. - PRInt32 bytesRead = 8; - bytesRead = s.read(bigBuffer, bytesRead); - if (bytesRead != 8) - return s; - bigBuffer[8] = '\0'; - sscanf(bigBuffer, "%x", (PRUint32*)&bytesRead); - if (bytesRead > MAX_PERSISTENT_DATA_SIZE) - { - // Try to tolerate encoded values with no length header - bytesRead = 8 + s.read(bigBuffer + 8, MAX_PERSISTENT_DATA_SIZE - 8); - } - else - { - // Now we know how many bytes to read, do it. - bytesRead = s.read(bigBuffer, bytesRead); - } - d.SetData(bigBuffer, bytesRead); - return s; -} - -//---------------------------------------------------------------------------------------- -nsOutputStream& operator << (nsOutputStream& s, const nsPersistentFileDescriptor& d) -// writes the data to a file -//---------------------------------------------------------------------------------------- -{ - char littleBuf[9]; - PRInt32 dataSize; - nsSimpleCharString data; - d.GetData(data, dataSize); - // First write (in hex) the length of the data to follow. Exactly 8 bytes - sprintf(littleBuf, "%0.8x", dataSize); - s << littleBuf; - // Now write the data itself - s << (const char*)data; - return s; -} - //======================================================================================== // class nsAutoCString //======================================================================================== @@ -1168,11 +1090,11 @@ nsAutoCString::~nsAutoCString() } //======================================================================================== -// class nsprPath +// class nsNSPRPath //======================================================================================== //---------------------------------------------------------------------------------------- -nsprPath::operator const char*() const +nsNSPRPath::operator const char*() const // NSPR expects a UNIX path on unix and Macintosh, but a native path on windows. NSPR // cannot be changed, so we have to do the dirty work. //---------------------------------------------------------------------------------------- @@ -1186,7 +1108,7 @@ nsprPath::operator const char*() const if (!unixPath) return nsnull; - ((nsprPath*)this)->modifiedNSPRPath + ((nsNSPRPath*)this)->modifiedNSPRPath = nsCRT::strdup(*unixPath == '/' ? unixPath + 1: unixPath); // Replace the bar @@ -1205,7 +1127,7 @@ nsprPath::operator const char*() const } //---------------------------------------------------------------------------------------- -nsprPath::~nsprPath() +nsNSPRPath::~nsNSPRPath() //---------------------------------------------------------------------------------------- { #ifdef XP_PC diff --git a/base/src/windows/nsFileSpecWin.cpp b/base/src/windows/nsFileSpecWin.cpp index 87acfe5d542a..45d1ab19ac43 100644 --- a/base/src/windows/nsFileSpecWin.cpp +++ b/base/src/windows/nsFileSpecWin.cpp @@ -177,7 +177,7 @@ PRBool nsFileSpec::Exists() const //---------------------------------------------------------------------------------------- { struct stat st; - return !mPath.IsEmpty() && 0 == stat(nsprPath(*this), &st); + return !mPath.IsEmpty() && 0 == stat(nsNSPRPath(*this), &st); } // nsFileSpec::Exists //---------------------------------------------------------------------------------------- @@ -185,7 +185,7 @@ void nsFileSpec::GetModDate(TimeStamp& outStamp) const //---------------------------------------------------------------------------------------- { struct stat st; - if (!mPath.IsEmpty() && stat(nsprPath(*this), &st) == 0) + if (!mPath.IsEmpty() && stat(nsNSPRPath(*this), &st) == 0) outStamp = st.st_mtime; else outStamp = 0; @@ -196,7 +196,7 @@ PRUint32 nsFileSpec::GetFileSize() const //---------------------------------------------------------------------------------------- { struct stat st; - if (!mPath.IsEmpty() && stat(nsprPath(*this), &st) == 0) + if (!mPath.IsEmpty() && stat(nsNSPRPath(*this), &st) == 0) return (PRUint32)st.st_size; return 0; } // nsFileSpec::GetFileSize @@ -206,7 +206,7 @@ PRBool nsFileSpec::IsFile() const //---------------------------------------------------------------------------------------- { struct stat st; - return !mPath.IsEmpty() && 0 == stat(nsprPath(*this), &st) && (_S_IFREG & st.st_mode); + return !mPath.IsEmpty() && 0 == stat(nsNSPRPath(*this), &st) && (_S_IFREG & st.st_mode); } // nsFileSpec::IsFile //---------------------------------------------------------------------------------------- @@ -214,7 +214,7 @@ PRBool nsFileSpec::IsDirectory() const //---------------------------------------------------------------------------------------- { struct stat st; - return !mPath.IsEmpty() && 0 == stat(nsprPath(*this), &st) && (_S_IFDIR & st.st_mode); + return !mPath.IsEmpty() && 0 == stat(nsNSPRPath(*this), &st) && (_S_IFDIR & st.st_mode); } // nsFileSpec::IsDirectory //---------------------------------------------------------------------------------------- @@ -253,7 +253,7 @@ void nsFileSpec::CreateDirectory(int /*mode*/) { // Note that mPath is canonical! if (!mPath.IsEmpty()) - mkdir(nsprPath(*this)); + mkdir(nsNSPRPath(*this)); } // nsFileSpec::CreateDirectory //---------------------------------------------------------------------------------------- @@ -270,11 +270,11 @@ void nsFileSpec::Delete(PRBool inRecursive) const child.Delete(inRecursive); } } - rmdir(nsprPath(*this)); + rmdir(nsNSPRPath(*this)); } else if (!mPath.IsEmpty()) { - remove(nsprPath(*this)); + remove(nsNSPRPath(*this)); } } // nsFileSpec::Delete diff --git a/base/tests/FilesTest.cpp b/base/tests/FilesTest.cpp index ed0a86913a56..7a996c547a24 100644 --- a/base/tests/FilesTest.cpp +++ b/base/tests/FilesTest.cpp @@ -43,6 +43,7 @@ struct FilesTest int CanonicalPath(const char* relativePath); int Persistence(const char* relativePath); int FileSpecEquality(const char *aFile, const char *bFile); + int FileSpecAppend(nsFileSpec& parent, const char* relativePath); int Copy(const char* sourceFile, const char* targDir); int Move(const char* sourceFile, const char* targDir); int Rename(const char* sourceFile, const char* newName); @@ -51,12 +52,12 @@ struct FilesTest int SpecialSystemDirectories(); - int NSPRCompatiblity(const char* sourceFile); + int NSPRCompatibility(const char* sourceFile); void Banner(const char* bannerString); int Passed(); int Failed(const char* explanation = nsnull); - void Inspect(); + int Inspect(); nsOutputConsoleStream mConsole; }; @@ -92,10 +93,11 @@ int FilesTest::Failed(const char* explanation) } //---------------------------------------------------------------------------------------- -void FilesTest::Inspect() +int FilesTest::Inspect() //---------------------------------------------------------------------------------------- { mConsole << nsEndl << "^^^^^^^^^^ PLEASE INSPECT OUTPUT FOR ERRORS" << nsEndl; + return 0; // for convenience } //---------------------------------------------------------------------------------------- @@ -136,12 +138,12 @@ void FilesTest::WriteStuff(nsOutputStream& s) } // WriteStuff //---------------------------------------------------------------------------------------- -int FilesTest::OutputStream(const char* relativePath) +int FilesTest::OutputStream(const char* relativeUnixPath) //---------------------------------------------------------------------------------------- { - nsFilePath myTextFilePath(relativePath, PR_TRUE); // relative path. - const char* pathAsString = (const char*)myTextFilePath; + nsFilePath myTextFilePath(relativeUnixPath, PR_TRUE); // convert to full path. nsFileSpec mySpec(myTextFilePath); + const char* pathAsString = (const char*)mySpec; { mConsole << "WRITING IDENTICAL OUTPUT TO " << pathAsString << nsEndl << nsEndl; nsOutputFileStream testStream(mySpec); @@ -166,7 +168,7 @@ int FilesTest::OutputStream(const char* relativePath) << nsEndl; return -1; } - FileSizeAndDate(relativePath); + FileSizeAndDate(relativeUnixPath); return Passed(); } @@ -310,8 +312,7 @@ int FilesTest::InputStream(const char* relativePath) testStream2.readline(line, sizeof(line)); mConsole << line << nsEndl; } - Inspect(); - return 0; + return Inspect(); } //---------------------------------------------------------------------------------------- @@ -356,8 +357,7 @@ int FilesTest::Parent( << "\n or as a URL" << "\n\t" << (const char*)url << nsEndl; - Inspect(); - return 0; + return Inspect(); } //---------------------------------------------------------------------------------------- @@ -429,17 +429,18 @@ int FilesTest::CreateDirectory(nsFileSpec& dirSpec) int FilesTest::CreateDirectoryRecursive(const char* aPath) //---------------------------------------------------------------------------------------- { - nsFileSpec dirSpec(aPath, PR_TRUE); + nsFilePath dirPath(aPath, PR_TRUE); mConsole << "Testing nsFilePath(X, PR_TRUE) using" << "\n\t" << (const char*)aPath << nsEndl; - - return Passed(); + + nsFileSpec spec(dirPath); + if (spec.Valid()) + return Passed(); + return Failed(); } - - //---------------------------------------------------------------------------------------- int FilesTest::IterateDirectoryChildren(nsFileSpec& startChild) //---------------------------------------------------------------------------------------- @@ -465,8 +466,7 @@ int FilesTest::IterateDirectoryChildren(nsFileSpec& startChild) mConsole << '\t' << itemName << nsEndl; nsCRT::free(itemName); } - Inspect(); - return 0; + return Inspect(); } //---------------------------------------------------------------------------------------- @@ -491,13 +491,38 @@ int FilesTest::CanonicalPath( return Passed(); } +//---------------------------------------------------------------------------------------- +int FilesTest::FileSpecAppend(nsFileSpec& parent, const char* relativePath) +//---------------------------------------------------------------------------------------- +{ + nsFilePath initialPath(parent); + const char* initialPathString = (const char*)initialPath; + mConsole << "Initial nsFileSpec:\n\t\"" << initialPathString << "\"" << nsEndl; + + nsFileSpec fileSpec(initialPath); + + mConsole << "Appending:\t\"" << relativePath << "\"" << nsEndl; + + fileSpec += relativePath; + + nsFilePath resultPath(fileSpec); + const char* resultPathString = (const char*)resultPath; + mConsole << "Result:\n\t\"" << resultPathString << "\"" << nsEndl; + + return Inspect(); +} // FilesTest::FileSpecAppend + //---------------------------------------------------------------------------------------- int FilesTest::FileSpecEquality(const char *aFile, const char *bFile) //---------------------------------------------------------------------------------------- { - nsFileSpec aFileSpec(aFile, PR_FALSE); - nsFileSpec bFileSpec(bFile, PR_FALSE); - nsFileSpec cFileSpec(bFile, PR_FALSE); // this should == bFile + nsFilePath aFilePath(aFile, PR_TRUE); + nsFilePath bFilePath(bFile, PR_TRUE); + + + nsFileSpec aFileSpec(aFilePath); + nsFileSpec bFileSpec(bFilePath); + nsFileSpec cFileSpec(bFilePath); // this should == bFile if (aFileSpec != bFileSpec && bFileSpec == cFileSpec ) @@ -506,26 +531,26 @@ int FilesTest::FileSpecEquality(const char *aFile, const char *bFile) } return Failed(); -} +} // FilesTest::FileSpecEquality //---------------------------------------------------------------------------------------- int FilesTest::Copy(const char* file, const char* dir) //---------------------------------------------------------------------------------------- { - nsFileSpec dirPath(dir, PR_TRUE); + nsFileSpec dirPath(nsFilePath(dir, PR_TRUE)); dirPath.CreateDirectory(); if (! dirPath.Exists()) return Failed(); - nsFileSpec mySpec(file, PR_TRUE); // relative path. + nsFileSpec mySpec(nsFilePath(file, PR_TRUE)); // relative path. { nsIOFileStream testStream(mySpec); // creates the file // Scope ends here, file gets closed } - nsFileSpec filePath(file); + nsFileSpec filePath(nsFilePath(file, PR_TRUE)); if (! filePath.Exists()) return Failed(); @@ -545,14 +570,14 @@ int FilesTest::Copy(const char* file, const char* dir) int FilesTest::Move(const char* file, const char* dir) //---------------------------------------------------------------------------------------- { - nsFileSpec dirPath(dir, PR_TRUE); + nsFileSpec dirPath(nsFilePath(dir, PR_TRUE)); dirPath.CreateDirectory(); if (! dirPath.Exists()) return Failed(); - nsFileSpec srcSpec(file, PR_TRUE); // relative path. + nsFileSpec srcSpec(nsFilePath(file, PR_TRUE)); // relative path. { nsIOFileStream testStream(srcSpec); // creates the file // file gets closed here because scope ends here. @@ -576,11 +601,12 @@ int FilesTest::Move(const char* file, const char* dir) int FilesTest::Execute(const char* appName, const char* args) //---------------------------------------------------------------------------------------- { - nsFileSpec appPath(appName, PR_FALSE); - if (!appPath.Exists()) + mConsole << "Attempting to execute " << appName << nsEndl; + nsFileSpec appSpec(appName, PR_FALSE); + if (!appSpec.Exists()) return Failed(); - nsresult error = appPath.Execute(args); + nsresult error = appSpec.Execute(args); if (NS_FAILED(error)) return Failed(); @@ -588,11 +614,13 @@ int FilesTest::Execute(const char* appName, const char* args) } //---------------------------------------------------------------------------------------- -int FilesTest::NSPRCompatiblity(const char* sourceFile) +int FilesTest::NSPRCompatibility(const char* relativeUnixFilePath) //---------------------------------------------------------------------------------------- { - nsFileSpec createTheFileSpec(sourceFile, PR_TRUE); // relative path. + nsFilePath filePath(relativeUnixFilePath, PR_TRUE); // relative path + + nsFileSpec createTheFileSpec(filePath); { nsIOFileStream testStream(createTheFileSpec); // creates the file // file gets closed here because scope ends here. @@ -600,10 +628,10 @@ int FilesTest::NSPRCompatiblity(const char* sourceFile) - nsFilePath filePath(sourceFile, PR_TRUE); PRFileDesc* fOut = NULL; - fOut = PR_Open( nsprPath(filePath), PR_RDONLY, 0 ); + // From an nsFilePath + fOut = PR_Open( nsNSPRPath(filePath), PR_RDONLY, 0 ); if ( fOut == NULL ) { return Failed(); @@ -614,9 +642,10 @@ int FilesTest::NSPRCompatiblity(const char* sourceFile) fOut = NULL; } + // From an nsFileSpec nsFileSpec fileSpec(filePath); - fOut = PR_Open( nsprPath(fileSpec), PR_RDONLY, 0 ); + fOut = PR_Open( nsNSPRPath(fileSpec), PR_RDONLY, 0 ); if ( fOut == NULL ) { return Failed(); @@ -627,9 +656,10 @@ int FilesTest::NSPRCompatiblity(const char* sourceFile) fOut = NULL; } + // From an nsFileURL nsFileURL fileURL(fileSpec); - fOut = PR_Open( nsprPath(fileURL), PR_RDONLY, 0 ); + fOut = PR_Open( nsNSPRPath(fileURL), PR_RDONLY, 0 ); if ( fOut == NULL ) { return Failed(); @@ -887,84 +917,118 @@ int FilesTest::RunAllTests() // For use with DEBUG defined. //---------------------------------------------------------------------------------------- { - // Test of mConsole output - + int rv = 0; + + // Test of mConsole output mConsole << "WRITING TEST OUTPUT TO CONSOLE" << nsEndl << nsEndl; // Test of nsFileSpec Banner("Interconversion"); WriteStuff(mConsole); - Inspect(); - + rv = Inspect(); + if (rv) + return rv; + Banner("Canonical Path"); - if (CanonicalPath("mumble/iotest.txt") != 0) - return -1; + rv = CanonicalPath("mumble/iotest.txt"); + if (rv) + return rv; Banner("OutputStream"); - if (OutputStream("mumble/iotest.txt") != 0) - return -1; + rv = OutputStream("mumble/iotest.txt"); + if (rv) + return rv; Banner("InputStream"); - if (InputStream("mumble/iotest.txt") != 0) - return -1; + rv = InputStream("mumble/iotest.txt"); + if (rv) + return rv; Banner("IOStream"); - if (IOStream("mumble/iotest.txt") != 0) - return -1; + rv = IOStream("mumble/iotest.txt"); + if (rv) + return rv; FileSizeAndDate("mumble/iotest.txt"); - if (InputStream("mumble/iotest.txt") != 0) - return -1; + rv = InputStream("mumble/iotest.txt"); + if (rv) + return rv; Banner("StringStream"); - if (StringStream() != 0) - return -1; + rv = StringStream(); + if (rv) + return rv; Banner("Parent"); nsFileSpec parent; - if (Parent("mumble/iotest.txt", parent) != 0) - return -1; + rv = Parent("mumble/iotest.txt", parent); + if (rv) + goto Clean; + Banner("FileSpec Append using Unix relative path"); + rv = FileSpecAppend(parent, "nested/unix/file.txt"); + if (rv) + goto Clean; + Banner("FileSpec Append using Native relative path"); +#ifdef XP_PC + rv = FileSpecAppend(parent, "nested\\windows\\file.txt"); +#elif defined(XP_MAC) + rv = FileSpecAppend(parent, ":nested:mac:file.txt"); +#else + rv = Passed(); +#endif // XP_MAC + if (rv) + goto Clean; + Banner("Delete"); - if (Delete(parent) != 0) - return -1; + rv = Delete(parent); + if (rv) + goto Clean; Banner("CreateDirectory"); - if (CreateDirectory(parent) != 0) - return -1; + rv = CreateDirectory(parent); + if (rv) + goto Clean; Banner("CreateDirectoryRecursive Relative (using nsFileSpec)"); - if (CreateDirectoryRecursive("mumble/dir1/dir2/dir3/") != 0) - return -1; + rv = CreateDirectoryRecursive("mumble/dir1/dir2/dir3/"); + if (rv) + goto Clean; #ifdef XP_PC Banner("CreateDirectoryRecursive Absolute (using nsFileSpec)"); - if (CreateDirectoryRecursive("c:\\temp\\dir1\\dir2\\dir3\\") != 0) - return -1; + rv = CreateDirectoryRecursive("c:\\temp\\dir1\\dir2\\dir3\\"); + if (rv) + goto Clean; #endif Banner("IterateDirectoryChildren"); - if (IterateDirectoryChildren(parent) != 0) - return -1; + rv = IterateDirectoryChildren(parent); + if (rv) + goto Clean; Banner("nsFileSpec equality"); - if (FileSpecEquality("mumble/a", "mumble/b") != 0) - return -1; + rv = FileSpecEquality("mumble/a", "mumble/b"); + if (rv) + goto Clean; Banner("Copy"); - if (Copy("mumble/copyfile.txt", "mumble/copy") != 0) - return -1; + rv = Copy("mumble/copyfile.txt", "mumble/copy"); + if (rv) + goto Clean; Banner("Move"); - if (Move("mumble/moveFile.txt", "mumble/move") != 0) - return -1; + rv = Move("mumble/moveFile.txt", "mumble/move"); + if (rv) + goto Clean; + Banner("Execute"); #ifdef XP_MAC // This path is hard-coded to test on jrm's machine. Finding an app // on an arbitrary Macintosh would cost more trouble than it's worth. - // Change path to suit. - if NS_FAILED(Execute("/Projects/Nav45_BRANCH/ns/cmd/macfe/"\ - "projects/client45/Client45PPC", "")) + // Change path to suit. This is currently a native path, as you can see. + if NS_FAILED(Execute("Projects:Nav45_BRANCH:ns:cmd:macfe:"\ + "projects:client45:Client45PPC", "")) #elif XP_PC if NS_FAILED(Execute("c:\\windows\\notepad.exe", "")) #else @@ -972,23 +1036,26 @@ int FilesTest::RunAllTests() #endif return -1; - Banner("NSPR Compatiblity"); - if (NSPRCompatiblity("mumble/aFile.txt") != 0) - return -1; + Banner("NSPR Compatibility"); + rv = NSPRCompatibility("mumble/aFile.txt"); + if (rv) + goto Clean; Banner("Special System Directories"); - if (SpecialSystemDirectories() != 0) - return -1; + rv = SpecialSystemDirectories(); + if (rv) + goto Clean; Banner("Persistence"); - if (Persistence("mumble/filedesc.dat") != 0) - return -1; + rv = Persistence("mumble/filedesc.dat"); + if (rv) + goto Clean; +Clean: Banner("Delete again (to clean up our mess)"); - if (Delete(parent) != 0) - return -1; + Delete(parent); - return 0; + return rv; } // FilesTest::RunAllTests //---------------------------------------------------------------------------------------- diff --git a/xpcom/io/nsFileSpec.cpp b/xpcom/io/nsFileSpec.cpp index ed861acd2c67..9170bc1b958c 100644 --- a/xpcom/io/nsFileSpec.cpp +++ b/xpcom/io/nsFileSpec.cpp @@ -18,7 +18,6 @@ #include "nsFileSpec.h" -#include "nsFileStream.h" #include "nsDebug.h" #include "nsEscape.h" @@ -596,13 +595,6 @@ void nsFileURL::operator = (const nsFileSpec& inOther) } // nsFileURL::operator = #endif -//---------------------------------------------------------------------------------------- -nsOutputStream& operator << (nsOutputStream& s, const nsFileURL& url) -//---------------------------------------------------------------------------------------- -{ - return (s << url.mURL); -} - //======================================================================================== // nsFilePath implementation //======================================================================================== @@ -691,15 +683,12 @@ void nsFilePath::operator = (const nsFileSpec& inOther) } #endif // XP_UNIX +#ifndef XP_MAC //---------------------------------------------------------------------------------------- void nsFilePath::operator = (const char* inString) //---------------------------------------------------------------------------------------- { NS_ASSERTION(strstr(inString, kFileURLPrefix) != inString, "URL passed as path"); -#ifdef XP_MAC - mFileSpec = inString; - mPath = (const char*)nsFilePath(mFileSpec); -#else mPath = inString; #ifdef XP_PC nsFileSpecHelpers::UnixToNative(mPath); @@ -709,8 +698,8 @@ void nsFilePath::operator = (const char* inString) #ifdef XP_PC nsFileSpecHelpers::NativeToUnix(mPath); #endif -#endif // XP_MAC } +#endif // XP_MAC #ifndef XP_MAC //---------------------------------------------------------------------------------------- @@ -945,23 +934,6 @@ void nsFileSpec::operator = (const char* inString) } #endif //XP_UNIX -#if (defined(XP_UNIX) || defined(XP_PC)) -//---------------------------------------------------------------------------------------- -nsOutputStream& operator << (nsOutputStream& s, const nsFileSpec& spec) -//---------------------------------------------------------------------------------------- -{ -#ifdef NS_DEBUG - static PRBool warnedOnce = PR_FALSE; - if (!warnedOnce) - { - NS_WARNING("This is for debugging only. Do not call this in shipped version!"); - warnedOnce = PR_TRUE; - } -#endif // NS_DEBUG - return (s << spec.GetCString()); -} -#endif // DEBUG ONLY! - //---------------------------------------------------------------------------------------- nsFileSpec nsFileSpec::operator + (const char* inRelativePath) const //---------------------------------------------------------------------------------------- @@ -1077,6 +1049,20 @@ nsPersistentFileDescriptor::~nsPersistentFileDescriptor() { } // nsPersistentFileDescriptor::~nsPersistentFileDescriptor +//---------------------------------------------------------------------------------------- +void nsPersistentFileDescriptor::GetData(nsSimpleCharString& outData) const +//---------------------------------------------------------------------------------------- +{ + outData = mDescriptorString; +} + +//---------------------------------------------------------------------------------------- +void nsPersistentFileDescriptor::SetData(const nsSimpleCharString& inData) +//---------------------------------------------------------------------------------------- +{ + SetData(inData, inData.Length()); +} + //---------------------------------------------------------------------------------------- void nsPersistentFileDescriptor::GetData(nsSimpleCharString& outData, PRInt32& outSize) const //---------------------------------------------------------------------------------------- @@ -1092,70 +1078,6 @@ void nsPersistentFileDescriptor::SetData(const nsSimpleCharString& inData, PRInt mDescriptorString.CopyFrom((const char*)inData, inSize); } -#define MAX_PERSISTENT_DATA_SIZE 1000 - -//---------------------------------------------------------------------------------------- -nsresult nsPersistentFileDescriptor::Read(nsIInputStream* aStream) -//---------------------------------------------------------------------------------------- -{ - nsInputStream inputStream(aStream); - inputStream >> *this; - return NS_OK; -} - -//---------------------------------------------------------------------------------------- -nsresult nsPersistentFileDescriptor::Write(nsIOutputStream* aStream) -//---------------------------------------------------------------------------------------- -{ - nsOutputStream outputStream(aStream); - outputStream << *this; - return NS_OK; -} - -//---------------------------------------------------------------------------------------- -nsInputStream& operator >> (nsInputStream& s, nsPersistentFileDescriptor& d) -// reads the data from a file -//---------------------------------------------------------------------------------------- -{ - char bigBuffer[MAX_PERSISTENT_DATA_SIZE + 1]; - // The first 8 bytes of the data should be a hex version of the data size to follow. - PRInt32 bytesRead = 8; - bytesRead = s.read(bigBuffer, bytesRead); - if (bytesRead != 8) - return s; - bigBuffer[8] = '\0'; - sscanf(bigBuffer, "%x", (PRUint32*)&bytesRead); - if (bytesRead > MAX_PERSISTENT_DATA_SIZE) - { - // Try to tolerate encoded values with no length header - bytesRead = 8 + s.read(bigBuffer + 8, MAX_PERSISTENT_DATA_SIZE - 8); - } - else - { - // Now we know how many bytes to read, do it. - bytesRead = s.read(bigBuffer, bytesRead); - } - d.SetData(bigBuffer, bytesRead); - return s; -} - -//---------------------------------------------------------------------------------------- -nsOutputStream& operator << (nsOutputStream& s, const nsPersistentFileDescriptor& d) -// writes the data to a file -//---------------------------------------------------------------------------------------- -{ - char littleBuf[9]; - PRInt32 dataSize; - nsSimpleCharString data; - d.GetData(data, dataSize); - // First write (in hex) the length of the data to follow. Exactly 8 bytes - sprintf(littleBuf, "%0.8x", dataSize); - s << littleBuf; - // Now write the data itself - s << (const char*)data; - return s; -} - //======================================================================================== // class nsAutoCString //======================================================================================== @@ -1168,11 +1090,11 @@ nsAutoCString::~nsAutoCString() } //======================================================================================== -// class nsprPath +// class nsNSPRPath //======================================================================================== //---------------------------------------------------------------------------------------- -nsprPath::operator const char*() const +nsNSPRPath::operator const char*() const // NSPR expects a UNIX path on unix and Macintosh, but a native path on windows. NSPR // cannot be changed, so we have to do the dirty work. //---------------------------------------------------------------------------------------- @@ -1186,7 +1108,7 @@ nsprPath::operator const char*() const if (!unixPath) return nsnull; - ((nsprPath*)this)->modifiedNSPRPath + ((nsNSPRPath*)this)->modifiedNSPRPath = nsCRT::strdup(*unixPath == '/' ? unixPath + 1: unixPath); // Replace the bar @@ -1205,7 +1127,7 @@ nsprPath::operator const char*() const } //---------------------------------------------------------------------------------------- -nsprPath::~nsprPath() +nsNSPRPath::~nsNSPRPath() //---------------------------------------------------------------------------------------- { #ifdef XP_PC diff --git a/xpcom/io/nsFileSpec.h b/xpcom/io/nsFileSpec.h index 21c3d32bbe03..936e2f2fb929 100644 --- a/xpcom/io/nsFileSpec.h +++ b/xpcom/io/nsFileSpec.h @@ -53,7 +53,7 @@ // // nsFilePath myPath("/Development/iotest.txt"); // -// nsOutputFileStream testStream(myPath); +// nsOutputFileStream testStream(nsFileSpec(myPath)); // testStream << "Hello World" << nsEndl; // // 4. Handy methods for manipulating file specifiers safely, e.g. MakeUnique(), @@ -63,35 +63,35 @@ // // Examples: // -// Initialize a URL from a string without suffix +// Initialize a URL from a string // // nsFileURL fileURL("file:///Development/MPW/MPW%20Shell"); // -// Initialize a Unix path from a URL +// Initialize a Unix-style path from a URL // // nsFilePath filePath(fileURL); // -// Initialize a native file spec from a URL +// Initialize a file spec from a URL // // nsFileSpec fileSpec(fileURL); // -// Make the spec unique (this one has no suffix). +// Make the spec unique. // // fileSpec.MakeUnique(); // -// Assign the spec to a URL +// Assign the spec to a URL (causing conversion) // // fileURL = fileSpec; // -// Assign a unix path using a string with a suffix. +// Assign a unix path using a string // // filePath = "/Development/MPW/SysErrs.err"; // -// Assign to a file spec using a unix path. +// Assign to a file spec using a unix path (causing conversion). // // fileSpec = filePath; // -// Make this unique (this one has a suffix). +// Make this unique. // // fileSpec.MakeUnique(); // @@ -103,10 +103,6 @@ // is solved by holding a "private" native file spec inside the // nsFilePath and nsFileURL classes, which is used when appropriate. // -// Not yet done: -// -// Equality operators... much more. -// //======================================================================================== #ifndef _FILESPEC_H_ @@ -153,8 +149,9 @@ //======================================================================================== class nsFileSpec; // Preferred. For i/o use nsInputFileStream, nsOutputFileStream -class nsFilePath; // This can be passed to NSPR file I/O routines, if you must. +class nsFilePath; class nsFileURL; +class nsNSPRPath; // This can be passed to NSPR file I/O routines, if you must. class nsPersistentFileDescriptor; // Used for storage across program launches. #define kFileURLPrefix "file://" @@ -167,6 +164,7 @@ class nsIInputStream; class nsOutputFileStream; class nsInputFileStream; class nsOutputConsoleStream; + class nsString; //======================================================================================== @@ -269,8 +267,12 @@ protected: void ReleaseData(); void ReallocData(PRUint32 inLength); -// DATA + //-------------------------------------------------- + // Data + //-------------------------------------------------- + protected: + struct Data { int mRefCount; PRUint32 mLength; @@ -289,8 +291,8 @@ class NS_BASE nsFileSpec nsFileSpec(); // These two meathods take *native* file paths. - NS_EXPLICIT nsFileSpec(const char* inString, PRBool inCreateDirs = PR_FALSE); - NS_EXPLICIT nsFileSpec(const nsString& inString, PRBool inCreateDirs = PR_FALSE); + NS_EXPLICIT nsFileSpec(const char* inNativePath, PRBool inCreateDirs = PR_FALSE); + NS_EXPLICIT nsFileSpec(const nsString& inNativePath, PRBool inCreateDirs = PR_FALSE); NS_EXPLICIT nsFileSpec(const nsFilePath& inPath); @@ -300,10 +302,10 @@ class NS_BASE nsFileSpec virtual ~nsFileSpec(); // These two operands take *native* file paths. - void operator = (const char* inPath); - void operator = (const nsString& inPath) + void operator = (const char* inNativePath); + void operator = (const nsString& inNativePath) { - const nsAutoCString path(inPath); + const nsAutoCString path(inNativePath); *this = path; } @@ -317,14 +319,19 @@ class NS_BASE nsFileSpec 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! const char* GetCString() const; - // This is the only conversion to const char* - // that is provided, and it allows the + // 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. + // 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. #ifdef XP_MAC // For Macintosh people, this is meant to be useful in its own right as a C++ version @@ -367,22 +374,15 @@ class NS_BASE nsFileSpec { #ifndef XP_MAC if (mPath.IsEmpty() && NS_SUCCEEDED(mError)) - ((nsFileSpec*)this)->mError = NS_FILE_FAILURE; + ((nsFileSpec*)this)->mError = NS_ERROR_NOT_INITIALIZED; #endif return mError; } PRBool Failed() const { return (PRBool)NS_FAILED(Error()); } - - friend NS_BASE nsOutputStream& operator << ( - nsOutputStream& s, - const nsFileSpec& spec); // THIS IS FOR DEBUGGING ONLY. - // see PersistentFileDescriptor for the real deal. - - - //-------------------------------------------------- - // Queries and path algebra. These do not modify the disk. - //-------------------------------------------------- + //-------------------------------------------------- + // Queries and path algebra. These do not modify the disk. + //-------------------------------------------------- char* GetLeafName() const; // Allocated. Use nsCRT::free(). void SetLeafName(const char* inLeafName); @@ -422,14 +422,14 @@ class NS_BASE nsFileSpec PRUint32 GetFileSize() const; PRUint32 GetDiskSpaceAvailable() const; - nsFileSpec operator + (const char* inRelativePath) const; - nsFileSpec operator + (const nsString& inRelativePath) const + nsFileSpec operator + (const char* inRelativeUnixPath) const; + nsFileSpec operator + (const nsString& inRelativeUnixPath) const { const nsAutoCString - relativePath(inRelativePath); + relativePath(inRelativeUnixPath); return *this + relativePath; } - void operator += (const char* inRelativePath); + 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 @@ -438,9 +438,9 @@ class NS_BASE nsFileSpec // away its leaf information, whereas this one assumes // this is a directory, and the relative path starts // "below" this. - void operator += (const nsString& inRelativePath) + void operator += (const nsString& inRelativeUnixPath) { - const nsAutoCString relativePath(inRelativePath); + const nsAutoCString relativePath(inRelativeUnixPath); *this += relativePath; } @@ -458,9 +458,9 @@ class NS_BASE nsFileSpec // More stringent than Exists() PRBool Exists() const; - //-------------------------------------------------- - // Creation and deletion of objects. These can modify the disk. - //-------------------------------------------------- + //-------------------------------------------------- + // Creation and deletion of objects. These can modify the disk. + //-------------------------------------------------- void CreateDirectory(int mode = 0700 /* for unix */); void CreateDir(int mode = 0700) { CreateDirectory(mode); } @@ -481,9 +481,9 @@ class NS_BASE nsFileSpec const nsAutoCString argsString(args); return Execute(argsString); } - //-------------------------------------------------- - // Data - //-------------------------------------------------- + //-------------------------------------------------- + // Data + //-------------------------------------------------- protected: friend class nsFilePath; @@ -509,8 +509,8 @@ class NS_BASE nsFileURL { public: nsFileURL(const nsFileURL& inURL); - NS_EXPLICIT nsFileURL(const char* inString, PRBool inCreateDirs = PR_FALSE); - NS_EXPLICIT nsFileURL(const nsString& inString, PRBool inCreateDirs = PR_FALSE); + NS_EXPLICIT nsFileURL(const char* inURLString, PRBool inCreateDirs = PR_FALSE); + NS_EXPLICIT nsFileURL(const nsString& inURLString, PRBool inCreateDirs = PR_FALSE); NS_EXPLICIT nsFileURL(const nsFilePath& inPath); NS_EXPLICIT nsFileURL(const nsFileSpec& inPath); virtual ~nsFileURL(); @@ -520,10 +520,10 @@ class NS_BASE nsFileURL // but should not provide a conversion constructor. void operator = (const nsFileURL& inURL); - void operator = (const char* inString); - void operator = (const nsString& inString) + void operator = (const char* inURLString); + void operator = (const nsString& inURLString) { - const nsAutoCString string(inString); + const nsAutoCString string(inURLString); *this = string; } void operator = (const nsFilePath& inOther); @@ -532,16 +532,20 @@ class NS_BASE nsFileURL void operator +=(const char* inRelativeUnixPath); nsFileURL operator +(const char* inRelativeUnixPath) const; operator const char* () const { return (const char*)mURL; } // deprecated. + const char* GetURLString() const { return (const char*)mURL; } + // Not allocated, so don't free it. const char* GetAsString() const { return (const char*)mURL; } - - friend NS_BASE nsOutputStream& operator << ( - nsOutputStream& s, const nsFileURL& spec); + // Not allocated, so don't free it. #ifdef XP_MAC // Accessor to allow quick assignment to a mFileSpec const nsFileSpec& GetFileSpec() const { return mFileSpec; } #endif + //-------------------------------------------------- + // Data + //-------------------------------------------------- + protected: friend class nsFilePath; // to allow construction of nsFilePath nsSimpleCharString mURL; @@ -562,8 +566,8 @@ class NS_BASE nsFilePath { public: nsFilePath(const nsFilePath& inPath); - NS_EXPLICIT nsFilePath(const char* inString, PRBool inCreateDirs = PR_FALSE); - NS_EXPLICIT nsFilePath(const nsString& inString, PRBool inCreateDirs = PR_FALSE); + NS_EXPLICIT nsFilePath(const char* inUnixPathString, PRBool inCreateDirs = PR_FALSE); + NS_EXPLICIT nsFilePath(const nsString& inUnixPathString, PRBool inCreateDirs = PR_FALSE); NS_EXPLICIT nsFilePath(const nsFileURL& inURL); NS_EXPLICIT nsFilePath(const nsFileSpec& inPath); virtual ~nsFilePath(); @@ -572,13 +576,13 @@ class NS_BASE nsFilePath operator const char* () const { return mPath; } // This will return a UNIX string. If you // need a string that can be passed into - // NSPR, take a look at the nsprPath class. + // NSPR, take a look at the nsNSPRPath class. void operator = (const nsFilePath& inPath); - void operator = (const char* inString); - void operator = (const nsString& inString) + void operator = (const char* inUnixPathString); + void operator = (const nsString& inUnixPathString) { - const nsAutoCString string(inString); + const nsAutoCString string(inUnixPathString); *this = string; } void operator = (const nsFileURL& inURL); @@ -593,6 +597,10 @@ class NS_BASE nsFilePath const nsFileSpec& GetFileSpec() const { return mFileSpec; } #endif + //-------------------------------------------------- + // Data + //-------------------------------------------------- + private: nsSimpleCharString mPath; @@ -622,8 +630,11 @@ class NS_BASE nsPersistentFileDescriptor NS_EXPLICIT nsPersistentFileDescriptor(const nsFileSpec& inPath); void operator = (const nsFileSpec& inPath); - nsresult Read(nsIInputStream* aStream); - nsresult Write(nsIOutputStream* aStream); + // The following four functions are declared here (as friends). Their implementations + // are in mozilla/base/src/nsFileSpecStreaming.cpp. + + friend nsresult Read(nsIInputStream* aStream, nsPersistentFileDescriptor&); + friend nsresult Write(nsIOutputStream* aStream, const nsPersistentFileDescriptor&); // writes the data to a file friend NS_BASE nsInputStream& operator >> (nsInputStream&, nsPersistentFileDescriptor&); // reads the data from a file @@ -631,11 +642,15 @@ class NS_BASE nsPersistentFileDescriptor // writes the data to a file friend class nsFileSpec; - private: - + void GetData(nsSimpleCharString& outData) const; + void SetData(const nsSimpleCharString& inData); void GetData(nsSimpleCharString& outData, PRInt32& outSize) const; void SetData(const nsSimpleCharString& inData, PRInt32 inSize); + //-------------------------------------------------- + // Data + //-------------------------------------------------- + protected: nsSimpleCharString mDescriptorString; @@ -654,7 +669,7 @@ class NS_BASE nsDirectoryIterator // // or: // -// for (nsDirectoryIterator i(parentDir, PR_FALSE); i.Exists(); i--) +// for (nsDirectoryIterator i(parentDir, -1); i.Exists(); i--) // { // // do something with i.Spec() // } @@ -681,6 +696,17 @@ class NS_BASE nsDirectoryIterator nsFileSpec& Spec() { return mCurrent; } private: + +#if defined(XP_MAC) + OSErr SetToIndex(); +#endif + + //-------------------------------------------------- + // Data + //-------------------------------------------------- + + private: + nsFileSpec mCurrent; PRBool mExists; @@ -689,35 +715,44 @@ class NS_BASE nsDirectoryIterator #elif defined(XP_PC) PRDir* mDir; // XXX why not use PRDir for Unix too? #elif defined(XP_MAC) - OSErr SetToIndex(); short mIndex; short mMaxIndex; #endif }; // class nsDirectoryIterator //======================================================================================== -class NS_BASE nsprPath +class NS_BASE nsNSPRPath // This class will allow you to pass any one of the nsFile* classes directly into NSPR // without the need to worry about whether you have the right kind of filepath or not. // It will also take care of cleaning up any allocated memory. //======================================================================================== { public: - NS_EXPLICIT nsprPath(const nsFileSpec& other) - : mFilePath(other), modifiedNSPRPath(nsnull) {} - NS_EXPLICIT nsprPath(const nsFileURL& other) - : mFilePath(other), modifiedNSPRPath(nsnull) {} - NS_EXPLICIT nsprPath(const nsFilePath& other) - : mFilePath(other), modifiedNSPRPath(nsnull) {} + NS_EXPLICIT nsNSPRPath(const nsFileSpec& inSpec) + : mFilePath(inSpec), modifiedNSPRPath(nsnull) {} + NS_EXPLICIT nsNSPRPath(const nsFileURL& inURL) + : mFilePath(inURL), modifiedNSPRPath(nsnull) {} + NS_EXPLICIT nsNSPRPath(const nsFilePath& inUnixPath) + : mFilePath(inUnixPath), modifiedNSPRPath(nsnull) {} - virtual ~nsprPath(); + virtual ~nsNSPRPath(); operator const char*() const; - // actually, can modify modifiedNSPRPath, but - // that's really just "mutable". + // Returns the path + // that NSPR file routines expect on each platform. + // Concerning constness, this can modify + // modifiedNSPRPath, but it's really just "mutable". + + //-------------------------------------------------- + // Data + //-------------------------------------------------- + private: - nsFilePath mFilePath; - char* modifiedNSPRPath; // Currently used only on XP_PC -}; // class nsprPath + + nsFilePath mFilePath; + char* modifiedNSPRPath; // Currently used only on XP_PC +}; // class nsNSPRPath + +typedef nsNSPRPath nsprPath; // old name. #endif // _FILESPEC_H_ diff --git a/xpcom/io/nsFileSpecMac.cpp b/xpcom/io/nsFileSpecMac.cpp index d6f2bf3294c0..41398b1b2185 100644 --- a/xpcom/io/nsFileSpecMac.cpp +++ b/xpcom/io/nsFileSpecMac.cpp @@ -16,8 +16,8 @@ * 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 "FullPath.h" #include "FileCopy.h" @@ -35,78 +35,78 @@ 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); } //----------------------------------- @@ -114,74 +114,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 //---------------------------------------------------------------------------------------- @@ -190,208 +190,244 @@ 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 - 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; - } - *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; + } + *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. - - size_t inLength = strlen(inPathNamePtr); - bool isRelative = (strchr(inPathNamePtr, ':') == 0 || *inPathNamePtr == ':'); - if (inLength < 255) - { - Str255 ppath; - MacFileHelpers::PLstrcpy(ppath, inPathNamePtr); - if (isRelative) - err = ::FSMakeFSSpec(ioSpec.vRefNum, ioSpec.parID, ppath, &ioSpec); - else - err = ::FSMakeFSSpec(0, 0, ppath, &ioSpec); - } - else if (!isRelative) - err = FSpLocationFromFullPath(inLength, inPathNamePtr, &ioSpec); + 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"); +#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 ((err == dirNFErr || err == bdNamErr) && inCreateDirs) - { - const char* path = inPathNamePtr; - 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; - // If we got "file not found", then - // we need to create a directory. - if (err == fnfErr && *nextColon) - err = FSpDirCreate(&ioSpec, smCurrentScript, &ioSpec.parID); - // For some reason, this usually returns fnfErr, even though it works. - if (err != noErr && err != fnfErr) - 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 //---------------------------------------------------------------------------------------- @@ -400,55 +436,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 //----------------------------------- @@ -459,223 +495,208 @@ 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 //======================================================================================== -// Macintosh nsFileSpec implementation +// Macintosh nsFileSpec implementation //======================================================================================== //---------------------------------------------------------------------------------------- nsFileSpec::nsFileSpec() //---------------------------------------------------------------------------------------- -: mError(NS_OK) +: mError(NS_ERROR_NOT_INITIALIZED) { - mSpec.name[0] = '\0'; + mSpec.name[0] = '\0'; } //---------------------------------------------------------------------------------------- nsFileSpec::nsFileSpec(const nsFileSpec& inSpec) //---------------------------------------------------------------------------------------- -: mSpec(inSpec.mSpec) -, mError(inSpec.Error()) +: mSpec(inSpec.mSpec) +, mError(inSpec.Error()) { } //---------------------------------------------------------------------------------------- -nsFileSpec::nsFileSpec(const char* inString, PRBool inCreateDirs) +nsFileSpec::nsFileSpec(const char* inNativePathString, PRBool inCreateDirs) //---------------------------------------------------------------------------------------- { - mSpec.vRefNum = 0; - mSpec.parID = 0; - // Convert unix (non-encoded) path to a spec. - mError = NS_FILE_RESULT( - MacFileHelpers::FSSpecFromUnixPath( - inString, - mSpec, false, false, true, inCreateDirs)); - if (mError == NS_FILE_RESULT(fnfErr)) - mError = NS_OK; + mSpec.vRefNum = 0; + mSpec.parID = 0; + + mError = NS_FILE_RESULT( + MacFileHelpers::FSSpecFromPathname( + inNativePathString, + mSpec, inCreateDirs)); + if (mError == NS_FILE_RESULT(fnfErr)) + mError = NS_OK; } // nsFileSpec::nsFileSpec //---------------------------------------------------------------------------------------- -nsFileSpec::nsFileSpec(const nsString& inString, PRBool inCreateDirs) +nsFileSpec::nsFileSpec(const nsString& inNativePathString, PRBool inCreateDirs) //---------------------------------------------------------------------------------------- { - mSpec.vRefNum = 0; - mSpec.parID = 0; - // Convert unix (non-encoded) path to a spec. - mError = NS_FILE_RESULT( - MacFileHelpers::FSSpecFromUnixPath( - nsAutoCString(inString), - mSpec, false, false, true, inCreateDirs)); - if (mError == NS_FILE_RESULT(fnfErr)) - mError = NS_OK; + mSpec.vRefNum = 0; + mSpec.parID = 0; + + 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) //---------------------------------------------------------------------------------------- { - 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, name, &mSpec)); + if (mError == NS_FILE_RESULT(fnfErr)) + mError = NS_OK; } //---------------------------------------------------------------------------------------- nsFileSpec::nsFileSpec(const nsFilePath& inPath) //---------------------------------------------------------------------------------------- { - *this = inPath.GetFileSpec(); + *this = inPath.GetFileSpec(); } //---------------------------------------------------------------------------------------- void nsFileSpec::operator = (const char* inString) //---------------------------------------------------------------------------------------- { - mPath.SetToEmpty(); + mPath.SetToEmpty(); - mSpec.vRefNum = 0; - mSpec.parID = 0; - // Convert unix (non-encoded) path to a spec. - mError = NS_FILE_RESULT( - MacFileHelpers::FSSpecFromUnixPath(inString, mSpec, false, false, true)); - if (mError == NS_FILE_RESULT(fnfErr)) - mError = NS_OK; + mSpec.vRefNum = 0; + mSpec.parID = 0; + + 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(); } // nsFileSpec::operator = //---------------------------------------------------------------------------------------- void nsFileSpec::operator = (const nsFilePath& inPath) //---------------------------------------------------------------------------------------- { - *this = inPath.GetFileSpec(); + *this = inPath.GetFileSpec(); } // nsFileSpec::operator = -#if DEBUG -//---------------------------------------------------------------------------------------- -nsOutputStream& operator << (nsOutputStream& s, const nsFileSpec& spec) -//---------------------------------------------------------------------------------------- -{ -#if 0 - s << spec.mSpec.vRefNum << ", " << spec.mSpec.parID << ", \""; - s.write((const char*)&spec.mSpec.name[1], spec.mSpec.name[0]); - return s << "\""; -#else - return s << "\"" << spec.GetCString() << "\""; -#endif -} // nsOutputStream& operator << (nsOutputStream&, const nsFileSpec&) -#endif - //---------------------------------------------------------------------------------------- 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; + CInfoPBRec pb; if (GetCatInfo(pb) == noErr) outStamp = ((DirInfo*)&pb)->ioDrMdDat; // The mod date is in the same spot for files and dirs. else @@ -686,7 +707,7 @@ void nsFileSpec::GetModDate(TimeStamp& outStamp) const PRUint32 nsFileSpec::GetFileSize() const //---------------------------------------------------------------------------------------- { - CInfoPBRec pb; + CInfoPBRec pb; if (noErr == GetCatInfo(pb)) return (PRUint32)((HFileInfo*)&pb)->ioFlLgLen; return 0; @@ -697,15 +718,15 @@ void nsFileSpec::SetLeafName(const char* inLeafName) // In leaf name can actually be a partial path... //---------------------------------------------------------------------------------------- { - mPath.SetToEmpty(); + 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; + // 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 //---------------------------------------------------------------------------------------- @@ -713,111 +734,132 @@ 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 //---------------------------------------------------------------------------------------- void nsFileSpec::ResolveAlias(PRBool& wasAliased) //---------------------------------------------------------------------------------------- { - Boolean wasAliased2; - mError = NS_FILE_RESULT(MacFileHelpers::ResolveAliasFile(mSpec, wasAliased2)); - wasAliased = (wasAliased2 != false); + Boolean wasAliased2; + mError = NS_FILE_RESULT(MacFileHelpers::ResolveAliasFile(mSpec, wasAliased2)); + wasAliased = (wasAliased2 != false); } // nsFileSpec::ResolveAlias //---------------------------------------------------------------------------------------- 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 //---------------------------------------------------------------------------------------- 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) //---------------------------------------------------------------------------------------- { - mPath.SetToEmpty(); - long dirID; - Boolean isDirectory; - mError = NS_FILE_RESULT(::FSpGetDirectoryID(&mSpec, &dirID, &isDirectory)); - if (NS_SUCCEEDED(mError) && isDirectory) - { - mSpec.parID = dirID; - // mSpec.vRefNum is already correct. - // Convert unix path (which is unencoded) to a spec + // 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; + + // 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)); - if (mError == NS_FILE_RESULT(fnfErr)) - mError = NS_OK; - } + 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; + mError = NS_FILE_RESULT(FSpDirCreate(&mSpec, smCurrentScript, &ignoredDirID)); } // nsFileSpec::CreateDirectory //---------------------------------------------------------------------------------------- void nsFileSpec::Delete(PRBool inRecursive) const //---------------------------------------------------------------------------------------- { - nsresult& mutableError = const_cast(this)->mError; - if (inRecursive) - { - // MoreFilesExtras - mutableError = NS_FILE_RESULT(::DeleteDirectory( - mSpec.vRefNum, - mSpec.parID, - const_cast(mSpec.name))); - } - else - mutableError = NS_FILE_RESULT(FSpDelete(&mSpec)); + nsresult& mutableError = const_cast(this)->mError; + if (inRecursive) + { + // MoreFilesExtras + mutableError = NS_FILE_RESULT(::DeleteDirectory( + mSpec.vRefNum, + mSpec.parID, + const_cast(mSpec.name))); + } + else + mutableError = NS_FILE_RESULT(FSpDelete(&mSpec)); } // nsFileSpec::Delete //---------------------------------------------------------------------------------------- @@ -862,7 +904,7 @@ nsresult nsFileSpec::Move(const nsFileSpec& newParentDir) // We can only move into a directory if (!newParentDir.IsDirectory()) - return NS_FILE_FAILURE; + return NS_FILE_FAILURE; nsresult result = NS_FILE_RESULT(::FSpMoveRenameCompat(&mSpec, &newParentDir.mSpec, @@ -903,30 +945,30 @@ nsresult nsFileSpec::Execute(const char* /*args - how can this be cross-platform OSErr nsFileSpec::GetCatInfo(CInfoPBRec& outInfo) const //---------------------------------------------------------------------------------------- { - DirInfo *dipb=(DirInfo *)&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); + 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() //---------------------------------------------------------------------------------------- PRUint32 nsFileSpec::GetDiskSpaceAvailable() const //---------------------------------------------------------------------------------------- { - HVolumeParam pb; - pb.ioCompletion = NULL; - pb.ioVolIndex = 0; - pb.ioNamePtr = NULL; - pb.ioVRefNum = mSpec.vRefNum; - - OSErr err = PBHGetVInfoSync( (HParmBlkPtr)&pb ); - - if ( err == noErr ) - return pb.ioVFrBlk * pb.ioVAlBlkSiz; - return ULONG_MAX; + HVolumeParam pb; + pb.ioCompletion = nsnull; + pb.ioVolIndex = 0; + pb.ioNamePtr = nsnull; + pb.ioVRefNum = mSpec.vRefNum; + + OSErr err = PBHGetVInfoSync( (HParmBlkPtr)&pb ); + + if ( err == noErr ) + return pb.ioVFrBlk * pb.ioVAlBlkSiz; + return ULONG_MAX; } // nsFileSpec::GetDiskSpace() //---------------------------------------------------------------------------------------- @@ -948,66 +990,85 @@ const char* nsFileSpec::GetCString() const } //======================================================================================== -// 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, + false, + 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) //---------------------------------------------------------------------------------------- -: mFileSpec(inString, inCreateDirs) { - // Make canonical and absolute. - char * path = MacFileHelpers::PathNameFromFSSpec( mFileSpec, true ); - path = MacFileHelpers::EncodeMacPath(path, true, false); - mPath = path; - delete [] path; -} + AssignFromPath(*this, inString, inCreateDirs); +} //nsFilePath::nsFilePath //---------------------------------------------------------------------------------------- nsFilePath::nsFilePath(const nsString& inString, PRBool inCreateDirs) //---------------------------------------------------------------------------------------- -: mFileSpec(nsAutoCString(inString), inCreateDirs) { - // Make canonical and absolute. - char * path = MacFileHelpers::PathNameFromFSSpec( mFileSpec, true ); - path = MacFileHelpers::EncodeMacPath(path, true, false); - mPath = path; - delete [] path; + AssignFromPath(*this, nsAutoCString(inString), inCreateDirs); +} + +//---------------------------------------------------------------------------------------- +void nsFilePath::operator = (const char* inString) +//---------------------------------------------------------------------------------------- +{ + 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; - delete [] path; - mFileSpec = inSpec; + char * path = MacFileHelpers::PathNameFromFSSpec(inSpec, true); + path = MacFileHelpers::EncodeMacPath(path, true, false); + mPath = path; + delete [] 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; - delete [] path; + char * path = MacFileHelpers::PathNameFromFSSpec(inOther.mFileSpec, true); + path = MacFileHelpers::EncodeMacPath(path, true, false); + mPath = path; + delete [] path; mFileSpec = inOther.GetFileSpec(); } @@ -1022,12 +1083,12 @@ nsFileURL::nsFileURL(const char* inString, PRBool inCreateDirs) { 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, // don't resolve alias - false, // must be a full path - inCreateDirs)); + inString + kFileURLPrefixLength, + mFileSpec.mSpec, + true, // need to decode + false, // don't resolve alias + false, // must be a full path + inCreateDirs)); if (mFileSpec.mError == NS_FILE_RESULT(fnfErr)) mFileSpec.mError = NS_OK; } // nsFileURL::nsFileURL @@ -1042,12 +1103,12 @@ nsFileURL::nsFileURL(const nsString& inString, PRBool inCreateDirs) 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, // don't resolve alias - false, // must be a full path - inCreateDirs)); + cstring + kFileURLPrefixLength, + mFileSpec.mSpec, + true, // need to decode + false, // don't resolve alias + false, // must be a full path + inCreateDirs)); if (mFileSpec.mError == NS_FILE_RESULT(fnfErr)) mFileSpec.mError = NS_OK; } // nsFileURL::nsFileURL @@ -1056,14 +1117,14 @@ nsFileURL::nsFileURL(const nsString& inString, PRBool inCreateDirs) nsFileURL::nsFileURL(const nsFilePath& inOther) //---------------------------------------------------------------------------------------- { - *this = inOther.GetFileSpec(); + *this = inOther.GetFileSpec(); } // nsFileURL::nsFileURL //---------------------------------------------------------------------------------------- nsFileURL::nsFileURL(const nsFileSpec& inOther) //---------------------------------------------------------------------------------------- { - *this = inOther; + *this = inOther; } // nsFileURL::nsFileURL //---------------------------------------------------------------------------------------- @@ -1078,14 +1139,14 @@ 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; - delete [] encodedPath; + char* path = MacFileHelpers::PathNameFromFSSpec( mFileSpec, true ); + char* encodedPath = MacFileHelpers::EncodeMacPath(path, true, true); + nsSimpleCharString encodedURL(kFileURLPrefix); + encodedURL += encodedPath; + delete [] encodedPath; mURL = encodedURL; - if (encodedURL[encodedURL.Length() - 1] != '/' && inOther.IsDirectory()) - mURL += "/"; + if (encodedURL[encodedURL.Length() - 1] != '/' && inOther.IsDirectory()) + mURL += "/"; } // nsFileURL::operator = //---------------------------------------------------------------------------------------- @@ -1095,102 +1156,102 @@ 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 - false, // don't resolve alias - false, // must be a full path - false)); // don't create dirs. + inString + kFileURLPrefixLength, + mFileSpec.mSpec, + true, // need to decode + false, // don't 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 = //======================================================================================== -// nsDirectoryIterator +// nsDirectoryIterator //======================================================================================== //---------------------------------------------------------------------------------------- nsDirectoryIterator::nsDirectoryIterator( - const nsFileSpec& inDirectory -, int inIterateDirection) + const nsFileSpec& inDirectory +, int inIterateDirection) //---------------------------------------------------------------------------------------- - : mCurrent(inDirectory) - , mExists(false) - , mIndex(-1) + : mCurrent(inDirectory) + , mExists(false) + , mIndex(-1) { - CInfoPBRec pb; + 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&(); - currentSpec.vRefNum = currentSpec.vRefNum; - currentSpec.parID = dipb->ioDrDirID; - mMaxIndex = pb.dirInfo.ioDrNmFls; - if (inIterateDirection > 0) - { - mIndex = 0; // ready to increment - ++(*this); // the pre-increment operator - } - else - { - mIndex = mMaxIndex + 1; // ready to decrement - --(*this); // the pre-decrement operator - } + // 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&(); + currentSpec.vRefNum = currentSpec.vRefNum; + currentSpec.parID = dipb->ioDrDirID; + mMaxIndex = pb.dirInfo.ioDrNmFls; + if (inIterateDirection > 0) + { + mIndex = 0; // ready to increment + ++(*this); // the pre-increment operator + } + else + { + mIndex = mMaxIndex + 1; // ready to decrement + --(*this); // the pre-decrement 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 = currentSpec.vRefNum; /* Might need to use vRefNum, not sure*/ - dipb->ioDrDirID = currentSpec.parID; - dipb->ioNamePtr = objectName; - OSErr err = PBGetCatInfoSync(&cipb); - FSSpec temp; - if (err == noErr) - err = FSMakeFSSpec(currentSpec.vRefNum, currentSpec.parID, objectName, &temp); - currentSpec = temp; // use the operator: it clears the string cache etc. - mExists = err == noErr; - return err; + 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 = currentSpec.vRefNum; /* Might need to use vRefNum, not sure*/ + dipb->ioDrDirID = currentSpec.parID; + dipb->ioNamePtr = objectName; + OSErr err = PBGetCatInfoSync(&cipb); + FSSpec temp; + if (err == noErr) + err = FSMakeFSSpec(currentSpec.vRefNum, currentSpec.parID, objectName, &temp); + currentSpec = temp; // use the operator: it clears the string cache etc. + mExists = err == noErr; + 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/xpcom/io/nsFileSpecWin.cpp b/xpcom/io/nsFileSpecWin.cpp index 87acfe5d542a..45d1ab19ac43 100644 --- a/xpcom/io/nsFileSpecWin.cpp +++ b/xpcom/io/nsFileSpecWin.cpp @@ -177,7 +177,7 @@ PRBool nsFileSpec::Exists() const //---------------------------------------------------------------------------------------- { struct stat st; - return !mPath.IsEmpty() && 0 == stat(nsprPath(*this), &st); + return !mPath.IsEmpty() && 0 == stat(nsNSPRPath(*this), &st); } // nsFileSpec::Exists //---------------------------------------------------------------------------------------- @@ -185,7 +185,7 @@ void nsFileSpec::GetModDate(TimeStamp& outStamp) const //---------------------------------------------------------------------------------------- { struct stat st; - if (!mPath.IsEmpty() && stat(nsprPath(*this), &st) == 0) + if (!mPath.IsEmpty() && stat(nsNSPRPath(*this), &st) == 0) outStamp = st.st_mtime; else outStamp = 0; @@ -196,7 +196,7 @@ PRUint32 nsFileSpec::GetFileSize() const //---------------------------------------------------------------------------------------- { struct stat st; - if (!mPath.IsEmpty() && stat(nsprPath(*this), &st) == 0) + if (!mPath.IsEmpty() && stat(nsNSPRPath(*this), &st) == 0) return (PRUint32)st.st_size; return 0; } // nsFileSpec::GetFileSize @@ -206,7 +206,7 @@ PRBool nsFileSpec::IsFile() const //---------------------------------------------------------------------------------------- { struct stat st; - return !mPath.IsEmpty() && 0 == stat(nsprPath(*this), &st) && (_S_IFREG & st.st_mode); + return !mPath.IsEmpty() && 0 == stat(nsNSPRPath(*this), &st) && (_S_IFREG & st.st_mode); } // nsFileSpec::IsFile //---------------------------------------------------------------------------------------- @@ -214,7 +214,7 @@ PRBool nsFileSpec::IsDirectory() const //---------------------------------------------------------------------------------------- { struct stat st; - return !mPath.IsEmpty() && 0 == stat(nsprPath(*this), &st) && (_S_IFDIR & st.st_mode); + return !mPath.IsEmpty() && 0 == stat(nsNSPRPath(*this), &st) && (_S_IFDIR & st.st_mode); } // nsFileSpec::IsDirectory //---------------------------------------------------------------------------------------- @@ -253,7 +253,7 @@ void nsFileSpec::CreateDirectory(int /*mode*/) { // Note that mPath is canonical! if (!mPath.IsEmpty()) - mkdir(nsprPath(*this)); + mkdir(nsNSPRPath(*this)); } // nsFileSpec::CreateDirectory //---------------------------------------------------------------------------------------- @@ -270,11 +270,11 @@ void nsFileSpec::Delete(PRBool inRecursive) const child.Delete(inRecursive); } } - rmdir(nsprPath(*this)); + rmdir(nsNSPRPath(*this)); } else if (!mPath.IsEmpty()) { - remove(nsprPath(*this)); + remove(nsNSPRPath(*this)); } } // nsFileSpec::Delete diff --git a/xpcom/tests/FilesTest.cpp b/xpcom/tests/FilesTest.cpp index ed0a86913a56..7a996c547a24 100644 --- a/xpcom/tests/FilesTest.cpp +++ b/xpcom/tests/FilesTest.cpp @@ -43,6 +43,7 @@ struct FilesTest int CanonicalPath(const char* relativePath); int Persistence(const char* relativePath); int FileSpecEquality(const char *aFile, const char *bFile); + int FileSpecAppend(nsFileSpec& parent, const char* relativePath); int Copy(const char* sourceFile, const char* targDir); int Move(const char* sourceFile, const char* targDir); int Rename(const char* sourceFile, const char* newName); @@ -51,12 +52,12 @@ struct FilesTest int SpecialSystemDirectories(); - int NSPRCompatiblity(const char* sourceFile); + int NSPRCompatibility(const char* sourceFile); void Banner(const char* bannerString); int Passed(); int Failed(const char* explanation = nsnull); - void Inspect(); + int Inspect(); nsOutputConsoleStream mConsole; }; @@ -92,10 +93,11 @@ int FilesTest::Failed(const char* explanation) } //---------------------------------------------------------------------------------------- -void FilesTest::Inspect() +int FilesTest::Inspect() //---------------------------------------------------------------------------------------- { mConsole << nsEndl << "^^^^^^^^^^ PLEASE INSPECT OUTPUT FOR ERRORS" << nsEndl; + return 0; // for convenience } //---------------------------------------------------------------------------------------- @@ -136,12 +138,12 @@ void FilesTest::WriteStuff(nsOutputStream& s) } // WriteStuff //---------------------------------------------------------------------------------------- -int FilesTest::OutputStream(const char* relativePath) +int FilesTest::OutputStream(const char* relativeUnixPath) //---------------------------------------------------------------------------------------- { - nsFilePath myTextFilePath(relativePath, PR_TRUE); // relative path. - const char* pathAsString = (const char*)myTextFilePath; + nsFilePath myTextFilePath(relativeUnixPath, PR_TRUE); // convert to full path. nsFileSpec mySpec(myTextFilePath); + const char* pathAsString = (const char*)mySpec; { mConsole << "WRITING IDENTICAL OUTPUT TO " << pathAsString << nsEndl << nsEndl; nsOutputFileStream testStream(mySpec); @@ -166,7 +168,7 @@ int FilesTest::OutputStream(const char* relativePath) << nsEndl; return -1; } - FileSizeAndDate(relativePath); + FileSizeAndDate(relativeUnixPath); return Passed(); } @@ -310,8 +312,7 @@ int FilesTest::InputStream(const char* relativePath) testStream2.readline(line, sizeof(line)); mConsole << line << nsEndl; } - Inspect(); - return 0; + return Inspect(); } //---------------------------------------------------------------------------------------- @@ -356,8 +357,7 @@ int FilesTest::Parent( << "\n or as a URL" << "\n\t" << (const char*)url << nsEndl; - Inspect(); - return 0; + return Inspect(); } //---------------------------------------------------------------------------------------- @@ -429,17 +429,18 @@ int FilesTest::CreateDirectory(nsFileSpec& dirSpec) int FilesTest::CreateDirectoryRecursive(const char* aPath) //---------------------------------------------------------------------------------------- { - nsFileSpec dirSpec(aPath, PR_TRUE); + nsFilePath dirPath(aPath, PR_TRUE); mConsole << "Testing nsFilePath(X, PR_TRUE) using" << "\n\t" << (const char*)aPath << nsEndl; - - return Passed(); + + nsFileSpec spec(dirPath); + if (spec.Valid()) + return Passed(); + return Failed(); } - - //---------------------------------------------------------------------------------------- int FilesTest::IterateDirectoryChildren(nsFileSpec& startChild) //---------------------------------------------------------------------------------------- @@ -465,8 +466,7 @@ int FilesTest::IterateDirectoryChildren(nsFileSpec& startChild) mConsole << '\t' << itemName << nsEndl; nsCRT::free(itemName); } - Inspect(); - return 0; + return Inspect(); } //---------------------------------------------------------------------------------------- @@ -491,13 +491,38 @@ int FilesTest::CanonicalPath( return Passed(); } +//---------------------------------------------------------------------------------------- +int FilesTest::FileSpecAppend(nsFileSpec& parent, const char* relativePath) +//---------------------------------------------------------------------------------------- +{ + nsFilePath initialPath(parent); + const char* initialPathString = (const char*)initialPath; + mConsole << "Initial nsFileSpec:\n\t\"" << initialPathString << "\"" << nsEndl; + + nsFileSpec fileSpec(initialPath); + + mConsole << "Appending:\t\"" << relativePath << "\"" << nsEndl; + + fileSpec += relativePath; + + nsFilePath resultPath(fileSpec); + const char* resultPathString = (const char*)resultPath; + mConsole << "Result:\n\t\"" << resultPathString << "\"" << nsEndl; + + return Inspect(); +} // FilesTest::FileSpecAppend + //---------------------------------------------------------------------------------------- int FilesTest::FileSpecEquality(const char *aFile, const char *bFile) //---------------------------------------------------------------------------------------- { - nsFileSpec aFileSpec(aFile, PR_FALSE); - nsFileSpec bFileSpec(bFile, PR_FALSE); - nsFileSpec cFileSpec(bFile, PR_FALSE); // this should == bFile + nsFilePath aFilePath(aFile, PR_TRUE); + nsFilePath bFilePath(bFile, PR_TRUE); + + + nsFileSpec aFileSpec(aFilePath); + nsFileSpec bFileSpec(bFilePath); + nsFileSpec cFileSpec(bFilePath); // this should == bFile if (aFileSpec != bFileSpec && bFileSpec == cFileSpec ) @@ -506,26 +531,26 @@ int FilesTest::FileSpecEquality(const char *aFile, const char *bFile) } return Failed(); -} +} // FilesTest::FileSpecEquality //---------------------------------------------------------------------------------------- int FilesTest::Copy(const char* file, const char* dir) //---------------------------------------------------------------------------------------- { - nsFileSpec dirPath(dir, PR_TRUE); + nsFileSpec dirPath(nsFilePath(dir, PR_TRUE)); dirPath.CreateDirectory(); if (! dirPath.Exists()) return Failed(); - nsFileSpec mySpec(file, PR_TRUE); // relative path. + nsFileSpec mySpec(nsFilePath(file, PR_TRUE)); // relative path. { nsIOFileStream testStream(mySpec); // creates the file // Scope ends here, file gets closed } - nsFileSpec filePath(file); + nsFileSpec filePath(nsFilePath(file, PR_TRUE)); if (! filePath.Exists()) return Failed(); @@ -545,14 +570,14 @@ int FilesTest::Copy(const char* file, const char* dir) int FilesTest::Move(const char* file, const char* dir) //---------------------------------------------------------------------------------------- { - nsFileSpec dirPath(dir, PR_TRUE); + nsFileSpec dirPath(nsFilePath(dir, PR_TRUE)); dirPath.CreateDirectory(); if (! dirPath.Exists()) return Failed(); - nsFileSpec srcSpec(file, PR_TRUE); // relative path. + nsFileSpec srcSpec(nsFilePath(file, PR_TRUE)); // relative path. { nsIOFileStream testStream(srcSpec); // creates the file // file gets closed here because scope ends here. @@ -576,11 +601,12 @@ int FilesTest::Move(const char* file, const char* dir) int FilesTest::Execute(const char* appName, const char* args) //---------------------------------------------------------------------------------------- { - nsFileSpec appPath(appName, PR_FALSE); - if (!appPath.Exists()) + mConsole << "Attempting to execute " << appName << nsEndl; + nsFileSpec appSpec(appName, PR_FALSE); + if (!appSpec.Exists()) return Failed(); - nsresult error = appPath.Execute(args); + nsresult error = appSpec.Execute(args); if (NS_FAILED(error)) return Failed(); @@ -588,11 +614,13 @@ int FilesTest::Execute(const char* appName, const char* args) } //---------------------------------------------------------------------------------------- -int FilesTest::NSPRCompatiblity(const char* sourceFile) +int FilesTest::NSPRCompatibility(const char* relativeUnixFilePath) //---------------------------------------------------------------------------------------- { - nsFileSpec createTheFileSpec(sourceFile, PR_TRUE); // relative path. + nsFilePath filePath(relativeUnixFilePath, PR_TRUE); // relative path + + nsFileSpec createTheFileSpec(filePath); { nsIOFileStream testStream(createTheFileSpec); // creates the file // file gets closed here because scope ends here. @@ -600,10 +628,10 @@ int FilesTest::NSPRCompatiblity(const char* sourceFile) - nsFilePath filePath(sourceFile, PR_TRUE); PRFileDesc* fOut = NULL; - fOut = PR_Open( nsprPath(filePath), PR_RDONLY, 0 ); + // From an nsFilePath + fOut = PR_Open( nsNSPRPath(filePath), PR_RDONLY, 0 ); if ( fOut == NULL ) { return Failed(); @@ -614,9 +642,10 @@ int FilesTest::NSPRCompatiblity(const char* sourceFile) fOut = NULL; } + // From an nsFileSpec nsFileSpec fileSpec(filePath); - fOut = PR_Open( nsprPath(fileSpec), PR_RDONLY, 0 ); + fOut = PR_Open( nsNSPRPath(fileSpec), PR_RDONLY, 0 ); if ( fOut == NULL ) { return Failed(); @@ -627,9 +656,10 @@ int FilesTest::NSPRCompatiblity(const char* sourceFile) fOut = NULL; } + // From an nsFileURL nsFileURL fileURL(fileSpec); - fOut = PR_Open( nsprPath(fileURL), PR_RDONLY, 0 ); + fOut = PR_Open( nsNSPRPath(fileURL), PR_RDONLY, 0 ); if ( fOut == NULL ) { return Failed(); @@ -887,84 +917,118 @@ int FilesTest::RunAllTests() // For use with DEBUG defined. //---------------------------------------------------------------------------------------- { - // Test of mConsole output - + int rv = 0; + + // Test of mConsole output mConsole << "WRITING TEST OUTPUT TO CONSOLE" << nsEndl << nsEndl; // Test of nsFileSpec Banner("Interconversion"); WriteStuff(mConsole); - Inspect(); - + rv = Inspect(); + if (rv) + return rv; + Banner("Canonical Path"); - if (CanonicalPath("mumble/iotest.txt") != 0) - return -1; + rv = CanonicalPath("mumble/iotest.txt"); + if (rv) + return rv; Banner("OutputStream"); - if (OutputStream("mumble/iotest.txt") != 0) - return -1; + rv = OutputStream("mumble/iotest.txt"); + if (rv) + return rv; Banner("InputStream"); - if (InputStream("mumble/iotest.txt") != 0) - return -1; + rv = InputStream("mumble/iotest.txt"); + if (rv) + return rv; Banner("IOStream"); - if (IOStream("mumble/iotest.txt") != 0) - return -1; + rv = IOStream("mumble/iotest.txt"); + if (rv) + return rv; FileSizeAndDate("mumble/iotest.txt"); - if (InputStream("mumble/iotest.txt") != 0) - return -1; + rv = InputStream("mumble/iotest.txt"); + if (rv) + return rv; Banner("StringStream"); - if (StringStream() != 0) - return -1; + rv = StringStream(); + if (rv) + return rv; Banner("Parent"); nsFileSpec parent; - if (Parent("mumble/iotest.txt", parent) != 0) - return -1; + rv = Parent("mumble/iotest.txt", parent); + if (rv) + goto Clean; + Banner("FileSpec Append using Unix relative path"); + rv = FileSpecAppend(parent, "nested/unix/file.txt"); + if (rv) + goto Clean; + Banner("FileSpec Append using Native relative path"); +#ifdef XP_PC + rv = FileSpecAppend(parent, "nested\\windows\\file.txt"); +#elif defined(XP_MAC) + rv = FileSpecAppend(parent, ":nested:mac:file.txt"); +#else + rv = Passed(); +#endif // XP_MAC + if (rv) + goto Clean; + Banner("Delete"); - if (Delete(parent) != 0) - return -1; + rv = Delete(parent); + if (rv) + goto Clean; Banner("CreateDirectory"); - if (CreateDirectory(parent) != 0) - return -1; + rv = CreateDirectory(parent); + if (rv) + goto Clean; Banner("CreateDirectoryRecursive Relative (using nsFileSpec)"); - if (CreateDirectoryRecursive("mumble/dir1/dir2/dir3/") != 0) - return -1; + rv = CreateDirectoryRecursive("mumble/dir1/dir2/dir3/"); + if (rv) + goto Clean; #ifdef XP_PC Banner("CreateDirectoryRecursive Absolute (using nsFileSpec)"); - if (CreateDirectoryRecursive("c:\\temp\\dir1\\dir2\\dir3\\") != 0) - return -1; + rv = CreateDirectoryRecursive("c:\\temp\\dir1\\dir2\\dir3\\"); + if (rv) + goto Clean; #endif Banner("IterateDirectoryChildren"); - if (IterateDirectoryChildren(parent) != 0) - return -1; + rv = IterateDirectoryChildren(parent); + if (rv) + goto Clean; Banner("nsFileSpec equality"); - if (FileSpecEquality("mumble/a", "mumble/b") != 0) - return -1; + rv = FileSpecEquality("mumble/a", "mumble/b"); + if (rv) + goto Clean; Banner("Copy"); - if (Copy("mumble/copyfile.txt", "mumble/copy") != 0) - return -1; + rv = Copy("mumble/copyfile.txt", "mumble/copy"); + if (rv) + goto Clean; Banner("Move"); - if (Move("mumble/moveFile.txt", "mumble/move") != 0) - return -1; + rv = Move("mumble/moveFile.txt", "mumble/move"); + if (rv) + goto Clean; + Banner("Execute"); #ifdef XP_MAC // This path is hard-coded to test on jrm's machine. Finding an app // on an arbitrary Macintosh would cost more trouble than it's worth. - // Change path to suit. - if NS_FAILED(Execute("/Projects/Nav45_BRANCH/ns/cmd/macfe/"\ - "projects/client45/Client45PPC", "")) + // Change path to suit. This is currently a native path, as you can see. + if NS_FAILED(Execute("Projects:Nav45_BRANCH:ns:cmd:macfe:"\ + "projects:client45:Client45PPC", "")) #elif XP_PC if NS_FAILED(Execute("c:\\windows\\notepad.exe", "")) #else @@ -972,23 +1036,26 @@ int FilesTest::RunAllTests() #endif return -1; - Banner("NSPR Compatiblity"); - if (NSPRCompatiblity("mumble/aFile.txt") != 0) - return -1; + Banner("NSPR Compatibility"); + rv = NSPRCompatibility("mumble/aFile.txt"); + if (rv) + goto Clean; Banner("Special System Directories"); - if (SpecialSystemDirectories() != 0) - return -1; + rv = SpecialSystemDirectories(); + if (rv) + goto Clean; Banner("Persistence"); - if (Persistence("mumble/filedesc.dat") != 0) - return -1; + rv = Persistence("mumble/filedesc.dat"); + if (rv) + goto Clean; +Clean: Banner("Delete again (to clean up our mess)"); - if (Delete(parent) != 0) - return -1; + Delete(parent); - return 0; + return rv; } // FilesTest::RunAllTests //----------------------------------------------------------------------------------------