From 0e3fcaece6bb567279f6422adfdfa046cb45aa4b Mon Sep 17 00:00:00 2001 From: "mcmullen%netscape.com" <mcmullen%netscape.com> Date: Wed, 10 Mar 1999 21:02:58 +0000 Subject: [PATCH] Added GetModDate and GetFileSize. Fixed a crash with a strcmp of null. --- base/public/nsFileSpec.h | 27 ++++++++++++++- base/src/mac/nsFileSpecMac.cpp | 54 ++++++++++++++++++++++-------- base/src/nsFileSpec.cpp | 26 ++++++++------ base/src/unix/nsFileSpecUnix.cpp | 21 ++++++++++++ base/src/windows/nsFileSpecWin.cpp | 38 ++++++++++++++++----- xpcom/io/nsFileSpec.cpp | 26 ++++++++------ xpcom/io/nsFileSpec.h | 27 ++++++++++++++- xpcom/io/nsFileSpecMac.cpp | 54 ++++++++++++++++++++++-------- xpcom/io/nsFileSpecUnix.cpp | 21 ++++++++++++ xpcom/io/nsFileSpecWin.cpp | 38 ++++++++++++++++----- 10 files changed, 264 insertions(+), 68 deletions(-) diff --git a/base/public/nsFileSpec.h b/base/public/nsFileSpec.h index fc8a1bae1a4d1..d847f754e045a 100644 --- a/base/public/nsFileSpec.h +++ b/base/public/nsFileSpec.h @@ -209,7 +209,7 @@ protected: //======================================================================================== class NS_BASE nsFileSpec // This is whatever each platform really prefers to describe files as. Declared first -// because the other two types have an embeded nsFileSpec object. +// because the other two types have an embedded nsFileSpec object. //======================================================================================== { public: @@ -310,6 +310,26 @@ class NS_BASE nsFileSpec // but a spec. Volumes on Macintosh can have identical // names. Perhaps could be used for an operator --() ? + typedef PRUint32 TimeStamp; // ie nsFileSpec::TimeStamp. This is 32 bits now, + // but might change, eg, to a 64-bit class. So use the + // typedef, and use a streaming operator to convert + // to a string, so that your code won't break. It's + // none of your business what the number means. Don't + // rely on the implementation. + void GetModDate(TimeStamp& outStamp) const; + // This will return different values on different + // platforms, even for the same file (eg, on a server). + // But if the platform is constant, it will increase after + // every file modification. + PRBool ModDateChanged(const TimeStamp& oldStamp) const + { + TimeStamp newStamp; + GetModDate(newStamp); + return newStamp != oldStamp; + } + + PRUint32 GetFileSize() const; + nsFileSpec operator + (const char* inRelativePath) const; nsFileSpec operator + (const nsString& inRelativePath) const { @@ -368,12 +388,17 @@ class NS_BASE nsFileSpec return Execute(argsString); } + protected: + #ifdef XP_MAC + OSErr GetCatInfo(CInfoPBRec& outInfo) const; + #endif //-------------------------------------------------- // Data //-------------------------------------------------- protected: friend class nsFilePath; + friend class nsDirectoryIterator; #ifdef XP_MAC FSSpec mSpec; #else diff --git a/base/src/mac/nsFileSpecMac.cpp b/base/src/mac/nsFileSpecMac.cpp index b54b76361e4d2..62c5de86007de 100644 --- a/base/src/mac/nsFileSpecMac.cpp +++ b/base/src/mac/nsFileSpecMac.cpp @@ -602,6 +602,27 @@ PRBool nsFileSpec::Exists() const return ::FSMakeFSSpec(mSpec.vRefNum, mSpec.parID, mSpec.name, &temp) == noErr; } // nsFileSpec::operator = +//---------------------------------------------------------------------------------------- +void nsFileSpec::GetModDate(TimeStamp& outStamp) const +//---------------------------------------------------------------------------------------- +{ + CInfoPBRec pb; + if (GetCatInfo(pb) == noErr) + outStamp = ((DirInfo*)&pb)->ioDrMdDat; // The mod date is in the same spot for files and dirs. + else + outStamp = 0; +} // nsFileSpec::GetModDate + +//---------------------------------------------------------------------------------------- +PRUint32 nsFileSpec::GetFileSize() const +//---------------------------------------------------------------------------------------- +{ + CInfoPBRec pb; + if (noErr == GetCatInfo(pb)) + return (PRUint32)((HFileInfo*)&pb)->ioFlLgLen; + return 0; +} // nsFileSpec::GetFileSize + //---------------------------------------------------------------------------------------- void nsFileSpec::SetLeafName(const char* inLeafName) // In leaf name can actually be a partial path... @@ -793,6 +814,19 @@ nsresult nsFileSpec::Execute(const char* /*args - how can this be cross-platform } // nsFileSpec::Execute +//---------------------------------------------------------------------------------------- +OSErr nsFileSpec::GetCatInfo(CInfoPBRec& outInfo) const +//---------------------------------------------------------------------------------------- +{ + DirInfo *dipb=(DirInfo *)&outInfo; + dipb->ioCompletion = nsnull; + dipb->ioFDirIndex = 0; // use dirID and name + dipb->ioVRefNum = mSpec.vRefNum; + dipb->ioDrDirID = mSpec.parID; + dipb->ioNamePtr = const_cast<nsFileSpec*>(this)->mSpec.name; + return PBGetCatInfoSync(&outInfo); +} // nsFileSpec::GetCatInfo() + //======================================================================================== // Macintosh nsFilePath implementation //======================================================================================== @@ -888,24 +922,15 @@ nsDirectoryIterator::nsDirectoryIterator( , mIndex(-1) { CInfoPBRec pb; - DirInfo* dipb = (DirInfo*)&pb; - // Sorry about this, there seems to be a bug in CWPro 4: - const FSSpec& inSpec = inDirectory.nsFileSpec::operator const FSSpec&(); - Str255 outName; - MacFileHelpers::PLstrcpy(outName, inSpec.name); - pb.hFileInfo.ioNamePtr = outName; - pb.hFileInfo.ioVRefNum = inSpec.vRefNum; - pb.hFileInfo.ioDirID = inSpec.parID; - pb.hFileInfo.ioFDirIndex = 0; // use ioNamePtr and ioDirID - - OSErr err = PBGetCatInfoSync( &pb ); - + OSErr err = inDirectory.GetCatInfo(pb); + // test that we have got a directory back, not a file - if ( (err != noErr ) || !( dipb->ioFlAttrib & 0x0010 ) ) + 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 = inSpec.vRefNum; + currentSpec.vRefNum = currentSpec.vRefNum; currentSpec.parID = dipb->ioDrDirID; mMaxIndex = pb.dirInfo.ioDrNmFls; if (inIterateDirection > 0) @@ -969,3 +994,4 @@ nsDirectoryIterator& nsDirectoryIterator::operator ++ () } return *this; } // nsDirectoryIterator::operator ++ + diff --git a/base/src/nsFileSpec.cpp b/base/src/nsFileSpec.cpp index 62c63b25ea41c..36d63c92385da 100644 --- a/base/src/nsFileSpec.cpp +++ b/base/src/nsFileSpec.cpp @@ -776,18 +776,22 @@ PRBool nsFileSpec::operator == (const nsFileSpec& inOther) const if ( inOther.mSpec.vRefNum == mSpec.vRefNum && inOther.mSpec.parID == mSpec.parID && EqualString(inOther.mSpec.name, mSpec.name, false, false)) - return (PR_TRUE); -#elif XP_PC - // windows does not care about case. - - if (_stricmp(mPath, inOther.mPath ) == 0) - return (PR_TRUE); + return PR_TRUE; #else - if (strcmp(mPath, inOther.mPath ) == 0) - return (PR_TRUE); -#endif - - return (PR_FALSE); + if (!mPath) + return inOther.mPath == nsNull; + if (!inOther.mPath) + return PR_FALSE; + #if defined(XP_PC) + // windows does not care about case. + if (_stricmp(mPath, inOther.mPath ) == 0) + return PR_TRUE; + #else + if (strcmp(mPath, inOther.mPath ) == 0) + return PR_TRUE; + #endif +#endif + return PR_FALSE; } //---------------------------------------------------------------------------------------- diff --git a/base/src/unix/nsFileSpecUnix.cpp b/base/src/unix/nsFileSpecUnix.cpp index d5ea52c5368bc..b3f368305a7c1 100644 --- a/base/src/unix/nsFileSpecUnix.cpp +++ b/base/src/unix/nsFileSpecUnix.cpp @@ -98,6 +98,27 @@ PRBool nsFileSpec::Exists() const return 0 == stat(mPath, &st); } // nsFileSpec::Exists +//---------------------------------------------------------------------------------------- +void nsFileSpec::GetModDate(TimeStamp& outStamp) const +//---------------------------------------------------------------------------------------- +{ + struct stat st; + if (stat(mPath, &st) == 0) + outStamp = st.st_mtime; + else + outStamp = 0; +} // nsFileSpec::GetModDate + +//---------------------------------------------------------------------------------------- +PRUint32 nsFileSpec::GetFileSize() const +//---------------------------------------------------------------------------------------- +{ + struct stat st; + if (stat(mPath, &st) == 0) + return (PRUint32)st.st_size; + return 0; +} // nsFileSpec::GetFileSize + //---------------------------------------------------------------------------------------- PRBool nsFileSpec::IsFile() const //---------------------------------------------------------------------------------------- diff --git a/base/src/windows/nsFileSpecWin.cpp b/base/src/windows/nsFileSpecWin.cpp index f93ce0ae2be21..1afee4ec6c9e0 100644 --- a/base/src/windows/nsFileSpecWin.cpp +++ b/base/src/windows/nsFileSpecWin.cpp @@ -41,14 +41,15 @@ void nsFileSpecHelpers::Canonify(char*& ioPath, PRBool inMakeDirs) //---------------------------------------------------------------------------------------- { if (!ioPath) - return; + return; - if (inMakeDirs) { - const int mode = 0700; - char* unixStylePath = nsFileSpecHelpers::StringDup(ioPath); - nsFileSpecHelpers::NativeToUnix(unixStylePath); - nsFileSpecHelpers::MakeAllDirectories(unixStylePath, mode); - delete[] unixStylePath; + if (inMakeDirs) + { + const int mode = 0700; + char* unixStylePath = nsFileSpecHelpers::StringDup(ioPath); + nsFileSpecHelpers::NativeToUnix(unixStylePath); + nsFileSpecHelpers::MakeAllDirectories(unixStylePath, mode); + delete[] unixStylePath; } char buffer[_MAX_PATH]; errno = 0; @@ -57,7 +58,7 @@ void nsFileSpecHelpers::Canonify(char*& ioPath, PRBool inMakeDirs) NS_ASSERTION( canonicalPath[0] != '\0', "Uh oh...couldn't convert" ); if (canonicalPath[0] == '\0') - return; + return; nsFileSpecHelpers::StringAssign(ioPath, canonicalPath); } @@ -189,6 +190,27 @@ PRBool nsFileSpec::Exists() const return 0 == stat(mPath, &st); } // nsFileSpec::Exists +//---------------------------------------------------------------------------------------- +void nsFileSpec::GetModDate(TimeStamp& outStamp) const +//---------------------------------------------------------------------------------------- +{ + struct stat st; + if (stat(mPath, &st) == 0) + outStamp = st.st_mtime; + else + outStamp = 0; +} // nsFileSpec::GetModDate + +//---------------------------------------------------------------------------------------- +PRUint32 nsFileSpec::GetFileSize() const +//---------------------------------------------------------------------------------------- +{ + struct stat st; + if (stat(mPath, &st) == 0) + return (PRUint32)st.st_size; + return 0; +} // nsFileSpec::GetFileSize + //---------------------------------------------------------------------------------------- PRBool nsFileSpec::IsFile() const //---------------------------------------------------------------------------------------- diff --git a/xpcom/io/nsFileSpec.cpp b/xpcom/io/nsFileSpec.cpp index 62c63b25ea41c..36d63c92385da 100644 --- a/xpcom/io/nsFileSpec.cpp +++ b/xpcom/io/nsFileSpec.cpp @@ -776,18 +776,22 @@ PRBool nsFileSpec::operator == (const nsFileSpec& inOther) const if ( inOther.mSpec.vRefNum == mSpec.vRefNum && inOther.mSpec.parID == mSpec.parID && EqualString(inOther.mSpec.name, mSpec.name, false, false)) - return (PR_TRUE); -#elif XP_PC - // windows does not care about case. - - if (_stricmp(mPath, inOther.mPath ) == 0) - return (PR_TRUE); + return PR_TRUE; #else - if (strcmp(mPath, inOther.mPath ) == 0) - return (PR_TRUE); -#endif - - return (PR_FALSE); + if (!mPath) + return inOther.mPath == nsNull; + if (!inOther.mPath) + return PR_FALSE; + #if defined(XP_PC) + // windows does not care about case. + if (_stricmp(mPath, inOther.mPath ) == 0) + return PR_TRUE; + #else + if (strcmp(mPath, inOther.mPath ) == 0) + return PR_TRUE; + #endif +#endif + return PR_FALSE; } //---------------------------------------------------------------------------------------- diff --git a/xpcom/io/nsFileSpec.h b/xpcom/io/nsFileSpec.h index fc8a1bae1a4d1..d847f754e045a 100644 --- a/xpcom/io/nsFileSpec.h +++ b/xpcom/io/nsFileSpec.h @@ -209,7 +209,7 @@ protected: //======================================================================================== class NS_BASE nsFileSpec // This is whatever each platform really prefers to describe files as. Declared first -// because the other two types have an embeded nsFileSpec object. +// because the other two types have an embedded nsFileSpec object. //======================================================================================== { public: @@ -310,6 +310,26 @@ class NS_BASE nsFileSpec // but a spec. Volumes on Macintosh can have identical // names. Perhaps could be used for an operator --() ? + typedef PRUint32 TimeStamp; // ie nsFileSpec::TimeStamp. This is 32 bits now, + // but might change, eg, to a 64-bit class. So use the + // typedef, and use a streaming operator to convert + // to a string, so that your code won't break. It's + // none of your business what the number means. Don't + // rely on the implementation. + void GetModDate(TimeStamp& outStamp) const; + // This will return different values on different + // platforms, even for the same file (eg, on a server). + // But if the platform is constant, it will increase after + // every file modification. + PRBool ModDateChanged(const TimeStamp& oldStamp) const + { + TimeStamp newStamp; + GetModDate(newStamp); + return newStamp != oldStamp; + } + + PRUint32 GetFileSize() const; + nsFileSpec operator + (const char* inRelativePath) const; nsFileSpec operator + (const nsString& inRelativePath) const { @@ -368,12 +388,17 @@ class NS_BASE nsFileSpec return Execute(argsString); } + protected: + #ifdef XP_MAC + OSErr GetCatInfo(CInfoPBRec& outInfo) const; + #endif //-------------------------------------------------- // Data //-------------------------------------------------- protected: friend class nsFilePath; + friend class nsDirectoryIterator; #ifdef XP_MAC FSSpec mSpec; #else diff --git a/xpcom/io/nsFileSpecMac.cpp b/xpcom/io/nsFileSpecMac.cpp index b54b76361e4d2..62c5de86007de 100644 --- a/xpcom/io/nsFileSpecMac.cpp +++ b/xpcom/io/nsFileSpecMac.cpp @@ -602,6 +602,27 @@ PRBool nsFileSpec::Exists() const return ::FSMakeFSSpec(mSpec.vRefNum, mSpec.parID, mSpec.name, &temp) == noErr; } // nsFileSpec::operator = +//---------------------------------------------------------------------------------------- +void nsFileSpec::GetModDate(TimeStamp& outStamp) const +//---------------------------------------------------------------------------------------- +{ + CInfoPBRec pb; + if (GetCatInfo(pb) == noErr) + outStamp = ((DirInfo*)&pb)->ioDrMdDat; // The mod date is in the same spot for files and dirs. + else + outStamp = 0; +} // nsFileSpec::GetModDate + +//---------------------------------------------------------------------------------------- +PRUint32 nsFileSpec::GetFileSize() const +//---------------------------------------------------------------------------------------- +{ + CInfoPBRec pb; + if (noErr == GetCatInfo(pb)) + return (PRUint32)((HFileInfo*)&pb)->ioFlLgLen; + return 0; +} // nsFileSpec::GetFileSize + //---------------------------------------------------------------------------------------- void nsFileSpec::SetLeafName(const char* inLeafName) // In leaf name can actually be a partial path... @@ -793,6 +814,19 @@ nsresult nsFileSpec::Execute(const char* /*args - how can this be cross-platform } // nsFileSpec::Execute +//---------------------------------------------------------------------------------------- +OSErr nsFileSpec::GetCatInfo(CInfoPBRec& outInfo) const +//---------------------------------------------------------------------------------------- +{ + DirInfo *dipb=(DirInfo *)&outInfo; + dipb->ioCompletion = nsnull; + dipb->ioFDirIndex = 0; // use dirID and name + dipb->ioVRefNum = mSpec.vRefNum; + dipb->ioDrDirID = mSpec.parID; + dipb->ioNamePtr = const_cast<nsFileSpec*>(this)->mSpec.name; + return PBGetCatInfoSync(&outInfo); +} // nsFileSpec::GetCatInfo() + //======================================================================================== // Macintosh nsFilePath implementation //======================================================================================== @@ -888,24 +922,15 @@ nsDirectoryIterator::nsDirectoryIterator( , mIndex(-1) { CInfoPBRec pb; - DirInfo* dipb = (DirInfo*)&pb; - // Sorry about this, there seems to be a bug in CWPro 4: - const FSSpec& inSpec = inDirectory.nsFileSpec::operator const FSSpec&(); - Str255 outName; - MacFileHelpers::PLstrcpy(outName, inSpec.name); - pb.hFileInfo.ioNamePtr = outName; - pb.hFileInfo.ioVRefNum = inSpec.vRefNum; - pb.hFileInfo.ioDirID = inSpec.parID; - pb.hFileInfo.ioFDirIndex = 0; // use ioNamePtr and ioDirID - - OSErr err = PBGetCatInfoSync( &pb ); - + OSErr err = inDirectory.GetCatInfo(pb); + // test that we have got a directory back, not a file - if ( (err != noErr ) || !( dipb->ioFlAttrib & 0x0010 ) ) + 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 = inSpec.vRefNum; + currentSpec.vRefNum = currentSpec.vRefNum; currentSpec.parID = dipb->ioDrDirID; mMaxIndex = pb.dirInfo.ioDrNmFls; if (inIterateDirection > 0) @@ -969,3 +994,4 @@ nsDirectoryIterator& nsDirectoryIterator::operator ++ () } return *this; } // nsDirectoryIterator::operator ++ + diff --git a/xpcom/io/nsFileSpecUnix.cpp b/xpcom/io/nsFileSpecUnix.cpp index d5ea52c5368bc..b3f368305a7c1 100644 --- a/xpcom/io/nsFileSpecUnix.cpp +++ b/xpcom/io/nsFileSpecUnix.cpp @@ -98,6 +98,27 @@ PRBool nsFileSpec::Exists() const return 0 == stat(mPath, &st); } // nsFileSpec::Exists +//---------------------------------------------------------------------------------------- +void nsFileSpec::GetModDate(TimeStamp& outStamp) const +//---------------------------------------------------------------------------------------- +{ + struct stat st; + if (stat(mPath, &st) == 0) + outStamp = st.st_mtime; + else + outStamp = 0; +} // nsFileSpec::GetModDate + +//---------------------------------------------------------------------------------------- +PRUint32 nsFileSpec::GetFileSize() const +//---------------------------------------------------------------------------------------- +{ + struct stat st; + if (stat(mPath, &st) == 0) + return (PRUint32)st.st_size; + return 0; +} // nsFileSpec::GetFileSize + //---------------------------------------------------------------------------------------- PRBool nsFileSpec::IsFile() const //---------------------------------------------------------------------------------------- diff --git a/xpcom/io/nsFileSpecWin.cpp b/xpcom/io/nsFileSpecWin.cpp index f93ce0ae2be21..1afee4ec6c9e0 100644 --- a/xpcom/io/nsFileSpecWin.cpp +++ b/xpcom/io/nsFileSpecWin.cpp @@ -41,14 +41,15 @@ void nsFileSpecHelpers::Canonify(char*& ioPath, PRBool inMakeDirs) //---------------------------------------------------------------------------------------- { if (!ioPath) - return; + return; - if (inMakeDirs) { - const int mode = 0700; - char* unixStylePath = nsFileSpecHelpers::StringDup(ioPath); - nsFileSpecHelpers::NativeToUnix(unixStylePath); - nsFileSpecHelpers::MakeAllDirectories(unixStylePath, mode); - delete[] unixStylePath; + if (inMakeDirs) + { + const int mode = 0700; + char* unixStylePath = nsFileSpecHelpers::StringDup(ioPath); + nsFileSpecHelpers::NativeToUnix(unixStylePath); + nsFileSpecHelpers::MakeAllDirectories(unixStylePath, mode); + delete[] unixStylePath; } char buffer[_MAX_PATH]; errno = 0; @@ -57,7 +58,7 @@ void nsFileSpecHelpers::Canonify(char*& ioPath, PRBool inMakeDirs) NS_ASSERTION( canonicalPath[0] != '\0', "Uh oh...couldn't convert" ); if (canonicalPath[0] == '\0') - return; + return; nsFileSpecHelpers::StringAssign(ioPath, canonicalPath); } @@ -189,6 +190,27 @@ PRBool nsFileSpec::Exists() const return 0 == stat(mPath, &st); } // nsFileSpec::Exists +//---------------------------------------------------------------------------------------- +void nsFileSpec::GetModDate(TimeStamp& outStamp) const +//---------------------------------------------------------------------------------------- +{ + struct stat st; + if (stat(mPath, &st) == 0) + outStamp = st.st_mtime; + else + outStamp = 0; +} // nsFileSpec::GetModDate + +//---------------------------------------------------------------------------------------- +PRUint32 nsFileSpec::GetFileSize() const +//---------------------------------------------------------------------------------------- +{ + struct stat st; + if (stat(mPath, &st) == 0) + return (PRUint32)st.st_size; + return 0; +} // nsFileSpec::GetFileSize + //---------------------------------------------------------------------------------------- PRBool nsFileSpec::IsFile() const //---------------------------------------------------------------------------------------- -- GitLab