diff --git a/xpcom/io/nsLocalFileMac.cpp b/xpcom/io/nsLocalFileMac.cpp new file mode 100644 index 000000000000..e2368a9b1221 --- /dev/null +++ b/xpcom/io/nsLocalFileMac.cpp @@ -0,0 +1,1094 @@ +/* -*- 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): + * Steve Dagley + * John R. McMullen + */ + + +#include "nsCOMPtr.h" +#include "nsIAllocator.h" + +#include "nsLocalFileMac.h" + +#include "nsISimpleEnumerator.h" +#include "nsIComponentManager.h" +#include "prtypes.h" +#include "prio.h" + +#include "FullPath.h" +#include "FileCopy.h" +#include "MoreFilesExtras.h" + +#include +#include +#include + +// Simple func to map Mac OS errors into nsresults +static nsresult MacErrorMapper(OSErr inErr) +{ + nsresult outErr; + + switch (inErr) + { + case fnfErr: + outErr = NS_ERROR_FILE_NOT_FOUND; + break; + + case dupFNErr: + outErr = NS_ERROR_FILE_ALREADY_EXISTS; + break; + + // Can't find good map for some + case bdNamErr: + outErr = NS_ERROR_FAILURE; + break; + + case noErr: + outErr = NS_OK; + + default: + outErr = NS_ERROR_FAILURE; + } + return outErr; +} + + +static void myPLstrcpy(Str255 dst, const char* src) +{ + int srcLength = strlen(src); + NS_ASSERTION(srcLength <= 255, "Oops, Str255 can't hold >255 chars"); + if (srcLength > 255) + srcLength = 255; + dst[0] = srcLength; + memcpy(&dst[1], src, srcLength); +} + +static void myPLstrncpy(Str255 dst, const char* src, int inMax) +{ + int srcLength = strlen(src); + if (srcLength > inMax) + srcLength = inMax; + dst[0] = srcLength; + memcpy(&dst[1], src, srcLength); +} + + +class nsDirEnumerator : public nsISimpleEnumerator +{ + public: + + NS_DECL_ISUPPORTS + + nsDirEnumerator() : mDir(nsnull) + { + NS_INIT_REFCNT(); + } + + nsresult Init(nsILocalFile* parent) + { + char* filepath; + parent->GetTarget(&filepath); + + if (filepath == nsnull) + { + parent->GetPath(&filepath); + } + + if (filepath == nsnull) + { + return NS_ERROR_OUT_OF_MEMORY; + } + + mDir = PR_OpenDir(filepath); + if (mDir == nsnull) // not a directory? + return NS_ERROR_FAILURE; + + mParent = parent; + return NS_OK; + } + + NS_IMETHOD HasMoreElements(PRBool *result) + { + nsresult rv; + if (mNext == nsnull && mDir) + { + PRDirEntry* entry = PR_ReadDir(mDir, PR_SKIP_BOTH); + if (entry == nsnull) + { + // end of dir entries + + PRStatus status = PR_CloseDir(mDir); + if (status != PR_SUCCESS) + return NS_ERROR_FAILURE; + mDir = nsnull; + + *result = PR_FALSE; + return NS_OK; + } + + nsCOMPtr file; + + rv = nsComponentManager::CreateInstance(NS_LOCAL_FILE_PROGID, + nsnull, + nsCOMTypeInfo::GetIID(), + getter_AddRefs(file)); + if (NS_FAILED(rv)) + return rv; + + rv = file->InitWithFile(mParent); + if (NS_FAILED(rv)) + return rv; + + rv = file->AppendPath(entry->name); + if (NS_FAILED(rv)) + return rv; + + mNext = file; + } + *result = mNext != nsnull; + return NS_OK; + } + + NS_IMETHOD GetNext(nsISupports **result) + { + nsresult rv; + PRBool hasMore; + rv = HasMoreElements(&hasMore); + if (NS_FAILED(rv)) return rv; + + *result = mNext; // might return nsnull + NS_IF_ADDREF(*result); + + mNext = null_nsCOMPtr(); + return NS_OK; + } + + virtual ~nsDirEnumerator() + { + if (mDir) + { + PRStatus status = PR_CloseDir(mDir); + NS_ASSERTION(status == PR_SUCCESS, "close failed"); + } + } + + protected: + PRDir* mDir; + nsCOMPtr mParent; + nsCOMPtr mNext; +}; + +NS_IMPL_ISUPPORTS(nsDirEnumerator, NS_GET_IID(nsISimpleEnumerator)); + + + + + + + + +nsLocalFile::nsLocalFile() +{ + NS_INIT_REFCNT(); + + MakeDirty(); +} + +nsLocalFile::~nsLocalFile() +{ +} + +/* nsISupports interface implementation. */ +NS_IMPL_ISUPPORTS2(nsLocalFile, nsILocalFile, nsIFile) +NS_METHOD +nsLocalFile::Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr) +{ + NS_ENSURE_ARG_POINTER(aInstancePtr); + NS_ENSURE_PROPER_AGGREGATION(outer, aIID); + + nsLocalFile* inst = new nsLocalFile(); + 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 +nsLocalFile::MakeDirty() +{ + mStatDirty = PR_TRUE; +} + + +NS_IMETHODIMP +nsLocalFile::InitWithKey(const char *fileKey) +{ + MakeDirty(); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsLocalFile::InitWithFile(nsIFile *file) +{ + MakeDirty(); + NS_ENSURE_ARG(file); + + // Until we have a version that extracts the FSSpec from the donor nsIFile just + // grab the + char* aFilePath; + file->GetPath(&aFilePath); + + // Be paranoid and see if we got a null string for the path + if (aFilePath == nsnull) + return NS_ERROR_FILE_UNRECOGNIZED_PATH; + + mWorkingPath.SetString(aFilePath); + nsAllocator::Free(aFilePath); + + return NS_OK; +} + +NS_IMETHODIMP +nsLocalFile::InitWithPath(const char *filePath) +{ + MakeDirty(); + NS_ENSURE_ARG(filePath); + + // Make sure there's a colon in the path and it is not the first character + // so we know we got a full path, not a partial one + if (strchr(filePath, ':') == 0 || *filePath == ':') + return NS_ERROR_FILE_UNRECOGNIZED_PATH; + + // Just save the specified file path since we can't actually do anything + // about turniung it into an FSSpec until the Create() method is called + mWorkingPath.SetString(filePath); + + return NS_OK; +} + + +NS_IMETHODIMP +nsLocalFile::Create(PRUint32 type, PRUint32 attributes) +{ + if (type != NORMAL_FILE_TYPE && type != DIRECTORY_TYPE) + return NS_ERROR_FILE_UNKNOWN_TYPE; + + OSErr err = noErr; + char* filePath = (char*) nsAllocator::Clone( mWorkingPath, strlen(mWorkingPath)+1 ); + size_t inLength = strlen(filePath); + + if (inLength < 255) + { + Str255 pascalpath; + myPLstrcpy(pascalpath, filePath); + err = ::FSMakeFSSpec(0, 0, pascalpath, &mSpec); + } + else + err = FSpLocationFromFullPath(inLength, filePath, &mSpec); + + if ((err == dirNFErr || err == bdNamErr)) + { + const char* path = filePath; + mSpec.vRefNum = 0; + mSpec.parID = 0; + + do + { + // Locate the colon that terminates the node. + // But if we've a partial path (starting with a colon), find the second one. + const char* nextColon = strchr(path + (*path == ':'), ':'); + // Well, if there are no more colons, point to the end of the string. + if (!nextColon) + nextColon = path + strlen(path); + + // Make a pascal string out of this node. Include initial + // and final colon, if any! + Str255 ppath; + myPLstrncpy(ppath, path, nextColon - path + 1); + + // Use this string as a relative path using the directory created + // on the previous round (or directory 0,0 on the first round). + err = ::FSMakeFSSpec(mSpec.vRefNum, mSpec.parID, ppath, &mSpec); + + // If this was the leaf node, then we are done. + if (!*nextColon) + break; + + // Since there's more to go, we have to get the directory ID, which becomes + // the parID for the next round. + if (err == noErr) + { + // The directory (or perhaps a file) exists. Find its dirID. + long dirID; + Boolean isDirectory; + err = ::FSpGetDirectoryID(&mSpec, &dirID, &isDirectory); + if (!isDirectory) + err = dupFNErr; // oops! a file exists with that name. + if (err != noErr) + break; // bail if we've got an error + mSpec.parID = dirID; + } + else if (err == fnfErr) + { + // If we got "file not found", then we need to create a directory. + err = ::FSpDirCreate(&mSpec, smCurrentScript, &mSpec.parID); + // For some reason, this usually returns fnfErr, even though it works. + if (err == fnfErr) + err = noErr; + } + if (err != noErr) + break; + path = nextColon; // next round + } while (true); + } + + if (err != noErr) + return (MacErrorMapper(err)); + + switch (type) + { + case NORMAL_FILE_TYPE: + // We really should use some sort of meaningful file type/creator but where + // do we get the info from? + err = ::FSpCreate(&mSpec, '????', '????', smCurrentScript); + return (MacErrorMapper(err)); + break; + + case DIRECTORY_TYPE: + err = ::FSpDirCreate(&mSpec, smCurrentScript, &mSpec.parID); + // For some reason, this usually returns fnfErr, even though it works. + if (err == fnfErr) + err = noErr; + return (MacErrorMapper(err)); + break; + + default: + // For now just fall out of the switch into the default return NS_ERROR_FILE_UNKNOWN_TYPE + break; + + } + + return NS_ERROR_FILE_UNKNOWN_TYPE; +} + +NS_IMETHODIMP +nsLocalFile::AppendPath(const char *node) +{ + if ( (node == nsnull) || (*node == '/') || strchr(node, '\\') ) + return NS_ERROR_FILE_UNRECOGNIZED_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 +nsLocalFile::Normalize() +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsLocalFile::GetLeafName(char * *aLeafName) +{ + NS_ENSURE_ARG_POINTER(aLeafName); + + const char* temp = mWorkingPath.GetBuffer(); + if(temp == nsnull) + return NS_ERROR_FILE_UNRECOGNIZED_PATH; + + const char* leaf = strrchr(temp, '\\'); + + // if the working path is just a node without any lashes. + if (leaf == nsnull) + leaf = temp; + else + leaf++; + + *aLeafName = (char*) nsAllocator::Clone(leaf, strlen(leaf)+1); + return NS_OK; +} + + +NS_IMETHODIMP +nsLocalFile::GetPath(char **_retval) +{ + NS_ENSURE_ARG_POINTER(_retval); + *_retval = (char*) nsAllocator::Clone(mWorkingPath, strlen(mWorkingPath)+1); + return NS_OK; +} + + + +nsresult +nsLocalFile::CopySingleFile(nsIFile *sourceFile, nsIFile *destParent, const char * newName, PRBool followSymlinks, PRBool move) +{ + nsresult rv; + char* filePath; + + // get the path that we are going to copy to. + // Since windows does not know how to auto + // resolve shortcust, we must work with the + // target. + char* inFilePath; + destParent->GetTarget(&inFilePath); + nsCString destPath = inFilePath; + nsAllocator::Free(inFilePath); + + destPath.Append("\\"); + + if (newName == nsnull) + { + char *aFileName; + sourceFile->GetLeafName(&aFileName); + destPath.Append(aFileName); + nsAllocator::Free(aFileName); + } + else + { + destPath.Append(newName); + } + + + if (followSymlinks) + { + rv = sourceFile->GetTarget(&filePath); + } + else + { + rv = sourceFile->GetPath(&filePath); + } + + if (NS_FAILED(rv)) + return rv; + + //int copyOK; + + if (!move) + { + //copyOK = CopyFile(filePath, destPath, PR_TRUE); + } + else + { + //copyOK = MoveFile(filePath, destPath); + } + + //if (!copyOK) // CopyFile and MoveFile returns non-zero if succeeds (backward if you ask me). + + nsAllocator::Free(filePath); + + return rv; +} + + +nsresult +nsLocalFile::CopyMove(nsIFile *newParentDir, const char *newName, PRBool followSymlinks, PRBool move) +{ + NS_ENSURE_ARG(newParentDir); + nsresult rv = NS_OK; + + // check to see if this exists, otherwise return an error. + PRBool sourceExists; + Exists(&sourceExists); + if (sourceExists == PR_FALSE) + { + return NS_ERROR_FILE_TARGET_DOES_NOT_EXIST; + } + + // make sure destination exists and is a directory. Create it if not there. + PRBool parentExists; + newParentDir->Exists(&parentExists); + if (parentExists == PR_FALSE) + { + rv = newParentDir->Create(DIRECTORY_TYPE, 0); + if (NS_FAILED(rv)) + return rv; + } + else + { + PRBool isDir; + newParentDir->IsDirectory(&isDir); + if (isDir == PR_FALSE) + { + if (followSymlinks) + { + PRBool isLink; + newParentDir->IsSymlink(&isLink); + if (isLink) + { + char* target; + newParentDir->GetTarget(&target); + + nsCOMPtr realDest; + + rv = nsComponentManager::CreateInstance(NS_LOCAL_FILE_PROGID, + nsnull, + nsCOMTypeInfo::GetIID(), + getter_AddRefs(realDest)); + if (NS_FAILED(rv)) + return rv; + + rv = realDest->InitWithPath(target); + + nsAllocator::Free(target); + + if (NS_FAILED(rv)) + return rv; + + return CopyMove(realDest, newName, followSymlinks, move); + } + } + else + { + return NS_ERROR_FILE_DESTINATION_NOT_DIR; + } + } + } + + // check to see if we are a directory, if so enumerate it. + + PRBool isDir; + IsDirectory(&isDir); + if (!isDir) + { + rv = CopySingleFile(this, newParentDir, newName, followSymlinks, move); + if (NS_FAILED(rv)) + return rv; + } + else + { + // create a new target destination in the new parentDir; + nsCOMPtr target; + + rv = nsComponentManager::CreateInstance(NS_LOCAL_FILE_PROGID, + nsnull, + nsCOMTypeInfo::GetIID(), + getter_AddRefs(target)); + if (NS_FAILED(rv)) + return rv; + + rv = target->InitWithFile(newParentDir); + if (NS_FAILED(rv)) + return rv; + + char *allocatedNewName; + if (!newName) + { + GetLeafName(&allocatedNewName);// this should be the leaf name of the + } + else + { + allocatedNewName = (char*) nsAllocator::Clone( newName, strlen(newName)+1 ); + } + + rv = target->AppendPath(allocatedNewName); + if (NS_FAILED(rv)) + return rv; + + nsAllocator::Free(allocatedNewName); + + target->Create(DIRECTORY_TYPE, 0); + if (NS_FAILED(rv)) + return rv; + + nsDirEnumerator* dirEnum = new nsDirEnumerator(); + if (!dirEnum) + return NS_ERROR_OUT_OF_MEMORY; + + rv = dirEnum->Init(this); + + nsCOMPtr iterator = do_QueryInterface(dirEnum); + + PRBool more; + iterator->HasMoreElements(&more); + while (more) + { + nsCOMPtr item; + nsCOMPtr file; + iterator->GetNext(getter_AddRefs(item)); + file = do_QueryInterface(item); + PRBool isDir, isLink; + + file->IsDirectory(&isDir); + file->IsSymlink(&isLink); + + if (move) + { + rv = file->MoveTo(target, nsnull); + } + else + { + if (followSymlinks) + rv = file->CopyToFollowingLinks(target, nsnull); + else + rv = file->CopyTo(target, nsnull); + } + + iterator->HasMoreElements(&more); + } + } + + + // If we moved, we want to adjust this. + if (move) + { + if (newName == nsnull) + { + char *aFileName; + GetLeafName(&aFileName); + InitWithFile(newParentDir); + AppendPath(aFileName); + nsAllocator::Free(aFileName); + } + else + { + InitWithFile(newParentDir); + AppendPath(newName); + } + MakeDirty(); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsLocalFile::CopyTo(nsIFile *newParentDir, const char *newName) +{ + return CopyMove(newParentDir, newName, PR_FALSE, PR_FALSE); +} + +NS_IMETHODIMP +nsLocalFile::CopyToFollowingLinks(nsIFile *newParentDir, const char *newName) +{ + return CopyMove(newParentDir, newName, PR_TRUE, PR_FALSE); +} + +NS_IMETHODIMP +nsLocalFile::MoveTo(nsIFile *newParentDir, const char *newName) +{ + return CopyMove(newParentDir, newName, PR_FALSE, PR_TRUE); +} + +NS_IMETHODIMP +nsLocalFile::Spawn(const char *args) +{ + PRBool isFile; + nsresult rv = IsFile(&isFile); + + if (NS_FAILED(rv)) + return rv; + + + return NS_ERROR_FILE_EXECUTION_FAILED; +} + +NS_IMETHODIMP +nsLocalFile::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) + { + nsDirEnumerator* dirEnum = new nsDirEnumerator(); + if (dirEnum) + return NS_ERROR_OUT_OF_MEMORY; + + rv = dirEnum->Init(this); + + nsCOMPtr iterator = do_QueryInterface(dirEnum); + + PRBool more; + iterator->HasMoreElements(&more); + while (more) + { + nsCOMPtr item; + nsCOMPtr 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 +nsLocalFile::GetLastModificationDate(PRInt64 *aLastModificationDate) +{ + NS_ENSURE_ARG(aLastModificationDate); + + aLastModificationDate->hi = 0; + aLastModificationDate->lo = 0; + + return NS_OK; +} + +NS_IMETHODIMP +nsLocalFile::SetLastModificationDate(PRInt64 aLastModificationDate) +{ + MakeDirty(); + + return NS_OK; +} + +NS_IMETHODIMP +nsLocalFile::GetLastModificationDateOfLink(PRInt64 *aLastModificationDate) +{ + NS_ENSURE_ARG(aLastModificationDate); + + aLastModificationDate->hi = 0; + aLastModificationDate->lo = 0; + + return NS_OK; +} + +NS_IMETHODIMP +nsLocalFile::SetLastModificationDateOfLink(PRInt64 aLastModificationDate) +{ + MakeDirty(); + + return NS_OK; +} + +NS_IMETHODIMP +nsLocalFile::GetPermissions(PRUint32 *aPermissions) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsLocalFile::GetPermissionsOfLink(PRUint32 *aPermissionsOfLink) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + + +NS_IMETHODIMP +nsLocalFile::SetPermissions(PRUint32 aPermissions) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsLocalFile::SetPermissionsOfLink(PRUint32 aPermissions) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + + +NS_IMETHODIMP +nsLocalFile::GetFileSize(PRInt64 *aFileSize) +{ + NS_ENSURE_ARG(aFileSize); + + aFileSize->hi = 0; + aFileSize->lo = 0; + + return NS_OK; +} + + +NS_IMETHODIMP +nsLocalFile::SetFileSize(PRInt64 aFileSize) +{ + + return NS_OK; +} + +NS_IMETHODIMP +nsLocalFile::GetFileSizeOfLink(PRInt64 *aFileSize) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsLocalFile::GetDiskSpaceAvailable(PRInt64 *aDiskSpaceAvailable) +{ + NS_ENSURE_ARG(aDiskSpaceAvailable); + + PRInt64 space64Bits; + + LL_I2L(space64Bits , LONG_MAX); + + XVolumeParam pb; + pb.ioCompletion = nsnull; + pb.ioVolIndex = 0; + pb.ioNamePtr = nsnull; + pb.ioVRefNum = mSpec.vRefNum; + + OSErr err = ::PBXGetVolInfoSync(&pb); + + if (err == noErr) + { + space64Bits.lo = pb.ioVFreeBytes.lo; + space64Bits.hi = pb.ioVFreeBytes.hi; + } + + *aDiskSpaceAvailable = space64Bits; + + return NS_OK; +} + +NS_IMETHODIMP +nsLocalFile::GetParent(nsIFile * *aParent) +{ + NS_ENSURE_ARG_POINTER(aParent); + + nsCString parentPath = mWorkingPath; + + PRInt32 offset = parentPath.RFindChar('\\'); + if (offset == -1) + return NS_ERROR_FILE_UNRECOGNIZED_PATH; + + parentPath.Truncate(offset); + + const char* filePath = parentPath.GetBuffer(); + + nsLocalFile* file = new nsLocalFile(); + if (file == nsnull) + return NS_ERROR_OUT_OF_MEMORY; + + file->AddRef(); + file->InitWithPath(filePath); + *aParent = file; + + return NS_OK; +} + +NS_IMETHODIMP +nsLocalFile::Exists(PRBool *_retval) +{ + NS_ENSURE_ARG(_retval); + + return NS_OK; +} + +NS_IMETHODIMP +nsLocalFile::IsWritable(PRBool *_retval) +{ + NS_ENSURE_ARG(_retval); + *_retval = PR_FALSE; + + return NS_OK; + + +} + +NS_IMETHODIMP +nsLocalFile::IsReadable(PRBool *_retval) +{ + NS_ENSURE_ARG(_retval); + *_retval = PR_FALSE; + + *_retval = PR_TRUE; + return NS_OK; +} + + +NS_IMETHODIMP +nsLocalFile::IsExecutable(PRBool *_retval) +{ + NS_ENSURE_ARG(_retval); + *_retval = PR_FALSE; + + return NS_OK; +} + + +NS_IMETHODIMP +nsLocalFile::IsDirectory(PRBool *_retval) +{ + NS_ENSURE_ARG(_retval); + *_retval = PR_FALSE; + + return NS_OK; +} + +NS_IMETHODIMP +nsLocalFile::IsFile(PRBool *_retval) +{ + NS_ENSURE_ARG(_retval); + *_retval = PR_FALSE; + + return NS_OK; +} + +NS_IMETHODIMP +nsLocalFile::IsHidden(PRBool *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsLocalFile::IsSymlink(PRBool *_retval) +{ + NS_ENSURE_ARG(_retval); + *_retval = PR_FALSE; + + return NS_OK; +} + +NS_IMETHODIMP +nsLocalFile::IsSpecial(PRBool *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsLocalFile::Equals(nsIFile *inFile, PRBool *_retval) +{ + NS_ENSURE_ARG(inFile); + NS_ENSURE_ARG(_retval); + *_retval = PR_FALSE; + + char* inFilePath; + inFile->GetPath(&inFilePath); + + char* filePath; + GetPath(&filePath); + + if (strcmp(inFilePath, filePath) == 0) + *_retval = PR_TRUE; + + nsAllocator::Free(inFilePath); + nsAllocator::Free(filePath); + + return NS_OK; +} + +NS_IMETHODIMP +nsLocalFile::IsContainedIn(nsIFile *inFile, PRBool recur, PRBool *_retval) +{ + NS_ENSURE_ARG(_retval); + *_retval = PR_FALSE; + return NS_ERROR_NOT_IMPLEMENTED; +} + + + +NS_IMETHODIMP +nsLocalFile::GetTarget(char **_retval) +{ + NS_ENSURE_ARG(_retval); + *_retval = nsnull; + + PRBool symLink; + + nsresult rv = IsSymlink(&symLink); + if (NS_FAILED(rv)) + return rv; + + if (!symLink) + { + return NS_ERROR_FILE_INVALID_PATH; + } + + *_retval = (char*) nsAllocator::Clone( mResolvedPath, strlen(mResolvedPath)+1 ); + return NS_OK; +} + + +NS_IMETHODIMP +nsLocalFile::GetDirectoryEntries(nsISimpleEnumerator * *entries) +{ + nsresult rv; + + *entries = nsnull; + + PRBool isDir; + rv = IsDirectory(&isDir); + if (NS_FAILED(rv)) + return rv; + if (!isDir) + return NS_ERROR_FILE_NOT_DIRECTORY; + + nsDirEnumerator* dirEnum = new nsDirEnumerator(); + if (dirEnum == nsnull) + return NS_ERROR_OUT_OF_MEMORY; + NS_ADDREF(dirEnum); + rv = dirEnum->Init(this); + if (NS_FAILED(rv)) + { + NS_RELEASE(dirEnum); + return rv; + } + + *entries = dirEnum; + return NS_OK; +} + + + + diff --git a/xpcom/io/nsLocalFileMac.h b/xpcom/io/nsLocalFileMac.h new file mode 100644 index 000000000000..51ce1c11b755 --- /dev/null +++ b/xpcom/io/nsLocalFileMac.h @@ -0,0 +1,80 @@ +/* -*- 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): + * Steve Dagley + */ + +#ifndef _nsLocalFileMAC_H_ +#define _nsLocalFileMAC_H_ + +#include "nscore.h" +#include "nsError.h" +#include "nsString.h" +#include "nsCRT.h" +#include "nsIFile.h" +#include "nsILocalFile.h" +#include "nsIFactory.h" +#include "nsLocalFile.h" + +#include + +class NS_COM nsLocalFile : public nsILocalFile +{ +public: + NS_DEFINE_STATIC_CID_ACCESSOR(NS_LOCAL_FILE_CID) + + nsLocalFile(); + virtual ~nsLocalFile(); + + static NS_METHOD Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr); + + // nsISupports interface + NS_DECL_ISUPPORTS + + // nsIFile interface + NS_DECL_NSIFILE + + // nsILocalFile interface + NS_DECL_NSILOCALFILE + +private: + + // this is the flag which indicates if I can used cached information about the file + PRBool mStatDirty; + + // this string will alway be in native format! + nsCString mWorkingPath; + + // this will be the resolved path which will *NEVER* be returned to the user + nsCString mResolvedPath; + + // The Mac data structure for a file system object + FSSpec mSpec; + + void MakeDirty(); + + nsresult CopyMove(nsIFile *newParentDir, const char *newName, PRBool followSymlinks, PRBool move); + nsresult CopySingleFile(nsIFile *source, nsIFile* dest, const char * newName, PRBool followSymlinks, PRBool move); + +}; + +#endif +