From d219f1385e232f5a568779ca72be83c47515be9e Mon Sep 17 00:00:00 2001 From: "dougt%netscape.com" Date: Mon, 26 Jul 1999 22:09:42 +0000 Subject: [PATCH] Fix for bug 10177 and 10041. git-svn-id: svn://10.0.0.236/trunk@41167 18797224-902f-48f8-a5cc-f745e15eee43 --- .../mailnews/base/src/nsMsgAccountManager.cpp | 2 +- .../mailnews/imap/src/nsImapMailFolder.cpp | 2 +- .../mailnews/local/src/nsLocalMailFolder.cpp | 2 +- .../modules/plugin/base/src/ns4xPlugin.cpp | 2 +- .../plugin/base/src/nsPluginHostImpl.cpp | 2 +- mozilla/modules/plugin/nglsrc/ns4xPlugin.cpp | 2 +- .../plugin/nglsrc/nsPluginHostImpl.cpp | 2 +- mozilla/netwerk/test/TestFileInput2.cpp | 2 +- .../pref-migrator/src/nsPrefMigration.cpp | 4 +- .../datasource/src/nsFileSystemDataSource.cpp | 2 +- .../rdf/datasource/src/nsSearchDataSource.cpp | 4 +- .../src/xpwidgets/nsFileSpecWithUIImpl.h | 8 ++ mozilla/xpcom/build/makefile.win | 1 + mozilla/xpcom/io/nsFileSpec.h | 30 +++-- mozilla/xpcom/io/nsFileSpecBeOS.cpp | 55 +++++++- mozilla/xpcom/io/nsFileSpecImpl.cpp | 19 ++- mozilla/xpcom/io/nsFileSpecImpl.h | 6 + mozilla/xpcom/io/nsFileSpecMac.cpp | 92 +++++++++---- mozilla/xpcom/io/nsFileSpecOS2.cpp | 40 +++++- mozilla/xpcom/io/nsFileSpecUnix.cpp | 59 ++++++++- mozilla/xpcom/io/nsFileSpecWin.cpp | 124 +++++++++++++++++- mozilla/xpcom/io/nsIFileSpec.idl | 4 + mozilla/xpcom/io/nsSpecialSystemDirectory.cpp | 3 +- .../xptinfo/src/nsInterfaceInfoManager.cpp | 2 +- .../history/src/nsGlobalHistory.cpp | 8 +- 25 files changed, 394 insertions(+), 83 deletions(-) diff --git a/mozilla/mailnews/base/src/nsMsgAccountManager.cpp b/mozilla/mailnews/base/src/nsMsgAccountManager.cpp index 1cb0378ba34..9881f7e98d1 100644 --- a/mozilla/mailnews/base/src/nsMsgAccountManager.cpp +++ b/mozilla/mailnews/base/src/nsMsgAccountManager.cpp @@ -1515,7 +1515,7 @@ nsMsgAccountManager::MigrateNewsAccounts(nsIMsgIdentity *identity, PRInt32 baseA dirWithTheNewsrcFiles = homeDir; } - for (nsDirectoryIterator i(dirWithTheNewsrcFiles); i.Exists(); i++) { + for (nsDirectoryIterator i(dirWithTheNewsrcFiles, PR_FALSE); i.Exists(); i++) { nsFileSpec possibleRcFile = i.Spec(); char *filename = possibleRcFile.GetLeafName(); diff --git a/mozilla/mailnews/imap/src/nsImapMailFolder.cpp b/mozilla/mailnews/imap/src/nsImapMailFolder.cpp index fe94a1f0486..9e88113b247 100644 --- a/mozilla/mailnews/imap/src/nsImapMailFolder.cpp +++ b/mozilla/mailnews/imap/src/nsImapMailFolder.cpp @@ -297,7 +297,7 @@ nsresult nsImapMailFolder::CreateSubFolders(nsFileSpec &path) nsAutoString currentFolderNameStr; nsCOMPtr child; char *folderName; - for (nsDirectoryIterator dir(path); dir.Exists(); dir++) + for (nsDirectoryIterator dir(path, PR_FALSE); dir.Exists(); dir++) { nsFileSpec currentFolderPath = (nsFileSpec&)dir; diff --git a/mozilla/mailnews/local/src/nsLocalMailFolder.cpp b/mozilla/mailnews/local/src/nsLocalMailFolder.cpp index 2352b6c3e0f..2cc3255850a 100644 --- a/mozilla/mailnews/local/src/nsLocalMailFolder.cpp +++ b/mozilla/mailnews/local/src/nsLocalMailFolder.cpp @@ -199,7 +199,7 @@ nsMsgLocalMailFolder::CreateSubFolders(nsFileSpec &path) nsAutoString currentFolderNameStr; nsCOMPtr child; char *folderName; - for (nsDirectoryIterator dir(path); dir.Exists(); dir++) { + for (nsDirectoryIterator dir(path, PR_FALSE); dir.Exists(); dir++) { nsFileSpec currentFolderPath = (nsFileSpec&)dir; folderName = currentFolderPath.GetLeafName(); diff --git a/mozilla/modules/plugin/base/src/ns4xPlugin.cpp b/mozilla/modules/plugin/base/src/ns4xPlugin.cpp index 7939ba4b7be..3d2abc84072 100644 --- a/mozilla/modules/plugin/base/src/ns4xPlugin.cpp +++ b/mozilla/modules/plugin/base/src/ns4xPlugin.cpp @@ -305,7 +305,7 @@ ns4xPlugin::CreatePlugin(nsPluginTag* pluginTag, nsIServiceManager* serviceMgr) short appRefNum = ::CurResFile(); short pluginRefNum; - for(nsDirectoryIterator iter(pluginsDir); iter.Exists(); iter++) + for(nsDirectoryIterator iter(pluginsDir, PR_TRUE); iter.Exists(); iter++) { const nsFileSpec& file = iter; if (pluginsDir.IsPluginFile(file)) diff --git a/mozilla/modules/plugin/base/src/nsPluginHostImpl.cpp b/mozilla/modules/plugin/base/src/nsPluginHostImpl.cpp index 7cb093ed7bb..2b7ebb732f6 100644 --- a/mozilla/modules/plugin/base/src/nsPluginHostImpl.cpp +++ b/mozilla/modules/plugin/base/src/nsPluginHostImpl.cpp @@ -2216,7 +2216,7 @@ NS_IMETHODIMP nsPluginHostImpl::LoadPlugins() if (! pluginsDir.Valid()) break; - for (nsDirectoryIterator iter(pluginsDir); iter.Exists(); iter++) { + for (nsDirectoryIterator iter(pluginsDir, PR_TRUE); iter.Exists(); iter++) { const nsFileSpec& file = iter; if (pluginsDir.IsPluginFile(file)) { nsPluginFile pluginFile(file); diff --git a/mozilla/modules/plugin/nglsrc/ns4xPlugin.cpp b/mozilla/modules/plugin/nglsrc/ns4xPlugin.cpp index 7939ba4b7be..3d2abc84072 100644 --- a/mozilla/modules/plugin/nglsrc/ns4xPlugin.cpp +++ b/mozilla/modules/plugin/nglsrc/ns4xPlugin.cpp @@ -305,7 +305,7 @@ ns4xPlugin::CreatePlugin(nsPluginTag* pluginTag, nsIServiceManager* serviceMgr) short appRefNum = ::CurResFile(); short pluginRefNum; - for(nsDirectoryIterator iter(pluginsDir); iter.Exists(); iter++) + for(nsDirectoryIterator iter(pluginsDir, PR_TRUE); iter.Exists(); iter++) { const nsFileSpec& file = iter; if (pluginsDir.IsPluginFile(file)) diff --git a/mozilla/modules/plugin/nglsrc/nsPluginHostImpl.cpp b/mozilla/modules/plugin/nglsrc/nsPluginHostImpl.cpp index 7cb093ed7bb..2b7ebb732f6 100644 --- a/mozilla/modules/plugin/nglsrc/nsPluginHostImpl.cpp +++ b/mozilla/modules/plugin/nglsrc/nsPluginHostImpl.cpp @@ -2216,7 +2216,7 @@ NS_IMETHODIMP nsPluginHostImpl::LoadPlugins() if (! pluginsDir.Valid()) break; - for (nsDirectoryIterator iter(pluginsDir); iter.Exists(); iter++) { + for (nsDirectoryIterator iter(pluginsDir, PR_TRUE); iter.Exists(); iter++) { const nsFileSpec& file = iter; if (pluginsDir.IsPluginFile(file)) { nsPluginFile pluginFile(file); diff --git a/mozilla/netwerk/test/TestFileInput2.cpp b/mozilla/netwerk/test/TestFileInput2.cpp index 84b956bbbba..bcb0144f4df 100644 --- a/mozilla/netwerk/test/TestFileInput2.cpp +++ b/mozilla/netwerk/test/TestFileInput2.cpp @@ -362,7 +362,7 @@ Test(CreateFun create, PRUint32 count, NS_ASSERTION(NS_SUCCEEDED(rv), "NS_NewISupportsArray failed"); nsFileSpec inDirSpec(inDir); - nsDirectoryIterator iter(inDirSpec); + nsDirectoryIterator iter(inDirSpec, PR_TRUE); for (i = 0; i < count && iter.Exists(); i++, iter++) { nsIThread* thread; nsIRunnable* worker; diff --git a/mozilla/profile/pref-migrator/src/nsPrefMigration.cpp b/mozilla/profile/pref-migrator/src/nsPrefMigration.cpp index 6df33933592..b9630f343b0 100644 --- a/mozilla/profile/pref-migrator/src/nsPrefMigration.cpp +++ b/mozilla/profile/pref-migrator/src/nsPrefMigration.cpp @@ -343,7 +343,7 @@ nsPrefMigration::GetSizes(nsFileSpec inputPath, PRBool readSubdirs, PRUint32 *si nsAutoString fileOrDirNameStr; PRInt32 len; - for (nsDirectoryIterator dir(inputPath); dir.Exists(); dir++) + for (nsDirectoryIterator dir(inputPath, PR_FALSE); dir.Exists(); dir++) { nsFileSpec fileOrDirName = (nsFileSpec&)dir; folderName = fileOrDirName.GetLeafName(); @@ -409,7 +409,7 @@ nsPrefMigration::DoTheCopy(nsFileSpec oldPath, nsFileSpec newPath, PRBool readSu char* folderName; nsAutoString fileOrDirNameStr; - for (nsDirectoryIterator dir(oldPath); dir.Exists(); dir++) + for (nsDirectoryIterator dir(oldPath, PR_FALSE); dir.Exists(); dir++) { nsFileSpec fileOrDirName = (nsFileSpec&)dir; //set first file or dir to a nsFileSpec folderName = fileOrDirName.GetLeafName(); //get the filename without the full path diff --git a/mozilla/rdf/datasource/src/nsFileSystemDataSource.cpp b/mozilla/rdf/datasource/src/nsFileSystemDataSource.cpp index 333baae07f1..b2ac67a0cef 100644 --- a/mozilla/rdf/datasource/src/nsFileSystemDataSource.cpp +++ b/mozilla/rdf/datasource/src/nsFileSystemDataSource.cpp @@ -1024,7 +1024,7 @@ FileSystemDataSource::GetFolderList(nsIRDFResource *source, nsISimpleEnumerator* nsFileURL parentDir(uri); nsNativeFileSpec nativeDir(parentDir); - for (nsDirectoryIterator i(nativeDir); i.Exists(); i++) + for (nsDirectoryIterator i(nativeDir, PR_FALSE); i.Exists(); i++) { const nsNativeFileSpec nativeSpec = (const nsNativeFileSpec &)i; if (!isVisible(nativeSpec)) continue; diff --git a/mozilla/rdf/datasource/src/nsSearchDataSource.cpp b/mozilla/rdf/datasource/src/nsSearchDataSource.cpp index e0034efbffb..c55c815f36b 100755 --- a/mozilla/rdf/datasource/src/nsSearchDataSource.cpp +++ b/mozilla/rdf/datasource/src/nsSearchDataSource.cpp @@ -1079,7 +1079,7 @@ SearchDataSource::GetSearchEngineList() searchSitesDir += "search"; nsFileSpec nativeDir(searchSitesDir); #endif - for (nsDirectoryIterator i(nativeDir); i.Exists(); i++) + for (nsDirectoryIterator i(nativeDir, PR_FALSE); i.Exists(); i++) { const nsFileSpec fileSpec = (const nsFileSpec &)i; const char *childURL = fileSpec; @@ -1229,7 +1229,7 @@ SearchDataSource::ReadFileContents(char *baseFilename, nsString& sourceContents) // on Mac, use system's search files nsSpecialSystemDirectory searchSitesDir(nsSpecialSystemDirectory::Mac_InternetSearchDirectory); nsFileSpec nativeDir(searchSitesDir); - for (nsDirectoryIterator i(nativeDir); i.Exists(); i++) + for (nsDirectoryIterator i(nativeDir, PR_FALSE); i.Exists(); i++) { const nsFileSpec fileSpec = (const nsFileSpec &)i; const char *childURL = fileSpec; diff --git a/mozilla/widget/src/xpwidgets/nsFileSpecWithUIImpl.h b/mozilla/widget/src/xpwidgets/nsFileSpecWithUIImpl.h index 241713b4016..80c69a645c7 100644 --- a/mozilla/widget/src/xpwidgets/nsFileSpecWithUIImpl.h +++ b/mozilla/widget/src/xpwidgets/nsFileSpecWithUIImpl.h @@ -131,6 +131,14 @@ class nsFileSpecWithUIImpl /* boolean isHidden (); */ NS_IMETHOD isHidden(PRBool *_retval) { return mBaseFileSpec ? mBaseFileSpec->isHidden(_retval) : NS_ERROR_NOT_INITIALIZED; } + + /* boolean isSymlink (); */ + NS_IMETHOD isSymlink(PRBool *_retval) + { return mBaseFileSpec ? mBaseFileSpec->isSymlink(_retval) : NS_ERROR_NOT_INITIALIZED; } + + /* void resolveSymlink (); */ + NS_IMETHOD resolveSymlink() + { return mBaseFileSpec ? mBaseFileSpec->resolveSymlink() : NS_ERROR_NOT_INITIALIZED; } /* readonly attribute unsigned long FileSize; */ NS_IMETHOD GetFileSize(PRUint32 *aFileSize) diff --git a/mozilla/xpcom/build/makefile.win b/mozilla/xpcom/build/makefile.win index 2ab1853e246..fc065ea1648 100644 --- a/mozilla/xpcom/build/makefile.win +++ b/mozilla/xpcom/build/makefile.win @@ -74,6 +74,7 @@ LLIBS = \ WIN_LIBS = \ shell32.lib \ + ole32.lib \ !if defined(MOZ_TRACE_XPCOM_REFCNT) imagehlp.lib \ !endif diff --git a/mozilla/xpcom/io/nsFileSpec.h b/mozilla/xpcom/io/nsFileSpec.h index ef9429a6c8c..320c22fd3fd 100644 --- a/mozilla/xpcom/io/nsFileSpec.h +++ b/mozilla/xpcom/io/nsFileSpec.h @@ -339,8 +339,10 @@ class NS_COM nsFileSpec nsFileSpec( short vRefNum, long parID, - ConstStr255Param name); - nsFileSpec(const FSSpec& inSpec); + ConstStr255Param name, + PRBool resolveAlias = PR_TRUE); + + nsFileSpec(const FSSpec& inSpec, PRBool resolveAlias = PR_TRUE); void operator = (const FSSpec& inSpec); operator FSSpec* () { return &mSpec; } @@ -357,8 +359,7 @@ class NS_COM nsFileSpec // a secret temp directory and modifies the spec to point // to it. Sets mError. void ResolveAlias(PRBool& wasAliased); - // Called for the spec of an alias. Modifies the spec to - // point to the original. Sets mError. + // ** do not use this function, instead us ResolveSymlink() void MakeUnique(ConstStr255Param inSuggestedLeafName); StringPtr GetLeafPName() { return mSpec.name; } ConstStr255Param GetLeafPName() const { return mSpec.name; } @@ -458,10 +459,15 @@ class NS_COM nsFileSpec PRBool IsHidden() const; + PRBool IsSymlink() const; //-------------------------------------------------- // Creation and deletion of objects. These can modify the disk. //-------------------------------------------------- + nsresult ResolveSymlink(PRBool& wasSymlink); + // Called for the spec of an alias. Modifies the spec to + // point to the original. Sets mError. + void CreateDirectory(int mode = 0700 /* for unix */); void CreateDir(int mode = 0700) { CreateDirectory(mode); } // workaround for yet another VC++ bug with long identifiers. @@ -664,26 +670,23 @@ class NS_COM nsDirectoryIterator // Example: // // nsFileSpec parentDir(...); // directory over whose children we shall iterate -// for (nsDirectoryIterator i(parentDir); i.Exists(); i++) +// for (nsDirectoryIterator i(parentDir, PR_FALSE); i.Exists(); i++) // { // // do something with i.Spec() // } // -// or: +// - or - // -// for (nsDirectoryIterator i(parentDir, -1); i.Exists(); i--) +// for (nsDirectoryIterator i(parentDir, PR_TRUE); i.Exists(); i--) // { // // do something with i.Spec() // } -// -// Currently, the only platform on which backwards iteration actually goes backwards -// is Macintosh. On other platforms, both styles will work, but will go forwards. +// This one passed the PR_TRUE flag which will resolve any symlink encountered. //======================================================================================== { public: - nsDirectoryIterator( - const nsFileSpec& parent, - int iterateDirection = +1); + nsDirectoryIterator( const nsFileSpec& parent, + PRBool resoveSymLinks); #ifndef XP_MAC // Macintosh currently doesn't allocate, so needn't clean up. virtual ~nsDirectoryIterator(); @@ -711,6 +714,7 @@ class NS_COM nsDirectoryIterator nsFileSpec mCurrent; PRBool mExists; + PRBool mResoveSymLinks; #if defined(XP_UNIX) || defined(XP_BEOS) DIR* mDir; diff --git a/mozilla/xpcom/io/nsFileSpecBeOS.cpp b/mozilla/xpcom/io/nsFileSpecBeOS.cpp index dd3051c62c4..d859ef17ac8 100644 --- a/mozilla/xpcom/io/nsFileSpecBeOS.cpp +++ b/mozilla/xpcom/io/nsFileSpecBeOS.cpp @@ -118,9 +118,50 @@ PRBool nsFileSpec::IsDirectory() const PRBool nsFileSpec::IsHidden() const //---------------------------------------------------------------------------------------- { - return PR_FALSE; // FIX!!!!! + PRBool hidden = PR_TRUE; + char *leafname = GetLeafName(); + if (nsnull != leafname) + { + if ((!strcmp(leafname, ".")) || (!strcmp(leafname, ".."))) + { + hidden = PR_FALSE; + } + nsCRT::free(leafname); + } + return hidden; } // nsFileSpec::IsHidden +//---------------------------------------------------------------------------------------- +PRBool nsFileSpec::IsSymlink() const +//---------------------------------------------------------------------------------------- +{ + struct stat st; + if (!mPath.IsEmpty() && stat(mPath, &st) == 0 && S_ISLNK(st.st_mode)) + return PR_TRUE; + + return PR_FALSE; +} // nsFileSpec::IsSymlink + +//---------------------------------------------------------------------------------------- +nsresult nsFileSpec::ResolveSymlink(PRBool& wasAliased) +//---------------------------------------------------------------------------------------- +{ + wasAliased = PR_FALSE; + + char resolvedPath[MAXPATHLEN]; + int charCount = readlink(mPath, (char*)&resolvedPath, MAXPATHLEN); + if (0 < charCount) + { + if (MAXPATHLEN > charCount) + resolvedPath[charCount] = '\0'; + + wasAliased = PR_TRUE; + mPath = (char*)&resolvedPath; + } + + return NS_OK; +} // nsFileSpec::ResolveSymlink + //---------------------------------------------------------------------------------------- void nsFileSpec::GetParent(nsFileSpec& outSpec) const //---------------------------------------------------------------------------------------- @@ -167,7 +208,7 @@ void nsFileSpec::Delete(PRBool inRecursive) const { if (inRecursive) { - for (nsDirectoryIterator i(*this); i.Exists(); i++) + for (nsDirectoryIterator i(*this, PR_FALSE); i.Exists(); i++) { nsFileSpec& child = (nsFileSpec&)i; child.Delete(inRecursive); @@ -190,7 +231,7 @@ void nsFileSpec::RecursiveCopy(nsFileSpec newDir) const newDir.CreateDirectory(); } - for (nsDirectoryIterator i(*this); i.Exists(); i++) + for (nsDirectoryIterator i(*this, PR_FALSE); i.Exists(); i++) { nsFileSpec& child = (nsFileSpec&)i; @@ -398,11 +439,12 @@ PRUint32 nsFileSpec::GetDiskSpaceAvailable() const //---------------------------------------------------------------------------------------- nsDirectoryIterator::nsDirectoryIterator( const nsFileSpec& inDirectory -, int /*inIterateDirection*/) +, PRBool resolveSymlinks) //---------------------------------------------------------------------------------------- : mCurrent(inDirectory) , mExists(PR_FALSE) , mDir(nsnull) + , mResoveSymLinks(resolveSymlinks) { mCurrent += "sysygy"; // prepare the path for SetLeafName mDir = opendir((const char*)nsFilePath(inDirectory)); @@ -435,6 +477,11 @@ nsDirectoryIterator& nsDirectoryIterator::operator ++ () { mExists = PR_TRUE; mCurrent.SetLeafName(entry->d_name); + if (mResoveSymLinks) + { + PRBool ignore; + mCurrent.ResolveSymlink(ignore); + } } return *this; } // nsDirectoryIterator::operator ++ diff --git a/mozilla/xpcom/io/nsFileSpecImpl.cpp b/mozilla/xpcom/io/nsFileSpecImpl.cpp index 54aa7333fcd..589604d47a1 100644 --- a/mozilla/xpcom/io/nsFileSpecImpl.cpp +++ b/mozilla/xpcom/io/nsFileSpecImpl.cpp @@ -309,6 +309,23 @@ NS_IMETHODIMP nsFileSpecImpl::isHidden(PRBool *_retval) return mFileSpec.Error(); } +//---------------------------------------------------------------------------------------- +NS_IMETHODIMP nsFileSpecImpl::isSymlink(PRBool *_retval) +//---------------------------------------------------------------------------------------- +{ + TEST_OUT_PTR(_retval) + *_retval = mFileSpec.IsSymlink(); + return mFileSpec.Error(); +} + +//---------------------------------------------------------------------------------------- +NS_IMETHODIMP nsFileSpecImpl::resolveSymlink() +//---------------------------------------------------------------------------------------- +{ + PRBool ignore; + return mFileSpec.ResolveSymlink(ignore); +} + //---------------------------------------------------------------------------------------- NS_IMETHODIMP nsFileSpecImpl::GetFileSize(PRUint32 *aFileSize) //---------------------------------------------------------------------------------------- @@ -646,7 +663,7 @@ NS_IMETHODIMP nsDirectoryIteratorImpl::Init(nsIFileSpec *parent) //---------------------------------------------------------------------------------------- { delete mDirectoryIterator; - mDirectoryIterator = new nsDirectoryIterator(FILESPEC(parent)); + mDirectoryIterator = new nsDirectoryIterator(FILESPEC(parent), PR_FALSE); if (!mDirectoryIterator) return NS_ERROR_OUT_OF_MEMORY; return NS_OK; diff --git a/mozilla/xpcom/io/nsFileSpecImpl.h b/mozilla/xpcom/io/nsFileSpecImpl.h index 8999034c903..7ea5a8a28ca 100644 --- a/mozilla/xpcom/io/nsFileSpecImpl.h +++ b/mozilla/xpcom/io/nsFileSpecImpl.h @@ -92,6 +92,12 @@ class NS_COM nsFileSpecImpl /* boolean isHidden (); */ NS_IMETHOD isHidden(PRBool *_retval); + /* boolean isSymlink (); */ + NS_IMETHOD isSymlink(PRBool *_retval); + + /* void resolveSymlink (); */ + NS_IMETHOD resolveSymlink(); + /* readonly attribute unsigned long FileSize; */ NS_IMETHOD GetFileSize(PRUint32 *aFileSize); diff --git a/mozilla/xpcom/io/nsFileSpecMac.cpp b/mozilla/xpcom/io/nsFileSpecMac.cpp index 93906182de9..49db232b083 100644 --- a/mozilla/xpcom/io/nsFileSpecMac.cpp +++ b/mozilla/xpcom/io/nsFileSpecMac.cpp @@ -599,13 +599,16 @@ nsFileSpec::nsFileSpec() } //---------------------------------------------------------------------------------------- -nsFileSpec::nsFileSpec(const FSSpec& inSpec) +nsFileSpec::nsFileSpec(const FSSpec& inSpec, PRBool resolveAlias) //---------------------------------------------------------------------------------------- : mSpec(inSpec) , mError(NS_OK) { - PRBool dummy; - ResolveAlias(dummy); + if (resolveAlias) + { + PRBool dummy; + ResolveSymlink(dummy); + } } //---------------------------------------------------------------------------------------- @@ -614,8 +617,6 @@ void nsFileSpec::operator = (const FSSpec& inSpec) { mSpec = inSpec; mError = NS_OK; - PRBool dummy; - ResolveAlias(dummy); } //---------------------------------------------------------------------------------------- @@ -639,8 +640,7 @@ nsFileSpec::nsFileSpec(const char* inNativePathString, PRBool inCreateDirs) mSpec, inCreateDirs)); if (mError == NS_FILE_RESULT(fnfErr)) mError = NS_OK; - PRBool dummy; - ResolveAlias(dummy); + } // nsFileSpec::nsFileSpec //---------------------------------------------------------------------------------------- @@ -656,19 +656,22 @@ nsFileSpec::nsFileSpec(const nsString& inNativePathString, PRBool inCreateDirs) mSpec, inCreateDirs)); if (mError == NS_FILE_RESULT(fnfErr)) mError = NS_OK; - PRBool dummy; - ResolveAlias(dummy); + } // nsFileSpec::nsFileSpec //---------------------------------------------------------------------------------------- -nsFileSpec::nsFileSpec(short vRefNum, long parID, ConstStr255Param name) +nsFileSpec::nsFileSpec(short vRefNum, long parID, ConstStr255Param name, PRBool resolveAlias) //---------------------------------------------------------------------------------------- { mError = NS_FILE_RESULT(::FSMakeFSSpec(vRefNum, parID, name, &mSpec)); if (mError == NS_FILE_RESULT(fnfErr)) mError = NS_OK; - PRBool dummy; - ResolveAlias(dummy); + + if (resolveAlias) + { + PRBool dummy; + ResolveSymlink(dummy); + } } //---------------------------------------------------------------------------------------- @@ -691,8 +694,7 @@ void nsFileSpec::operator = (const char* inString) MacFileHelpers::FSSpecFromPathname(inString, mSpec, true)); if (mError == NS_FILE_RESULT(fnfErr)) mError = NS_OK; - PRBool dummy; - ResolveAlias(dummy); + } // nsFileSpec::operator = //---------------------------------------------------------------------------------------- @@ -792,6 +794,8 @@ void nsFileSpec::MakeUnique(ConstStr255Param inSuggestedLeafName) void nsFileSpec::ResolveAlias(PRBool& wasAliased) //---------------------------------------------------------------------------------------- { + NS_ASSERTION(0, "Use ResolveSymlink not ResolveAlias!"); + Boolean wasAliased2; // Type conversion Boolean <--> PRBool OSErr err = MacFileHelpers::ResolveAliasFile(mSpec, wasAliased2); if (wasAliased2) @@ -835,6 +839,37 @@ PRBool nsFileSpec::IsHidden() const return hidden; } // nsFileSpec::IsHidden +//---------------------------------------------------------------------------------------- +PRBool nsFileSpec::IsSymlink() const +//---------------------------------------------------------------------------------------- +{ + CInfoPBRec cInfo; + PRBool hidden = PR_FALSE; + + if (noErr == GetCatInfo(cInfo)) + if (cInfo.hFileInfo.ioFlFndrInfo.fdFlags & kIsAlias) + hidden = PR_TRUE; + + return hidden; +} // nsFileSpec::IsSymlink + +//---------------------------------------------------------------------------------------- +nsresult nsFileSpec::ResolveSymlink(PRBool& wasAliased) +//---------------------------------------------------------------------------------------- +{ + Boolean wasAliased2; // Type conversion Boolean <--> PRBool + OSErr err = MacFileHelpers::ResolveAliasFile(mSpec, wasAliased2); + if (wasAliased2) + { + mError = NS_FILE_RESULT(err); + wasAliased = PR_TRUE; + } + else + wasAliased = PR_FALSE; + + return mError; +} // nsFileSpec::ResolveSymlink + //---------------------------------------------------------------------------------------- void nsFileSpec::GetParent(nsFileSpec& outSpec) const //---------------------------------------------------------------------------------------- @@ -884,8 +919,7 @@ void nsFileSpec::operator += (const char* inRelativePath) } if (mError == NS_FILE_RESULT(fnfErr)) mError = NS_OK; - PRBool dummy; - ResolveAlias(dummy); + } // nsFileSpec::operator += //---------------------------------------------------------------------------------------- @@ -931,7 +965,7 @@ void nsFileSpec::RecursiveCopy(nsFileSpec newDir) const newDir.CreateDirectory(); } - for (nsDirectoryIterator i(*this); i.Exists(); i++) + for (nsDirectoryIterator i(*this, PR_FALSE); i.Exists(); i++) { nsFileSpec& child = (nsFileSpec&)i; @@ -1276,11 +1310,12 @@ void nsFileURL::operator = (const char* inString) //---------------------------------------------------------------------------------------- nsDirectoryIterator::nsDirectoryIterator( const nsFileSpec& inDirectory -, int inIterateDirection) +, PRBool resolveSymLinks) //---------------------------------------------------------------------------------------- : mCurrent(inDirectory) , mExists(false) , mIndex(-1) + , mResoveSymLinks(resolveSymLinks) { CInfoPBRec pb; OSErr err = inDirectory.GetCatInfo(pb); @@ -1294,16 +1329,9 @@ nsDirectoryIterator::nsDirectoryIterator( mVRefNum = currentSpec.vRefNum; mParID = dipb->ioDrDirID; mMaxIndex = pb.dirInfo.ioDrNmFls; - if (inIterateDirection > 0) - { - mIndex = 0; // ready to increment - ++(*this); // the pre-increment operator - } - else - { - mIndex = mMaxIndex + 1; // ready to decrement - --(*this); // the pre-decrement operator - } + mIndex = 0; // ready to increment + ++(*this); // the pre-increment operator + } // nsDirectoryIterator::nsDirectoryIterator //---------------------------------------------------------------------------------------- @@ -1324,8 +1352,14 @@ OSErr nsDirectoryIterator::SetToIndex() FSSpec temp; if (err == noErr) err = FSMakeFSSpec(mVRefNum, mParID, objectName, &temp); - mCurrent = temp; // use the operator: it clears the string cache and resolves the alias. + mCurrent = temp; // use the operator: it clears the string cache. mExists = err == noErr; + + if (mExists && mResoveSymLinks) + { + PRBool ignore; + mCurrent.ResolveSymlink(ignore); + } return err; } // nsDirectoryIterator::SetToIndex() diff --git a/mozilla/xpcom/io/nsFileSpecOS2.cpp b/mozilla/xpcom/io/nsFileSpecOS2.cpp index 16cf99fa372..1b119fb523f 100644 --- a/mozilla/xpcom/io/nsFileSpecOS2.cpp +++ b/mozilla/xpcom/io/nsFileSpecOS2.cpp @@ -194,11 +194,35 @@ PRBool nsFileSpec::IsDirectory() const return (0 == stat( mPath, &st)) && (S_IFDIR == (st.st_mode & S_IFDIR)); } +// Really should factor out DosQPI() call to an internal GetFS3() method and then use +// here, in IsDirectory(), IsFile(), GetModDate(), GetFileSize() [and a future IsReadOnly()] +// and lose the clumsy stat() calls. Exists() too. + PRBool nsFileSpec::IsHidden() const { - return PR_FALSE; // FIX! + FILESTATUS3 fs3; + APIRET rc; + PRBool bHidden = PR_FALSE; // XXX how do I return an error? + rc = DosQueryPathInfo( mPath, FIL_STANDARD, &fs3, sizeof fs3); + if( !rc) + bHidden = fs3.attrFile & FILE_HIDDEN ? PR_TRUE : PR_FALSE; + + return bHidden; } +// On FAT or HPFS there's no such thing as a symlink; it's possible that JFS +// (new with Warp Server for e-business) does know what they are. Someone +// with a recent toolkit should check it out, but this will be OK for now. +PRBool nsFileSpec::IsSymlink() const +{ + return PR_FALSE; +} + +nsresult nsFileSpec::ResolveSymlink(PRBool& wasAliased) +{ + return NS_OK; +} + void nsFileSpec::GetModDate( TimeStamp& outStamp) const { struct stat st; @@ -280,7 +304,7 @@ void nsFileSpec::Delete( PRBool inRecursive) const { if( inRecursive) { - for( nsDirectoryIterator i(*this); i.Exists(); i++) + for( nsDirectoryIterator i(*this, PR_FALSE); i.Exists(); i++) { nsFileSpec &child = (nsFileSpec &) i; child.Delete( inRecursive); @@ -404,8 +428,11 @@ nsresult nsFileSpec::Execute( const char *inArgs) const // nsDirectoryIterator ------------------------------------------------------ nsDirectoryIterator::nsDirectoryIterator( const nsFileSpec &aDirectory, - int inIterateDirection) - : mCurrent( aDirectory), mDir( nsnull), mExists(PR_FALSE) + PRBool resolveSymlinks) +: mCurrent( aDirectory), + mDir( nsnull), + mExists(PR_FALSE), + mResoveSymLinks(resolveSymlinks) { mDir = PR_OpenDir( aDirectory); mCurrent += "dummy"; @@ -428,6 +455,11 @@ nsDirectoryIterator &nsDirectoryIterator::operator ++ () { mExists = PR_TRUE; mCurrent.SetLeafName( entry->name); + if (mResoveSymLinks) + { + PRBool ignore; + mCurrent.ResolveSymlink(ignore); + } } return *this; } diff --git a/mozilla/xpcom/io/nsFileSpecUnix.cpp b/mozilla/xpcom/io/nsFileSpecUnix.cpp index 116d936ca2f..357b88befd7 100644 --- a/mozilla/xpcom/io/nsFileSpecUnix.cpp +++ b/mozilla/xpcom/io/nsFileSpecUnix.cpp @@ -200,6 +200,38 @@ PRBool nsFileSpec::IsHidden() const return hidden; } // nsFileSpec::IsHidden +//---------------------------------------------------------------------------------------- +PRBool nsFileSpec::IsSymlink() const +//---------------------------------------------------------------------------------------- +{ + struct stat st; + if (!mPath.IsEmpty() && stat(mPath, &st) == 0 && S_ISLNK(st.st_mode)) + return PR_TRUE; + + return PR_FALSE; +} // nsFileSpec::IsSymlink + +//---------------------------------------------------------------------------------------- +nsresult nsFileSpec::ResolveSymlink(PRBool& wasAliased) +//---------------------------------------------------------------------------------------- +{ + wasAliased = PR_FALSE; + + char resolvedPath[MAXPATHLEN]; + int charCount = readlink(mPath, (char*)&resolvedPath, MAXPATHLEN); + if (0 < charCount) + { + if (MAXPATHLEN > charCount) + resolvedPath[charCount] = '\0'; + + wasAliased = PR_TRUE; + mPath = (char*)&resolvedPath; + } + + return NS_OK; +} // nsFileSpec::ResolveSymlink + + //---------------------------------------------------------------------------------------- void nsFileSpec::GetParent(nsFileSpec& outSpec) const //---------------------------------------------------------------------------------------- @@ -246,7 +278,7 @@ void nsFileSpec::Delete(PRBool inRecursive) const { if (inRecursive) { - for (nsDirectoryIterator i(*this); i.Exists(); i++) + for (nsDirectoryIterator i(*this, PR_FALSE); i.Exists(); i++) { nsFileSpec& child = (nsFileSpec&)i; child.Delete(inRecursive); @@ -269,7 +301,7 @@ void nsFileSpec::RecursiveCopy(nsFileSpec newDir) const newDir.CreateDirectory(); } - for (nsDirectoryIterator i(*this); i.Exists(); i++) + for (nsDirectoryIterator i(*this, PR_FALSE); i.Exists(); i++) { nsFileSpec& child = (nsFileSpec&)i; @@ -445,6 +477,9 @@ nsresult nsFileSpec::Execute(const char* inArgs ) const PRUint32 nsFileSpec::GetDiskSpaceAvailable() const //---------------------------------------------------------------------------------------- { + +#if defined(HAVE_SYS_STATFS_H) || defined(HAVE_SYS_STATVFS_H) + char curdir [MAXPATHLEN]; if (mPath.IsEmpty()) { @@ -467,7 +502,17 @@ PRUint32 nsFileSpec::GetDiskSpaceAvailable() const 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); + +#else + /* + ** This platform doesn't have statfs or statvfs, so we don't have much + ** choice but to "hope for the best as we did in cheddar". + */ + return ULONG_MAX; +#endif /* HAVE_SYS_STATFS_H or HAVE_SYS_STATVFS_H */ + } // nsFileSpec::GetDiskSpace() //======================================================================================== @@ -475,13 +520,12 @@ PRUint32 nsFileSpec::GetDiskSpaceAvailable() const //======================================================================================== //---------------------------------------------------------------------------------------- -nsDirectoryIterator::nsDirectoryIterator( - const nsFileSpec& inDirectory -, int /*inIterateDirection*/) +nsDirectoryIterator::nsDirectoryIterator(const nsFileSpec& inDirectory, PRBool resolveSymLinks) //---------------------------------------------------------------------------------------- : mCurrent(inDirectory) , mExists(PR_FALSE) , mDir(nsnull) + , mResoveSymLinks(resolveSymLinks) { mCurrent += "sysygy"; // prepare the path for SetLeafName mDir = opendir((const char*)nsFilePath(inDirectory)); @@ -514,6 +558,11 @@ nsDirectoryIterator& nsDirectoryIterator::operator ++ () { mExists = PR_TRUE; mCurrent.SetLeafName(entry->d_name); + if (mResoveSymLinks) + { + PRBool ignore; + mCurrent.ResolveSymlink(ignore); + } } return *this; } // nsDirectoryIterator::operator ++ diff --git a/mozilla/xpcom/io/nsFileSpecWin.cpp b/mozilla/xpcom/io/nsFileSpecWin.cpp index ec5bb981e53..cfcd9adbb54 100644 --- a/mozilla/xpcom/io/nsFileSpecWin.cpp +++ b/mozilla/xpcom/io/nsFileSpecWin.cpp @@ -27,6 +27,9 @@ #include "nsError.h" #include "windows.h" +#include "shlobj.h" +#include "shellapi.h" +#include "shlguid.h" #ifdef UNICODE #define CreateDirectoryW CreateDirectory @@ -235,6 +238,113 @@ PRBool nsFileSpec::IsHidden() const } // nsFileSpec::IsHidden +//---------------------------------------------------------------------------------------- +PRBool nsFileSpec::IsSymlink() const +//---------------------------------------------------------------------------------------- +{ + HRESULT hres; + IShellLink* psl; + + PRBool isSymlink = PR_FALSE; + + CoInitialize(NULL); + // Get a pointer to the IShellLink interface. + hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**)&psl); + if (SUCCEEDED(hres)) + { + IPersistFile* ppf; + + // Get a pointer to the IPersistFile interface. + hres = psl->QueryInterface(IID_IPersistFile, (void**)&ppf); + + if (SUCCEEDED(hres)) + { + WORD wsz[MAX_PATH]; + // Ensure that the string is Unicode. + MultiByteToWideChar(CP_ACP, 0, mPath, -1, wsz, MAX_PATH); + + // Load the shortcut. + hres = ppf->Load(wsz, STGM_READ); + if (SUCCEEDED(hres)) + { + isSymlink = PR_TRUE; + } + + // Release the pointer to the IPersistFile interface. + ppf->Release(); + } + + // Release the pointer to the IShellLink interface. + psl->Release(); + } + + return isSymlink; +} + + +//---------------------------------------------------------------------------------------- +nsresult nsFileSpec::ResolveSymlink(PRBool& wasSymlink) +//---------------------------------------------------------------------------------------- +{ + wasSymlink = PR_FALSE; // assume failure + + HRESULT hres; + IShellLink* psl; + + // Get a pointer to the IShellLink interface. + hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**)&psl); + if (SUCCEEDED(hres)) + { + IPersistFile* ppf; + + // Get a pointer to the IPersistFile interface. + hres = psl->QueryInterface(IID_IPersistFile, (void**)&ppf); + + if (SUCCEEDED(hres)) + { + WORD wsz[MAX_PATH]; + // Ensure that the string is Unicode. + MultiByteToWideChar(CP_ACP, 0, mPath, -1, wsz, MAX_PATH); + + // Load the shortcut. + hres = ppf->Load(wsz, STGM_READ); + if (SUCCEEDED(hres)) + { + wasSymlink = PR_TRUE; + + // Resolve the link. + hres = psl->Resolve(nsnull, SLR_NO_UI ); + if (SUCCEEDED(hres)) + { + char szGotPath[MAX_PATH]; + WIN32_FIND_DATA wfd; + + // Get the path to the link target. + hres = psl->GetPath( szGotPath, MAX_PATH, &wfd, SLGP_UNCPRIORITY ); + + if (SUCCEEDED(hres)) + { + // Here we modify the nsFileSpec; + mPath = szGotPath; + mError = NS_OK; + } + } + } + // Release the pointer to the IPersistFile interface. + ppf->Release(); + } + // Release the pointer to the IShellLink interface. + psl->Release(); + } + + if (SUCCEEDED(hres)) + return NS_OK; + + return NS_FILE_FAILURE; +} + + + //---------------------------------------------------------------------------------------- void nsFileSpec::GetParent(nsFileSpec& outSpec) const //---------------------------------------------------------------------------------------- @@ -282,7 +392,7 @@ void nsFileSpec::Delete(PRBool inRecursive) const { if (inRecursive) { - for (nsDirectoryIterator i(*this); i.Exists(); i++) + for (nsDirectoryIterator i(*this, PR_FALSE); i.Exists(); i++) { nsFileSpec& child = (nsFileSpec&)i; child.Delete(inRecursive); @@ -308,7 +418,7 @@ void nsFileSpec::RecursiveCopy(nsFileSpec newDir) const newDir.CreateDirectory(); } - for (nsDirectoryIterator i(*this); i.Exists(); i++) + for (nsDirectoryIterator i(*this, PR_FALSE); i.Exists(); i++) { nsFileSpec& child = (nsFileSpec&)i; @@ -474,13 +584,12 @@ PRUint32 nsFileSpec::GetDiskSpaceAvailable() const //======================================================================================== //---------------------------------------------------------------------------------------- -nsDirectoryIterator::nsDirectoryIterator( - const nsFileSpec& inDirectory -, int inIterateDirection) +nsDirectoryIterator::nsDirectoryIterator(const nsFileSpec& inDirectory, PRBool resolveSymlink) //---------------------------------------------------------------------------------------- : mCurrent(inDirectory) , mDir(nsnull) , mExists(PR_FALSE) + , mResoveSymLinks(resolveSymlink) { mDir = PR_OpenDir(inDirectory); mCurrent += "dummy"; @@ -507,6 +616,11 @@ nsDirectoryIterator& nsDirectoryIterator::operator ++ () { mExists = PR_TRUE; mCurrent.SetLeafName(entry->name); + if (mResoveSymLinks) + { + PRBool ignore; + mCurrent.ResolveSymlink(ignore); + } } return *this; } // nsDirectoryIterator::operator ++ diff --git a/mozilla/xpcom/io/nsIFileSpec.idl b/mozilla/xpcom/io/nsIFileSpec.idl index 20a9fbb1f79..adb3be302fa 100644 --- a/mozilla/xpcom/io/nsIFileSpec.idl +++ b/mozilla/xpcom/io/nsIFileSpec.idl @@ -91,6 +91,10 @@ interface nsIFileSpec : nsISupports void createDir(); void touch(); + + boolean isSymlink(); + void resolveSymlink(); + void rename([const] in string newLeafName); void copyToDir([const] in nsIFileSpec newParentDir); void moveToDir([const] in nsIFileSpec newParentDir); diff --git a/mozilla/xpcom/io/nsSpecialSystemDirectory.cpp b/mozilla/xpcom/io/nsSpecialSystemDirectory.cpp index c83fcd1c732..56d3b4a968c 100644 --- a/mozilla/xpcom/io/nsSpecialSystemDirectory.cpp +++ b/mozilla/xpcom/io/nsSpecialSystemDirectory.cpp @@ -165,7 +165,8 @@ static void GetCurrentProcessDirectory(nsFileSpec& aFileSpec) { aFileSpec = nsFileSpec(appFSSpec.vRefNum, catInfo.dirInfo.ioDrParID, - name); + name, + PR_TRUE); return; } } diff --git a/mozilla/xpcom/reflect/xptinfo/src/nsInterfaceInfoManager.cpp b/mozilla/xpcom/reflect/xptinfo/src/nsInterfaceInfoManager.cpp index bed7582157c..ff361dfc5b3 100644 --- a/mozilla/xpcom/reflect/xptinfo/src/nsInterfaceInfoManager.cpp +++ b/mozilla/xpcom/reflect/xptinfo/src/nsInterfaceInfoManager.cpp @@ -347,7 +347,7 @@ nsInterfaceInfoManager::initInterfaceTables() int which = 0; #endif - for (nsDirectoryIterator i(sysdir); i.Exists(); i++) { + for (nsDirectoryIterator i(sysdir, PR_FALSE); i.Exists(); i++) { // XXX need to copy? nsFileSpec spec = i.Spec(); diff --git a/mozilla/xpfe/components/history/src/nsGlobalHistory.cpp b/mozilla/xpfe/components/history/src/nsGlobalHistory.cpp index ef242079cae..cd40bf7f964 100644 --- a/mozilla/xpfe/components/history/src/nsGlobalHistory.cpp +++ b/mozilla/xpfe/components/history/src/nsGlobalHistory.cpp @@ -675,14 +675,8 @@ nsGlobalHistory::ReadHistory() rv = GetHistoryDir(&dir); if (NS_FAILED(rv)) return rv; - for (nsDirectoryIterator i(dir); i.Exists(); i++) { + for (nsDirectoryIterator i(dir, PR_TRUE); i.Exists(); i++) { const nsFileSpec spec = i.Spec(); -#ifdef XP_MAC - { - PRBool wasAlias; - spec.ResolveAlias(wasAlias); - } -#endif // convert to a path so we can inspect it: we only want to read const char* path = (const char*) spec;