Merge backout of ad9a4a3a5409, b=506812 CLOSED TREE

This commit is contained in:
Josh Aas 2009-07-31 16:50:28 -04:00
commit 45269a732a
2 changed files with 164 additions and 120 deletions

View File

@ -43,6 +43,8 @@
#include "nsString.h"
#include "nsIHashable.h"
class nsDirEnumerator;
// Mac OS X 10.4 does not have stat64/lstat64
#if defined(HAVE_STAT64) && defined(HAVE_LSTAT64) && (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_4)
#define STAT stat64
@ -69,6 +71,8 @@
class NS_COM nsLocalFile : public nsILocalFileMac,
public nsIHashable
{
friend class nsDirEnumerator;
public:
NS_DEFINE_STATIC_CID_ACCESSOR(NS_LOCAL_FILE_CID)

View File

@ -67,7 +67,6 @@
#include <sys/statvfs.h>
#include <stdlib.h>
#include <utime.h>
#include <dirent.h>
#define CHECK_INIT() \
PR_BEGIN_MACRO \
@ -79,7 +78,17 @@ static nsresult MacErrorMapper(OSErr inErr);
static void CopyUTF8toUTF16NFC(const nsACString& aSrc, nsAString& aResult);
static nsresult CFStringReftoUTF8(CFStringRef aInStrRef, nsACString& aOutStr);
const char kPathSepChar = '/';
#pragma mark -
#pragma mark [FSRef operator==]
bool operator==(const FSRef& lhs, const FSRef& rhs)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
return (::FSCompareFSRefs(&lhs, &rhs) == noErr);
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(false);
}
#pragma mark -
#pragma mark [StFollowLinksState]
@ -113,136 +122,167 @@ class StFollowLinksState
#pragma mark -
#pragma mark [nsDirEnumerator]
class NS_COM
nsDirEnumerator : public nsISimpleEnumerator,
public nsIDirectoryEnumerator
class nsDirEnumerator : public nsISimpleEnumerator,
public nsIDirectoryEnumerator
{
public:
nsDirEnumerator();
public:
// nsISupports interface
NS_DECL_ISUPPORTS
NS_DECL_ISUPPORTS
// nsISimpleEnumerator interface
NS_DECL_NSISIMPLEENUMERATOR
nsDirEnumerator() :
mIterator(nsnull),
mFSRefsArray(nsnull),
mArrayCnt(0), mArrayIndex(0)
{
}
// nsIDirectoryEnumerator interface
NS_DECL_NSIDIRECTORYENUMERATOR
nsresult Init(nsILocalFileMac* parent)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
NS_IMETHOD Init(nsLocalFile *parent);
NS_ENSURE_ARG(parent);
OSErr err;
nsresult rv;
FSRef parentRef;
rv = parent->GetFSRef(&parentRef);
if (NS_FAILED(rv))
return rv;
mFSRefsArray = (FSRef *)nsMemory::Alloc(sizeof(FSRef)
* kRequestCountPerIteration);
if (!mFSRefsArray)
return NS_ERROR_OUT_OF_MEMORY;
err = ::FSOpenIterator(&parentRef, kFSIterateFlat, &mIterator);
if (err != noErr)
return MacErrorMapper(err);
return NS_OK;
private:
~nsDirEnumerator();
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
protected:
NS_IMETHOD GetNextEntry();
NS_IMETHOD HasMoreElements(PRBool *result)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
DIR *mDir;
struct dirent *mEntry;
nsCString mParentPath;
if (!mIterator || !mFSRefsArray) {
*result = PR_FALSE;
return NS_OK;
}
if (mNext == nsnull) {
if (mArrayIndex >= mArrayCnt) {
ItemCount actualCnt;
OSErr err = ::FSGetCatalogInfoBulk(mIterator,
kRequestCountPerIteration,
&actualCnt,
nsnull,
kFSCatInfoNone,
nsnull,
mFSRefsArray,
nsnull,
nsnull);
if (err == noErr || err == errFSNoMoreItems) {
mArrayCnt = actualCnt;
mArrayIndex = 0;
}
}
if (mArrayIndex < mArrayCnt) {
nsRefPtr<nsLocalFile> newFile = new nsLocalFile;
if (!newFile)
return NS_ERROR_OUT_OF_MEMORY;
FSRef fsRef = mFSRefsArray[mArrayIndex];
if (NS_FAILED(newFile->InitWithFSRef(&fsRef)))
return NS_ERROR_FAILURE;
mArrayIndex++;
mNext = newFile;
}
}
*result = mNext != nsnull;
if (!*result)
Close();
return NS_OK;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
NS_IMETHOD GetNext(nsISupports **result)
{
NS_ENSURE_ARG_POINTER(result);
*result = nsnull;
nsresult rv;
PRBool hasMore;
rv = HasMoreElements(&hasMore);
if (NS_FAILED(rv)) return rv;
*result = mNext; // might return nsnull
NS_IF_ADDREF(*result);
mNext = nsnull;
return NS_OK;
}
NS_IMETHOD GetNextFile(nsIFile **result)
{
*result = nsnull;
PRBool hasMore = PR_FALSE;
nsresult rv = HasMoreElements(&hasMore);
if (NS_FAILED(rv) || !hasMore)
return rv;
*result = mNext;
NS_IF_ADDREF(*result);
mNext = nsnull;
return NS_OK;
}
NS_IMETHOD Close()
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
if (mIterator) {
::FSCloseIterator(mIterator);
mIterator = nsnull;
}
if (mFSRefsArray) {
nsMemory::Free(mFSRefsArray);
mFSRefsArray = nsnull;
}
return NS_OK;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
private:
~nsDirEnumerator()
{
Close();
}
protected:
// According to Apple doc, request the number of objects
// per call that will fit in 4 VM pages.
enum {
kRequestCountPerIteration = ((4096 * 4) / sizeof(FSRef))
};
nsCOMPtr<nsILocalFileMac> mNext;
FSIterator mIterator;
FSRef *mFSRefsArray;
PRInt32 mArrayCnt, mArrayIndex;
};
nsDirEnumerator::nsDirEnumerator() :
mDir(nsnull),
mEntry(nsnull)
{
}
nsDirEnumerator::~nsDirEnumerator()
{
Close();
}
NS_IMPL_ISUPPORTS2(nsDirEnumerator, nsISimpleEnumerator, nsIDirectoryEnumerator)
NS_IMETHODIMP
nsDirEnumerator::Init(nsLocalFile *parent)
{
nsCAutoString dirPath;
if (NS_FAILED(parent->GetNativePath(dirPath)) ||
dirPath.IsEmpty()) {
return NS_ERROR_FILE_INVALID_PATH;
}
if (NS_FAILED(parent->GetNativePath(mParentPath)))
return NS_ERROR_FAILURE;
mDir = opendir(dirPath.get());
if (!mDir)
return NSRESULT_FOR_ERRNO();
return GetNextEntry();
}
NS_IMETHODIMP
nsDirEnumerator::HasMoreElements(PRBool *result)
{
*result = mDir && mEntry;
if (!*result)
Close();
return NS_OK;
}
NS_IMETHODIMP
nsDirEnumerator::GetNext(nsISupports **_retval)
{
nsCOMPtr<nsIFile> file;
nsresult rv = GetNextFile(getter_AddRefs(file));
if (NS_FAILED(rv))
return rv;
NS_IF_ADDREF(*_retval = file);
return NS_OK;
}
NS_IMETHODIMP
nsDirEnumerator::GetNextEntry()
{
do {
errno = 0;
mEntry = readdir(mDir);
// end of dir or error
if (!mEntry)
return NSRESULT_FOR_ERRNO();
// keep going past "." and ".."
} while (mEntry->d_name[0] == '.' &&
(mEntry->d_name[1] == '\0' || // .\0
(mEntry->d_name[1] == '.' &&
mEntry->d_name[2] == '\0'))); // ..\0
return NS_OK;
}
NS_IMETHODIMP
nsDirEnumerator::GetNextFile(nsIFile **_retval)
{
nsresult rv;
if (!mDir || !mEntry) {
*_retval = nsnull;
return NS_OK;
}
nsCOMPtr<nsILocalFile> file = new nsLocalFile();
if (!file)
return NS_ERROR_OUT_OF_MEMORY;
if (NS_FAILED(rv = file->InitWithNativePath(mParentPath)) ||
NS_FAILED(rv = file->AppendNative(nsDependentCString(mEntry->d_name))))
return rv;
*_retval = file;
NS_ADDREF(*_retval);
return GetNextEntry();
}
NS_IMETHODIMP
nsDirEnumerator::Close()
{
if (mDir) {
closedir(mDir);
mDir = nsnull;
}
return NS_OK;
}
const char kPathSepChar = '/';
#pragma mark -
#pragma mark [CTORs/DTOR]