diff --git a/mozilla/base/public/nsFileSpec.h b/mozilla/base/public/nsFileSpec.h index d847f754e04..5d5eacf820d 100644 --- a/mozilla/base/public/nsFileSpec.h +++ b/mozilla/base/public/nsFileSpec.h @@ -236,12 +236,16 @@ class NS_BASE nsFileSpec PRBool operator ==(const nsFileSpec& inOther) const; PRBool operator !=(const nsFileSpec& inOther) const; -#ifndef XP_MAC - operator const char* () const { return mPath; } - // This is the only automatic conversion to const char* + operator const char* () const { return GetCString(); } + // Same as GetCString (please read the comments). + const char* GetCString() const; + // This is the only conversion to const char* // that is provided, and it allows the - // path to be "passed" to NSPR file routines. -#endif + // 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. #ifdef XP_MAC // For Macintosh people, this is meant to be useful in its own right as a C++ version @@ -259,6 +263,11 @@ class NS_BASE nsFileSpec operator const FSSpec* const () { return &mSpec; } operator FSSpec& () { return mSpec; } operator const FSSpec& () const { return mSpec; } + + const FSSpec& GetFSSpec() const { return mSpec; } + FSSpec& GetFSSpec() { return mSpec; } + ConstFSSpecPtr GetFSSpecPtr() const { return &mSpec; } + FSSpecPtr GetFSSpecPtr() { return &mSpec; } void MakeAliasSafe(); // Called for the spec of an alias. Copies the alias to // a secret temp directory and modifies the spec to point @@ -329,6 +338,7 @@ class NS_BASE nsFileSpec } PRUint32 GetFileSize() const; + PRUint32 GetDiskSpaceAvailable() const; nsFileSpec operator + (const char* inRelativePath) const; nsFileSpec operator + (const nsString& inRelativePath) const @@ -398,12 +408,12 @@ class NS_BASE nsFileSpec protected: friend class nsFilePath; + friend class nsFileURL; friend class nsDirectoryIterator; #ifdef XP_MAC FSSpec mSpec; -#else - char* mPath; #endif + char* mPath; nsresult mError; }; // class nsFileSpec @@ -440,7 +450,7 @@ class NS_BASE nsFileURL void operator = (const nsFilePath& inOther); void operator = (const nsFileSpec& inOther); - operator const char* const () { return mURL; } // deprecated. + operator const char* () const { return mURL; } // deprecated. const char* GetAsString() const { return mURL; } friend NS_BASE nsOutputStream& operator << ( @@ -465,8 +475,9 @@ class NS_BASE nsFileURL //======================================================================================== class NS_BASE nsFilePath -// This is a string that looks like "/foo/bar/mumble%20fish". Same as nsFileURL, but -// without the "file:// prefix". +// This is a string that looks like "/foo/bar/mumble fish". Same as nsFileURL, but +// without the "file:// prefix", and NOT %20 ENCODED! Strings passed in must be +// valid unix-style paths in this format. //======================================================================================== { public: diff --git a/mozilla/base/src/mac/nsFileSpecMac.cpp b/mozilla/base/src/mac/nsFileSpecMac.cpp index 62c5de86007..68dc06c24a9 100644 --- a/mozilla/base/src/mac/nsFileSpecMac.cpp +++ b/mozilla/base/src/mac/nsFileSpecMac.cpp @@ -45,20 +45,23 @@ namespace MacFileHelpers void PLstrncpy(Str255 dst, const char* src, int inMaxLen); void SwapSlashColon(char * s); - OSErr FSSpecFromFullUnixPath( + OSErr FSSpecFromUnixPath( const char * unixPath, - FSSpec& outSpec, + FSSpec& ioSpec, + Boolean hexDecode, Boolean resolveAlias, Boolean allowPartial = false, Boolean createDirs = false); - char* MacPathFromUnixPath(const char* unixPath); + 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& outSpec, + FSSpec& ioSpec, Boolean inCreateDirs); char* PathNameFromFSSpec( const FSSpec& inSpec, @@ -212,7 +215,7 @@ OSErr MacFileHelpers::MakeAliasSafe(FSSpec& inOutSpec) } // MacFileHelpers::MakeAliasSafe //---------------------------------------------------------------------------------------- -char* MacFileHelpers::MacPathFromUnixPath(const char* unixPath) +char* MacFileHelpers::MacPathFromUnixPath(const char* unixPath, Boolean hexDecode) //---------------------------------------------------------------------------------------- { // Relying on the fact that the unix path is always longer than the mac path: @@ -227,7 +230,8 @@ char* MacFileHelpers::MacPathFromUnixPath(const char* unixPath) else if (strchr(src, '/')) // * partial path, and not just a leaf name *dst++ = ':'; strcpy(dst, src); - nsUnescape(dst); // Hex Decode + if (hexDecode) + nsUnescape(dst); // Hex Decode MacFileHelpers::SwapSlashColon(dst); } return result; @@ -236,7 +240,7 @@ char* MacFileHelpers::MacPathFromUnixPath(const char* unixPath) //---------------------------------------------------------------------------------------- OSErr MacFileHelpers::FSSpecFromPathname( const char* inPathNamePtr, - FSSpec& outSpec, + 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. @@ -247,20 +251,26 @@ OSErr MacFileHelpers::FSSpecFromPathname( // 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); - err = ::FSMakeFSSpec(0, 0, ppath, &outSpec); + if (isRelative) + err = ::FSMakeFSSpec(ioSpec.vRefNum, ioSpec.parID, ppath, &ioSpec); + else + err = ::FSMakeFSSpec(0, 0, ppath, &ioSpec); } - else - err = FSpLocationFromFullPath(inLength, inPathNamePtr, &outSpec); + else if (!isRelative) + err = FSpLocationFromFullPath(inLength, inPathNamePtr, &ioSpec); + else + err = bdNamErr; - if (err == dirNFErr && inCreateDirs) + if ((err == dirNFErr || err == bdNamErr) && inCreateDirs) { const char* path = inPathNamePtr; - outSpec.vRefNum = 0; - outSpec.parID = 0; + 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. @@ -276,7 +286,7 @@ OSErr MacFileHelpers::FSSpecFromPathname( // 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(outSpec.vRefNum, outSpec.parID, ppath, &outSpec); + err = ::FSMakeFSSpec(ioSpec.vRefNum, ioSpec.parID, ppath, &ioSpec); // If this was the leaf node, then we are done. if (!*nextColon) @@ -285,7 +295,7 @@ OSErr MacFileHelpers::FSSpecFromPathname( // If we got "file not found", then // we need to create a directory. if (err == fnfErr && *nextColon) - err = FSpDirCreate(&outSpec, smCurrentScript, &outSpec.parID); + err = FSpDirCreate(&ioSpec, smCurrentScript, &ioSpec.parID); // For some reason, this usually returns fnfErr, even though it works. if (err != noErr && err != fnfErr) return err; @@ -368,9 +378,10 @@ OSErr MacFileHelpers::ResolveAliasFile(FSSpec& inOutSpec, Boolean& wasAliased) } // MacFileHelpers::ResolveAliasFile //----------------------------------- -OSErr MacFileHelpers::FSSpecFromFullUnixPath( +OSErr MacFileHelpers::FSSpecFromUnixPath( const char * unixPath, - FSSpec& outSpec, + FSSpec& ioSpec, + Boolean hexDecode, Boolean resolveAlias, Boolean allowPartial, Boolean createDirs) @@ -382,7 +393,7 @@ OSErr MacFileHelpers::FSSpecFromFullUnixPath( { if (unixPath == nsnull) return badFidErr; - char* macPath = MacPathFromUnixPath(unixPath); + char* macPath = MacPathFromUnixPath(unixPath, hexDecode); if (!macPath) return memFullErr; @@ -391,12 +402,12 @@ OSErr MacFileHelpers::FSSpecFromFullUnixPath( { NS_ASSERTION(*unixPath == '/' /*full path*/, "Not a full Unix path!"); } - err = FSSpecFromPathname(macPath, outSpec, createDirs); + err = FSSpecFromPathname(macPath, ioSpec, createDirs); if (err == fnfErr) err = noErr; Boolean dummy; if (err == noErr && resolveAlias) // Added - err = MacFileHelpers::ResolveAliasFile(outSpec, dummy); + err = MacFileHelpers::ResolveAliasFile(ioSpec, dummy); delete [] macPath; NS_ASSERTION(err==noErr||err==fnfErr||err==dirNFErr||err==nsvErr, "Not a path!"); return err; @@ -508,6 +519,7 @@ Clean: nsFileSpec::nsFileSpec() //---------------------------------------------------------------------------------------- : mError(NS_OK) +, mPath(nsnull) { mSpec.name[0] = '\0'; } @@ -516,6 +528,7 @@ nsFileSpec::nsFileSpec() nsFileSpec::nsFileSpec(const nsFileSpec& inSpec) //---------------------------------------------------------------------------------------- : mSpec(inSpec.mSpec) +, mPath(nsnull) , mError(inSpec.Error()) { } @@ -523,10 +536,15 @@ nsFileSpec::nsFileSpec(const nsFileSpec& inSpec) //---------------------------------------------------------------------------------------- nsFileSpec::nsFileSpec(const char* inString, PRBool inCreateDirs) //---------------------------------------------------------------------------------------- +: mPath(nsnull) { - mError = NS_FILE_RESULT(MacFileHelpers::FSSpecFromFullUnixPath( - inString, mSpec, false, true, inCreateDirs)); - // allow a partial path, create as necessary + 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; } // nsFileSpec::nsFileSpec @@ -534,55 +552,57 @@ nsFileSpec::nsFileSpec(const char* inString, PRBool inCreateDirs) //---------------------------------------------------------------------------------------- nsFileSpec::nsFileSpec(const nsString& inString, PRBool inCreateDirs) //---------------------------------------------------------------------------------------- +: mPath(nsnull) { - mError = NS_FILE_RESULT(MacFileHelpers::FSSpecFromFullUnixPath( - nsAutoCString(inString), mSpec, false, true, inCreateDirs)); - // allow a partial path, create as necessary + 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; } // nsFileSpec::nsFileSpec //---------------------------------------------------------------------------------------- -nsFileSpec::nsFileSpec( - short vRefNum, - long parID, - ConstStr255Param name) +nsFileSpec::nsFileSpec(short vRefNum, long parID, ConstStr255Param name) //---------------------------------------------------------------------------------------- +: mPath(nsnull) { mError = NS_FILE_RESULT(::FSMakeFSSpec(vRefNum, parID, name, &mSpec)); if (mError == NS_FILE_RESULT(fnfErr)) - mError = noErr; + mError = NS_OK; } //---------------------------------------------------------------------------------------- nsFileSpec::nsFileSpec(const nsFilePath& inPath) //---------------------------------------------------------------------------------------- +: mPath(nsnull) { *this = inPath.GetFileSpec(); } -#if DEBUG -//---------------------------------------------------------------------------------------- -nsOutputStream& operator << (nsOutputStream& s, const nsFileSpec& spec) -//---------------------------------------------------------------------------------------- -{ - s << spec.mSpec.vRefNum << ", " << spec.mSpec.parID << ", \""; - s.write((const char*)&spec.mSpec.name[1], spec.mSpec.name[0]); - return s << "\""; -} // nsOutputStream& operator << (nsOutputStream&, const nsFileSpec&) -#endif - //---------------------------------------------------------------------------------------- void nsFileSpec::operator = (const char* inString) //---------------------------------------------------------------------------------------- { - mError = NS_FILE_RESULT(MacFileHelpers::FSSpecFromFullUnixPath(inString, mSpec, false)); + nsFileSpecHelpers::StringAssign(mPath, nsnull); + + 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; } // nsFileSpec::operator = //---------------------------------------------------------------------------------------- void nsFileSpec::operator = (const nsFileSpec& inSpec) //---------------------------------------------------------------------------------------- { + nsFileSpecHelpers::StringAssign(mPath, nsnull); mSpec = inSpec.mSpec; mError = inSpec.Error(); } // nsFileSpec::operator = @@ -594,13 +614,28 @@ void nsFileSpec::operator = (const nsFilePath& inPath) *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; -} // nsFileSpec::operator = +} // nsFileSpec::Exists() //---------------------------------------------------------------------------------------- void nsFileSpec::GetModDate(TimeStamp& outStamp) const @@ -628,11 +663,15 @@ void nsFileSpec::SetLeafName(const char* inLeafName) // In leaf name can actually be a partial path... //---------------------------------------------------------------------------------------- { - // what about long relative paths? Hmm? + nsFileSpecHelpers::StringAssign(mPath, nsnull); + + // 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 //---------------------------------------------------------------------------------------- @@ -650,6 +689,7 @@ char* nsFileSpec::GetLeafName() const void nsFileSpec::MakeAliasSafe() //---------------------------------------------------------------------------------------- { + nsFileSpecHelpers::StringAssign(mPath, nsnull); mError = NS_FILE_RESULT(MacFileHelpers::MakeAliasSafe(mSpec)); } // nsFileSpec::MakeAliasSafe @@ -657,6 +697,7 @@ void nsFileSpec::MakeAliasSafe() void nsFileSpec::MakeUnique(ConstStr255Param inSuggestedLeafName) //---------------------------------------------------------------------------------------- { + nsFileSpecHelpers::StringAssign(mPath, nsnull); if (inSuggestedLeafName[0] > 0) MacFileHelpers::PLstrcpy(mSpec.name, inSuggestedLeafName); @@ -708,11 +749,14 @@ void nsFileSpec::operator += (const char* inRelativePath) mError = NS_FILE_RESULT(::FSpGetDirectoryID(&mSpec, &dirID, &isDirectory)); if (NS_SUCCEEDED(mError) && isDirectory) { - Str255 partialPath; - MacFileHelpers::PLstrcpy(partialPath, inRelativePath); - mError = NS_FILE_RESULT(::FSMakeFSSpec(mSpec.vRefNum, dirID, partialPath, *this)); - //if (NS_SUCCEEDED(mError)) - // SetLeafName(inRelativePath); + mSpec.parID = dirID; + // mSpec.vRefNum is already correct. + // 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; } } // nsFileSpec::operator += @@ -721,7 +765,7 @@ void nsFileSpec::CreateDirectory(int /* unix mode */) //---------------------------------------------------------------------------------------- { long ignoredDirID; - FSpDirCreate(&mSpec, smCurrentScript, &ignoredDirID); + mError = NS_FILE_RESULT(FSpDirCreate(&mSpec, smCurrentScript, &ignoredDirID)); } // nsFileSpec::CreateDirectory //---------------------------------------------------------------------------------------- @@ -827,6 +871,41 @@ OSErr nsFileSpec::GetCatInfo(CInfoPBRec& outInfo) const 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; +} // nsFileSpec::GetDiskSpace() + +//---------------------------------------------------------------------------------------- +const char* nsFileSpec::GetCString() const +// This is the only conversion to const char* that is provided, and it allows the +// path to be "passed" to NSPR file routines. This practice is VERY EVIL and should only +// be used to support legacy code. Using it guarantees bugs on Macintosh. The string is +// cached and freed by the nsFileSpec destructor, so do not delete (or free) it. +//---------------------------------------------------------------------------------------- +{ + if (!mPath) + { + const_cast(this)->mPath + = MacFileHelpers::PathNameFromFSSpec(mSpec, true); + if (!mPath) + const_cast(this)->mError = NS_ERROR_OUT_OF_MEMORY; + } + return mPath; +} + //======================================================================================== // Macintosh nsFilePath implementation //======================================================================================== @@ -839,7 +918,7 @@ nsFilePath::nsFilePath(const char* inString, PRBool inCreateDirs) { // Make canonical and absolute. char * path = MacFileHelpers::PathNameFromFSSpec( mFileSpec, TRUE ); - mPath = MacFileHelpers::EncodeMacPath(path, true, true); + mPath = MacFileHelpers::EncodeMacPath(path, true, false); } //---------------------------------------------------------------------------------------- @@ -850,28 +929,42 @@ nsFilePath::nsFilePath(const nsString& inString, PRBool inCreateDirs) { // Make canonical and absolute. char * path = MacFileHelpers::PathNameFromFSSpec( mFileSpec, TRUE ); - mPath = MacFileHelpers::EncodeMacPath(path, true, true); + mPath = MacFileHelpers::EncodeMacPath(path, true, false); } //---------------------------------------------------------------------------------------- nsFilePath::nsFilePath(const nsFileSpec& inSpec) //---------------------------------------------------------------------------------------- -: mFileSpec(inSpec) +: mPath(nsnull) { - char * path = MacFileHelpers::PathNameFromFSSpec( inSpec.mSpec, TRUE ); - mPath = MacFileHelpers::EncodeMacPath(path, true, true); + *this = inSpec; +} + +//---------------------------------------------------------------------------------------- +nsFilePath::nsFilePath(const nsFileURL& inOther) +//---------------------------------------------------------------------------------------- +: mPath(nsnull) +{ + *this = inOther.GetFileSpec(); } //---------------------------------------------------------------------------------------- void nsFilePath::operator = (const nsFileSpec& inSpec) //---------------------------------------------------------------------------------------- { - delete [] mPath; char * path = MacFileHelpers::PathNameFromFSSpec( inSpec.mSpec, TRUE ); - mPath = MacFileHelpers::EncodeMacPath(path, true, true); + delete [] mPath; + mPath = MacFileHelpers::EncodeMacPath(path, true, false); mFileSpec = inSpec; } // nsFilePath::operator = +//---------------------------------------------------------------------------------------- +void nsFilePath::operator = (const nsFileURL& inOther) +//---------------------------------------------------------------------------------------- +{ + *this = inOther.GetFileSpec(); +} + //======================================================================================== // nsFileURL implementation //======================================================================================== @@ -879,35 +972,87 @@ void nsFilePath::operator = (const nsFileSpec& inSpec) //---------------------------------------------------------------------------------------- nsFileURL::nsFileURL(const char* inString, PRBool inCreateDirs) //---------------------------------------------------------------------------------------- -: mURL(nsnull) -, mFileSpec(inString + kFileURLPrefixLength, inCreateDirs) -{ - NS_ASSERTION(strstr(inString, kFileURLPrefix) == inString, "Not a URL!"); - // Make canonical and absolute. - char* path = MacFileHelpers::PathNameFromFSSpec( mFileSpec, TRUE ); - char* escapedPath = MacFileHelpers::EncodeMacPath(path, true, true); - mURL = nsFileSpecHelpers::StringDup(kFileURLPrefix, kFileURLPrefixLength + strlen(escapedPath)); - strcat(mURL, escapedPath); - delete [] escapedPath; +: mURL(nsFileSpecHelpers::StringDup(inString)) +{ + NS_ASSERTION(strstr(mURL, kFileURLPrefix) == mURL, "Not a URL!"); + mFileSpec.mError = NS_FILE_RESULT(MacFileHelpers::FSSpecFromUnixPath( + mURL + 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 //---------------------------------------------------------------------------------------- nsFileURL::nsFileURL(const nsString& inString, PRBool inCreateDirs) //---------------------------------------------------------------------------------------- +: mURL(nsFileSpecHelpers::StringDup(nsAutoCString(inString))) +{ + NS_ASSERTION(strstr(mURL, kFileURLPrefix) == mURL, "Not a URL!"); + mFileSpec.mError = NS_FILE_RESULT(MacFileHelpers::FSSpecFromUnixPath( + mURL + 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 + +//---------------------------------------------------------------------------------------- +nsFileURL::nsFileURL(const nsFilePath& inOther) +//---------------------------------------------------------------------------------------- : mURL(nsnull) { - nsAutoCString aString(inString); - const char* aCString = (const char*)aString; - NS_ASSERTION(strstr(aCString, kFileURLPrefix) == aCString, "Not a URL!"); - mFileSpec = aCString + kFileURLPrefixLength; - // Make canonical and absolute. - char* path = MacFileHelpers::PathNameFromFSSpec( mFileSpec, TRUE ); - char* escapedPath = MacFileHelpers::EncodeMacPath(path, true, true); - mURL = nsFileSpecHelpers::StringDup(kFileURLPrefix, kFileURLPrefixLength + strlen(escapedPath)); - strcat(mURL, escapedPath); - delete [] escapedPath; + *this = inOther.GetFileSpec(); } // nsFileURL::nsFileURL +//---------------------------------------------------------------------------------------- +nsFileURL::nsFileURL(const nsFileSpec& inOther) +: mURL(nsnull) +//---------------------------------------------------------------------------------------- +{ + *this = inOther; +} // nsFileURL::nsFileURL + +//---------------------------------------------------------------------------------------- +void nsFileURL::operator = (const nsFilePath& inOther) +//---------------------------------------------------------------------------------------- +{ + *this = inOther.GetFileSpec(); +} // nsFileURL::operator = + +//---------------------------------------------------------------------------------------- +void nsFileURL::operator = (const nsFileSpec& inOther) +//---------------------------------------------------------------------------------------- +{ + mFileSpec = inOther; + delete [] mURL; + char* path = MacFileHelpers::PathNameFromFSSpec( mFileSpec, TRUE ); + mURL = MacFileHelpers::EncodeMacPath(path, true, true); +} // nsFileURL::operator = + +//---------------------------------------------------------------------------------------- +void nsFileURL::operator = (const char* inString) +//---------------------------------------------------------------------------------------- +{ + nsFileSpecHelpers::StringAssign(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. + if (mFileSpec.mError == NS_FILE_RESULT(fnfErr)) + mFileSpec.mError = NS_OK; +} // nsFileURL::operator = + //======================================================================================== // nsDirectoryIterator //======================================================================================== diff --git a/mozilla/base/src/nsFileSpec.cpp b/mozilla/base/src/nsFileSpec.cpp index 4de19724f5b..8a195923198 100644 --- a/mozilla/base/src/nsFileSpec.cpp +++ b/mozilla/base/src/nsFileSpec.cpp @@ -341,25 +341,23 @@ nsFileURL::nsFileURL(const nsFileURL& inOther) { } // nsFileURL::nsFileURL +#ifndef XP_MAC //---------------------------------------------------------------------------------------- nsFileURL::nsFileURL(const nsFilePath& inOther) //---------------------------------------------------------------------------------------- : mURL(nsFileSpecHelpers::AllocCat(kFileURLPrefix, (const char*)inOther)) -#ifdef XP_MAC -, mFileSpec(inOther.GetFileSpec()) -#endif { } // nsFileURL::nsFileURL +#endif +#ifndef XP_MAC //---------------------------------------------------------------------------------------- nsFileURL::nsFileURL(const nsFileSpec& inOther) : mURL(nsFileSpecHelpers::AllocCat(kFileURLPrefix, (const char*)nsFilePath(inOther))) -#ifdef XP_MAC -, mFileSpec(inOther) -#endif //---------------------------------------------------------------------------------------- { } // nsFileURL::nsFileURL +#endif //---------------------------------------------------------------------------------------- nsFileURL::~nsFileURL() @@ -368,16 +366,15 @@ nsFileURL::~nsFileURL() delete [] mURL; } +#ifndef XP_MAC //---------------------------------------------------------------------------------------- void nsFileURL::operator = (const char* inString) //---------------------------------------------------------------------------------------- { nsFileSpecHelpers::StringAssign(mURL, inString); NS_ASSERTION(strstr(inString, kFileURLPrefix) == inString, "Not a URL!"); -#ifdef XP_MAC - mFileSpec = inString + kFileURLPrefixLength; -#endif } // nsFileURL::operator = +#endif //---------------------------------------------------------------------------------------- void nsFileURL::operator = (const nsFileURL& inOther) @@ -389,28 +386,25 @@ void nsFileURL::operator = (const nsFileURL& inOther) #endif } // nsFileURL::operator = +#ifndef XP_MAC //---------------------------------------------------------------------------------------- void nsFileURL::operator = (const nsFilePath& inOther) //---------------------------------------------------------------------------------------- { delete [] mURL; mURL = nsFileSpecHelpers::AllocCat(kFileURLPrefix, (const char*)inOther); -#ifdef XP_MAC - mFileSpec = inOther.GetFileSpec(); -#endif } // nsFileURL::operator = +#endif +#ifndef XP_MAC //---------------------------------------------------------------------------------------- void nsFileURL::operator = (const nsFileSpec& inOther) //---------------------------------------------------------------------------------------- { delete [] mURL; mURL = nsFileSpecHelpers::AllocCat(kFileURLPrefix, (const char*)nsFilePath(inOther)); -#ifdef XP_MAC - mFileSpec = inOther; -#endif } // nsFileURL::operator = - +#endif //---------------------------------------------------------------------------------------- nsOutputStream& operator << (nsOutputStream& s, const nsFileURL& url) @@ -471,15 +465,14 @@ nsFilePath::nsFilePath(const nsString& inString, PRBool inCreateDirs) } #endif +#ifndef XP_MAC //---------------------------------------------------------------------------------------- nsFilePath::nsFilePath(const nsFileURL& inOther) //---------------------------------------------------------------------------------------- : mPath(nsFileSpecHelpers::StringDup(inOther.mURL + kFileURLPrefixLength)) -#ifdef XP_MAC -, mFileSpec(inOther.GetFileSpec()) -#endif { } +#endif #ifdef XP_UNIX //---------------------------------------------------------------------------------------- @@ -527,15 +520,14 @@ void nsFilePath::operator = (const char* inString) #endif // XP_MAC } +#ifndef XP_MAC //---------------------------------------------------------------------------------------- void nsFilePath::operator = (const nsFileURL& inOther) //---------------------------------------------------------------------------------------- { nsFileSpecHelpers::StringAssign(mPath, (const char*)nsFilePath(inOther)); -#ifdef XP_MAC - mFileSpec = inOther.GetFileSpec(); -#endif } +#endif //---------------------------------------------------------------------------------------- void nsFilePath::operator = (const nsFilePath& inOther) @@ -564,9 +556,7 @@ nsFileSpec::nsFileSpec() //---------------------------------------------------------------------------------------- nsFileSpec::nsFileSpec(const nsPersistentFileDescriptor& inDescriptor) //---------------------------------------------------------------------------------------- -#ifndef XP_MAC : mPath(nsnull) -#endif { *this = inDescriptor; } @@ -574,9 +564,7 @@ nsFileSpec::nsFileSpec(const nsPersistentFileDescriptor& inDescriptor) //---------------------------------------------------------------------------------------- nsFileSpec::nsFileSpec(const nsFileURL& inURL) //---------------------------------------------------------------------------------------- -#ifndef XP_MAC : mPath(nsnull) -#endif { *this = nsFilePath(inURL); // convert to unix path first } @@ -653,6 +641,7 @@ void nsFileSpec::operator = (const nsPersistentFileDescriptor& inDescriptor) Boolean changed; mError = NS_FILE_RESULT(::ResolveAlias(nsnull, aliasH, &mSpec, &changed)); DisposeHandle((Handle) aliasH); + delete [] mPath; #else nsFileSpecHelpers::StringAssign(mPath, (char*)data); mError = NS_OK; @@ -721,9 +710,7 @@ nsFileSpec::nsFileSpec(const nsString& inString, PRBool inCreateDirs) nsFileSpec::~nsFileSpec() //---------------------------------------------------------------------------------------- { -#ifndef XP_MAC delete [] mPath; -#endif } #if defined(XP_UNIX) || defined(XP_PC) @@ -754,7 +741,15 @@ void nsFileSpec::operator = (const char* inString) nsOutputStream& operator << (nsOutputStream& s, const nsFileSpec& spec) //---------------------------------------------------------------------------------------- { - return (s << (const char*)spec.mPath); +#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! @@ -773,15 +768,17 @@ PRBool nsFileSpec::operator == (const nsFileSpec& inOther) const { #ifdef XP_MAC - if ( inOther.mSpec.vRefNum == mSpec.vRefNum && + if ( inOther.mSpec.vRefNum == mSpec.vRefNum && inOther.mSpec.parID == mSpec.parID && - EqualString(inOther.mSpec.name, mSpec.name, false, false)) + EqualString(inOther.mSpec.name, mSpec.name, false, true)) return PR_TRUE; #else - if (!mPath) - return inOther.mPath == nsnull; - if (!inOther.mPath) - return PR_FALSE; + PRBool amEmpty = !mPath || !*mPath; + PRBool heEmpty = !inOther.mPath || !*inOther.mPath; + if (amEmpty) // we're the same if he's empty... + return heEmpty; + if (heEmpty) // ('cuz I'm not...) + return PR_FALSE; #if defined(XP_PC) // windows does not care about case. if (_stricmp(mPath, inOther.mPath ) == 0) @@ -801,6 +798,21 @@ PRBool nsFileSpec::operator != (const nsFileSpec& inOther) const return (! (*this == inOther) ); } +#ifndef XP_MAC +//---------------------------------------------------------------------------------------- +const char* nsFileSpec::GetCString() const +// This is the only automatic conversion to const char* +// that is provided, and it allows the +// path to be "passed" to NSPR file routines. This practice +// is VERY EVIL and should only be used to support legacy +// code. Using it guarantees bugs on Macintosh. The path is NOT allocated, so do +// not even think of deleting (or freeing) it. +//---------------------------------------------------------------------------------------- +{ + return mPath; +} +#endif + //======================================================================================== // class nsPersistentFileDescriptor //======================================================================================== @@ -835,13 +847,9 @@ void nsPersistentFileDescriptor::operator = (const nsFileSpec& inSpec) if (inSpec.Error()) return; AliasHandle aliasH; -/* - This is killing the tree. mcmullen will need to look at this. - - OSErr err = NewAlias(nil, inSpec.operator const FSSpec* const (), &aliasH); + OSErr err = NewAlias(nil, inSpec.GetFSSpecPtr(), &aliasH); if (err != noErr) return; -*/ PRUint32 bytes = GetHandleSize((Handle) aliasH); HLock((Handle) aliasH); @@ -851,7 +859,7 @@ void nsPersistentFileDescriptor::operator = (const nsFileSpec& inSpec) nsFileSpecHelpers::StringAssign(mDescriptorString, buf); PR_Free(buf); #else - nsFileSpecHelpers::StringAssign(mDescriptorString, inSpec); + nsFileSpecHelpers::StringAssign(mDescriptorString, inSpec.GetCString()); #endif // XP_MAC } // nsPersistentFileDescriptor::operator = @@ -914,7 +922,7 @@ nsInputStream& operator >> (nsInputStream& s, nsPersistentFileDescriptor& d) if (bytesRead != 8) return s; bigBuffer[8] = '\0'; - sscanf(bigBuffer, "%lx", &bytesRead); + sscanf(bigBuffer, "%lx", (PRUint32*)&bytesRead); if (bytesRead > MAX_PERSISTENT_DATA_SIZE) return s; // preposterous. // Now we know how many bytes to read, do it. diff --git a/mozilla/base/src/nsIFileStream.cpp b/mozilla/base/src/nsIFileStream.cpp index 05a0a4ff829..997f9d7d1d1 100644 --- a/mozilla/base/src/nsIFileStream.cpp +++ b/mozilla/base/src/nsIFileStream.cpp @@ -123,7 +123,7 @@ class FileImpl if (mFailed) return NS_ERROR_FAILURE; PRInt32 bytesWrit = PR_Write(mFileDesc, aBuf, aCount); - if (bytesWrit != aCount) + if (bytesWrit != (PRInt32)aCount) { mFailed = PR_TRUE; *aWriteCount = 0; diff --git a/mozilla/base/src/nsSpecialSystemDirectory.cpp b/mozilla/base/src/nsSpecialSystemDirectory.cpp index 797e264beb5..9edd50eeac3 100644 --- a/mozilla/base/src/nsSpecialSystemDirectory.cpp +++ b/mozilla/base/src/nsSpecialSystemDirectory.cpp @@ -355,16 +355,15 @@ void nsSpecialSystemDirectory::operator = (OSType folderType) break; } // switch } // for - mSpec.name[0] = '\0'; - dipb->ioNamePtr = (StringPtr)&mSpec.name; + StrFileName filename; + filename[0] = '\0'; + dipb->ioNamePtr = (StringPtr)&filename; dipb->ioFDirIndex = -1; - mError = PBGetCatInfoSync(&cinfo); - + mError = NS_FILE_RESULT(PBGetCatInfoSync(&cinfo)); if (NS_SUCCEEDED(mError)) { - mSpec.vRefNum = dipb->ioVRefNum; - mSpec.parID = dipb->ioDrParID; + mError = NS_FILE_RESULT(FSMakeFSSpec(dipb->ioVRefNum, dipb->ioDrParID, filename, &mSpec)); } } #endif // XP_MAC diff --git a/mozilla/base/src/unix/nsFileSpecUnix.cpp b/mozilla/base/src/unix/nsFileSpecUnix.cpp index b3f368305a7..5af2eb10a30 100644 --- a/mozilla/base/src/unix/nsFileSpecUnix.cpp +++ b/mozilla/base/src/unix/nsFileSpecUnix.cpp @@ -25,9 +25,42 @@ #include #include #include +#include #include "nsError.h" -//---------------------------------------------------------------------------------------- +#if defined(IRIX) || defined(OSF1) || defined(SOLARIS) || defined(UNIXWARE) || defined(SNI) || defined(NCR) || defined(NEC) || defined(DGUX) +#include /* for statvfs() */ +#define STATFS statvfs +#elif defined(SCO_SV) +#define _SVID3/* for statvfs.h */ +#include /* for statvfs() */ +#define STATFS statvfs +#elif defined(HPUX) +#include /* for statfs() */ +#define STATFS statfs +#elif defined(LINUX) +#include /* for statfs() */ +#define STATFS statfs +#elif defined(SUNOS4) +#include /* for statfs() */ +extern "C" int statfs(char *, struct statfs *); +#define STATFS statfs +#else +#if defined(BSDI) || defined(NETBSD) || defined(OPENBSD) || defined(RHAPSODY) || defined(FREEBSD) +#include /* for statfs() */ +#define STATFS statfs +#else +#include /* for statfs() */ +#define STATFS statfs +extern "C" int statfs(char *, struct statfs *); +#endif +#endif + +#if defined(OSF1) +extern "C" int statvfs(const char *, struct statvfs *); +#endif + + //---------------------------------------------------------------------------------------- void nsFileSpecHelpers::Canonify(char*& ioPath, PRBool inMakeDirs) // Canonify, make absolute, and check whether directories exist //---------------------------------------------------------------------------------------- @@ -271,12 +304,14 @@ nsresult nsFileSpec::Copy(const nsFileSpec& inParentDirectory) const if (inParentDirectory.IsDirectory() && (! IsDirectory() ) ) { char *leafname = GetLeafName(); - char* destPath = nsFileSpecHelpers::StringDup(inParentDirectory, ( strlen(inParentDirectory) + 1 + strlen(leafname) ) ); + char* destPath = nsFileSpecHelpers::StringDup( + inParentDirectory.GetCString(), + strlen(inParentDirectory.GetCString()) + 1 + strlen(leafname)); strcat(destPath, "/"); strcat(destPath, leafname); delete [] leafname; - result = NS_FILE_RESULT(CrudeFileCopy(*this, destPath)); + result = NS_FILE_RESULT(CrudeFileCopy(GetCString(), destPath)); delete [] destPath; } @@ -295,13 +330,13 @@ nsresult nsFileSpec::Move(const nsFileSpec& inNewParentDirectory) const char *leafname = GetLeafName(); char* destPath = nsFileSpecHelpers::StringDup( - inNewParentDirectory, - strlen(inNewParentDirectory) + 1 + strlen(leafname)); + inNewParentDirectory.GetCString(), + strlen(inNewParentDirectory.GetCString()) + 1 + strlen(leafname)); strcat(destPath, "/"); strcat(destPath, leafname); delete [] leafname; - result = NS_FILE_RESULT(CrudeFileCopy(*this, destPath)); + result = NS_FILE_RESULT(CrudeFileCopy(GetCString(), destPath)); if (result == NS_OK) { // cast to fix const-ness @@ -333,6 +368,31 @@ nsresult nsFileSpec::Execute(const char* inArgs ) const } // nsFileSpec::Execute +//---------------------------------------------------------------------------------------- +PRUint32 nsFileSpec::GetDiskSpaceAvailable() const +//---------------------------------------------------------------------------------------- +{ + char curdir [MAXPATHLEN]; + if (!mPath || !*mPath) + { + (void) getcwd(curdir, MAXPATHLEN); + if (!curdir) + return ULONG_MAX; /* hope for the best as we did in cheddar */ + } + else + sprintf(curdir, "%.200s", mPath); + + struct STATFS fs_buf; + if (STATFS(curdir, &fs_buf) < 0) + return ULONG_MAX; /* hope for the best as we did in cheddar */ + +#ifdef DEBUG_DISK_SPACE + printf("DiskSpaceAvailable: %d bytes\n", + fs_buf.f_bsize * (fs_buf.f_bavail - 1)); +#endif + return fs_buf.f_bsize * (fs_buf.f_bavail - 1); +} // nsFileSpec::GetDiskSpace() + //======================================================================================== // nsDirectoryIterator //======================================================================================== diff --git a/mozilla/base/src/windows/nsFileSpecWin.cpp b/mozilla/base/src/windows/nsFileSpecWin.cpp index 1afee4ec6c9..d30521e0b10 100644 --- a/mozilla/base/src/windows/nsFileSpecWin.cpp +++ b/mozilla/base/src/windows/nsFileSpecWin.cpp @@ -248,7 +248,12 @@ void nsFileSpec::operator += (const char* inRelativePath) nsFileSpecHelpers::ReallocCat(mPath, "x"); else nsFileSpecHelpers::ReallocCat(mPath, "\\x"); - SetLeafName(inRelativePath); + + // If it's a (unix) relative path, make it native + char* dosPath = nsFileSpecHelpers::StringDup(inRelativePath); + nsFileSpecHelpers::UnixToNative(dosPath); + SetLeafName(dosPath); + delete [] dosPath; } // nsFileSpec::operator += //---------------------------------------------------------------------------------------- @@ -380,6 +385,49 @@ nsresult nsFileSpec::Execute(const char* inArgs ) const return NS_FILE_FAILURE; } // nsFileSpec::Execute +//---------------------------------------------------------------------------------------- +PRUint32 nsFileSpec::GetDiskSpaceAvailable() const +//---------------------------------------------------------------------------------------- +{ + char aDrive[_MAX_DRIVE + 2]; + _splitpath( mPath, aDrive, NULL, NULL, NULL); + + if (aDrive[0] == '\0') + { + // The back end is always trying to pass us paths that look + // like /c|/netscape/mail. See if we've got one of them + if (strlen(mPath) > 2 && mPath[0] == '/' && mPath[2] == '|') + { + aDrive[0] = mPath[1]; + aDrive[1] = ':'; + aDrive[2] = '\0'; + } + else + { + // Return bogus large number and hope for the best + return ULONG_MAX; + } + } + + strcat(aDrive, "\\"); + + PRUint32 dwSectorsPerCluster = 0; + PRUint32 dwBytesPerSector = 0; + PRUint32 dwFreeClusters = 0; + PRUint32 dwTotalClusters = 0; + if (!GetDiskFreeSpace(aDrive, + &dwSectorsPerCluster, + &dwBytesPerSector, + &dwFreeClusters, + &dwTotalClusters)) + { + return ULONG_MAX; // Return bogus large number and hope for the best + } + + // We can now figure free disk space. + return dwFreeClusters * dwSectorsPerCluster * dwBytesPerSector; +} // nsFileSpec::GetDiskSpaceAvailable() + //======================================================================================== // nsDirectoryIterator //======================================================================================== diff --git a/mozilla/base/tests/FilesTest.cpp b/mozilla/base/tests/FilesTest.cpp index e66942089f0..4bcdaaef8d4 100644 --- a/mozilla/base/tests/FilesTest.cpp +++ b/mozilla/base/tests/FilesTest.cpp @@ -744,6 +744,19 @@ int FilesTest::SpecialSystemDirectories() return Failed(); } + systemDir = nsSpecialSystemDirectory::Mac_DocumentsDirectory; + mConsole << "Mac_DocumentsDirectory yields \t"; + + if (systemDir.Valid()) + { + mConsole << systemDir << nsEndl; + } + else + { + mConsole << "nsnull" << nsEndl; + return Failed(); + } + #elif XP_PC systemDir = nsSpecialSystemDirectory::Win_SystemDirectory; mConsole << "Win_SystemDirectory yields \t"; @@ -865,7 +878,7 @@ int FilesTest::RunAllTests() if (IterateDirectoryChildren(parent) != 0) return -1; - Banner("Equals operator of nsFileSpec"); + Banner("nsFileSpec equality"); if (FileSpecEquality("mumble/a", "mumble/b") != 0) return -1; diff --git a/mozilla/xpcom/io/nsFileSpec.cpp b/mozilla/xpcom/io/nsFileSpec.cpp index 4de19724f5b..8a195923198 100644 --- a/mozilla/xpcom/io/nsFileSpec.cpp +++ b/mozilla/xpcom/io/nsFileSpec.cpp @@ -341,25 +341,23 @@ nsFileURL::nsFileURL(const nsFileURL& inOther) { } // nsFileURL::nsFileURL +#ifndef XP_MAC //---------------------------------------------------------------------------------------- nsFileURL::nsFileURL(const nsFilePath& inOther) //---------------------------------------------------------------------------------------- : mURL(nsFileSpecHelpers::AllocCat(kFileURLPrefix, (const char*)inOther)) -#ifdef XP_MAC -, mFileSpec(inOther.GetFileSpec()) -#endif { } // nsFileURL::nsFileURL +#endif +#ifndef XP_MAC //---------------------------------------------------------------------------------------- nsFileURL::nsFileURL(const nsFileSpec& inOther) : mURL(nsFileSpecHelpers::AllocCat(kFileURLPrefix, (const char*)nsFilePath(inOther))) -#ifdef XP_MAC -, mFileSpec(inOther) -#endif //---------------------------------------------------------------------------------------- { } // nsFileURL::nsFileURL +#endif //---------------------------------------------------------------------------------------- nsFileURL::~nsFileURL() @@ -368,16 +366,15 @@ nsFileURL::~nsFileURL() delete [] mURL; } +#ifndef XP_MAC //---------------------------------------------------------------------------------------- void nsFileURL::operator = (const char* inString) //---------------------------------------------------------------------------------------- { nsFileSpecHelpers::StringAssign(mURL, inString); NS_ASSERTION(strstr(inString, kFileURLPrefix) == inString, "Not a URL!"); -#ifdef XP_MAC - mFileSpec = inString + kFileURLPrefixLength; -#endif } // nsFileURL::operator = +#endif //---------------------------------------------------------------------------------------- void nsFileURL::operator = (const nsFileURL& inOther) @@ -389,28 +386,25 @@ void nsFileURL::operator = (const nsFileURL& inOther) #endif } // nsFileURL::operator = +#ifndef XP_MAC //---------------------------------------------------------------------------------------- void nsFileURL::operator = (const nsFilePath& inOther) //---------------------------------------------------------------------------------------- { delete [] mURL; mURL = nsFileSpecHelpers::AllocCat(kFileURLPrefix, (const char*)inOther); -#ifdef XP_MAC - mFileSpec = inOther.GetFileSpec(); -#endif } // nsFileURL::operator = +#endif +#ifndef XP_MAC //---------------------------------------------------------------------------------------- void nsFileURL::operator = (const nsFileSpec& inOther) //---------------------------------------------------------------------------------------- { delete [] mURL; mURL = nsFileSpecHelpers::AllocCat(kFileURLPrefix, (const char*)nsFilePath(inOther)); -#ifdef XP_MAC - mFileSpec = inOther; -#endif } // nsFileURL::operator = - +#endif //---------------------------------------------------------------------------------------- nsOutputStream& operator << (nsOutputStream& s, const nsFileURL& url) @@ -471,15 +465,14 @@ nsFilePath::nsFilePath(const nsString& inString, PRBool inCreateDirs) } #endif +#ifndef XP_MAC //---------------------------------------------------------------------------------------- nsFilePath::nsFilePath(const nsFileURL& inOther) //---------------------------------------------------------------------------------------- : mPath(nsFileSpecHelpers::StringDup(inOther.mURL + kFileURLPrefixLength)) -#ifdef XP_MAC -, mFileSpec(inOther.GetFileSpec()) -#endif { } +#endif #ifdef XP_UNIX //---------------------------------------------------------------------------------------- @@ -527,15 +520,14 @@ void nsFilePath::operator = (const char* inString) #endif // XP_MAC } +#ifndef XP_MAC //---------------------------------------------------------------------------------------- void nsFilePath::operator = (const nsFileURL& inOther) //---------------------------------------------------------------------------------------- { nsFileSpecHelpers::StringAssign(mPath, (const char*)nsFilePath(inOther)); -#ifdef XP_MAC - mFileSpec = inOther.GetFileSpec(); -#endif } +#endif //---------------------------------------------------------------------------------------- void nsFilePath::operator = (const nsFilePath& inOther) @@ -564,9 +556,7 @@ nsFileSpec::nsFileSpec() //---------------------------------------------------------------------------------------- nsFileSpec::nsFileSpec(const nsPersistentFileDescriptor& inDescriptor) //---------------------------------------------------------------------------------------- -#ifndef XP_MAC : mPath(nsnull) -#endif { *this = inDescriptor; } @@ -574,9 +564,7 @@ nsFileSpec::nsFileSpec(const nsPersistentFileDescriptor& inDescriptor) //---------------------------------------------------------------------------------------- nsFileSpec::nsFileSpec(const nsFileURL& inURL) //---------------------------------------------------------------------------------------- -#ifndef XP_MAC : mPath(nsnull) -#endif { *this = nsFilePath(inURL); // convert to unix path first } @@ -653,6 +641,7 @@ void nsFileSpec::operator = (const nsPersistentFileDescriptor& inDescriptor) Boolean changed; mError = NS_FILE_RESULT(::ResolveAlias(nsnull, aliasH, &mSpec, &changed)); DisposeHandle((Handle) aliasH); + delete [] mPath; #else nsFileSpecHelpers::StringAssign(mPath, (char*)data); mError = NS_OK; @@ -721,9 +710,7 @@ nsFileSpec::nsFileSpec(const nsString& inString, PRBool inCreateDirs) nsFileSpec::~nsFileSpec() //---------------------------------------------------------------------------------------- { -#ifndef XP_MAC delete [] mPath; -#endif } #if defined(XP_UNIX) || defined(XP_PC) @@ -754,7 +741,15 @@ void nsFileSpec::operator = (const char* inString) nsOutputStream& operator << (nsOutputStream& s, const nsFileSpec& spec) //---------------------------------------------------------------------------------------- { - return (s << (const char*)spec.mPath); +#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! @@ -773,15 +768,17 @@ PRBool nsFileSpec::operator == (const nsFileSpec& inOther) const { #ifdef XP_MAC - if ( inOther.mSpec.vRefNum == mSpec.vRefNum && + if ( inOther.mSpec.vRefNum == mSpec.vRefNum && inOther.mSpec.parID == mSpec.parID && - EqualString(inOther.mSpec.name, mSpec.name, false, false)) + EqualString(inOther.mSpec.name, mSpec.name, false, true)) return PR_TRUE; #else - if (!mPath) - return inOther.mPath == nsnull; - if (!inOther.mPath) - return PR_FALSE; + PRBool amEmpty = !mPath || !*mPath; + PRBool heEmpty = !inOther.mPath || !*inOther.mPath; + if (amEmpty) // we're the same if he's empty... + return heEmpty; + if (heEmpty) // ('cuz I'm not...) + return PR_FALSE; #if defined(XP_PC) // windows does not care about case. if (_stricmp(mPath, inOther.mPath ) == 0) @@ -801,6 +798,21 @@ PRBool nsFileSpec::operator != (const nsFileSpec& inOther) const return (! (*this == inOther) ); } +#ifndef XP_MAC +//---------------------------------------------------------------------------------------- +const char* nsFileSpec::GetCString() const +// This is the only automatic conversion to const char* +// that is provided, and it allows the +// path to be "passed" to NSPR file routines. This practice +// is VERY EVIL and should only be used to support legacy +// code. Using it guarantees bugs on Macintosh. The path is NOT allocated, so do +// not even think of deleting (or freeing) it. +//---------------------------------------------------------------------------------------- +{ + return mPath; +} +#endif + //======================================================================================== // class nsPersistentFileDescriptor //======================================================================================== @@ -835,13 +847,9 @@ void nsPersistentFileDescriptor::operator = (const nsFileSpec& inSpec) if (inSpec.Error()) return; AliasHandle aliasH; -/* - This is killing the tree. mcmullen will need to look at this. - - OSErr err = NewAlias(nil, inSpec.operator const FSSpec* const (), &aliasH); + OSErr err = NewAlias(nil, inSpec.GetFSSpecPtr(), &aliasH); if (err != noErr) return; -*/ PRUint32 bytes = GetHandleSize((Handle) aliasH); HLock((Handle) aliasH); @@ -851,7 +859,7 @@ void nsPersistentFileDescriptor::operator = (const nsFileSpec& inSpec) nsFileSpecHelpers::StringAssign(mDescriptorString, buf); PR_Free(buf); #else - nsFileSpecHelpers::StringAssign(mDescriptorString, inSpec); + nsFileSpecHelpers::StringAssign(mDescriptorString, inSpec.GetCString()); #endif // XP_MAC } // nsPersistentFileDescriptor::operator = @@ -914,7 +922,7 @@ nsInputStream& operator >> (nsInputStream& s, nsPersistentFileDescriptor& d) if (bytesRead != 8) return s; bigBuffer[8] = '\0'; - sscanf(bigBuffer, "%lx", &bytesRead); + sscanf(bigBuffer, "%lx", (PRUint32*)&bytesRead); if (bytesRead > MAX_PERSISTENT_DATA_SIZE) return s; // preposterous. // Now we know how many bytes to read, do it. diff --git a/mozilla/xpcom/io/nsFileSpec.h b/mozilla/xpcom/io/nsFileSpec.h index d847f754e04..5d5eacf820d 100644 --- a/mozilla/xpcom/io/nsFileSpec.h +++ b/mozilla/xpcom/io/nsFileSpec.h @@ -236,12 +236,16 @@ class NS_BASE nsFileSpec PRBool operator ==(const nsFileSpec& inOther) const; PRBool operator !=(const nsFileSpec& inOther) const; -#ifndef XP_MAC - operator const char* () const { return mPath; } - // This is the only automatic conversion to const char* + operator const char* () const { return GetCString(); } + // Same as GetCString (please read the comments). + const char* GetCString() const; + // This is the only conversion to const char* // that is provided, and it allows the - // path to be "passed" to NSPR file routines. -#endif + // 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. #ifdef XP_MAC // For Macintosh people, this is meant to be useful in its own right as a C++ version @@ -259,6 +263,11 @@ class NS_BASE nsFileSpec operator const FSSpec* const () { return &mSpec; } operator FSSpec& () { return mSpec; } operator const FSSpec& () const { return mSpec; } + + const FSSpec& GetFSSpec() const { return mSpec; } + FSSpec& GetFSSpec() { return mSpec; } + ConstFSSpecPtr GetFSSpecPtr() const { return &mSpec; } + FSSpecPtr GetFSSpecPtr() { return &mSpec; } void MakeAliasSafe(); // Called for the spec of an alias. Copies the alias to // a secret temp directory and modifies the spec to point @@ -329,6 +338,7 @@ class NS_BASE nsFileSpec } PRUint32 GetFileSize() const; + PRUint32 GetDiskSpaceAvailable() const; nsFileSpec operator + (const char* inRelativePath) const; nsFileSpec operator + (const nsString& inRelativePath) const @@ -398,12 +408,12 @@ class NS_BASE nsFileSpec protected: friend class nsFilePath; + friend class nsFileURL; friend class nsDirectoryIterator; #ifdef XP_MAC FSSpec mSpec; -#else - char* mPath; #endif + char* mPath; nsresult mError; }; // class nsFileSpec @@ -440,7 +450,7 @@ class NS_BASE nsFileURL void operator = (const nsFilePath& inOther); void operator = (const nsFileSpec& inOther); - operator const char* const () { return mURL; } // deprecated. + operator const char* () const { return mURL; } // deprecated. const char* GetAsString() const { return mURL; } friend NS_BASE nsOutputStream& operator << ( @@ -465,8 +475,9 @@ class NS_BASE nsFileURL //======================================================================================== class NS_BASE nsFilePath -// This is a string that looks like "/foo/bar/mumble%20fish". Same as nsFileURL, but -// without the "file:// prefix". +// This is a string that looks like "/foo/bar/mumble fish". Same as nsFileURL, but +// without the "file:// prefix", and NOT %20 ENCODED! Strings passed in must be +// valid unix-style paths in this format. //======================================================================================== { public: diff --git a/mozilla/xpcom/io/nsFileSpecMac.cpp b/mozilla/xpcom/io/nsFileSpecMac.cpp index 62c5de86007..68dc06c24a9 100644 --- a/mozilla/xpcom/io/nsFileSpecMac.cpp +++ b/mozilla/xpcom/io/nsFileSpecMac.cpp @@ -45,20 +45,23 @@ namespace MacFileHelpers void PLstrncpy(Str255 dst, const char* src, int inMaxLen); void SwapSlashColon(char * s); - OSErr FSSpecFromFullUnixPath( + OSErr FSSpecFromUnixPath( const char * unixPath, - FSSpec& outSpec, + FSSpec& ioSpec, + Boolean hexDecode, Boolean resolveAlias, Boolean allowPartial = false, Boolean createDirs = false); - char* MacPathFromUnixPath(const char* unixPath); + 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& outSpec, + FSSpec& ioSpec, Boolean inCreateDirs); char* PathNameFromFSSpec( const FSSpec& inSpec, @@ -212,7 +215,7 @@ OSErr MacFileHelpers::MakeAliasSafe(FSSpec& inOutSpec) } // MacFileHelpers::MakeAliasSafe //---------------------------------------------------------------------------------------- -char* MacFileHelpers::MacPathFromUnixPath(const char* unixPath) +char* MacFileHelpers::MacPathFromUnixPath(const char* unixPath, Boolean hexDecode) //---------------------------------------------------------------------------------------- { // Relying on the fact that the unix path is always longer than the mac path: @@ -227,7 +230,8 @@ char* MacFileHelpers::MacPathFromUnixPath(const char* unixPath) else if (strchr(src, '/')) // * partial path, and not just a leaf name *dst++ = ':'; strcpy(dst, src); - nsUnescape(dst); // Hex Decode + if (hexDecode) + nsUnescape(dst); // Hex Decode MacFileHelpers::SwapSlashColon(dst); } return result; @@ -236,7 +240,7 @@ char* MacFileHelpers::MacPathFromUnixPath(const char* unixPath) //---------------------------------------------------------------------------------------- OSErr MacFileHelpers::FSSpecFromPathname( const char* inPathNamePtr, - FSSpec& outSpec, + 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. @@ -247,20 +251,26 @@ OSErr MacFileHelpers::FSSpecFromPathname( // 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); - err = ::FSMakeFSSpec(0, 0, ppath, &outSpec); + if (isRelative) + err = ::FSMakeFSSpec(ioSpec.vRefNum, ioSpec.parID, ppath, &ioSpec); + else + err = ::FSMakeFSSpec(0, 0, ppath, &ioSpec); } - else - err = FSpLocationFromFullPath(inLength, inPathNamePtr, &outSpec); + else if (!isRelative) + err = FSpLocationFromFullPath(inLength, inPathNamePtr, &ioSpec); + else + err = bdNamErr; - if (err == dirNFErr && inCreateDirs) + if ((err == dirNFErr || err == bdNamErr) && inCreateDirs) { const char* path = inPathNamePtr; - outSpec.vRefNum = 0; - outSpec.parID = 0; + 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. @@ -276,7 +286,7 @@ OSErr MacFileHelpers::FSSpecFromPathname( // 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(outSpec.vRefNum, outSpec.parID, ppath, &outSpec); + err = ::FSMakeFSSpec(ioSpec.vRefNum, ioSpec.parID, ppath, &ioSpec); // If this was the leaf node, then we are done. if (!*nextColon) @@ -285,7 +295,7 @@ OSErr MacFileHelpers::FSSpecFromPathname( // If we got "file not found", then // we need to create a directory. if (err == fnfErr && *nextColon) - err = FSpDirCreate(&outSpec, smCurrentScript, &outSpec.parID); + err = FSpDirCreate(&ioSpec, smCurrentScript, &ioSpec.parID); // For some reason, this usually returns fnfErr, even though it works. if (err != noErr && err != fnfErr) return err; @@ -368,9 +378,10 @@ OSErr MacFileHelpers::ResolveAliasFile(FSSpec& inOutSpec, Boolean& wasAliased) } // MacFileHelpers::ResolveAliasFile //----------------------------------- -OSErr MacFileHelpers::FSSpecFromFullUnixPath( +OSErr MacFileHelpers::FSSpecFromUnixPath( const char * unixPath, - FSSpec& outSpec, + FSSpec& ioSpec, + Boolean hexDecode, Boolean resolveAlias, Boolean allowPartial, Boolean createDirs) @@ -382,7 +393,7 @@ OSErr MacFileHelpers::FSSpecFromFullUnixPath( { if (unixPath == nsnull) return badFidErr; - char* macPath = MacPathFromUnixPath(unixPath); + char* macPath = MacPathFromUnixPath(unixPath, hexDecode); if (!macPath) return memFullErr; @@ -391,12 +402,12 @@ OSErr MacFileHelpers::FSSpecFromFullUnixPath( { NS_ASSERTION(*unixPath == '/' /*full path*/, "Not a full Unix path!"); } - err = FSSpecFromPathname(macPath, outSpec, createDirs); + err = FSSpecFromPathname(macPath, ioSpec, createDirs); if (err == fnfErr) err = noErr; Boolean dummy; if (err == noErr && resolveAlias) // Added - err = MacFileHelpers::ResolveAliasFile(outSpec, dummy); + err = MacFileHelpers::ResolveAliasFile(ioSpec, dummy); delete [] macPath; NS_ASSERTION(err==noErr||err==fnfErr||err==dirNFErr||err==nsvErr, "Not a path!"); return err; @@ -508,6 +519,7 @@ Clean: nsFileSpec::nsFileSpec() //---------------------------------------------------------------------------------------- : mError(NS_OK) +, mPath(nsnull) { mSpec.name[0] = '\0'; } @@ -516,6 +528,7 @@ nsFileSpec::nsFileSpec() nsFileSpec::nsFileSpec(const nsFileSpec& inSpec) //---------------------------------------------------------------------------------------- : mSpec(inSpec.mSpec) +, mPath(nsnull) , mError(inSpec.Error()) { } @@ -523,10 +536,15 @@ nsFileSpec::nsFileSpec(const nsFileSpec& inSpec) //---------------------------------------------------------------------------------------- nsFileSpec::nsFileSpec(const char* inString, PRBool inCreateDirs) //---------------------------------------------------------------------------------------- +: mPath(nsnull) { - mError = NS_FILE_RESULT(MacFileHelpers::FSSpecFromFullUnixPath( - inString, mSpec, false, true, inCreateDirs)); - // allow a partial path, create as necessary + 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; } // nsFileSpec::nsFileSpec @@ -534,55 +552,57 @@ nsFileSpec::nsFileSpec(const char* inString, PRBool inCreateDirs) //---------------------------------------------------------------------------------------- nsFileSpec::nsFileSpec(const nsString& inString, PRBool inCreateDirs) //---------------------------------------------------------------------------------------- +: mPath(nsnull) { - mError = NS_FILE_RESULT(MacFileHelpers::FSSpecFromFullUnixPath( - nsAutoCString(inString), mSpec, false, true, inCreateDirs)); - // allow a partial path, create as necessary + 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; } // nsFileSpec::nsFileSpec //---------------------------------------------------------------------------------------- -nsFileSpec::nsFileSpec( - short vRefNum, - long parID, - ConstStr255Param name) +nsFileSpec::nsFileSpec(short vRefNum, long parID, ConstStr255Param name) //---------------------------------------------------------------------------------------- +: mPath(nsnull) { mError = NS_FILE_RESULT(::FSMakeFSSpec(vRefNum, parID, name, &mSpec)); if (mError == NS_FILE_RESULT(fnfErr)) - mError = noErr; + mError = NS_OK; } //---------------------------------------------------------------------------------------- nsFileSpec::nsFileSpec(const nsFilePath& inPath) //---------------------------------------------------------------------------------------- +: mPath(nsnull) { *this = inPath.GetFileSpec(); } -#if DEBUG -//---------------------------------------------------------------------------------------- -nsOutputStream& operator << (nsOutputStream& s, const nsFileSpec& spec) -//---------------------------------------------------------------------------------------- -{ - s << spec.mSpec.vRefNum << ", " << spec.mSpec.parID << ", \""; - s.write((const char*)&spec.mSpec.name[1], spec.mSpec.name[0]); - return s << "\""; -} // nsOutputStream& operator << (nsOutputStream&, const nsFileSpec&) -#endif - //---------------------------------------------------------------------------------------- void nsFileSpec::operator = (const char* inString) //---------------------------------------------------------------------------------------- { - mError = NS_FILE_RESULT(MacFileHelpers::FSSpecFromFullUnixPath(inString, mSpec, false)); + nsFileSpecHelpers::StringAssign(mPath, nsnull); + + 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; } // nsFileSpec::operator = //---------------------------------------------------------------------------------------- void nsFileSpec::operator = (const nsFileSpec& inSpec) //---------------------------------------------------------------------------------------- { + nsFileSpecHelpers::StringAssign(mPath, nsnull); mSpec = inSpec.mSpec; mError = inSpec.Error(); } // nsFileSpec::operator = @@ -594,13 +614,28 @@ void nsFileSpec::operator = (const nsFilePath& inPath) *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; -} // nsFileSpec::operator = +} // nsFileSpec::Exists() //---------------------------------------------------------------------------------------- void nsFileSpec::GetModDate(TimeStamp& outStamp) const @@ -628,11 +663,15 @@ void nsFileSpec::SetLeafName(const char* inLeafName) // In leaf name can actually be a partial path... //---------------------------------------------------------------------------------------- { - // what about long relative paths? Hmm? + nsFileSpecHelpers::StringAssign(mPath, nsnull); + + // 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 //---------------------------------------------------------------------------------------- @@ -650,6 +689,7 @@ char* nsFileSpec::GetLeafName() const void nsFileSpec::MakeAliasSafe() //---------------------------------------------------------------------------------------- { + nsFileSpecHelpers::StringAssign(mPath, nsnull); mError = NS_FILE_RESULT(MacFileHelpers::MakeAliasSafe(mSpec)); } // nsFileSpec::MakeAliasSafe @@ -657,6 +697,7 @@ void nsFileSpec::MakeAliasSafe() void nsFileSpec::MakeUnique(ConstStr255Param inSuggestedLeafName) //---------------------------------------------------------------------------------------- { + nsFileSpecHelpers::StringAssign(mPath, nsnull); if (inSuggestedLeafName[0] > 0) MacFileHelpers::PLstrcpy(mSpec.name, inSuggestedLeafName); @@ -708,11 +749,14 @@ void nsFileSpec::operator += (const char* inRelativePath) mError = NS_FILE_RESULT(::FSpGetDirectoryID(&mSpec, &dirID, &isDirectory)); if (NS_SUCCEEDED(mError) && isDirectory) { - Str255 partialPath; - MacFileHelpers::PLstrcpy(partialPath, inRelativePath); - mError = NS_FILE_RESULT(::FSMakeFSSpec(mSpec.vRefNum, dirID, partialPath, *this)); - //if (NS_SUCCEEDED(mError)) - // SetLeafName(inRelativePath); + mSpec.parID = dirID; + // mSpec.vRefNum is already correct. + // 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; } } // nsFileSpec::operator += @@ -721,7 +765,7 @@ void nsFileSpec::CreateDirectory(int /* unix mode */) //---------------------------------------------------------------------------------------- { long ignoredDirID; - FSpDirCreate(&mSpec, smCurrentScript, &ignoredDirID); + mError = NS_FILE_RESULT(FSpDirCreate(&mSpec, smCurrentScript, &ignoredDirID)); } // nsFileSpec::CreateDirectory //---------------------------------------------------------------------------------------- @@ -827,6 +871,41 @@ OSErr nsFileSpec::GetCatInfo(CInfoPBRec& outInfo) const 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; +} // nsFileSpec::GetDiskSpace() + +//---------------------------------------------------------------------------------------- +const char* nsFileSpec::GetCString() const +// This is the only conversion to const char* that is provided, and it allows the +// path to be "passed" to NSPR file routines. This practice is VERY EVIL and should only +// be used to support legacy code. Using it guarantees bugs on Macintosh. The string is +// cached and freed by the nsFileSpec destructor, so do not delete (or free) it. +//---------------------------------------------------------------------------------------- +{ + if (!mPath) + { + const_cast(this)->mPath + = MacFileHelpers::PathNameFromFSSpec(mSpec, true); + if (!mPath) + const_cast(this)->mError = NS_ERROR_OUT_OF_MEMORY; + } + return mPath; +} + //======================================================================================== // Macintosh nsFilePath implementation //======================================================================================== @@ -839,7 +918,7 @@ nsFilePath::nsFilePath(const char* inString, PRBool inCreateDirs) { // Make canonical and absolute. char * path = MacFileHelpers::PathNameFromFSSpec( mFileSpec, TRUE ); - mPath = MacFileHelpers::EncodeMacPath(path, true, true); + mPath = MacFileHelpers::EncodeMacPath(path, true, false); } //---------------------------------------------------------------------------------------- @@ -850,28 +929,42 @@ nsFilePath::nsFilePath(const nsString& inString, PRBool inCreateDirs) { // Make canonical and absolute. char * path = MacFileHelpers::PathNameFromFSSpec( mFileSpec, TRUE ); - mPath = MacFileHelpers::EncodeMacPath(path, true, true); + mPath = MacFileHelpers::EncodeMacPath(path, true, false); } //---------------------------------------------------------------------------------------- nsFilePath::nsFilePath(const nsFileSpec& inSpec) //---------------------------------------------------------------------------------------- -: mFileSpec(inSpec) +: mPath(nsnull) { - char * path = MacFileHelpers::PathNameFromFSSpec( inSpec.mSpec, TRUE ); - mPath = MacFileHelpers::EncodeMacPath(path, true, true); + *this = inSpec; +} + +//---------------------------------------------------------------------------------------- +nsFilePath::nsFilePath(const nsFileURL& inOther) +//---------------------------------------------------------------------------------------- +: mPath(nsnull) +{ + *this = inOther.GetFileSpec(); } //---------------------------------------------------------------------------------------- void nsFilePath::operator = (const nsFileSpec& inSpec) //---------------------------------------------------------------------------------------- { - delete [] mPath; char * path = MacFileHelpers::PathNameFromFSSpec( inSpec.mSpec, TRUE ); - mPath = MacFileHelpers::EncodeMacPath(path, true, true); + delete [] mPath; + mPath = MacFileHelpers::EncodeMacPath(path, true, false); mFileSpec = inSpec; } // nsFilePath::operator = +//---------------------------------------------------------------------------------------- +void nsFilePath::operator = (const nsFileURL& inOther) +//---------------------------------------------------------------------------------------- +{ + *this = inOther.GetFileSpec(); +} + //======================================================================================== // nsFileURL implementation //======================================================================================== @@ -879,35 +972,87 @@ void nsFilePath::operator = (const nsFileSpec& inSpec) //---------------------------------------------------------------------------------------- nsFileURL::nsFileURL(const char* inString, PRBool inCreateDirs) //---------------------------------------------------------------------------------------- -: mURL(nsnull) -, mFileSpec(inString + kFileURLPrefixLength, inCreateDirs) -{ - NS_ASSERTION(strstr(inString, kFileURLPrefix) == inString, "Not a URL!"); - // Make canonical and absolute. - char* path = MacFileHelpers::PathNameFromFSSpec( mFileSpec, TRUE ); - char* escapedPath = MacFileHelpers::EncodeMacPath(path, true, true); - mURL = nsFileSpecHelpers::StringDup(kFileURLPrefix, kFileURLPrefixLength + strlen(escapedPath)); - strcat(mURL, escapedPath); - delete [] escapedPath; +: mURL(nsFileSpecHelpers::StringDup(inString)) +{ + NS_ASSERTION(strstr(mURL, kFileURLPrefix) == mURL, "Not a URL!"); + mFileSpec.mError = NS_FILE_RESULT(MacFileHelpers::FSSpecFromUnixPath( + mURL + 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 //---------------------------------------------------------------------------------------- nsFileURL::nsFileURL(const nsString& inString, PRBool inCreateDirs) //---------------------------------------------------------------------------------------- +: mURL(nsFileSpecHelpers::StringDup(nsAutoCString(inString))) +{ + NS_ASSERTION(strstr(mURL, kFileURLPrefix) == mURL, "Not a URL!"); + mFileSpec.mError = NS_FILE_RESULT(MacFileHelpers::FSSpecFromUnixPath( + mURL + 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 + +//---------------------------------------------------------------------------------------- +nsFileURL::nsFileURL(const nsFilePath& inOther) +//---------------------------------------------------------------------------------------- : mURL(nsnull) { - nsAutoCString aString(inString); - const char* aCString = (const char*)aString; - NS_ASSERTION(strstr(aCString, kFileURLPrefix) == aCString, "Not a URL!"); - mFileSpec = aCString + kFileURLPrefixLength; - // Make canonical and absolute. - char* path = MacFileHelpers::PathNameFromFSSpec( mFileSpec, TRUE ); - char* escapedPath = MacFileHelpers::EncodeMacPath(path, true, true); - mURL = nsFileSpecHelpers::StringDup(kFileURLPrefix, kFileURLPrefixLength + strlen(escapedPath)); - strcat(mURL, escapedPath); - delete [] escapedPath; + *this = inOther.GetFileSpec(); } // nsFileURL::nsFileURL +//---------------------------------------------------------------------------------------- +nsFileURL::nsFileURL(const nsFileSpec& inOther) +: mURL(nsnull) +//---------------------------------------------------------------------------------------- +{ + *this = inOther; +} // nsFileURL::nsFileURL + +//---------------------------------------------------------------------------------------- +void nsFileURL::operator = (const nsFilePath& inOther) +//---------------------------------------------------------------------------------------- +{ + *this = inOther.GetFileSpec(); +} // nsFileURL::operator = + +//---------------------------------------------------------------------------------------- +void nsFileURL::operator = (const nsFileSpec& inOther) +//---------------------------------------------------------------------------------------- +{ + mFileSpec = inOther; + delete [] mURL; + char* path = MacFileHelpers::PathNameFromFSSpec( mFileSpec, TRUE ); + mURL = MacFileHelpers::EncodeMacPath(path, true, true); +} // nsFileURL::operator = + +//---------------------------------------------------------------------------------------- +void nsFileURL::operator = (const char* inString) +//---------------------------------------------------------------------------------------- +{ + nsFileSpecHelpers::StringAssign(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. + if (mFileSpec.mError == NS_FILE_RESULT(fnfErr)) + mFileSpec.mError = NS_OK; +} // nsFileURL::operator = + //======================================================================================== // nsDirectoryIterator //======================================================================================== diff --git a/mozilla/xpcom/io/nsFileSpecUnix.cpp b/mozilla/xpcom/io/nsFileSpecUnix.cpp index b3f368305a7..5af2eb10a30 100644 --- a/mozilla/xpcom/io/nsFileSpecUnix.cpp +++ b/mozilla/xpcom/io/nsFileSpecUnix.cpp @@ -25,9 +25,42 @@ #include #include #include +#include #include "nsError.h" -//---------------------------------------------------------------------------------------- +#if defined(IRIX) || defined(OSF1) || defined(SOLARIS) || defined(UNIXWARE) || defined(SNI) || defined(NCR) || defined(NEC) || defined(DGUX) +#include /* for statvfs() */ +#define STATFS statvfs +#elif defined(SCO_SV) +#define _SVID3/* for statvfs.h */ +#include /* for statvfs() */ +#define STATFS statvfs +#elif defined(HPUX) +#include /* for statfs() */ +#define STATFS statfs +#elif defined(LINUX) +#include /* for statfs() */ +#define STATFS statfs +#elif defined(SUNOS4) +#include /* for statfs() */ +extern "C" int statfs(char *, struct statfs *); +#define STATFS statfs +#else +#if defined(BSDI) || defined(NETBSD) || defined(OPENBSD) || defined(RHAPSODY) || defined(FREEBSD) +#include /* for statfs() */ +#define STATFS statfs +#else +#include /* for statfs() */ +#define STATFS statfs +extern "C" int statfs(char *, struct statfs *); +#endif +#endif + +#if defined(OSF1) +extern "C" int statvfs(const char *, struct statvfs *); +#endif + + //---------------------------------------------------------------------------------------- void nsFileSpecHelpers::Canonify(char*& ioPath, PRBool inMakeDirs) // Canonify, make absolute, and check whether directories exist //---------------------------------------------------------------------------------------- @@ -271,12 +304,14 @@ nsresult nsFileSpec::Copy(const nsFileSpec& inParentDirectory) const if (inParentDirectory.IsDirectory() && (! IsDirectory() ) ) { char *leafname = GetLeafName(); - char* destPath = nsFileSpecHelpers::StringDup(inParentDirectory, ( strlen(inParentDirectory) + 1 + strlen(leafname) ) ); + char* destPath = nsFileSpecHelpers::StringDup( + inParentDirectory.GetCString(), + strlen(inParentDirectory.GetCString()) + 1 + strlen(leafname)); strcat(destPath, "/"); strcat(destPath, leafname); delete [] leafname; - result = NS_FILE_RESULT(CrudeFileCopy(*this, destPath)); + result = NS_FILE_RESULT(CrudeFileCopy(GetCString(), destPath)); delete [] destPath; } @@ -295,13 +330,13 @@ nsresult nsFileSpec::Move(const nsFileSpec& inNewParentDirectory) const char *leafname = GetLeafName(); char* destPath = nsFileSpecHelpers::StringDup( - inNewParentDirectory, - strlen(inNewParentDirectory) + 1 + strlen(leafname)); + inNewParentDirectory.GetCString(), + strlen(inNewParentDirectory.GetCString()) + 1 + strlen(leafname)); strcat(destPath, "/"); strcat(destPath, leafname); delete [] leafname; - result = NS_FILE_RESULT(CrudeFileCopy(*this, destPath)); + result = NS_FILE_RESULT(CrudeFileCopy(GetCString(), destPath)); if (result == NS_OK) { // cast to fix const-ness @@ -333,6 +368,31 @@ nsresult nsFileSpec::Execute(const char* inArgs ) const } // nsFileSpec::Execute +//---------------------------------------------------------------------------------------- +PRUint32 nsFileSpec::GetDiskSpaceAvailable() const +//---------------------------------------------------------------------------------------- +{ + char curdir [MAXPATHLEN]; + if (!mPath || !*mPath) + { + (void) getcwd(curdir, MAXPATHLEN); + if (!curdir) + return ULONG_MAX; /* hope for the best as we did in cheddar */ + } + else + sprintf(curdir, "%.200s", mPath); + + struct STATFS fs_buf; + if (STATFS(curdir, &fs_buf) < 0) + return ULONG_MAX; /* hope for the best as we did in cheddar */ + +#ifdef DEBUG_DISK_SPACE + printf("DiskSpaceAvailable: %d bytes\n", + fs_buf.f_bsize * (fs_buf.f_bavail - 1)); +#endif + return fs_buf.f_bsize * (fs_buf.f_bavail - 1); +} // nsFileSpec::GetDiskSpace() + //======================================================================================== // nsDirectoryIterator //======================================================================================== diff --git a/mozilla/xpcom/io/nsFileSpecWin.cpp b/mozilla/xpcom/io/nsFileSpecWin.cpp index 1afee4ec6c9..d30521e0b10 100644 --- a/mozilla/xpcom/io/nsFileSpecWin.cpp +++ b/mozilla/xpcom/io/nsFileSpecWin.cpp @@ -248,7 +248,12 @@ void nsFileSpec::operator += (const char* inRelativePath) nsFileSpecHelpers::ReallocCat(mPath, "x"); else nsFileSpecHelpers::ReallocCat(mPath, "\\x"); - SetLeafName(inRelativePath); + + // If it's a (unix) relative path, make it native + char* dosPath = nsFileSpecHelpers::StringDup(inRelativePath); + nsFileSpecHelpers::UnixToNative(dosPath); + SetLeafName(dosPath); + delete [] dosPath; } // nsFileSpec::operator += //---------------------------------------------------------------------------------------- @@ -380,6 +385,49 @@ nsresult nsFileSpec::Execute(const char* inArgs ) const return NS_FILE_FAILURE; } // nsFileSpec::Execute +//---------------------------------------------------------------------------------------- +PRUint32 nsFileSpec::GetDiskSpaceAvailable() const +//---------------------------------------------------------------------------------------- +{ + char aDrive[_MAX_DRIVE + 2]; + _splitpath( mPath, aDrive, NULL, NULL, NULL); + + if (aDrive[0] == '\0') + { + // The back end is always trying to pass us paths that look + // like /c|/netscape/mail. See if we've got one of them + if (strlen(mPath) > 2 && mPath[0] == '/' && mPath[2] == '|') + { + aDrive[0] = mPath[1]; + aDrive[1] = ':'; + aDrive[2] = '\0'; + } + else + { + // Return bogus large number and hope for the best + return ULONG_MAX; + } + } + + strcat(aDrive, "\\"); + + PRUint32 dwSectorsPerCluster = 0; + PRUint32 dwBytesPerSector = 0; + PRUint32 dwFreeClusters = 0; + PRUint32 dwTotalClusters = 0; + if (!GetDiskFreeSpace(aDrive, + &dwSectorsPerCluster, + &dwBytesPerSector, + &dwFreeClusters, + &dwTotalClusters)) + { + return ULONG_MAX; // Return bogus large number and hope for the best + } + + // We can now figure free disk space. + return dwFreeClusters * dwSectorsPerCluster * dwBytesPerSector; +} // nsFileSpec::GetDiskSpaceAvailable() + //======================================================================================== // nsDirectoryIterator //======================================================================================== diff --git a/mozilla/xpcom/io/nsIFileStream.cpp b/mozilla/xpcom/io/nsIFileStream.cpp index 05a0a4ff829..997f9d7d1d1 100644 --- a/mozilla/xpcom/io/nsIFileStream.cpp +++ b/mozilla/xpcom/io/nsIFileStream.cpp @@ -123,7 +123,7 @@ class FileImpl if (mFailed) return NS_ERROR_FAILURE; PRInt32 bytesWrit = PR_Write(mFileDesc, aBuf, aCount); - if (bytesWrit != aCount) + if (bytesWrit != (PRInt32)aCount) { mFailed = PR_TRUE; *aWriteCount = 0; diff --git a/mozilla/xpcom/io/nsSpecialSystemDirectory.cpp b/mozilla/xpcom/io/nsSpecialSystemDirectory.cpp index 797e264beb5..9edd50eeac3 100644 --- a/mozilla/xpcom/io/nsSpecialSystemDirectory.cpp +++ b/mozilla/xpcom/io/nsSpecialSystemDirectory.cpp @@ -355,16 +355,15 @@ void nsSpecialSystemDirectory::operator = (OSType folderType) break; } // switch } // for - mSpec.name[0] = '\0'; - dipb->ioNamePtr = (StringPtr)&mSpec.name; + StrFileName filename; + filename[0] = '\0'; + dipb->ioNamePtr = (StringPtr)&filename; dipb->ioFDirIndex = -1; - mError = PBGetCatInfoSync(&cinfo); - + mError = NS_FILE_RESULT(PBGetCatInfoSync(&cinfo)); if (NS_SUCCEEDED(mError)) { - mSpec.vRefNum = dipb->ioVRefNum; - mSpec.parID = dipb->ioDrParID; + mError = NS_FILE_RESULT(FSMakeFSSpec(dipb->ioVRefNum, dipb->ioDrParID, filename, &mSpec)); } } #endif // XP_MAC diff --git a/mozilla/xpcom/tests/FilesTest.cpp b/mozilla/xpcom/tests/FilesTest.cpp index e66942089f0..4bcdaaef8d4 100644 --- a/mozilla/xpcom/tests/FilesTest.cpp +++ b/mozilla/xpcom/tests/FilesTest.cpp @@ -744,6 +744,19 @@ int FilesTest::SpecialSystemDirectories() return Failed(); } + systemDir = nsSpecialSystemDirectory::Mac_DocumentsDirectory; + mConsole << "Mac_DocumentsDirectory yields \t"; + + if (systemDir.Valid()) + { + mConsole << systemDir << nsEndl; + } + else + { + mConsole << "nsnull" << nsEndl; + return Failed(); + } + #elif XP_PC systemDir = nsSpecialSystemDirectory::Win_SystemDirectory; mConsole << "Win_SystemDirectory yields \t"; @@ -865,7 +878,7 @@ int FilesTest::RunAllTests() if (IterateDirectoryChildren(parent) != 0) return -1; - Banner("Equals operator of nsFileSpec"); + Banner("nsFileSpec equality"); if (FileSpecEquality("mumble/a", "mumble/b") != 0) return -1;