Fixes for 28257, 21628, 27076, 18186, 25584

1) Implement nsDirectoryService.  This makes the service extensible so that
components can do delayed registration.

2) Fixes windows Append meathod which did not work with . prepended files.

3) Fixes memory leaks in nsDirectoryService

4) Fixes SetPermissions() on Win32.  This was in my tree for a while.  It basically
calls through to chmod just like on unix.

5) Fixes GetModificationDate. Win32 now return PRTime for dates.

r = scc, valeski, warren, wtc (suggestions)
a = jevering


git-svn-id: svn://10.0.0.236/trunk@61389 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
dougt%netscape.com
2000-02-21 21:51:47 +00:00
parent 7d0ede603e
commit 6cea14f715
4 changed files with 238 additions and 242 deletions

View File

@@ -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<nsIDirectoryServiceProvider> 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<nsIFile> 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<nsIFile> 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<nsISupports> 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<nsILocalFile> 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;
}

View File

@@ -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<nsISupportsArray> mProviders;
};

View File

@@ -39,7 +39,9 @@
#include "shellapi.h"
#include "shlguid.h"
#include <stdio.h>
#include <io.h>
#include <stdio.h>
#include <stdlib.h>
#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;
}

View File

@@ -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