gecko-dev/xpcom/io/nsIFileImplWin.cpp

991 строка
25 KiB
C++

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code,
* released March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Doug Turner <dougt@netscape.com>
*/
#include "nsCOMPtr.h"
#include "nsIAllocator.h"
#include "nsIFileImplWin.h"
#include "nsFileUtils.h"
#include "prtypes.h"
#include "prio.h"
#include <direct.h>
#include "windows.h"
// For older version (<6.0) of the VC Compiler
#if (_MSC_VER == 1100)
#define INITGUID
#include "objbase.h"
DEFINE_OLEGUID(IID_IPersistFile, 0x0000010BL, 0, 0);
#endif
#include "shlobj.h"
#include "shellapi.h"
#include "shlguid.h"
nsIFileImpl::nsIFileImpl()
{
NS_INIT_REFCNT();
CoInitialize(NULL); // FIX: we should probably move somewhere higher up during startup
makeDirty();
}
nsIFileImpl::~nsIFileImpl()
{
CoUninitialize();
}
/* nsISupports interface implementation. */
NS_IMPL_ISUPPORTS1(nsIFileImpl, nsIFile)
NS_METHOD
nsIFileImpl::Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr)
{
NS_ENSURE_ARG_POINTER(aInstancePtr);
NS_ENSURE_PROPER_AGGREGATION(outer, aIID);
nsIFileImpl* inst = new nsIFileImpl();
if (inst == NULL)
return NS_ERROR_OUT_OF_MEMORY;
nsresult rv = inst->QueryInterface(aIID, aInstancePtr);
if (NS_FAILED(rv))
{
delete inst;
return rv;
}
return NS_OK;
}
// This function resets any cached information about the file.
void
nsIFileImpl::makeDirty()
{
mResolutionDirty = PR_TRUE;
mStatDirty = PR_TRUE;
}
//----------------------------------------------------------------------------------------
//
// resolveWorkingPath
// this function will walk the native path of |this| resolving any symbolic
// links found. The new resulting path will be placed into mResolvedPath
// and mResolutionDirty will be set to true.
//----------------------------------------------------------------------------------------
nsresult
nsIFileImpl::resolveWorkingPath()
{
if (!mResolutionDirty)
return NS_OK;
nsresult rv = NS_OK;
HRESULT hres;
IShellLink* psl;
// Get the native path for |this|
char* filePath = (char*) nsAllocator::Clone( mWorkingPath, strlen(mWorkingPath)+1 );
if (filePath == nsnull)
return NS_ERROR_NULL_POINTER;
// 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))
{
char* slash = strchr(filePath, '\\');
if (slash == nsnull)
return NS_ERROR_NULL_POINTER;
// skip the first '\\'
slash = strchr(++slash, '\\');
while (slash)
{
*slash = '\0';
WORD wsz[MAX_PATH];
if (strstr(filePath, ".lnk") == 0)
{
char linkStr[MAX_PATH];
strcpy(linkStr, filePath);
strcat(linkStr, ".lnk");
// Ensure that the string is Unicode.
MultiByteToWideChar(CP_ACP, 0, linkStr, -1, wsz, MAX_PATH);
}
else
{
// Ensure that the string is Unicode.
MultiByteToWideChar(CP_ACP, 0, filePath, -1, wsz, MAX_PATH);
}
// Load the shortcut.
hres = ppf->Load(wsz, STGM_READ);
if (SUCCEEDED(hres))
{
// 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))
{
char *temp = (char*) nsAllocator::Alloc( MAX_PATH );
char *carot;
strcpy(temp, szGotPath);
strcat(temp, "\\");
// save where we left off.
carot = (temp + strlen(temp) -1 );
// append all the stuff that we have not done.
strcat(temp, ++slash);
nsAllocator::Free(filePath);
filePath = temp;
slash = carot;
}
}
}
*slash = '\\';
++slash;
slash = strchr(slash, '\\');
rv = NS_OK;
}
// Release the pointer to the IPersistFile interface.
ppf->Release();
}
// Release the pointer to the IShellLink interface.
psl->Release();
}
mResolvedPath.SetString(filePath);
if(filePath)
nsAllocator::Free(filePath);
return rv;
}
nsresult
nsIFileImpl::bufferedStat(struct stat *st)
{
if (!mStatDirty)
{
*st = mBuffered_st;
return mBuffered_stat_rv;
}
nsresult rv = resolveWorkingPath();
if (NS_FAILED(rv))
return rv;
const char *filePath = mResolvedPath.GetBuffer();
mBuffered_stat_rv = stat(filePath, &mBuffered_st);
*st = mBuffered_st;
return rv;
}
NS_IMETHODIMP
nsIFileImpl::InitWithKey(const char *fileKey)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsIFileImpl::InitWithFile(nsIFile *file)
{
NS_ENSURE_ARG(file);
// TODO: how do we get to the |file|'s working XXXXXX
// directory so that we do not expose
// symlinked directories.
char* aFilePath;
file->GetPath(nsIFile::NATIVE_PATH, &aFilePath);
if (aFilePath == nsnull)
return NS_ERROR_FILE_UNRECONGNIZED_PATH;
mWorkingPath.SetString(aFilePath);
nsAllocator::Free(aFilePath);
makeDirty();
return NS_OK;
}
NS_IMETHODIMP
nsIFileImpl::InitWithPath(PRUint32 pathType, const char *filePath)
{
NS_ENSURE_ARG(filePath);
makeDirty();
char* nativeFilePath = nsnull;
char* temp;
if (pathType == nsIFile::UNIX_PATH)
{
if (*filePath != '/')
return NS_ERROR_FILE_INVALID_PATH;
// Since it was an absolute path, check for the drive letter
// format looks like: /d|/
// ^
// |
// filePath
char* colonPointer = ((char*)(filePath)) + 2; // this case is okay since I am not changing
if (strstr(filePath, "|/") == colonPointer) // filePath
{
// allocate new string
nativeFilePath = (char*) nsAllocator::Clone( filePath+1, strlen(filePath+1)+1 );
nativeFilePath[1] = ':';
}
else
{
// there is not a drive letter specifier. we need to preserve the first slash.
nativeFilePath = (char*) nsAllocator::Clone( filePath, strlen(filePath)+1 );
}
// Convert '/' to '\'.
temp = nativeFilePath;
do
{
if (*temp == '/')
*temp = '\\';
}
while (*temp++);
}
else if (pathType == nsIFile::NATIVE_PATH || pathType == nsIFile::NSPR_PATH) //TODO does NSPR take any other kind of path?
{
// just do a sanity check. if it has any forward slashes, it is not a Native path
// on windows. Also, it must have a colon at after the first char.
if ((strchr(filePath, '/') == 0) && filePath[1] == ':')
{
// This is a native path
nativeFilePath = (char*) nsAllocator::Clone( filePath, strlen(filePath)+1 );
}
}
// kill any trailing seperator
if(nativeFilePath)
{
temp = nativeFilePath;
int len = strlen(temp) - 1;
if(temp[len] == '\\')
temp[len] = '\0';
}
if (nativeFilePath == nsnull)
return NS_ERROR_FILE_UNRECONGNIZED_PATH;
mWorkingPath.SetString(nativeFilePath);
nsAllocator::Free( nativeFilePath );
return NS_OK;
}
NS_IMETHODIMP
nsIFileImpl::Create(PRUint32 type, PRUint32 attributes)
{
nsresult rv = resolveWorkingPath();
if (NS_FAILED(rv))
return rv;
if (type != NORMAL_FILE_TYPE && type != DIRECTORY_TYPE)
return NS_ERROR_FILE_UNKNOWN_TYPE;
// create nested directories to target
char* slash = strchr(mResolvedPath, '\\');
// skip the first '\\'
++slash;
slash = strchr(slash, '\\');
while (slash)
{
*slash = '\0';
int result = mkdir(mResolvedPath); // todo: pass back the result
*slash = '\\';
++slash;
slash = strchr(slash, '\\');
}
if (type == NORMAL_FILE_TYPE)
{
PRFileDesc* file = PR_Open(mResolvedPath, PR_RDONLY | PR_CREATE_FILE | PR_APPEND, attributes);
if (file) PR_Close(file);
return NS_OK;
}
if (type == DIRECTORY_TYPE)
{
int result = mkdir(mResolvedPath); // todo: pass back the result
return NS_OK;
}
return NS_ERROR_FILE_UNKNOWN_TYPE;
}
NS_IMETHODIMP
nsIFileImpl::AppendPath(const char *node)
{
if ( (node == nsnull) || (*node == '/') || strchr(node, '\\') )
return NS_ERROR_FILE_UNRECONGNIZED_PATH;
makeDirty();
// We only can append relative unix styles strings.
// Convert '\' to '/'
nsString path(node);
char* nodeCString = path.ToNewCString();
char* temp = nodeCString;
for (; *temp; temp++)
{
if (*temp == '/')
*temp = '\\';
}
// kill any trailing seperator
if(nodeCString)
{
temp = nodeCString;
int len = strlen(temp) - 1;
if(temp[len] == '\\')
temp[len] = '\0';
}
mWorkingPath.Append("\\");
mWorkingPath.Append(nodeCString);
Recycle(nodeCString);
return NS_OK;
}
NS_IMETHODIMP
nsIFileImpl::GetFileName(char * *aFileName)
{
NS_ENSURE_ARG_POINTER(aFileName);
const char* temp = mWorkingPath.GetBuffer();
if(temp == nsnull)
return NS_ERROR_FILE_UNRECONGNIZED_PATH;
const char* leaf = strrchr(temp, '\\');
// if the working path is just a node without any lashes.
if (leaf == nsnull)
leaf = temp;
else
leaf++;
*aFileName = (char*) nsAllocator::Clone(leaf, strlen(leaf)+1);
return NS_OK;
}
NS_IMETHODIMP
nsIFileImpl::GetPath(PRUint32 pathType, char **_retval)
{
NS_ENSURE_ARG_POINTER(_retval);
*_retval = nsnull;
nsresult rv = resolveWorkingPath();
if (NS_FAILED(rv)) return rv;
const char *filePath = mResolvedPath.GetBuffer();
char* canonicalPath = (char*) nsAllocator::Clone(filePath, strlen(filePath)+1);
if (canonicalPath == nsnull)
return NS_ERROR_NULL_POINTER;
if (pathType == nsIFile::UNIX_PATH)
{
// Convert the drive-letter separator, if present
nsString path;
path.SetString("/");
char* cp = (char*)canonicalPath + 1;
if (strstr(cp, ":\\") == cp)
*cp = '|'; // absolute path
else
path.SetString("\0"); // relative path
// Convert '\' to '/'
for (; *cp; cp++)
{
if (*cp == '\\')
*cp = '/';
}
path.Append(canonicalPath);
cp = path.ToNewCString();
*_retval = (char*) nsAllocator::Clone(cp, strlen(cp)+1);
delete [] cp;
}
else if (pathType == nsIFile::NATIVE_PATH || pathType == nsIFile::NSPR_PATH) //TODO does NSPR take any other kind of path?
{
*_retval = (char*) nsAllocator::Clone(canonicalPath, strlen(canonicalPath)+1);
}
nsAllocator::Free((char*)canonicalPath);
if (*_retval == nsnull)
return NS_ERROR_FILE_UNRECONGNIZED_PATH;
return NS_OK;
}
nsresult
nsIFileImpl::copymove(nsIFile *newParentDir, const char *newName, PRBool followSymlinks, PRBool move)
{
NS_ENSURE_ARG(newParentDir);
PRBool exists;
nsresult rv = IsExists(&exists);
if (NS_FAILED(rv))
return rv;
if (!exists)
return NS_ERROR_FILE_TARGET_DOES_NOT_EXIST;
const char *filePath = mResolvedPath.GetBuffer();
newParentDir->IsExists(&exists);
if (exists == PR_FALSE)
{
rv = newParentDir->Create(DIRECTORY_TYPE, 0644);
if (NS_FAILED(rv))
return rv;
}
else
{
PRBool isDir;
newParentDir->IsDirectory(&isDir);
if (isDir == PR_FALSE)
return NS_ERROR_FILE_DESTINATION_NOT_DIR;
}
// get the path that we are going to copy to.
char* inFilePath;
newParentDir->GetPath(nsIFile::NATIVE_PATH, &inFilePath); //todo this needs to return a resolved path?
nsCString inFileCString = inFilePath;
nsAllocator::Free(inFilePath);
inFileCString.Append("\\");
if (newName == nsnull)
{
char *aFileName;
GetFileName(&aFileName);
inFileCString.Append(aFileName);
nsAllocator::Free(aFileName);
}
else
{
inFileCString.Append(newName);
}
// check to see if we are a directory, if so enumerate it.
PRBool isDir;
IsDirectory(&isDir);
if (isDir)
{
nsCOMPtr<nsIDirectoryEnumerator> iterator;
NS_NewDirectoryEnumerator(this, followSymlinks, getter_AddRefs(iterator));
PRBool more;
iterator->HasMoreElements(&more);
while (more)
{
nsCOMPtr<nsISupports> item;
nsCOMPtr<nsIFile> file;
iterator->GetNext(getter_AddRefs(item));
file = do_QueryInterface(item);
char* filePath;
file->GetPath(nsIFile::NATIVE_PATH, &filePath);
int copyOK;
if (!move)
copyOK = CopyFile(filePath, inFileCString, PR_TRUE);
else
copyOK = MoveFile(filePath, inFileCString);
nsAllocator::Free(filePath);
// CopyFile returns non-zero if succeeds
if (!copyOK)
return NS_ERROR_FILE_COPY_OR_MOVE_FAILED;;
iterator->HasMoreElements(&more);
}
}
else
{
char* filePath;
newParentDir->GetPath(nsIFile::NATIVE_PATH, &filePath);
int copyOK;
if (!move)
copyOK = CopyFile(filePath, inFileCString, PR_TRUE);
else
copyOK = MoveFile(filePath, inFileCString);
nsAllocator::Free(filePath);
// CopyFile returns non-zero if succeeds
if (!copyOK)
return NS_ERROR_FILE_COPY_OR_MOVE_FAILED;;
}
// If we moved, we want to adjust this.
if (move)
{
if (newName == nsnull)
{
char *aFileName;
GetFileName(&aFileName);
InitWithFile(newParentDir);
AppendPath(aFileName);
nsAllocator::Free(aFileName);
}
else
{
InitWithFile(newParentDir);
AppendPath(newName);
}
makeDirty();
}
return NS_OK;
}
NS_IMETHODIMP
nsIFileImpl::CopyTo(nsIFile *newParentDir, const char *newName)
{
return copymove(newParentDir, newName, PR_FALSE, PR_FALSE);
}
NS_IMETHODIMP
nsIFileImpl::CopyToFollowingLinks(nsIFile *newParentDir, const char *newName)
{
return copymove(newParentDir, newName, PR_TRUE, PR_FALSE);
}
NS_IMETHODIMP
nsIFileImpl::MoveTo(nsIFile *newParentDir, const char *newName)
{
return copymove(newParentDir, newName, PR_FALSE, PR_TRUE);
}
NS_IMETHODIMP
nsIFileImpl::MoveToFollowingLinks(nsIFile *newParentDir, const char *newName)
{
return copymove(newParentDir, newName, PR_TRUE, PR_TRUE);
}
NS_IMETHODIMP
nsIFileImpl::Execute(const char *args)
{
PRBool isFile;
nsresult rv = IsFile(&isFile);
if (NS_FAILED(rv))
return rv;
nsCString fileNameWithArgs(mResolvedPath);
if(args)
{
fileNameWithArgs.Append(" ");
fileNameWithArgs.Append(args);
}
int execResult = WinExec( fileNameWithArgs, SW_NORMAL );
if (execResult > 31)
return NS_OK;
return NS_ERROR_FILE_EXECUTION_FAILED;
}
NS_IMETHODIMP
nsIFileImpl::Delete(PRBool recursive)
{
makeDirty();
PRBool isDir;
nsresult rv = IsDirectory(&isDir);
if (NS_FAILED(rv))
return rv;
const char *filePath = mResolvedPath.GetBuffer();
if (isDir)
{
if (recursive)
{
nsCOMPtr<nsIDirectoryEnumerator> iterator;
NS_NewDirectoryEnumerator(this, false, getter_AddRefs(iterator));
PRBool more;
iterator->HasMoreElements(&more);
while (more)
{
nsCOMPtr<nsISupports> item;
nsCOMPtr<nsIFile> file;
iterator->GetNext(getter_AddRefs(item));
file = do_QueryInterface(item);
file->Delete(recursive);
iterator->HasMoreElements(&more);
}
}
rmdir(filePath); // todo: save return value?
}
else
{
remove(filePath); // todo: save return value?
}
return NS_OK;
}
NS_IMETHODIMP
nsIFileImpl::GetLastModificationDate(PRUint32 *aLastModificationDate)
{
NS_ENSURE_ARG(aLastModificationDate);
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsIFileImpl::SetLastModificationDate(PRUint32 aLastModificationDate)
{
makeDirty();
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsIFileImpl::GetLastModificationDateOfLink(PRUint32 *aLastModificationDateOfLink)
{
NS_ENSURE_ARG(aLastModificationDateOfLink);
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsIFileImpl::SetLastModificationDateOfLink(PRUint32 aLastModificationDateOfLink)
{
makeDirty();
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsIFileImpl::GetPermissions(PRUint32 *aPermissions)
{
NS_ENSURE_ARG(aPermissions);
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsIFileImpl::GetPermissionsOfLink(PRUint32 *aPermissionsOfLink)
{
NS_ENSURE_ARG(aPermissionsOfLink);
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsIFileImpl::GetFileSize(PRUint32 *aFileSize)
{
NS_ENSURE_ARG(aFileSize);
*aFileSize = 0;
struct stat st;
nsresult rv = bufferedStat( &st );
if (NS_FAILED(rv))
return rv;
if (0 == mBuffered_stat_rv)
*aFileSize = (PRUint32)st.st_size;
return NS_OK;
}
NS_IMETHODIMP
nsIFileImpl::GetFileSizeOfLink(PRUint32 *aFileSizeOfLink)
{
/* Link files on windows are not auto resolved. */
return GetFileSize(aFileSizeOfLink);
}
NS_IMETHODIMP
nsIFileImpl::GetDiskSpaceAvailable(PRInt64 *aDiskSpaceAvailable)
{
NS_ENSURE_ARG(aDiskSpaceAvailable);
nsresult rv = resolveWorkingPath();
if (NS_FAILED(rv))
return rv;
const char *filePath = mResolvedPath.GetBuffer();
PRInt64 int64;
LL_I2L(int64 , LONG_MAX);
char aDrive[_MAX_DRIVE + 2];
_splitpath( (const char*)filePath, aDrive, NULL, NULL, NULL);
strcat(aDrive, "\\");
// Check disk space
DWORD dwSecPerClus, dwBytesPerSec, dwFreeClus, dwTotalClus;
ULARGE_INTEGER liFreeBytesAvailableToCaller, liTotalNumberOfBytes, liTotalNumberOfFreeBytes;
double nBytes = 0;
BOOL (WINAPI* getDiskFreeSpaceExA)(LPCTSTR lpDirectoryName,
PULARGE_INTEGER lpFreeBytesAvailableToCaller,
PULARGE_INTEGER lpTotalNumberOfBytes,
PULARGE_INTEGER lpTotalNumberOfFreeBytes) = NULL;
HINSTANCE hInst = LoadLibrary("KERNEL32.DLL");
NS_ASSERTION(hInst != NULL, "COULD NOT LOAD KERNEL32.DLL");
if (hInst != NULL)
{
getDiskFreeSpaceExA = (BOOL (WINAPI*)(LPCTSTR lpDirectoryName,
PULARGE_INTEGER lpFreeBytesAvailableToCaller,
PULARGE_INTEGER lpTotalNumberOfBytes,
PULARGE_INTEGER lpTotalNumberOfFreeBytes))
GetProcAddress(hInst, "GetDiskFreeSpaceExA");
FreeLibrary(hInst);
}
if (getDiskFreeSpaceExA && (*getDiskFreeSpaceExA)(aDrive,
&liFreeBytesAvailableToCaller,
&liTotalNumberOfBytes,
&liTotalNumberOfFreeBytes))
{
nBytes = (double)(signed __int64)liFreeBytesAvailableToCaller.QuadPart;
}
else if ( GetDiskFreeSpace(aDrive, &dwSecPerClus, &dwBytesPerSec, &dwFreeClus, &dwTotalClus))
{
nBytes = (double)dwFreeClus*(double)dwSecPerClus*(double) dwBytesPerSec;
}
return (PRInt64)nBytes;
}
NS_IMETHODIMP
nsIFileImpl::GetParent(nsIFile * *aParent)
{
NS_ENSURE_ARG_POINTER(aParent);
nsCString parentPath = mWorkingPath;
PRInt32 offset = parentPath.RFindChar('\\');
if (offset == -1)
return NS_ERROR_FILE_UNRECONGNIZED_PATH;
parentPath.Truncate(offset);
const char* filePath = parentPath.GetBuffer();
nsIFileImpl* file = new nsIFileImpl();
if (file == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
file->AddRef();
file->InitWithPath(nsIFile::NATIVE_PATH, filePath);
*aParent = file;
return NS_OK;
}
NS_IMETHODIMP
nsIFileImpl::IsExists(PRBool *_retval)
{
NS_ENSURE_ARG(_retval);
struct stat st;
nsresult rv = bufferedStat( &st );
if (0 == mBuffered_stat_rv)
*_retval = PR_TRUE;
else
*_retval = PR_FALSE;
return rv;
}
NS_IMETHODIMP
nsIFileImpl::IsWriteable(PRBool *_retval)
{
NS_ENSURE_ARG(_retval);
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsIFileImpl::IsReadable(PRBool *_retval)
{
NS_ENSURE_ARG(_retval);
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsIFileImpl::IsDirectory(PRBool *_retval)
{
NS_ENSURE_ARG(_retval);
struct stat st;
nsresult rv = bufferedStat( &st );
if (0 == mBuffered_stat_rv && (_S_IFDIR & st.st_mode))
*_retval = PR_TRUE;
else
*_retval = PR_FALSE;
return rv;
}
NS_IMETHODIMP
nsIFileImpl::IsFile(PRBool *_retval)
{
NS_ENSURE_ARG(_retval);
struct stat st;
nsresult rv = bufferedStat( &st );
if (0 == mBuffered_stat_rv && (_S_IFREG & st.st_mode))
*_retval = PR_TRUE;
else
*_retval = PR_FALSE;
return rv;
}
NS_IMETHODIMP
nsIFileImpl::IsHidden(PRBool *_retval)
{
NS_ENSURE_ARG(_retval);
nsresult rv = resolveWorkingPath();
const char* in = mWorkingPath.GetBuffer();
DWORD attr = GetFileAttributes(in);
if (FILE_ATTRIBUTE_HIDDEN & attr)
*_retval = PR_TRUE;
else
*_retval = PR_FALSE;
return rv;
}
NS_IMETHODIMP
nsIFileImpl::IsSymlink(PRBool *_retval)
{
NS_ENSURE_ARG(_retval);
// just check for the .lnk extension
*_retval = PR_FALSE;
if (mWorkingPath.Find(".lnk", PR_FALSE, (mWorkingPath.Length() - 4)))
*_retval = PR_TRUE;
return NS_OK;
}
NS_IMETHODIMP
nsIFileImpl::IsEqual(nsIFile *inFile, PRBool *_retval)
{
NS_ENSURE_ARG(inFile);
NS_ENSURE_ARG(_retval);
*_retval = PR_FALSE;
char* inFilePath;
inFile->GetPath(nsIFile::NATIVE_PATH, &inFilePath);
char* filePath;
GetPath(nsIFile::NATIVE_PATH, &filePath);
if (strcmp(inFilePath, filePath) == 0)
*_retval = PR_TRUE;
nsAllocator::Free(inFilePath);
nsAllocator::Free(filePath);
return NS_OK;
}
NS_IMETHODIMP
nsIFileImpl::IsContainedIn(nsIFile *inFile, PRBool *_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}