diff --git a/mozilla/xpcom/io/nsDirectoryService.cpp b/mozilla/xpcom/io/nsDirectoryService.cpp index 8bb64b5564e..6219be6751d 100644 --- a/mozilla/xpcom/io/nsDirectoryService.cpp +++ b/mozilla/xpcom/io/nsDirectoryService.cpp @@ -55,6 +55,14 @@ +#ifdef XP_MAC +#define COMPONENT_REGISTRY_NAME "Component Registry" +#define COMPONENT_DIRECTORY "Components" +#else +#define COMPONENT_REGISTRY_NAME "component.reg" +#define COMPONENT_DIRECTORY "components" +#endif + @@ -225,25 +233,31 @@ static nsresult GetCurrentProcessDirectory(nsILocalFile** aFile) nsDirectoryService* nsDirectoryService::mService = nsnull; -nsDirectoryService::nsDirectoryService(nsISupports* outer) +nsDirectoryService::nsDirectoryService() { - NS_INIT_AGGREGATED(outer); + NS_INIT_REFCNT(); + mHashtable = new nsHashtable(256, PR_TRUE); + NS_ASSERTION(mHashtable != NULL, "hashtable null error"); + + NS_NewISupportsArray(getter_AddRefs(mProviders)); + NS_ASSERTION(mProviders != NULL, "providers null error"); + + RegisterProvider(NS_STATIC_CAST(nsIDirectoryServiceProvider*, this)); } NS_METHOD nsDirectoryService::Create(nsISupports *outer, REFNSIID aIID, void **aResult) { - NS_ENSURE_ARG_POINTER(aResult); - NS_ENSURE_PROPER_AGGREGATION(outer, aIID); - + NS_ENSURE_ARG_POINTER(aResult); + if (mService == nsnull) { - mService = new nsDirectoryService(outer); + mService = new nsDirectoryService(); if (mService == NULL) return NS_ERROR_OUT_OF_MEMORY; } - return mService->AggregatedQueryInterface(aIID, aResult); + return mService->QueryInterface(aIID, aResult); } PRBool @@ -256,102 +270,87 @@ nsDirectoryService::ReleaseValues(nsHashKey* key, void* data, void* closure) nsDirectoryService::~nsDirectoryService() { - Enumerate(ReleaseValues); + if (mHashtable) + mHashtable->Enumerate(ReleaseValues); } -NS_IMPL_AGGREGATED(nsDirectoryService); +NS_IMPL_ISUPPORTS3(nsDirectoryService, nsIProperties, nsIDirectoryService, nsIDirectoryServiceProvider) -NS_METHOD -nsDirectoryService::AggregatedQueryInterface(const nsIID& aIID, void** aInstancePtr) -{ - NS_ENSURE_ARG_POINTER(aInstancePtr); - - if (aIID.Equals(NS_GET_IID(nsISupports))) - *aInstancePtr = GetInner(); - else if (aIID.Equals(NS_GET_IID(nsIProperties))) - *aInstancePtr = NS_STATIC_CAST(nsIProperties*, this); - else { - *aInstancePtr = nsnull; - return NS_NOINTERFACE; - } - - NS_ADDREF((nsISupports*)*aInstancePtr); - return NS_OK; -} NS_IMETHODIMP nsDirectoryService::Define(const char* prop, nsISupports* initialValue) { - nsStringKey key(prop); - if (Exists(&key)) - return NS_ERROR_FAILURE; - - nsISupports* prevValue = (nsISupports*)Put(&key, initialValue); - NS_ASSERTION(prevValue == NULL, "hashtable error"); - NS_IF_ADDREF(initialValue); - return NS_OK; + return Set(prop, initialValue); } NS_IMETHODIMP nsDirectoryService::Undefine(const char* prop) { nsStringKey key(prop); - if (!Exists(&key)) + if (!mHashtable->Exists(&key)) return NS_ERROR_FAILURE; - nsISupports* prevValue = (nsISupports*)Remove(&key); + nsISupports* prevValue = (nsISupports*)mHashtable->Remove(&key); NS_IF_RELEASE(prevValue); return NS_OK; } +typedef struct FileData + +{ + const char* property; + nsIFile* file; + PRBool persistant; + +} FileData; + +static PRBool FindProviderFile(nsISupports* aElement, void *aData) +{ + nsCOMPtr prov = do_QueryInterface(aElement); + if (!prov) + return PR_FALSE; + + FileData* fileData = (FileData*)aData; + prov->GetFile(fileData->property, &fileData->persistant, &(fileData->file) ); + if (fileData->file) + return PR_FALSE; + + return PR_TRUE; +} + NS_IMETHODIMP nsDirectoryService::Get(const char* prop, const nsIID & uuid, void* *result) { nsStringKey key(prop); - if (!Exists(&key)) + if (!mHashtable->Exists(&key)) { - // check to see if it is one of our defaults - - if (strncmp(prop, "xpcom.currentProcess.componentRegistry", 38) == 0) - { - nsILocalFile* localFile; - - nsresult rv = GetCurrentProcessDirectory(&localFile); - if (NS_FAILED(rv)) - return rv; - -#ifdef XP_MAC - localFile->Append("Component Registry"); -#else - localFile->Append("component.reg"); -#endif /* XP_MAC */ - - Set(prop, NS_STATIC_CAST(nsILocalFile*, localFile)); - } - else if (strncmp(prop, "xpcom.currentProcess.componentDirectory", 39) == 0) - { - nsILocalFile* localFile; + // it is not one of our defaults, lets check any providers + FileData fileData; + fileData.property = prop; + fileData.file = nsnull; + fileData.persistant = PR_TRUE; - nsresult rv = GetCurrentProcessDirectory(&localFile); - if (NS_FAILED(rv)) - return rv; - -#ifdef XP_MAC - localFile->Append("Components"); -#else - localFile->Append("components"); -#endif /* XP_MAC */ - - Set(prop, NS_STATIC_CAST(nsILocalFile*, localFile)); - } + mProviders->EnumerateForwards(FindProviderFile, &fileData); + + if (fileData.file) + { + if (!fileData.persistant) + { + nsresult rv = (fileData.file)->QueryInterface(uuid, result); + NS_RELEASE(fileData.file); + return rv; + } + Set(prop, NS_STATIC_CAST(nsIFile*, fileData.file)); + NS_RELEASE(fileData.file); + } } // now check again to see if it was added above. - if (Exists(&key)) + if (mHashtable->Exists(&key)) { nsCOMPtr ourFile; - nsISupports* value = (nsISupports*)nsHashtable::Get(&key); + nsISupports* value = (nsISupports*)mHashtable->Get(&key); if (value && NS_SUCCEEDED(value->QueryInterface(NS_GET_IID(nsIFile), getter_AddRefs(ourFile)))) { @@ -368,7 +367,7 @@ NS_IMETHODIMP nsDirectoryService::Set(const char* prop, nsISupports* value) { nsStringKey key(prop); - if (Exists(&key) || value == nsnull) + if (mHashtable->Exists(&key) || value == nsnull) return NS_ERROR_FAILURE; nsCOMPtr ourFile; @@ -378,7 +377,8 @@ nsDirectoryService::Set(const char* prop, nsISupports* value) nsIFile* cloneFile; ourFile->Clone(&cloneFile); - nsISupports* prevValue = (nsISupports*)Put(&key, value); + nsISupports* prevValue = (nsISupports*)mHashtable->Put(&key, + NS_STATIC_CAST(nsISupports*,cloneFile)); NS_IF_RELEASE(prevValue); return NS_OK; } @@ -401,3 +401,52 @@ nsDirectoryService::Has(const char *prop, PRBool *_retval) return rv; } + +NS_IMETHODIMP +nsDirectoryService::RegisterProvider(nsIDirectoryServiceProvider *prov) +{ + if (!prov) + return NS_ERROR_FAILURE; + + nsCOMPtr supports = do_QueryInterface(prov); + if (supports) + return mProviders->AppendElement(supports); + return NS_ERROR_FAILURE; +} + + + + +NS_IMETHODIMP +nsDirectoryService::GetFile(const char *prop, PRBool *persistant, nsIFile **_retval) +{ + nsCOMPtr localFile; + nsresult rv; + + *_retval = nsnull; + *persistant = PR_TRUE; + + // check to see if it is one of our defaults + + if (strncmp(prop, "xpcom.currentProcess.componentRegistry", 38) == 0) + { + rv = GetCurrentProcessDirectory(getter_AddRefs(localFile)); + if (NS_FAILED(rv)) return rv; + localFile->Append(COMPONENT_REGISTRY_NAME); + } + else if (strncmp(prop, "xpcom.currentProcess.componentDirectory", 39) == 0) + { + rv = GetCurrentProcessDirectory(getter_AddRefs(localFile)); + if (NS_FAILED(rv)) return rv; + localFile->Append(COMPONENT_DIRECTORY); + } + + if (localFile) + return localFile->QueryInterface(NS_GET_IID(nsIFile), (void**)_retval); + + return NS_OK; +} + + + + diff --git a/mozilla/xpcom/io/nsDirectoryService.h b/mozilla/xpcom/io/nsDirectoryService.h index 4aa6645abc6..526cffa3ecc 100644 --- a/mozilla/xpcom/io/nsDirectoryService.h +++ b/mozilla/xpcom/io/nsDirectoryService.h @@ -23,35 +23,36 @@ #ifndef nsDirectoryService_h___ #define nsDirectoryService_h___ -#include "nsIProperties.h" +#include "nsIDirectoryService.h" #include "nsHashtable.h" -#include "nsAgg.h" #include "nsIFile.h" +#include "nsISupportsArray.h" +class nsDirectoryService : public nsIDirectoryService, public nsIProperties, public nsIDirectoryServiceProvider +{ + public: -#define NS_DIRECTORY_SERVICE_PROGID "component://netscape/file/directory_service" -#define NS_DIRECTORY_SERVICE_CLASSNAME "nsIFile Directory Service" + NS_DEFINE_STATIC_CID_ACCESSOR(NS_DIRECTORY_SERVICE_CID); + // nsISupports interface + NS_DECL_ISUPPORTS -class nsDirectoryService : public nsIProperties, public nsHashtable { -public: + NS_DECL_NSIPROPERTIES - NS_DEFINE_STATIC_CID_ACCESSOR(NS_DIRECTORY_SERVICE_CID) + NS_DECL_NSIDIRECTORYSERVICE - NS_DECL_AGGREGATED + NS_DECL_NSIDIRECTORYSERVICEPROVIDER - NS_DECL_NSIPROPERTIES - - // nsProperties methods: - nsDirectoryService(nsISupports* outer); + nsDirectoryService(); virtual ~nsDirectoryService(); static NS_METHOD Create(nsISupports *aOuter, REFNSIID aIID, void **aResult); - static PRBool ReleaseValues(nsHashKey* key, void* data, void* closure); private: static nsDirectoryService* mService; - + static PRBool ReleaseValues(nsHashKey* key, void* data, void* closure); + nsHashtable* mHashtable; + nsCOMPtr mProviders; }; diff --git a/mozilla/xpcom/io/nsLocalFileWin.cpp b/mozilla/xpcom/io/nsLocalFileWin.cpp index d648a12546b..18874680348 100644 --- a/mozilla/xpcom/io/nsLocalFileWin.cpp +++ b/mozilla/xpcom/io/nsLocalFileWin.cpp @@ -39,7 +39,9 @@ #include "shellapi.h" #include "shlguid.h" -#include +#include +#include +#include #include "prproces.h" @@ -117,70 +119,6 @@ myLL_L2II(PRInt64 result, PRInt32 *hi, PRInt32 *lo ) LL_L2I(*lo, a64); } -nsresult -MyGetFileAttributesEx(const char* file, WIN32_FILE_ATTRIBUTE_DATA* data) -{ - BOOL okay; - if (!data || !file) - return NS_ERROR_FAILURE; - - okay = PR_FALSE; - - memset(data, 0, sizeof(WIN32_FILE_ATTRIBUTE_DATA)); - data->dwFileAttributes = GetFileAttributes(file); - - if(data->dwFileAttributes != 0xFFFFFFFF) - { - if(! (data->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) - { - HANDLE hFile = CreateFile(file, - 0, - FILE_SHARE_READ, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL); - - if (hFile != INVALID_HANDLE_VALUE) - { - okay = GetFileTime(hFile, - &data->ftCreationTime, - &data->ftLastAccessTime, - &data->ftLastWriteTime); - if (okay) - { - // Try to obtain hFile's huge size. - data->nFileSizeLow = GetFileSize (hFile, - &data->nFileSizeHigh); - - if (data->nFileSizeLow == 0xFFFFFFFF && - GetLastError() != NO_ERROR ) - { - //error in getting filesize - okay = PR_FALSE; - } - else - { - okay = PR_TRUE; - } - } - - CloseHandle(hFile); - } - } - else - { - // it is a directory, I dont think that there is a wy to get the time or size. - okay = PR_TRUE; - } - } - - if (!okay) - return ConvertWinError(GetLastError()); - - return NS_OK; -} - class nsDirEnumerator : public nsISimpleEnumerator { @@ -564,24 +502,24 @@ nsLocalFile::ResolveAndStat(PRBool resolveTerminal) } mLastResolution = resolveTerminal; - const char *workingFilePath = mWorkingPath.GetBuffer(); - nsresult result; - - // First we will see if the workingPath exists. If it does, then we // can simply use that as the resolved path. This simplification can // be done on windows cause its symlinks (shortcuts) use the .lnk // file extension. - result = MyGetFileAttributesEx( workingFilePath, &mFileAttrData); - if ( NS_SUCCEEDED(result) ) + const char *workingFilePath = mWorkingPath.GetBuffer(); + + PRStatus status = PR_GetFileInfo64(workingFilePath, &mFileInfo64); + if ( status == PR_SUCCESS ) { mResolvedPath.SetString(workingFilePath); mDirty = PR_FALSE; return NS_OK; } + nsresult result; + // okay, something is wrong with the working path. We will try to resolve it. char *resolvePath; @@ -602,10 +540,13 @@ nsLocalFile::ResolveAndStat(PRBool resolveTerminal) char linkStr[MAX_PATH]; strcpy(linkStr, mResolvedPath.GetBuffer()); strcat(linkStr, ".lnk"); - result = MyGetFileAttributesEx(linkStr, &mFileAttrData); - if (NS_SUCCEEDED(result)) + status = PR_GetFileInfo64(linkStr, &mFileInfo64); + + if ( status == PR_SUCCESS ) mDirty = PR_FALSE; + else + result = NS_ERROR_FAILURE; return result; } @@ -744,7 +685,7 @@ nsLocalFile::Append(const char *node) { if ( (node == nsnull) || (*node == '/') || - (*node == '.') || + (strstr(node, "..") != nsnull) || (strchr(node, '\\') != nsnull) || (strchr(node, '/') != nsnull) ) { @@ -1198,60 +1139,10 @@ nsLocalFile::GetLastModificationDate(PRInt64 *aLastModificationDate) if (NS_FAILED(rv)) return rv; - PRUint32 high = mFileAttrData.ftLastWriteTime.dwHighDateTime; - PRUint32 low = mFileAttrData.ftLastWriteTime.dwLowDateTime; - - myLL_II2L(high, low, aLastModificationDate); - + *aLastModificationDate = mFileInfo64.modifyTime; return NS_OK; } -NS_IMETHODIMP -nsLocalFile::SetLastModificationDate(PRInt64 aLastModificationDate) -{ - nsresult rv = ResolveAndStat(PR_TRUE); - - if (NS_FAILED(rv)) - return rv; - - FILETIME time = mFileAttrData.ftLastWriteTime; - - PRInt32 hi, lo; - myLL_L2II(aLastModificationDate, &hi, &lo ); - - time.dwHighDateTime = hi; - time.dwLowDateTime = lo; - - const char *filePath = mResolvedPath.GetBuffer(); - - HANDLE file = CreateFile( filePath, // pointer to name of the file - GENERIC_WRITE, // access (write) mode - 0, // share mode - NULL, // pointer to security attributes - OPEN_EXISTING, // how to create - 0, // file attributes (??xxx) - NULL); - - if (!file) - { - // could not open file for writing. - MakeDirty(); - return NS_ERROR_FAILURE; //TODO better error code - } - - if ( 0 == SetFileTime(file, NULL, &time, &time) ) - { - // could not set time - MakeDirty(); - return NS_ERROR_FAILURE; - } - - - MakeDirty(); - - CloseHandle( file ); - return NS_OK; -} NS_IMETHODIMP nsLocalFile::GetLastModificationDateOfLink(PRInt64 *aLastModificationDate) @@ -1265,26 +1156,42 @@ nsLocalFile::GetLastModificationDateOfLink(PRInt64 *aLastModificationDate) if (NS_FAILED(rv)) return rv; - FILETIME time = mFileAttrData.ftLastWriteTime; - - myLL_II2L(time.dwHighDateTime, time.dwLowDateTime, aLastModificationDate); - + *aLastModificationDate = mFileInfo64.modifyTime; return NS_OK; } + +NS_IMETHODIMP +nsLocalFile::SetLastModificationDate(PRInt64 aLastModificationDate) +{ + return nsLocalFile::SetModDate(aLastModificationDate, PR_TRUE); +} + + NS_IMETHODIMP nsLocalFile::SetLastModificationDateOfLink(PRInt64 aLastModificationDate) { - nsresult rv = ResolveAndStat(PR_FALSE); + return nsLocalFile::SetModDate(aLastModificationDate, PR_FALSE); +} + +static const PRTime filetime_offset = 116444736000000000i64; +nsresult +nsLocalFile::SetModDate(PRInt64 aLastModificationDate, PRBool resolveTerminal) +{ + nsresult rv = ResolveAndStat(resolveTerminal); if (NS_FAILED(rv)) return rv; - PRInt32 hi, lo; - myLL_L2II(aLastModificationDate, &hi, &lo ); - - FILETIME time = mFileAttrData.ftLastWriteTime; + PRInt64 windowsTime = aLastModificationDate; + + windowsTime = (windowsTime + filetime_offset) * 10i64; + + PRInt32 hi, lo; + myLL_L2II(windowsTime, &hi, &lo ); + + FILETIME time; time.dwHighDateTime = hi; time.dwLowDateTime = lo; @@ -1298,31 +1205,36 @@ nsLocalFile::SetLastModificationDateOfLink(PRInt64 aLastModificationDate) 0, // file attributes (??xxx) NULL); + MakeDirty(); + if (!file) { // could not open file for writing. - MakeDirty(); return NS_ERROR_FAILURE; //TODO better error code } if ( 0 == SetFileTime(file, NULL, &time, &time) ) { // could not set time - MakeDirty(); return NS_ERROR_FAILURE; } - - MakeDirty(); - CloseHandle( file ); return NS_OK; -} +} NS_IMETHODIMP nsLocalFile::GetPermissions(PRUint32 *aPermissions) { - return NS_ERROR_NOT_IMPLEMENTED; + nsresult rv = ResolveAndStat(PR_TRUE); + + if (NS_FAILED(rv)) + return rv; + + const char *filePath = mResolvedPath.GetBuffer(); + + + return NS_OK; } NS_IMETHODIMP @@ -1335,13 +1247,31 @@ nsLocalFile::GetPermissionsOfLink(PRUint32 *aPermissionsOfLink) NS_IMETHODIMP nsLocalFile::SetPermissions(PRUint32 aPermissions) { - return NS_ERROR_NOT_IMPLEMENTED; + nsresult rv = ResolveAndStat(PR_TRUE); + + if (NS_FAILED(rv)) + return rv; + + const char *filePath = mResolvedPath.GetBuffer(); + if( chmod(filePath, aPermissions) == -1 ) + return NS_ERROR_FAILURE; + + return NS_OK; } NS_IMETHODIMP nsLocalFile::SetPermissionsOfLink(PRUint32 aPermissions) { - return NS_ERROR_NOT_IMPLEMENTED; + nsresult rv = ResolveAndStat(PR_FALSE); + + if (NS_FAILED(rv)) + return rv; + + const char *filePath = mResolvedPath.GetBuffer(); + if( chmod(filePath, aPermissions) == -1 ) + return NS_ERROR_FAILURE; + + return NS_OK; } @@ -1357,8 +1287,8 @@ nsLocalFile::GetFileSize(PRInt64 *aFileSize) if (NS_FAILED(rv)) return rv; - myLL_II2L(mFileAttrData.nFileSizeHigh, mFileAttrData.nFileSizeLow, aFileSize); + *aFileSize = mFileInfo64.size; return NS_OK; } @@ -1430,7 +1360,7 @@ nsLocalFile::GetFileSizeOfLink(PRInt64 *aFileSize) if (NS_FAILED(rv)) return rv; - myLL_II2L(mFileAttrData.nFileSizeHigh, mFileAttrData.nFileSizeLow, aFileSize); + *aFileSize = mFileInfo64.size; return NS_OK; } @@ -1547,7 +1477,10 @@ nsLocalFile::IsWritable(PRBool *_retval) if (NS_FAILED(rv)) return rv; - *_retval = !((mFileAttrData.dwFileAttributes & FILE_ATTRIBUTE_READONLY) != 0); + const char *workingFilePath = mWorkingPath.GetBuffer(); + DWORD word = GetFileAttributes(workingFilePath); + + *_retval = !((word & FILE_ATTRIBUTE_READONLY) != 0); return NS_OK; } @@ -1618,8 +1551,8 @@ nsLocalFile::IsDirectory(PRBool *_retval) if (NS_FAILED(rv)) return rv; - - *_retval = ((mFileAttrData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0); + + *_retval = (mFileInfo64.type == PR_FILE_DIRECTORY); return NS_OK; } @@ -1627,9 +1560,15 @@ nsLocalFile::IsDirectory(PRBool *_retval) NS_IMETHODIMP nsLocalFile::IsFile(PRBool *_retval) { - nsresult rv = IsDirectory(_retval); - *_retval = !*_retval; + NS_ENSURE_ARG(_retval); + *_retval = PR_FALSE; + nsresult rv = ResolveAndStat(PR_TRUE); + + if (NS_FAILED(rv)) + return rv; + + *_retval = (mFileInfo64.type == PR_FILE_FILE); return rv; } @@ -1644,7 +1583,10 @@ nsLocalFile::IsHidden(PRBool *_retval) if (NS_FAILED(rv)) return rv; - *_retval = ((mFileAttrData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) != 0); + const char *workingFilePath = mWorkingPath.GetBuffer(); + DWORD word = GetFileAttributes(workingFilePath); + + *_retval = ((word & FILE_ATTRIBUTE_HIDDEN) != 0); return NS_OK; } @@ -1684,7 +1626,10 @@ nsLocalFile::IsSpecial(PRBool *_retval) if (NS_FAILED(rv)) return rv; - *_retval = ((mFileAttrData.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) != 0); + const char *workingFilePath = mWorkingPath.GetBuffer(); + DWORD word = GetFileAttributes(workingFilePath); + + *_retval = ((word & FILE_ATTRIBUTE_SYSTEM) != 0); return NS_OK; } diff --git a/mozilla/xpcom/io/nsLocalFileWin.h b/mozilla/xpcom/io/nsLocalFileWin.h index d0830e5f2cf..e9b90771766 100644 --- a/mozilla/xpcom/io/nsLocalFileWin.h +++ b/mozilla/xpcom/io/nsLocalFileWin.h @@ -79,8 +79,8 @@ private: IPersistFile* mPersistFile; IShellLink* mShellLink; - - WIN32_FILE_ATTRIBUTE_DATA mFileAttrData; + + PRFileInfo64 mFileInfo64; void MakeDirty(); nsresult ResolveAndStat(PRBool resolveTerminal); @@ -89,6 +89,7 @@ private: nsresult CopyMove(nsIFile *newParentDir, const char *newName, PRBool followSymlinks, PRBool move); nsresult CopySingleFile(nsIFile *source, nsIFile* dest, const char * newName, PRBool followSymlinks, PRBool move); + nsresult SetModDate(PRInt64 aLastModificationDate, PRBool resolveTerminal); }; #endif