diff --git a/mozilla/base/macbuild/TestFiles.mcp b/mozilla/base/macbuild/TestFiles.mcp index d80accd17c3..d07bcf358ce 100644 Binary files a/mozilla/base/macbuild/TestFiles.mcp and b/mozilla/base/macbuild/TestFiles.mcp differ diff --git a/mozilla/base/macbuild/base.mcp b/mozilla/base/macbuild/base.mcp index 3a61f312208..ad6f373a92c 100644 Binary files a/mozilla/base/macbuild/base.mcp and b/mozilla/base/macbuild/base.mcp differ diff --git a/mozilla/base/public/MANIFEST b/mozilla/base/public/MANIFEST index 0e7e3985838..74bb280e91a 100644 --- a/mozilla/base/public/MANIFEST +++ b/mozilla/base/public/MANIFEST @@ -5,6 +5,7 @@ nsAutoLock.h nsISizeOfHandler.h nsFileStream.h +nsIFileStream.h nsFileSpec.h nsRepeater.h nsIProperties.h diff --git a/mozilla/base/public/Makefile.in b/mozilla/base/public/Makefile.in index 86cfb1af1ae..d962f628f00 100644 --- a/mozilla/base/public/Makefile.in +++ b/mozilla/base/public/Makefile.in @@ -32,6 +32,7 @@ EXPORTS = \ nsEscape.h \ nsFileSpec.h \ nsFileStream.h \ + nsIFileStream.h \ $(NULL) EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS)) diff --git a/mozilla/base/public/makefile.win b/mozilla/base/public/makefile.win index c2f80e3616b..512b6a4265e 100644 --- a/mozilla/base/public/makefile.win +++ b/mozilla/base/public/makefile.win @@ -28,6 +28,7 @@ EXPORTS = \ nsEscape.h \ nsFileSpec.h \ nsFileStream.h \ + nsIFileStream.h \ $(NULL) MODULE = raptor diff --git a/mozilla/base/public/nsFileSpec.h b/mozilla/base/public/nsFileSpec.h index 2cdce813668..78c30012f0f 100644 --- a/mozilla/base/public/nsFileSpec.h +++ b/mozilla/base/public/nsFileSpec.h @@ -24,7 +24,16 @@ // // Classes defined: // -// nsFilePath, nsFileURL, nsNativeFileSpec. +// nsFilePath, nsFileURL, nsFileSpec, nsPersistentFileDescriptor. +// +// Q. How should I represent files at run time? +// A. Use nsFileSpec. Using char* will lose information on some platforms. +// +// Q. Then what are nsFilePath and nsFileURL for? +// A. Only when you need a char* parameter for legacy code. +// +// Q. How should I represent files in a persistent way (eg, in a disk file)? +// A. Use nsPersistentFileDescriptor. Convert to and from nsFileSpec at run time. // // This suite provides the following services: // @@ -63,7 +72,7 @@ // // Initialize a native file spec from a URL // -// nsNativeFileSpec fileSpec(fileURL); +// nsFileSpec fileSpec(fileURL); // // Make the spec unique (this one has no suffix). // @@ -103,6 +112,7 @@ #define _FILESPEC_H_ #include "nscore.h" +#include "nsError.h" //======================================================================================== // Compiler-specific macros, as needed @@ -116,11 +126,13 @@ #define NS_NAMESPACE_PROTOTYPE #define NS_NAMESPACE namespace #define NS_NAMESPACE_END +#define NS_EXPLICIT explicit #else #define NS_NAMESPACE_PROTOTYPE static #define NS_NAMESPACE struct #define NS_NAMESPACE_END ; +#define NS_EXPLICIT #endif //=========================== End Compiler-specific macros =============================== @@ -137,33 +149,50 @@ // Here are the allowable ways to describe a file. //======================================================================================== -class nsFilePath; // This can be passed to NSPR file I/O routines. +class nsFileSpec; // Preferred. For i/o use nsInputFileStream, nsOutputFileStream +class nsFilePath; // This can be passed to NSPR file I/O routines, if you must. class nsFileURL; -class nsNativeFileSpec; +class nsPersistentFileDescriptor; // Used for storage across program launches. #define kFileURLPrefix "file://" #define kFileURLPrefixLength (7) -class nsBasicOutStream; +class nsOutputStream; +class nsInputStream; +class nsOutputFileStream; +class nsInputFileStream; //======================================================================================== -class NS_BASE nsNativeFileSpec +// Conversion of native file errors to nsresult values. These are really only for use +// in the file module, clients of this interface shouldn't really need them. +// Error results returned from this interface have, in the low-order 16 bits, +// native errors that are masked to 16 bits. Assumption: a native error of 0 is success +// on all platforms. Note the way we define this using an inline function. This +// avoids multiple evaluation if people go NS_FILE_RESULT(function_call()). +#define NS_FILE_RESULT(x) ns_file_convert_result((PRInt32)x) +nsresult ns_file_convert_result(PRInt32 nativeErr); +#define NS_FILE_FAILURE NS_FILE_RESULT(-1) + +//======================================================================================== +class NS_BASE nsFileSpec // This is whatever each platform really prefers to describe files as. Declared first -// because the other two types have an embeded nsNativeFileSpec object. +// because the other two types have an embeded nsFileSpec object. //======================================================================================== { public: - nsNativeFileSpec(); - explicit nsNativeFileSpec(const char* inString, bool inCreateDirs = false); - explicit nsNativeFileSpec(const nsFilePath& inPath); - explicit nsNativeFileSpec(const nsFileURL& inURL); - nsNativeFileSpec(const nsNativeFileSpec& inPath); - virtual ~nsNativeFileSpec(); + nsFileSpec(); + NS_EXPLICIT nsFileSpec(const char* inString, PRBool inCreateDirs = PR_FALSE); + NS_EXPLICIT nsFileSpec(const nsFilePath& inPath); + NS_EXPLICIT nsFileSpec(const nsFileURL& inURL); + NS_EXPLICIT nsFileSpec(const nsPersistentFileDescriptor& inURL); + nsFileSpec(const nsFileSpec& inPath); + virtual ~nsFileSpec(); void operator = (const char* inPath); void operator = (const nsFilePath& inPath); void operator = (const nsFileURL& inURL); - void operator = (const nsNativeFileSpec& inOther); + void operator = (const nsFileSpec& inOther); + void operator = (const nsPersistentFileDescriptor& inOther); #ifndef XP_MAC operator const char* () const { return mPath; } @@ -175,23 +204,22 @@ class NS_BASE nsNativeFileSpec #ifdef XP_MAC // For Macintosh people, this is meant to be useful in its own right as a C++ version // of the FSSpec struct. - nsNativeFileSpec( + nsFileSpec( short vRefNum, long parID, ConstStr255Param name); - nsNativeFileSpec(const FSSpec& inSpec) - : mSpec(inSpec), mError(noErr) {} + nsFileSpec(const FSSpec& inSpec) + : mSpec(inSpec), mError(NS_OK) {} operator FSSpec* () { return &mSpec; } operator const FSSpec* const () { return &mSpec; } operator FSSpec& () { return mSpec; } operator const FSSpec& () const { return mSpec; } - OSErr Error() const { return mError; } void MakeAliasSafe(); // Called for the spec of an alias. Copies the alias to // a secret temp directory and modifies the spec to point // to it. Sets mError. - void ResolveAlias(bool& wasAliased); + void ResolveAlias(PRBool& wasAliased); // Called for the spec of an alias. Modifies the spec to // point to the original. Sets mError. void MakeUnique(ConstStr255Param inSuggestedLeafName); @@ -199,15 +227,15 @@ class NS_BASE nsNativeFileSpec ConstStr255Param GetLeafPName() const { return mSpec.name; } #endif // end of Macintosh utility methods. -#ifdef XP_MAC - bool Valid() const { return mError == noErr; } -#else - bool Valid() const { return true; } // Fixme. -#endif // XP_MAC + PRBool Valid() const { return NS_SUCCEEDED(Error()); } + nsresult Error() const { return mError; } - friend NS_BASE nsBasicOutStream& operator << ( - nsBasicOutStream& s, - const nsNativeFileSpec& spec); +#if DEBUG + friend NS_BASE nsOutputStream& operator << ( + nsOutputStream& s, + const nsFileSpec& spec); // THIS IS FOR DEBUGGING ONLY. + // see PersistentFileDescriptor for the real deal. +#endif //-------------------------------------------------- // Queries and path algebra. These do not modify the disk. @@ -218,7 +246,7 @@ class NS_BASE nsNativeFileSpec // inLeafName can be a relative path, so this allows // one kind of concatenation of "paths". - void GetParent(nsNativeFileSpec& outSpec) const; + void GetParent(nsFileSpec& outSpec) const; // Return the filespec of the parent directory. Used // in conjunction with GetLeafName(), this lets you // parse a path into a list of node names. Beware, @@ -226,7 +254,7 @@ class NS_BASE nsNativeFileSpec // but a spec. Volumes on Macintosh can have identical // names. Perhaps could be used for an operator --() ? - nsNativeFileSpec operator + (const char* inRelativePath) const; + nsFileSpec operator + (const char* inRelativePath) const; void operator += (const char* inRelativePath); // Concatenate the relative path to this directory. // Used for constructing the filespec of a descendant. @@ -240,19 +268,24 @@ class NS_BASE nsNativeFileSpec void MakeUnique(); void MakeUnique(const char* inSuggestedLeafName); - bool IsDirectory() const; + PRBool IsDirectory() const; // More stringent than Exists() - bool IsFile() const; + PRBool IsFile() const; // More stringent than Exists() - bool Exists() const; + PRBool Exists() const; //-------------------------------------------------- // Creation and deletion of objects. These can modify the disk. //-------------------------------------------------- void CreateDirectory(int mode = 0700 /* for unix */); - void Delete(bool inRecursive); + void Delete(PRBool inRecursive); + nsresult Rename(const char* inNewName); // not const: gets updated + nsresult Copy(const nsFileSpec& inNewParentDirectory) const; + nsresult Move(const nsFileSpec& inNewParentDirectory) const; + nsresult Execute(const char* args) const; + //-------------------------------------------------- // Data //-------------------------------------------------- @@ -261,11 +294,15 @@ class NS_BASE nsNativeFileSpec friend class nsFilePath; #ifdef XP_MAC FSSpec mSpec; - OSErr mError; #else char* mPath; #endif -}; // class nsNativeFileSpec + nsresult mError; +}; // class nsFileSpec + +// FOR HISTORICAL REASONS: + +typedef nsFileSpec nsNativeFileSpec; //======================================================================================== class NS_BASE nsFileURL @@ -276,9 +313,9 @@ class NS_BASE nsFileURL { public: nsFileURL(const nsFileURL& inURL); - explicit nsFileURL(const char* inString, bool inCreateDirs = false); - explicit nsFileURL(const nsFilePath& inPath); - explicit nsFileURL(const nsNativeFileSpec& inPath); + NS_EXPLICIT nsFileURL(const char* inString, PRBool inCreateDirs = PR_FALSE); + NS_EXPLICIT nsFileURL(const nsFilePath& inPath); + NS_EXPLICIT nsFileURL(const nsFileSpec& inPath); virtual ~nsFileURL(); // nsString GetString() const { return mPath; } @@ -288,14 +325,14 @@ class NS_BASE nsFileURL void operator = (const nsFileURL& inURL); void operator = (const char* inString); void operator = (const nsFilePath& inOther); - void operator = (const nsNativeFileSpec& inOther); + void operator = (const nsFileSpec& inOther); - friend NS_BASE nsBasicOutStream& operator << ( - nsBasicOutStream& s, const nsFileURL& spec); + friend NS_BASE nsOutputStream& operator << ( + nsOutputStream& s, const nsFileURL& spec); #ifdef XP_MAC - // Accessor to allow quick assignment to a mNativeFileSpec - const nsNativeFileSpec& GetNativeSpec() const { return mNativeFileSpec; } + // Accessor to allow quick assignment to a mFileSpec + const nsFileSpec& GetFileSpec() const { return mFileSpec; } #endif private: // Should not be defined (only nsFilePath is to be treated as strings. @@ -306,8 +343,8 @@ class NS_BASE nsFileURL char* mURL; #ifdef XP_MAC // Since the path on the macintosh does not uniquely specify a file (volumes - // can have the same name), stash the secret nsNativeFileSpec, too. - nsNativeFileSpec mNativeFileSpec; + // can have the same name), stash the secret nsFileSpec, too. + nsFileSpec mFileSpec; #endif }; // class nsFileURL @@ -319,9 +356,9 @@ class NS_BASE nsFilePath { public: nsFilePath(const nsFilePath& inPath); - explicit nsFilePath(const char* inString, bool inCreateDirs = false); - explicit nsFilePath(const nsFileURL& inURL); - explicit nsFilePath(const nsNativeFileSpec& inPath); + NS_EXPLICIT nsFilePath(const char* inString, PRBool inCreateDirs = PR_FALSE); + NS_EXPLICIT nsFilePath(const nsFileURL& inURL); + NS_EXPLICIT nsFilePath(const nsFileSpec& inPath); virtual ~nsFilePath(); @@ -337,12 +374,12 @@ class NS_BASE nsFilePath void operator = (const nsFilePath& inPath); void operator = (const char* inString); void operator = (const nsFileURL& inURL); - void operator = (const nsNativeFileSpec& inOther); + void operator = (const nsFileSpec& inOther); #ifdef XP_MAC public: - // Accessor to allow quick assignment to a mNativeFileSpec - const nsNativeFileSpec& GetNativeSpec() const { return mNativeFileSpec; } + // Accessor to allow quick assignment to a mFileSpec + const nsFileSpec& GetFileSpec() const { return mFileSpec; } #endif private: @@ -350,26 +387,59 @@ class NS_BASE nsFilePath char* mPath; #ifdef XP_MAC // Since the path on the macintosh does not uniquely specify a file (volumes - // can have the same name), stash the secret nsNativeFileSpec, too. - nsNativeFileSpec mNativeFileSpec; + // can have the same name), stash the secret nsFileSpec, too. + nsFileSpec mFileSpec; #endif }; // class nsFilePath +//======================================================================================== +class NS_BASE nsPersistentFileDescriptor +//======================================================================================== +{ + public: + nsPersistentFileDescriptor() : mDescriptorString(nsnull) {} + // For use prior to reading in from a stream + nsPersistentFileDescriptor(const nsPersistentFileDescriptor& inPath); + virtual ~nsPersistentFileDescriptor(); + void operator = (const nsPersistentFileDescriptor& inPath); + + // Conversions + nsPersistentFileDescriptor(const nsFileSpec& inPath); + void operator = (const nsFileSpec& inPath); + + friend NS_BASE nsInputStream& operator >> (nsInputStream&, nsPersistentFileDescriptor&); + // reads the data from a file + friend NS_BASE nsOutputStream& operator << (nsOutputStream&, const nsPersistentFileDescriptor&); + // writes the data to a file + friend class nsFileSpec; + + private: + // Here are the ways to get data in and out of a file. + void GetData(void*& outData, PRInt32& outSize) const; + // DON'T FREE the returned data! + void SetData(const void* inData, PRInt32 inSize); + + private: + + char* mDescriptorString; + +}; // class nsPersistentFileDescriptor + //======================================================================================== class NS_BASE nsDirectoryIterator // Example: // -// nsNativeFileSpec parentDir(...); // directory over whose children we shall iterate +// nsFileSpec parentDir(...); // directory over whose children we shall iterate // for (nsDirectoryIterator i(parentDir); i; i++) // { -// // do something with (const nsNativeFileSpec&)i +// // do something with (const nsFileSpec&)i // } // // or: // -// for (nsDirectoryIterator i(parentDir, false); i; i--) +// for (nsDirectoryIterator i(parentDir, PR_FALSE); i; i--) // { -// // do something with (const nsNativeFileSpec&)i +// // do something with (const nsFileSpec&)i // } // // Currently, the only platform on which backwards iteration actually goes backwards @@ -378,21 +448,21 @@ class NS_BASE nsDirectoryIterator { public: nsDirectoryIterator( - const nsNativeFileSpec& parent, + const nsFileSpec& parent, int iterateDirection = +1); #ifndef XP_MAC // Macintosh currently doesn't allocate, so needn't clean up. virtual ~nsDirectoryIterator(); #endif - operator bool() const { return mExists; } + PRBool Exists() const { return mExists; } nsDirectoryIterator& operator ++(); // moves to the next item, if any. nsDirectoryIterator& operator ++(int) { return ++(*this); } // post-increment. nsDirectoryIterator& operator --(); // moves to the previous item, if any. nsDirectoryIterator& operator --(int) { return --(*this); } // post-decrement. - operator nsNativeFileSpec&() { return mCurrent; } + operator nsFileSpec&() { return mCurrent; } private: - nsNativeFileSpec mCurrent; - bool mExists; + nsFileSpec mCurrent; + bool mExists; // MUST be bool. #if defined(XP_UNIX) DIR* mDir; diff --git a/mozilla/base/public/nsFileStream.h b/mozilla/base/public/nsFileStream.h index f56f25f772d..823a4c73c72 100644 --- a/mozilla/base/public/nsFileStream.h +++ b/mozilla/base/public/nsFileStream.h @@ -19,14 +19,31 @@ // First checked in on 98/11/20 by John R. McMullen in the wrong directory. // Checked in again 98/12/04. // Polished version 98/12/08. +// Completely rewritten to integrate with nsIInputStream and nsIOutputStream (the +// xpcom stream objects. //======================================================================================== // // Classes defined: // -// single-byte char: -// +// nsInputStream, nsOutputStream +// These are the lightweight STATICALLY LINKED wrappers for +// the xpcom objects nsIInputStream and nsIOutputstream. +// Possible uses: +// If you are implementing a function that accepts one of these xpcom +// streams, just make one of these little jobbies on the stack, and +// the handy << or >> notation can be yours. +// // nsInputFileStream, nsOutputFileStream +// These are the STATICALLY LINKED versions of the file i/o streams, +// which wrap the NSPR file i/o plus console i/o. +// +// Related files: +// prio.h the NSPR file i/o C API), which is wrapped by +// THIS FILE statically linked C++ wrappers, which in turn are wrapped by +// nsIFileStream.h COM wrappers for this file, which are wrapped by +// nsAutoFileStream.h more easily used, nicer syntax wrappers for the +// COMified ones. Wrapper of a wrapper of a wrapper. // // This suite provide the following services: // @@ -41,13 +58,13 @@ // // Basic example: // -// nsFilePath myPath("/Development/iotest.txt"); +// nsFileSpec myPath("/Development/iotest.txt"); // // nsOutputFileStream testStream(myPath); // testStream << "Hello World" << nsEndl; // -// 4. Requires streams to be constructed using typesafe nsFilePath specifier -// (not the notorious and bug prone const char*), namely nsFilePath. See +// 4. Requires streams to be constructed using typesafe nsFileSpec specifier +// (not the notorious and bug prone const char*), namely nsFileSpec. See // nsFileSpec.h for more details. // // 5. Fixes a bug that have been there for a long time, and @@ -73,7 +90,13 @@ #else #include "prio.h" #endif -#include "nsFileSpec.h" + +#include "nsIFileStream.h" +#include "nsCOMPtr.h" + +class nsFileSpec; +class nsInputFileStream; +class nsOutputFileStream; //======================================================================================== // Compiler-specific macros, as needed @@ -133,201 +156,392 @@ using std::ostream; //=========================== End Compiler-specific macros =============================== //======================================================================================== -class NS_BASE nsBasicFileStream +class NS_BASE nsInputStream +// This is a convenience class, for use on the STACK ("new" junkies: get detoxed first). +// Given a COM-style stream, this allows you to use the >> operators. It also acquires and +// reference counts its stream. +// Please read the comments at the top of this file //======================================================================================== { public: - nsBasicFileStream(); - nsBasicFileStream(PRFileDesc* desc, int nsprMode); - nsBasicFileStream( - const nsFilePath& inFile, - int nsprMode, - PRIntn accessMode); - virtual ~nsBasicFileStream(); + nsInputStream(nsIInputStream* inStream) + : mInputStream(do_QueryInterface(inStream)) + , mEOF(PR_FALSE) + {} + virtual ~nsInputStream(); + + nsCOMPtr GetIStream() const + { + return mInputStream; + } + char eof() const { return mEOF; } + char get(); + PRInt32 read(void* s, PRInt32 n) + { + if (!mInputStream) + return 0; + PRInt32 result = 0; + mInputStream->Read((char*)s, 0, n, (PRUint32*)&result); + if (result < n) + mEOF = PR_TRUE; + return result; + } + // Input streamers. Add more as needed (int&, unsigned int& etc). (but you have to + // add delegators to the derived classes, too, because these operators don't inherit). + nsInputStream& operator >> (char& ch); - inline PRBool is_open() const { return mFileDesc != 0; } - void open( - const nsFilePath& inFile, - int nsprMode, - PRIntn accessMode); - void close(); - PRIntn tell() const; - void seek(PRInt32 offset) { seek(PR_SEEK_SET, offset); } - void seek(PRSeekWhence whence, PRInt32 offset); - PRBool eof() const { return mEOF; } - PRBool failed() const { return mFailed; } - // call PR_GetError() for details -protected: - - PRFileDesc* GetFileDescriptor() const { return mFileDesc; } - -protected: - - friend class nsBasicInStream; - friend class nsBasicOutStream; - - PRFileDesc* mFileDesc; - int mNSPRMode; - PRBool mFailed; - PRBool mEOF; -}; // class nsBasicFileStream - -//======================================================================================== -class NS_BASE nsBasicInStream -//======================================================================================== -{ -protected: - nsBasicInStream(nsBasicFileStream& inStream, istream* stream); - -public: - - nsBasicInStream& operator >> (nsBasicInStream& (*pf)(nsBasicInStream&)) + // Support manipulators + nsInputStream& operator >> (nsInputStream& (*pf)(nsInputStream&)) { return pf(*this); - } - void get(char& c); - PRInt32 read(void* s, PRInt32 n); + } +private: + + nsInputStream& operator >> (char* buf); // TOO DANGEROUS. DON'T DEFINE. + +// DATA +protected: + nsCOMPtr mInputStream; + PRBool mEOF; +}; // class nsInputStream + +typedef nsInputStream nsBasicInStream; // historic support for this name + +//======================================================================================== +class NS_BASE nsOutputStream +// This is a convenience class, for use on the STACK ("new" junkies, get detoxed first). +// Given a COM-style stream, this allows you to use the << operators. It also acquires and +// reference counts its stream. +// Please read the comments at the top of this file +//======================================================================================== +{ +public: + nsOutputStream() {} + nsOutputStream(nsIOutputStream* inStream) + : mOutputStream(do_QueryInterface(inStream)) + {} + + virtual ~nsOutputStream(); + + nsCOMPtr GetIStream() const + { + return mOutputStream; + } + void put(char c); + PRInt32 write(const void* s, PRInt32 n) + { + if (!mOutputStream) + return 0; + PRInt32 result = 0; + mOutputStream->Write((char*)s, 0, n, (PRUint32*)&result); + return result; + } + virtual void flush(); + + // Output streamers. Add more as needed (but you have to add delegators to the derived + // classes, too, because these operators don't inherit). + nsOutputStream& operator << (const char* buf); + nsOutputStream& operator << (char ch); + nsOutputStream& operator << (short val); + nsOutputStream& operator << (unsigned short val); + nsOutputStream& operator << (long val); + nsOutputStream& operator << (unsigned long val); + + // Support manipulators + nsOutputStream& operator << (nsOutputStream& (*pf)(nsOutputStream&)) + { + return pf(*this); + } + +// DATA +protected: + nsCOMPtr mOutputStream; +}; // class nsOutputStream + +typedef nsOutputStream nsBasicOutStream; // Historic support for this name + +//======================================================================================== +class NS_BASE nsFileClient +// Because COM does not allow us to write functions which return a boolean value etc, +// this class is here to take care of the tedious "declare variable then call with +// the address of the variable" chores. +//======================================================================================== +{ +public: + nsFileClient() // for delayed opening + : mResult(NS_OK) + { + } + nsFileClient(const nsCOMPtr& inFile) + : mFile(do_QueryInterface(inFile)) + , mResult(NS_OK) + { + } + + PRBool is_file() const + { + return mFile ? PR_TRUE : PR_FALSE; + } + void open( + const nsFileSpec& inFile, + int nsprMode, + PRIntn accessMode) + { + if (mFile) + mResult = mFile->Open(inFile, nsprMode, accessMode); + } + PRBool is_open() const + { + PRBool result = PR_FALSE; + if (mFile) + mFile->GetIsOpen(&result); + return result; + } + PRBool failed() const + { + return NS_FAILED(mResult); + } + void seek(PRInt32 offset) + { + seek(PR_SEEK_SET, offset); + } + + void seek(PRSeekWhence whence, PRInt32 offset) + { + if (mFile) + mResult = mFile->Seek(whence, offset); + } + PRIntn tell() + { + PRIntn result = -1; + if (mFile) + mResult = mFile->Tell(&result); + return result; + } + +// DATA +protected: + nsCOMPtr mFile; + PRBool mResult; +}; // class nsFileClient + +//======================================================================================== +class NS_BASE nsInputFileStream +// Please read the comments at the top of this file +//======================================================================================== +: public nsInputStream +, public nsFileClient +{ +public: + enum { kDefaultMode = PR_RDONLY }; + nsInputFileStream(nsIInputStream* inStream) + : nsInputStream(inStream) + , nsFileClient(do_QueryInterface(inStream)) + , mFileInputStream(do_QueryInterface(inStream)) + { + } + nsInputFileStream( + const nsFileSpec& inFile, + int nsprMode = kDefaultMode, + PRIntn accessMode = 00700) // <- OCTAL + : nsInputStream(nsnull) + { + nsISupports* stream; + NS_NewIOFileStream( + &stream, + inFile, nsprMode, accessMode); + mFile = nsQueryInterface(stream); + mInputStream = nsQueryInterface(stream); + mFileInputStream = nsQueryInterface(stream); + } + PRBool readline(char* s, PRInt32 n); // Result always null-terminated. // Check eof() before each call. // CAUTION: false result only indicates line was truncated // to fit buffer, or an error occurred (OTHER THAN eof). - // Input streamers. Add more as needed - nsBasicInStream& operator >> (char& ch); - - istream* GetStandardStream() const { return mStdStream; } - -protected: - - nsBasicFileStream& mBase; - istream* mStdStream; -}; // class nsBasicInStream - -//======================================================================================== -class NS_BASE nsBasicOutStream -//======================================================================================== -{ -protected: - - nsBasicOutStream(nsBasicFileStream& inStream, ostream* stream); - -public: - - nsBasicOutStream& operator << (nsBasicOutStream& (*pf)(nsBasicOutStream&)) - { - return pf(*this); - } - void put(char c); - PRInt32 write(const void* s, PRInt32 n); - void flush(); - - // Output streamers. Add more as needed - nsBasicOutStream& operator << (const char* buf); - nsBasicOutStream& operator << (char ch); - nsBasicOutStream& operator << (short val); - nsBasicOutStream& operator << (unsigned short val); - nsBasicOutStream& operator << (long val); - nsBasicOutStream& operator << (unsigned long val); - - ostream* GetStandardStream() const { return mStdStream; } - -protected: - - nsBasicFileStream& mBase; - ostream* mStdStream; -}; // class nsBasicOutStream - -//======================================================================================== -class NS_BASE nsInputFileStream -//======================================================================================== -: public nsBasicFileStream -, public nsBasicInStream -{ -public: - enum { kDefaultMode = PR_RDONLY }; - nsInputFileStream(istream* stream = CONSOLE_IN); - nsInputFileStream( - const nsFilePath& inFile, - int nsprMode = kDefaultMode, - PRIntn accessMode = 00700) // <- OCTAL - : nsBasicFileStream(inFile, nsprMode, accessMode) - , nsBasicInStream(*this, 0) - {} - - void open( - const nsFilePath& inFile, + void Open( + const nsFileSpec& inFile, int nsprMode = kDefaultMode, PRIntn accessMode = 00700) // <- OCTAL { - nsBasicFileStream::open(inFile, nsprMode, accessMode); + if (mFile) + mFile->Open(inFile, nsprMode, accessMode); } -private: - nsInputFileStream& operator >> (char* buf); // TOO DANGEROUS. DON'T DEFINE. + // Input streamers. Unfortunately, they don't inherit! + nsInputStream& operator >> (char& ch) + { return nsInputStream::operator >>(ch); } + nsInputStream& operator >> (nsInputStream& (*pf)(nsInputStream&)) + { return nsInputStream::operator >>(pf); } +// DATA +protected: + nsCOMPtr mFileInputStream; }; // class nsInputFileStream //======================================================================================== class NS_BASE nsOutputFileStream +// Please read the comments at the top of this file //======================================================================================== -: public nsBasicFileStream -, public nsBasicOutStream +: public nsOutputStream +, public nsFileClient { public: enum { kDefaultMode = (PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE) }; - nsOutputFileStream(ostream* stream = CONSOLE_OUT); + nsOutputFileStream() {} + nsOutputFileStream(nsIOutputStream* inStream) + : nsOutputStream(inStream) + , nsFileClient(do_QueryInterface(inStream)) + , mFileOutputStream(do_QueryInterface(inStream)) + { + } nsOutputFileStream( - const nsFilePath& inFile, + const nsFileSpec& inFile, int nsprMode = kDefaultMode, PRIntn accessMode = 00700) // <- OCTAL - : nsBasicFileStream(inFile, nsprMode, accessMode) - , nsBasicOutStream(*this, 0) - {} - - inline void open( - const nsFilePath& inFile, - int nsprMode = kDefaultMode, - PRIntn accessMode = 00700) // <- OCTAL + : nsOutputStream(nsnull) { - nsBasicFileStream::open(inFile, nsprMode, accessMode); + nsISupports* stream; + if (NS_FAILED(NS_NewIOFileStream( + &stream, + inFile, nsprMode, accessMode))) + return; + mFile = nsQueryInterface(stream); + mOutputStream = nsQueryInterface(stream); + mFileOutputStream = nsQueryInterface(stream); } + + virtual void flush(); + + // Output streamers. Unfortunately, they don't inherit! + nsOutputStream& operator << (const char* buf) + { return nsOutputStream::operator << (buf); } + nsOutputStream& operator << (char ch) + { return nsOutputStream::operator << (ch); } + nsOutputStream& operator << (short val) + { return nsOutputStream::operator << (val); } + nsOutputStream& operator << (unsigned short val) + { return nsOutputStream::operator << (val); } + nsOutputStream& operator << (long val) + { return nsOutputStream::operator << (val); } + nsOutputStream& operator << (unsigned long val) + { return nsOutputStream::operator << (val); } + nsOutputStream& operator << (nsOutputStream& (*pf)(nsOutputStream&)) + { return nsOutputStream::operator << (pf); } + +// DATA +protected: + nsCOMPtr mFileOutputStream; }; // class nsOutputFileStream //======================================================================================== -class NS_BASE nsIOFileStream +class NS_BASE nsOutputConsoleStream +// Please read the comments at the top of this file //======================================================================================== -: public nsBasicFileStream -, public nsBasicOutStream -, public nsBasicInStream +: public nsOutputFileStream +{ +public: + + nsOutputConsoleStream() + { + nsISupports* stream; + if (NS_FAILED(NS_NewOutputConsoleStream(&stream))) + return; + mFile = nsQueryInterface(stream); + mOutputStream = nsQueryInterface(stream); + mFileOutputStream = nsQueryInterface(stream); + } + + // Output streamers. Unfortunately, they don't inherit! + nsOutputStream& operator << (const char* buf) + { return nsOutputStream::operator << (buf); } + nsOutputStream& operator << (char ch) + { return nsOutputStream::operator << (ch); } + nsOutputStream& operator << (short val) + { return nsOutputStream::operator << (val); } + nsOutputStream& operator << (unsigned short val) + { return nsOutputStream::operator << (val); } + nsOutputStream& operator << (long val) + { return nsOutputStream::operator << (val); } + nsOutputStream& operator << (unsigned long val) + { return nsOutputStream::operator << (val); } + nsOutputStream& operator << (nsOutputStream& (*pf)(nsOutputStream&)) + { return nsOutputStream::operator << (pf); } + +}; // class nsOutputConsoleStream + +//======================================================================================== +class NS_BASE nsIOFileStream +// Please read the comments at the top of this file +//======================================================================================== +: public nsInputFileStream +, public nsOutputStream { public: enum { kDefaultMode = (PR_RDWR | PR_CREATE_FILE) }; nsIOFileStream( - const nsFilePath& inFile, + nsIInputStream* inInputStream + , nsIOutputStream* inOutputStream) + : nsInputFileStream(inInputStream) + , nsOutputStream(inOutputStream) + , mFileOutputStream(do_QueryInterface(inOutputStream)) + { + } + nsIOFileStream( + const nsFileSpec& inFile, int nsprMode = kDefaultMode, PRIntn accessMode = 00700) // <- OCTAL - : nsBasicFileStream(inFile, nsprMode, accessMode) - , nsBasicInStream(*this, 0) - , nsBasicOutStream(*this, 0) - {} - - inline void open( - const nsFilePath& inFile, - int nsprMode = kDefaultMode, - PRIntn accessMode = 00700) // <- OCTAL + : nsInputFileStream(nsnull) + , nsOutputStream(nsnull) { - nsBasicFileStream::open(inFile, nsprMode, accessMode); + nsISupports* stream; + if (NS_FAILED(NS_NewIOFileStream( + &stream, + inFile, nsprMode, accessMode))) + return; + mFile = nsQueryInterface(stream); + mInputStream = nsQueryInterface(stream); + mOutputStream = nsQueryInterface(stream); + mFileInputStream = nsQueryInterface(stream); + mFileOutputStream = nsQueryInterface(stream); } -}; // class nsIOFileStream + + // Output streamers. Unfortunately, they don't inherit! + nsOutputStream& operator << (const char* buf) + { return nsOutputStream::operator << (buf); } + nsOutputStream& operator << (char ch) + { return nsOutputStream::operator << (ch); } + nsOutputStream& operator << (short val) + { return nsOutputStream::operator << (val); } + nsOutputStream& operator << (unsigned short val) + { return nsOutputStream::operator << (val); } + nsOutputStream& operator << (long val) + { return nsOutputStream::operator << (val); } + nsOutputStream& operator << (unsigned long val) + { return nsOutputStream::operator << (val); } + nsOutputStream& operator << (nsOutputStream& (*pf)(nsOutputStream&)) + { return nsOutputStream::operator << (pf); } + // Input streamers. Unfortunately, they don't inherit! + nsInputStream& operator >> (char& ch) + { return nsInputStream::operator >>(ch); } + nsInputStream& operator >> (nsInputStream& (*pf)(nsInputStream&)) + { return nsInputStream::operator >>(pf); } + // DATA +protected: + nsCOMPtr mFileOutputStream; +}; // class nsIOFileStream + //======================================================================================== // Manipulators //======================================================================================== -NS_BASE nsBasicOutStream& nsEndl(nsBasicOutStream& os); - + +NS_BASE nsOutputStream& nsEndl(nsOutputStream& os); // outputs and FLUSHES. + #endif /* _FILESTREAM_H_ */ diff --git a/mozilla/base/public/nsIFileStream.h b/mozilla/base/public/nsIFileStream.h new file mode 100644 index 00000000000..da731e4f494 --- /dev/null +++ b/mozilla/base/public/nsIFileStream.h @@ -0,0 +1,127 @@ +/* -*- 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.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ +#ifndef nsIFileStream_h___ +#define nsIFileStream_h___ + +#include "nsIInputStream.h" +#include "nsIOutputStream.h" +#include "prio.h" + +class nsFileSpec; + +/* a6cf90e8-15b3-11d2-932e-00805f8add32 */ +#define NS_IFILE_IID \ +{ 0xa6cf90e8, 0x15b3, 0x11d2, \ + {0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32} } + +//======================================================================================== +class nsIFile +// Represents a file, and supports Open, Tell etc. +//======================================================================================== +: public nsISupports +{ +public: + static const nsIID& IID() { static nsIID iid = NS_IFILE_IID; return iid; } + NS_IMETHOD Open( + const nsFileSpec& inFile, + int nsprMode, + PRIntn accessMode) = 0; + // Note: Open() is only needed after + // an explicit Close(). All file streams + // are automatically opened on construction. + NS_IMETHOD Seek(PRSeekWhence whence, PRInt32 offset) = 0; + NS_IMETHOD GetIsOpen(PRBool* outOpen) = 0; + NS_IMETHOD Tell(PRIntn* outWhere) = 0; +}; // class nsIFile + +/* a6cf90e6-15b3-11d2-932e-00805f8add32 */ +#define NS_IFILEINPUTSTREAM_IID \ +{ 0xa6cf90e6, 0x15b3, 0x11d2, \ + {0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32} } + +//======================================================================================== +class nsIFileInputStream +// These are additional file-specific methods that files have, above what +// nsIInputStream supports. The current implementation supports both +// interfaces. +//======================================================================================== +: public nsISupports +{ +public: + static const nsIID& IID() { static nsIID iid = NS_IFILEINPUTSTREAM_IID; return iid; } +}; // class nsIFileInputStream + +/* a6cf90e7-15b3-11d2-932e-00805f8add32 */ +#define NS_IFILEOUTPUTSTREAM_IID \ +{ 0xa6cf90e7, 0x15b3, 0x11d2, \ + {0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32} } + +//======================================================================================== +class nsIFileOutputStream +// These are additional file-specific methods that files have, above what +// nsIOutputStream supports. The current implementation supports both +// interfaces. +//======================================================================================== +: public nsISupports +{ +public: + static const nsIID& IID() { static nsIID iid = NS_IFILEOUTPUTSTREAM_IID; return iid; } + NS_IMETHOD Flush() = 0; + // Forces a write to disk. +}; // class nsIFileOutputStream + +//---------------------------------------------------------------------------------------- +NS_BASE nsresult NS_NewTypicalInputFileStream( + nsISupports** aStreamResult, + const nsFileSpec& inFile + /*Default nsprMode == PR_RDONLY*/ + /*Default accessmode = 0700 (octal)*/); +// Factory method to get an nsInputStream from a file, using most common options + +//---------------------------------------------------------------------------------------- +extern "C" NS_BASE nsresult NS_NewOutputConsoleStream( + nsISupports** aStreamResult); + // Factory method to get an nsOutputStream to the console. + +//---------------------------------------------------------------------------------------- +extern "C" NS_BASE nsresult NS_NewTypicalOutputFileStream( + nsISupports** aStreamResult, // will implement all the above interfaces + const nsFileSpec& inFile + /*default nsprMode= (PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE)*/ + /*Default accessMode= 0700 (octal)*/); + // Factory method to get an nsOutputStream to a file - most common case. + +//---------------------------------------------------------------------------------------- +extern "C" NS_BASE nsresult NS_NewTypicalIOFileStream( + nsISupports** aStreamResult, // will implement all the above interfaces + const nsFileSpec& inFile + /*default nsprMode = (PR_RDWR | PR_CREATE_FILE)*/ + /*Default accessMode = 0700 (octal)*/); + // Factory method to get an object that implements both nsIInputStream + // and nsIOutputStream, associated with a single file. + +//---------------------------------------------------------------------------------------- +extern "C" NS_BASE nsresult NS_NewIOFileStream( + nsISupports** aStreamResult, // will implement all the above interfaces + const nsFileSpec& inFile, + PRInt32 nsprMode, + PRInt32 accessMode); + // Factory method to get an object that implements both nsIInputStream + // and nsIOutputStream, associated with a single file. + +#endif /* nsIFileStream_h___ */ diff --git a/mozilla/base/src/Makefile.in b/mozilla/base/src/Makefile.in index 4ab95c708b9..d0119a3969e 100644 --- a/mozilla/base/src/Makefile.in +++ b/mozilla/base/src/Makefile.in @@ -39,6 +39,7 @@ CPPSRCS = \ nsEscape.cpp \ nsFileSpec.cpp \ nsFileStream.cpp \ + nsIFileStream.cpp \ nsProperties.cpp \ nsRBTree.cpp \ nsSizeOfHandler.cpp \ diff --git a/mozilla/base/src/mac/nsFileSpecMac.cpp b/mozilla/base/src/mac/nsFileSpecMac.cpp index dfa4da0ec28..a403ccb19a6 100644 --- a/mozilla/base/src/mac/nsFileSpecMac.cpp +++ b/mozilla/base/src/mac/nsFileSpecMac.cpp @@ -28,6 +28,7 @@ #include #include #include +#include const unsigned char* kAliasHavenFolderName = "\pnsAliasHaven"; @@ -74,7 +75,7 @@ namespace MacFileHelpers // to support attaching of aliases in mail. void EnsureAliasHaven(); void SetNoResolve(Boolean inResolve); - bool IsAliasSafe(const FSSpec& inSpec); + PRBool IsAliasSafe(const FSSpec& inSpec); OSErr MakeAliasSafe(FSSpec& inOutSpec); OSErr ResolveAliasFile(FSSpec& inOutSpec, Boolean& wasAliased); @@ -131,8 +132,8 @@ char* MacFileHelpers::EncodeMacPath( // Method: Swap ':' and '/', hex escape the result //----------------------------------- { - if (inPath == NULL) - return NULL; + if (inPath == nsnull) + return nsnull; int pathSize = strlen(inPath); // XP code sometimes chokes if there's a final slash in the unix path. @@ -145,8 +146,8 @@ char* MacFileHelpers::EncodeMacPath( pathSize--; } - char * newPath = NULL; - char * finalPath = NULL; + char * newPath = nsnull; + char * finalPath = nsnull; if (prependSlash) { @@ -188,10 +189,10 @@ OSErr MacFileHelpers::MakeAliasSafe(FSSpec& inOutSpec) //---------------------------------------------------------------------------------------- { EnsureAliasHaven(); - nsNativeFileSpec dstDirSpec(sAliasHavenVRefNum, sAliasHavenDirID, "\p"); + nsFileSpec dstDirSpec(sAliasHavenVRefNum, sAliasHavenDirID, "\p"); // Make sure its name is unique - nsNativeFileSpec havenSpec(sAliasHavenVRefNum, sAliasHavenDirID, "\pG'day"); + nsFileSpec havenSpec(sAliasHavenVRefNum, sAliasHavenDirID, "\pG'day"); if (havenSpec.Valid()) havenSpec.MakeUnique(inOutSpec.name); // Copy the file into the haven directory @@ -221,9 +222,9 @@ char* MacFileHelpers::MacPathFromUnixPath(const char* unixPath) { char* dst = result; const char* src = unixPath; - if (*src == '/') // ¥ full path + if (*src == '/') // * full path src++; - else if (strchr(src, '/')) // ¥ partial path, and not just a leaf name + else if (strchr(src, '/')) // * partial path, and not just a leaf name *dst++ = ':'; strcpy(dst, src); nsUnescape(dst); // Hex Decode @@ -346,7 +347,7 @@ void MacFileHelpers::EnsureAliasHaven() } // MacFileHelpers::EnsureAliasHaven //---------------------------------------------------------------------------------------- -bool MacFileHelpers::IsAliasSafe(const FSSpec& inSpec) +PRBool MacFileHelpers::IsAliasSafe(const FSSpec& inSpec) // Returns true if the alias is in the alias haven directory, or if alias resolution // has been turned off. //---------------------------------------------------------------------------------------- @@ -379,7 +380,7 @@ OSErr MacFileHelpers::FSSpecFromFullUnixPath( // then it is combined with inOutSpec's vRefNum and parID to form a new spec. //----------------------------------- { - if (unixPath == NULL) + if (unixPath == nsnull) return badFidErr; char* macPath = MacPathFromUnixPath(unixPath); if (!macPath) @@ -413,7 +414,7 @@ char* MacFileHelpers::PathNameFromFSSpec( const FSSpec& inSpec, Boolean wantLeaf OSErr err = noErr; short fullPathLength = 0; - Handle fullPath = NULL; + Handle fullPath = nsnull; FSSpec tempSpec = inSpec; if ( tempSpec.parID == fsRtParID ) @@ -471,7 +472,7 @@ char* MacFileHelpers::PathNameFromFSSpec( const FSSpec& inSpec, Boolean wantLeaf tempSpec.name[tempSpec.name[0]] = ':'; /* Add directory name to beginning of fullPath */ - (void) Munger(fullPath, 0, NULL, 0, &tempSpec.name[1], tempSpec.name[0]); + (void) Munger(fullPath, 0, nsnull, 0, &tempSpec.name[1], tempSpec.name[0]); err = MemError(); } } while ( err == noErr && pb.dirInfo.ioDrDirID != fsRtDirID ); @@ -500,19 +501,19 @@ Clean: } // MacFileHelpers::PathNameFromFSSpec //======================================================================================== -// Macintosh nsNativeFileSpec implementation +// Macintosh nsFileSpec implementation //======================================================================================== //---------------------------------------------------------------------------------------- -nsNativeFileSpec::nsNativeFileSpec() +nsFileSpec::nsFileSpec() //---------------------------------------------------------------------------------------- -: mError(noErr) +: mError(NS_OK) { mSpec.name[0] = '\0'; } //---------------------------------------------------------------------------------------- -nsNativeFileSpec::nsNativeFileSpec(const nsNativeFileSpec& inSpec) +nsFileSpec::nsFileSpec(const nsFileSpec& inSpec) //---------------------------------------------------------------------------------------- : mSpec(inSpec.mSpec) , mError(inSpec.Error()) @@ -520,87 +521,90 @@ nsNativeFileSpec::nsNativeFileSpec(const nsNativeFileSpec& inSpec) } //---------------------------------------------------------------------------------------- -nsNativeFileSpec::nsNativeFileSpec(const char* inString, bool inCreateDirs) +nsFileSpec::nsFileSpec(const char* inString, PRBool inCreateDirs) //---------------------------------------------------------------------------------------- { - mError = MacFileHelpers::FSSpecFromFullUnixPath( - inString, mSpec, true, true, inCreateDirs); + mError = NS_FILE_RESULT(MacFileHelpers::FSSpecFromFullUnixPath( + inString, mSpec, false, true, inCreateDirs)); // allow a partial path, create as necessary - if (mError == fnfErr) - mError = noErr; -} // nsNativeFileSpec::nsNativeFileSpec + if (mError == NS_FILE_RESULT(fnfErr)) + mError = NS_OK; +} // nsFileSpec::nsFileSpec //---------------------------------------------------------------------------------------- -nsNativeFileSpec::nsNativeFileSpec( +nsFileSpec::nsFileSpec( short vRefNum, long parID, ConstStr255Param name) //---------------------------------------------------------------------------------------- { - mError = ::FSMakeFSSpec(vRefNum, parID, name, &mSpec); - if (mError == fnfErr) + mError = NS_FILE_RESULT(::FSMakeFSSpec(vRefNum, parID, name, &mSpec)); + if (mError == NS_FILE_RESULT(fnfErr)) mError = noErr; } //---------------------------------------------------------------------------------------- -nsNativeFileSpec::nsNativeFileSpec(const nsFilePath& inPath) +nsFileSpec::nsFileSpec(const nsFilePath& inPath) //---------------------------------------------------------------------------------------- { - *this = inPath.GetNativeSpec(); + *this = inPath.GetFileSpec(); } +#if DEBUG //---------------------------------------------------------------------------------------- -nsBasicOutStream& operator << (nsBasicOutStream& s, const nsNativeFileSpec& spec) +nsOutputStream& operator << (nsOutputStream& s, const nsFileSpec& spec) //---------------------------------------------------------------------------------------- { s << spec.mSpec.vRefNum << ", " << spec.mSpec.parID << ", \""; s.write((const char*)&spec.mSpec.name[1], spec.mSpec.name[0]); return s << "\""; -} // nsOutputFileStream& operator << (nsOutputFileStream&, const nsNativeFileSpec&) +} // nsOutputStream& operator << (nsOutputStream&, const nsFileSpec&) +#endif //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::operator = (const char* inString) +void nsFileSpec::operator = (const char* inString) //---------------------------------------------------------------------------------------- { - mError = MacFileHelpers::FSSpecFromFullUnixPath(inString, mSpec, true); -} // nsNativeFileSpec::operator = + mError = NS_FILE_RESULT(MacFileHelpers::FSSpecFromFullUnixPath(inString, mSpec, false)); +} // nsFileSpec::operator = //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::operator = (const nsNativeFileSpec& inSpec) +void nsFileSpec::operator = (const nsFileSpec& inSpec) //---------------------------------------------------------------------------------------- { mSpec = inSpec.mSpec; mError = inSpec.Error(); -} // nsNativeFileSpec::operator = +} // nsFileSpec::operator = //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::operator = (const nsFilePath& inPath) +void nsFileSpec::operator = (const nsFilePath& inPath) //---------------------------------------------------------------------------------------- { - *this = inPath.GetNativeSpec(); -} // nsNativeFileSpec::operator = + *this = inPath.GetFileSpec(); +} // nsFileSpec::operator = //---------------------------------------------------------------------------------------- -bool nsNativeFileSpec::Exists() const +PRBool nsFileSpec::Exists() const //---------------------------------------------------------------------------------------- { FSSpec temp; return ::FSMakeFSSpec(mSpec.vRefNum, mSpec.parID, mSpec.name, &temp) == noErr; -} // nsNativeFileSpec::operator = +} // nsFileSpec::operator = //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::SetLeafName(const char* inLeafName) +void nsFileSpec::SetLeafName(const char* inLeafName) // In leaf name can actually be a partial path... //---------------------------------------------------------------------------------------- { // what about long relative paths? Hmm? Str255 partialPath; MacFileHelpers::PLstrcpy(partialPath, inLeafName); - mError = FSMakeFSSpec(mSpec.vRefNum, mSpec.parID, partialPath, &mSpec); -} // nsNativeFileSpec::SetLeafName + mError = NS_FILE_RESULT( + ::FSMakeFSSpec(mSpec.vRefNum, mSpec.parID, partialPath, &mSpec)); +} // nsFileSpec::SetLeafName //---------------------------------------------------------------------------------------- -char* nsNativeFileSpec::GetLeafName() const +char* nsFileSpec::GetLeafName() const // Result needs to be delete[]ed. //---------------------------------------------------------------------------------------- { @@ -608,133 +612,206 @@ char* nsNativeFileSpec::GetLeafName() const memcpy(leaf, &mSpec.name[1], mSpec.name[0]); leaf[mSpec.name[0]] = '\0'; return nsFileSpecHelpers::StringDup(leaf); -} // nsNativeFileSpec::GetLeafName +} // nsFileSpec::GetLeafName //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::MakeAliasSafe() +void nsFileSpec::MakeAliasSafe() //---------------------------------------------------------------------------------------- { - mError = MacFileHelpers::MakeAliasSafe(mSpec); -} // nsNativeFileSpec::MakeAliasSafe + mError = NS_FILE_RESULT(MacFileHelpers::MakeAliasSafe(mSpec)); +} // nsFileSpec::MakeAliasSafe //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::MakeUnique(ConstStr255Param inSuggestedLeafName) +void nsFileSpec::MakeUnique(ConstStr255Param inSuggestedLeafName) //---------------------------------------------------------------------------------------- { if (inSuggestedLeafName[0] > 0) MacFileHelpers::PLstrcpy(mSpec.name, inSuggestedLeafName); MakeUnique(); -} // nsNativeFileSpec::MakeUnique +} // nsFileSpec::MakeUnique //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::ResolveAlias(bool& wasAliased) +void nsFileSpec::ResolveAlias(PRBool& wasAliased) //---------------------------------------------------------------------------------------- { Boolean wasAliased2; - mError = MacFileHelpers::ResolveAliasFile(mSpec, wasAliased2); + mError = NS_FILE_RESULT(MacFileHelpers::ResolveAliasFile(mSpec, wasAliased2)); wasAliased = (wasAliased2 != false); -} // nsNativeFileSpec::ResolveAlias +} // nsFileSpec::ResolveAlias //---------------------------------------------------------------------------------------- -bool nsNativeFileSpec::IsFile() const +PRBool nsFileSpec::IsFile() const //---------------------------------------------------------------------------------------- { long dirID; Boolean isDirectory; return (noErr == FSpGetDirectoryID(&mSpec, &dirID, &isDirectory) && !isDirectory); -} // nsNativeFileSpec::IsFile +} // nsFileSpec::IsFile //---------------------------------------------------------------------------------------- -bool nsNativeFileSpec::IsDirectory() const +PRBool nsFileSpec::IsDirectory() const //---------------------------------------------------------------------------------------- { long dirID; Boolean isDirectory; return (noErr == FSpGetDirectoryID(&mSpec, &dirID, &isDirectory) && isDirectory); -} // nsNativeFileSpec::IsDirectory +} // nsFileSpec::IsDirectory //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::GetParent(nsNativeFileSpec& outSpec) const +void nsFileSpec::GetParent(nsFileSpec& outSpec) const //---------------------------------------------------------------------------------------- { - if (mError == noErr) - outSpec.mError = FSMakeFSSpec(mSpec.vRefNum, mSpec.parID, NULL, outSpec); -} // nsNativeFileSpec::GetParent + if (NS_SUCCEEDED(mError)) + outSpec.mError + = NS_FILE_RESULT(::FSMakeFSSpec(mSpec.vRefNum, mSpec.parID, nsnull, outSpec)); +} // nsFileSpec::GetParent //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::operator += (const char* inRelativePath) +void nsFileSpec::operator += (const char* inRelativePath) //---------------------------------------------------------------------------------------- { long dirID; Boolean isDirectory; - mError = FSpGetDirectoryID(&mSpec, &dirID, &isDirectory); - if (mError == noErr && isDirectory) + mError = NS_FILE_RESULT(::FSpGetDirectoryID(&mSpec, &dirID, &isDirectory)); + if (NS_SUCCEEDED(mError) && isDirectory) { Str255 partialPath; MacFileHelpers::PLstrcpy(partialPath, inRelativePath); - mError = FSMakeFSSpec(mSpec.vRefNum, dirID, partialPath, *this); - //if (mError == noErr) + mError = NS_FILE_RESULT(::FSMakeFSSpec(mSpec.vRefNum, dirID, partialPath, *this)); + //if (NS_SUCCEEDED(mError)) // SetLeafName(inRelativePath); } -} // nsNativeFileSpec::operator += +} // nsFileSpec::operator += //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::CreateDirectory(int /* unix mode */) +void nsFileSpec::CreateDirectory(int /* unix mode */) //---------------------------------------------------------------------------------------- { long ignoredDirID; FSpDirCreate(&mSpec, smCurrentScript, &ignoredDirID); -} // nsNativeFileSpec::CreateDirectory +} // nsFileSpec::CreateDirectory //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::Delete(bool inRecursive) +void nsFileSpec::Delete(PRBool inRecursive) //---------------------------------------------------------------------------------------- { if (inRecursive) { // MoreFilesExtras - mError = DeleteDirectory( + mError = NS_FILE_RESULT(::DeleteDirectory( mSpec.vRefNum, mSpec.parID, - const_cast(mSpec.name)); + const_cast(mSpec.name))); } else - mError = FSpDelete(&mSpec); -} // nsNativeFileSpec::Delete + mError = NS_FILE_RESULT(FSpDelete(&mSpec)); +} // nsFileSpec::Delete +//---------------------------------------------------------------------------------------- +nsresult nsFileSpec::Rename(const char* inNewName) +//---------------------------------------------------------------------------------------- +{ + if (strchr(inNewName, '/')) + return -1; // no relative paths here! + Str255 pName; + MacFileHelpers::PLstrcpy(pName, inNewName); + if (FSpRename(&mSpec, pName) != noErr) + return -1; + SetLeafName(inNewName); + return 0; +} // nsFileSpec::Rename + +//---------------------------------------------------------------------------------------- +nsresult nsFileSpec::Copy(const nsFileSpec& newParentDir) const +//---------------------------------------------------------------------------------------- +{ + // We can only copy into a directory, and (for now) can not copy entire directories + + if (!newParentDir.IsDirectory() || (IsDirectory() ) ) + return NS_FILE_FAILURE; + + + nsresult result = NS_FILE_RESULT(::FSpFileCopy( &mSpec, + &newParentDir.mSpec, + const_cast(GetLeafPName()), + nsnull, + 0, + true)); + + return result; + +} // nsFileSpec::Copy + +//---------------------------------------------------------------------------------------- +nsresult nsFileSpec::Move(const nsFileSpec& newParentDir) const +//---------------------------------------------------------------------------------------- +{ + // We can only move into a directory + + if (!newParentDir.IsDirectory()) + return NS_FILE_FAILURE; + + nsresult result = NS_FILE_RESULT(::FSpMoveRenameCompat(&mSpec, + &newParentDir.mSpec, + const_cast(GetLeafPName()))); + + return result; +} // nsFileSpec::Move + +//---------------------------------------------------------------------------------------- +nsresult nsFileSpec::Execute(const char* /*args - how can this be cross-platform? problem! */ ) const +//---------------------------------------------------------------------------------------- +{ + if (IsDirectory()) + return NS_FILE_FAILURE; + + LaunchParamBlockRec launchThis; + launchThis.launchAppSpec = const_cast(&mSpec); + launchThis.launchAppParameters = nsnull; // args; + /* launch the thing */ + launchThis.launchBlockID = extendedBlock; + launchThis.launchEPBLength = extendedBlockLen; + launchThis.launchFileFlags = nsnull; + launchThis.launchControlFlags = launchContinue + launchNoFileFlags + launchUseMinimum; + launchThis.launchControlFlags += launchDontSwitch; + + nsresult result = NS_FILE_RESULT(::LaunchApplication(&launchThis)); + return result; + +} // nsFileSpec::Execute //======================================================================================== // Macintosh nsFilePath implementation //======================================================================================== //---------------------------------------------------------------------------------------- -nsFilePath::nsFilePath(const char* inString, bool inCreateDirs) +nsFilePath::nsFilePath(const char* inString, PRBool inCreateDirs) //---------------------------------------------------------------------------------------- : mPath(nsnull) -, mNativeFileSpec(inString, inCreateDirs) +, mFileSpec(inString, inCreateDirs) { // Make canonical and absolute. - char * path = MacFileHelpers::PathNameFromFSSpec( mNativeFileSpec, TRUE ); + char * path = MacFileHelpers::PathNameFromFSSpec( mFileSpec, TRUE ); mPath = MacFileHelpers::EncodeMacPath(path, true, true); } //---------------------------------------------------------------------------------------- -nsFilePath::nsFilePath(const nsNativeFileSpec& inSpec) +nsFilePath::nsFilePath(const nsFileSpec& inSpec) //---------------------------------------------------------------------------------------- -: mNativeFileSpec(inSpec) +: mFileSpec(inSpec) { char * path = MacFileHelpers::PathNameFromFSSpec( inSpec.mSpec, TRUE ); mPath = MacFileHelpers::EncodeMacPath(path, true, true); } //---------------------------------------------------------------------------------------- -void nsFilePath::operator = (const nsNativeFileSpec& inSpec) +void nsFilePath::operator = (const nsFileSpec& inSpec) //---------------------------------------------------------------------------------------- { delete [] mPath; char * path = MacFileHelpers::PathNameFromFSSpec( inSpec.mSpec, TRUE ); mPath = MacFileHelpers::EncodeMacPath(path, true, true); - mNativeFileSpec = inSpec; + mFileSpec = inSpec; } // nsFilePath::operator = //======================================================================================== @@ -742,14 +819,14 @@ void nsFilePath::operator = (const nsNativeFileSpec& inSpec) //======================================================================================== //---------------------------------------------------------------------------------------- -nsFileURL::nsFileURL(const char* inString, bool inCreateDirs) +nsFileURL::nsFileURL(const char* inString, PRBool inCreateDirs) //---------------------------------------------------------------------------------------- : mURL(nsnull) -, mNativeFileSpec(inString + kFileURLPrefixLength, inCreateDirs) +, mFileSpec(inString + kFileURLPrefixLength, inCreateDirs) { NS_ASSERTION(strstr(inString, kFileURLPrefix) == inString, "Not a URL!"); // Make canonical and absolute. - char* path = MacFileHelpers::PathNameFromFSSpec( mNativeFileSpec, TRUE ); + char* path = MacFileHelpers::PathNameFromFSSpec( mFileSpec, TRUE ); char* escapedPath = MacFileHelpers::EncodeMacPath(path, true, true); mURL = nsFileSpecHelpers::StringDup(kFileURLPrefix, kFileURLPrefixLength + strlen(escapedPath)); strcat(mURL, escapedPath); @@ -762,7 +839,7 @@ nsFileURL::nsFileURL(const char* inString, bool inCreateDirs) //---------------------------------------------------------------------------------------- nsDirectoryIterator::nsDirectoryIterator( - const nsNativeFileSpec& inDirectory + const nsFileSpec& inDirectory , int inIterateDirection) //---------------------------------------------------------------------------------------- : mCurrent(inDirectory) @@ -772,7 +849,7 @@ nsDirectoryIterator::nsDirectoryIterator( CInfoPBRec pb; DirInfo* dipb = (DirInfo*)&pb; // Sorry about this, there seems to be a bug in CWPro 4: - const FSSpec& inSpec = inDirectory.nsNativeFileSpec::operator const FSSpec&(); + const FSSpec& inSpec = inDirectory.nsFileSpec::operator const FSSpec&(); Str255 outName; MacFileHelpers::PLstrcpy(outName, inSpec.name); pb.hFileInfo.ioNamePtr = outName; @@ -786,7 +863,7 @@ nsDirectoryIterator::nsDirectoryIterator( if ( (err != noErr ) || !( dipb->ioFlAttrib & 0x0010 ) ) return; // Sorry about this, there seems to be a bug in CWPro 4: - FSSpec& currentSpec = mCurrent.nsNativeFileSpec::operator FSSpec&(); + FSSpec& currentSpec = mCurrent.nsFileSpec::operator FSSpec&(); currentSpec.vRefNum = inSpec.vRefNum; currentSpec.parID = dipb->ioDrDirID; mMaxIndex = pb.dirInfo.ioDrNmFls; @@ -809,10 +886,10 @@ OSErr nsDirectoryIterator::SetToIndex() CInfoPBRec cipb; DirInfo *dipb=(DirInfo *)&cipb; Str255 objectName; - dipb->ioCompletion = NULL; + dipb->ioCompletion = nsnull; dipb->ioFDirIndex = mIndex; // Sorry about this, there seems to be a bug in CWPro 4: - FSSpec& currentSpec = mCurrent.nsNativeFileSpec::operator FSSpec&(); + FSSpec& currentSpec = mCurrent.nsFileSpec::operator FSSpec&(); dipb->ioVRefNum = currentSpec.vRefNum; /* Might need to use vRefNum, not sure*/ dipb->ioDrDirID = currentSpec.parID; dipb->ioNamePtr = objectName; diff --git a/mozilla/base/src/makefile.win b/mozilla/base/src/makefile.win index fb3298c1e30..df3b68a47b1 100644 --- a/mozilla/base/src/makefile.win +++ b/mozilla/base/src/makefile.win @@ -41,6 +41,7 @@ CPPSRCS = \ nsFileSpec.cpp \ nsFileStream.cpp \ nsEscape.cpp \ + nsIFileStream.cpp \ $(NULL) CPP_OBJS = \ @@ -61,6 +62,7 @@ CPP_OBJS = \ .\$(OBJDIR)\nsFileSpec.obj \ .\$(OBJDIR)\nsFileStream.obj \ .\$(OBJDIR)\nsEscape.obj \ + .\$(OBJDIR)\nsIFileStream.obj \ $(NULL) EXPORTS=nscore.h nsIArena.h nsIAtom.h nsIByteBuffer.h \ diff --git a/mozilla/base/src/nsFileSpec.cpp b/mozilla/base/src/nsFileSpec.cpp index cf591af221f..9b0d62fb174 100644 --- a/mozilla/base/src/nsFileSpec.cpp +++ b/mozilla/base/src/nsFileSpec.cpp @@ -22,6 +22,9 @@ #include "nsDebug.h" #include "prtypes.h" +#include "plstr.h" +#include "plbase64.h" +#include "prmem.h" #include #include @@ -40,7 +43,7 @@ NS_NAMESPACE nsFileSpecHelpers char inSeparator, const char* inLeafName); #ifndef XP_MAC - NS_NAMESPACE_PROTOTYPE void Canonify(char*& ioPath, bool inMakeDirs); + NS_NAMESPACE_PROTOTYPE void Canonify(char*& ioPath, PRBool inMakeDirs); NS_NAMESPACE_PROTOTYPE void MakeAllDirectories(const char* inPath, int mode); #endif NS_NAMESPACE_PROTOTYPE char* GetLeaf(const char* inPath, char inSeparator); // allocated @@ -54,6 +57,14 @@ NS_NAMESPACE nsFileSpecHelpers #endif } NS_NAMESPACE_END +//---------------------------------------------------------------------------------------- +nsresult ns_file_convert_result(PRInt32 nativeErr) +//---------------------------------------------------------------------------------------- +{ + return nativeErr ? + NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES,((nativeErr)&0xFFFF)) + : NS_OK; +} //---------------------------------------------------------------------------------------- char* nsFileSpecHelpers::StringDup( @@ -65,7 +76,7 @@ char* nsFileSpecHelpers::StringDup( allocLength = strlen(inString); char* newPath = inString || allocLength ? new char[allocLength + 1] : nsnull; if (!newPath) - return NULL; + return nsnull; strcpy(newPath, inString); return newPath; } // nsFileSpecHelpers::StringDup @@ -77,7 +88,7 @@ char* nsFileSpecHelpers::AllocCat( //---------------------------------------------------------------------------------------- { if (!inString1) - return inString2 ? StringDup(inString2) : (char*)NULL; + return inString2 ? StringDup(inString2) : (char*)nsnull; if (!inString2) return StringDup(inString1); char* outString = StringDup(inString1, strlen(inString1) + strlen(inString2)); @@ -95,7 +106,7 @@ char* nsFileSpecHelpers::StringAssign( if (!inString2) { delete [] ioString; - ioString = (char*)NULL; + ioString = (char*)nsnull; return ioString; } if (!ioString || (strlen(inString2) > strlen(ioString))) @@ -125,8 +136,19 @@ void nsFileSpecHelpers::LeafReplace( } char* lastSeparator = strrchr(ioPath, inSeparator); int oldLength = strlen(ioPath); - *(++lastSeparator) = '\0'; // strip the current leaf name - int newLength = lastSeparator - ioPath + strlen(inLeafName); + PRBool trailingSeparator = (lastSeparator + 1 == ioPath + oldLength); + if (trailingSeparator) + { + *lastSeparator = '\0'; + lastSeparator = strrchr(ioPath, inSeparator); + } + if (lastSeparator) + lastSeparator++; // point at the trailing string + else + lastSeparator = ioPath; // the full monty + *lastSeparator = '\0'; // strip the current leaf name + + int newLength = (lastSeparator - ioPath) + strlen(inLeafName) + int(trailingSeparator); if (newLength > oldLength) { char* newPath = StringDup(ioPath, newLength + 1); @@ -134,7 +156,14 @@ void nsFileSpecHelpers::LeafReplace( ioPath = newPath; } strcat(ioPath, inLeafName); -} // nsNativeFileSpec::LeafReplace + if (trailingSeparator) + { + // If the original ended in a slash, then the new one should, too. + char sepStr[2] = "/"; + *sepStr = inSeparator; + strcat(ioPath, sepStr); + } +} // nsFileSpecHelpers::LeafReplace //---------------------------------------------------------------------------------------- char* nsFileSpecHelpers::GetLeaf(const char* inPath, char inSeparator) @@ -142,12 +171,32 @@ char* nsFileSpecHelpers::GetLeaf(const char* inPath, char inSeparator) //---------------------------------------------------------------------------------------- { if (!inPath) - return NULL; - char* lastSeparator = strrchr(inPath, inSeparator); - if (lastSeparator) - return StringDup(++lastSeparator); - return StringDup(inPath); -} // nsNativeFileSpec::GetLeaf + return nsnull; + const char* lastSeparator = strrchr(inPath, inSeparator); + + // If there was no separator, then return a copy of the caller's path. + if (!lastSeparator) + return StringDup(inPath); + + // So there's at least one separator. What's just after it? + // If the separator was not the last character, return the trailing string. + const char* leafPointer = lastSeparator + 1; + if (*leafPointer) + return StringDup(leafPointer); + + // So now, separator was the last character. Poke in a null instead. + *(char*)lastSeparator = '\0'; // Should use const_cast, but Unix has old compiler. + leafPointer = strrchr(inPath, inSeparator); + char* result = leafPointer ? StringDup(leafPointer++) : StringDup(inPath); + // Restore the poked null before returning. + *(char*)lastSeparator = inSeparator; +#ifdef XP_PC + // If it's a drive letter use the colon notation. + if (!leafPointer && strlen(result) == 2 && result[1] == '|') + result[1] = ':'; +#endif + return result; +} // nsFileSpecHelpers::GetLeaf #if defined(XP_UNIX) || defined(XP_PC) @@ -177,7 +226,7 @@ void nsFileSpecHelpers::MakeAllDirectories(const char* inPath, int mode) if (currentEnd) { *currentEnd = '\0'; - nsNativeFileSpec spec(nsFilePath(pathCopy, false)); + nsFileSpec spec(nsFilePath(pathCopy, PR_FALSE)); do { // If the node doesn't exist, and it is not the initial node in a full path, @@ -209,7 +258,7 @@ char* nsFileSpecHelpers::ReallocCat(char*& ioString, const char* inString1) delete [] ioString; ioString = newString; return ioString; -} // nsNativeFileSpec::ReallocCat +} // nsFileSpecHelpers::ReallocCat #if defined(XP_PC) #include "windows/nsFileSpecWin.cpp" // Windows-specific implementations @@ -225,7 +274,7 @@ char* nsFileSpecHelpers::ReallocCat(char*& ioString, const char* inString1) #ifndef XP_MAC //---------------------------------------------------------------------------------------- -nsFileURL::nsFileURL(const char* inString, bool inCreateDirs) +nsFileURL::nsFileURL(const char* inString, PRBool inCreateDirs) //---------------------------------------------------------------------------------------- : mURL(nsnull) { @@ -243,7 +292,7 @@ nsFileURL::nsFileURL(const nsFileURL& inOther) //---------------------------------------------------------------------------------------- : mURL(nsFileSpecHelpers::StringDup(inOther.mURL)) #ifdef XP_MAC -, mNativeFileSpec(inOther.GetNativeSpec()) +, mFileSpec(inOther.GetFileSpec()) #endif { } // nsFileURL::nsFileURL @@ -253,16 +302,16 @@ nsFileURL::nsFileURL(const nsFilePath& inOther) //---------------------------------------------------------------------------------------- : mURL(nsFileSpecHelpers::AllocCat(kFileURLPrefix, (const char*)inOther)) #ifdef XP_MAC -, mNativeFileSpec(inOther.GetNativeSpec()) +, mFileSpec(inOther.GetFileSpec()) #endif { } // nsFileURL::nsFileURL //---------------------------------------------------------------------------------------- -nsFileURL::nsFileURL(const nsNativeFileSpec& inOther) +nsFileURL::nsFileURL(const nsFileSpec& inOther) : mURL(nsFileSpecHelpers::AllocCat(kFileURLPrefix, (const char*)nsFilePath(inOther))) #ifdef XP_MAC -, mNativeFileSpec(inOther) +, mFileSpec(inOther) #endif //---------------------------------------------------------------------------------------- { @@ -282,7 +331,7 @@ void nsFileURL::operator = (const char* inString) nsFileSpecHelpers::StringAssign(mURL, inString); NS_ASSERTION(strstr(inString, kFileURLPrefix) == inString, "Not a URL!"); #ifdef XP_MAC - mNativeFileSpec = inString + kFileURLPrefixLength; + mFileSpec = inString + kFileURLPrefixLength; #endif } // nsFileURL::operator = @@ -292,7 +341,7 @@ void nsFileURL::operator = (const nsFileURL& inOther) { mURL = nsFileSpecHelpers::StringAssign(mURL, inOther.mURL); #ifdef XP_MAC - mNativeFileSpec = inOther.GetNativeSpec(); + mFileSpec = inOther.GetFileSpec(); #endif } // nsFileURL::operator = @@ -303,27 +352,29 @@ void nsFileURL::operator = (const nsFilePath& inOther) delete [] mURL; mURL = nsFileSpecHelpers::AllocCat(kFileURLPrefix, (const char*)inOther); #ifdef XP_MAC - mNativeFileSpec = inOther.GetNativeSpec(); + mFileSpec = inOther.GetFileSpec(); #endif } // nsFileURL::operator = //---------------------------------------------------------------------------------------- -void nsFileURL::operator = (const nsNativeFileSpec& inOther) +void nsFileURL::operator = (const nsFileSpec& inOther) //---------------------------------------------------------------------------------------- { delete [] mURL; mURL = nsFileSpecHelpers::AllocCat(kFileURLPrefix, (const char*)nsFilePath(inOther)); #ifdef XP_MAC - mNativeFileSpec = inOther; + mFileSpec = inOther; #endif } // nsFileURL::operator = +#if DEBUG //---------------------------------------------------------------------------------------- -nsBasicOutStream& operator << (nsBasicOutStream& s, const nsFileURL& url) +nsOutputStream& operator << (nsOutputStream& s, const nsFileURL& url) //---------------------------------------------------------------------------------------- { return (s << url.mURL); } +#endif //======================================================================================== // nsFilePath implementation @@ -332,14 +383,14 @@ nsBasicOutStream& operator << (nsBasicOutStream& s, const nsFileURL& url) nsFilePath::nsFilePath(const nsFilePath& inPath) : mPath(nsFileSpecHelpers::StringDup(inPath.mPath)) #ifdef XP_MAC - , mNativeFileSpec(inPath.mNativeFileSpec) + , mFileSpec(inPath.mFileSpec) #endif { } #ifndef XP_MAC //---------------------------------------------------------------------------------------- -nsFilePath::nsFilePath(const char* inString, bool inCreateDirs) +nsFilePath::nsFilePath(const char* inString, PRBool inCreateDirs) //---------------------------------------------------------------------------------------- : mPath(nsFileSpecHelpers::StringDup(inString)) { @@ -362,14 +413,14 @@ nsFilePath::nsFilePath(const nsFileURL& inOther) //---------------------------------------------------------------------------------------- : mPath(nsFileSpecHelpers::StringDup(inOther.mURL + kFileURLPrefixLength)) #ifdef XP_MAC -, mNativeFileSpec(inOther.GetNativeSpec()) +, mFileSpec(inOther.GetFileSpec()) #endif { } #ifdef XP_UNIX //---------------------------------------------------------------------------------------- -nsFilePath::nsFilePath(const nsNativeFileSpec& inOther) +nsFilePath::nsFilePath(const nsFileSpec& inOther) //---------------------------------------------------------------------------------------- : mPath(nsFileSpecHelpers::StringDup(inOther.mPath)) { @@ -385,7 +436,7 @@ nsFilePath::~nsFilePath() #ifdef XP_UNIX //---------------------------------------------------------------------------------------- -void nsFilePath::operator = (const nsNativeFileSpec& inOther) +void nsFilePath::operator = (const nsFileSpec& inOther) //---------------------------------------------------------------------------------------- { mPath = nsFileSpecHelpers::StringAssign(mPath, inOther.mPath); @@ -398,14 +449,14 @@ void nsFilePath::operator = (const char* inString) { NS_ASSERTION(strstr(inString, kFileURLPrefix) != inString, "URL passed as path"); #ifdef XP_MAC - mNativeFileSpec = inString; - nsFileSpecHelpers::StringAssign(mPath, (const char*)nsFilePath(mNativeFileSpec)); + mFileSpec = inString; + nsFileSpecHelpers::StringAssign(mPath, (const char*)nsFilePath(mFileSpec)); #else #ifdef XP_PC nsFileSpecHelpers::UnixToNative(mPath); #endif // Make canonical and absolute. - nsFileSpecHelpers::Canonify(mPath, false /* XXX? */); + nsFileSpecHelpers::Canonify(mPath, PR_FALSE /* XXX? */); #ifdef XP_PC nsFileSpecHelpers::NativeToUnix(mPath); #endif @@ -418,7 +469,7 @@ void nsFilePath::operator = (const nsFileURL& inOther) { nsFileSpecHelpers::StringAssign(mPath, (const char*)nsFilePath(inOther)); #ifdef XP_MAC - mNativeFileSpec = inOther.GetNativeSpec(); + mFileSpec = inOther.GetFileSpec(); #endif } @@ -433,40 +484,51 @@ void nsFilePath::operator = (const nsFilePath& inOther) } //======================================================================================== -// nsNativeFileSpec implementation +// nsFileSpec implementation //======================================================================================== #ifndef XP_MAC //---------------------------------------------------------------------------------------- -nsNativeFileSpec::nsNativeFileSpec() +nsFileSpec::nsFileSpec() //---------------------------------------------------------------------------------------- -: mPath(NULL) +: mPath(nsnull) +, mError(NS_OK) { } #endif //---------------------------------------------------------------------------------------- -nsNativeFileSpec::nsNativeFileSpec(const nsFileURL& inURL) +nsFileSpec::nsFileSpec(const nsPersistentFileDescriptor& inDescriptor) //---------------------------------------------------------------------------------------- #ifndef XP_MAC -: mPath(NULL) +: mPath(nsnull) +#endif +{ + *this = inDescriptor; +} + +//---------------------------------------------------------------------------------------- +nsFileSpec::nsFileSpec(const nsFileURL& inURL) +//---------------------------------------------------------------------------------------- +#ifndef XP_MAC +: mPath(nsnull) #endif { *this = nsFilePath(inURL); // convert to unix path first } //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::MakeUnique(const char* inSuggestedLeafName) +void nsFileSpec::MakeUnique(const char* inSuggestedLeafName) //---------------------------------------------------------------------------------------- { if (inSuggestedLeafName && *inSuggestedLeafName) SetLeafName(inSuggestedLeafName); MakeUnique(); -} // nsNativeFileSpec::MakeUnique +} // nsFileSpec::MakeUnique //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::MakeUnique() +void nsFileSpec::MakeUnique() //---------------------------------------------------------------------------------------- { if (!Exists()) @@ -497,51 +559,82 @@ void nsNativeFileSpec::MakeUnique() if (*suffix) delete [] suffix; delete [] leafName; -} // nsNativeFileSpec::MakeUnique +} // nsFileSpec::MakeUnique //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::operator = (const nsFileURL& inURL) +void nsFileSpec::operator = (const nsFileURL& inURL) //---------------------------------------------------------------------------------------- { *this = nsFilePath(inURL); // convert to unix path first } +//---------------------------------------------------------------------------------------- +void nsFileSpec::operator = (const nsPersistentFileDescriptor& inDescriptor) +//---------------------------------------------------------------------------------------- +{ + + void* data; + PRInt32 dataSize; + inDescriptor.GetData(data, dataSize); + +#ifdef XP_MAC + char* decodedData = PL_Base64Decode((const char*)data, (int)dataSize, nsnull); + // Cast to an alias record and resolve. + AliasHandle aliasH = nsnull; + mError = NS_FILE_RESULT(PtrToHand(decodedData, &(Handle)aliasH, (dataSize * 3) / 4)); + PR_Free(decodedData); + if (NS_SUCCEEDED(mError)) + return; // not enough memory? + + Boolean changed; + mError = NS_FILE_RESULT(::ResolveAlias(nsnull, aliasH, &mSpec, &changed)); + DisposeHandle((Handle) aliasH); +#else + nsFileSpecHelpers::StringAssign(mPath, (char*)data); + mError = NS_OK; +#endif +} + //======================================================================================== -// UNIX & WIN nsNativeFileSpec implementation +// UNIX & WIN nsFileSpec implementation //======================================================================================== #ifdef XP_UNIX //---------------------------------------------------------------------------------------- -nsNativeFileSpec::nsNativeFileSpec(const nsFilePath& inPath) +nsFileSpec::nsFileSpec(const nsFilePath& inPath) //---------------------------------------------------------------------------------------- : mPath(nsFileSpecHelpers::StringDup((const char*)inPath)) +, mError(NS_OK) { } #endif // XP_UNIX #ifdef XP_UNIX //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::operator = (const nsFilePath& inPath) +void nsFileSpec::operator = (const nsFilePath& inPath) //---------------------------------------------------------------------------------------- { nsFileSpecHelpers::StringAssign(mPath, (const char*)inPath); + mError = NS_OK; } #endif //XP_UNIX #if defined(XP_UNIX) || defined(XP_PC) //---------------------------------------------------------------------------------------- -nsNativeFileSpec::nsNativeFileSpec(const nsNativeFileSpec& inSpec) +nsFileSpec::nsFileSpec(const nsFileSpec& inSpec) //---------------------------------------------------------------------------------------- : mPath(nsFileSpecHelpers::StringDup(inSpec.mPath)) +, mError(NS_OK) { } #endif //XP_UNIX #if defined(XP_UNIX) || defined(XP_PC) //---------------------------------------------------------------------------------------- -nsNativeFileSpec::nsNativeFileSpec(const char* inString, bool inCreateDirs) +nsFileSpec::nsFileSpec(const char* inString, PRBool inCreateDirs) //---------------------------------------------------------------------------------------- : mPath(nsFileSpecHelpers::StringDup(inString)) +, mError(NS_OK) { // Make canonical and absolute. nsFileSpecHelpers::Canonify(mPath, inCreateDirs); @@ -549,7 +642,7 @@ nsNativeFileSpec::nsNativeFileSpec(const char* inString, bool inCreateDirs) #endif //XP_UNIX,PC //---------------------------------------------------------------------------------------- -nsNativeFileSpec::~nsNativeFileSpec() +nsFileSpec::~nsFileSpec() //---------------------------------------------------------------------------------------- { #ifndef XP_MAC @@ -559,39 +652,160 @@ nsNativeFileSpec::~nsNativeFileSpec() #if defined(XP_UNIX) || defined(XP_PC) //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::operator = (const nsNativeFileSpec& inSpec) +void nsFileSpec::operator = (const nsFileSpec& inSpec) //---------------------------------------------------------------------------------------- { mPath = nsFileSpecHelpers::StringAssign(mPath, inSpec.mPath); + mError = inSpec.Error(); } #endif //XP_UNIX #if defined(XP_UNIX) || defined(XP_PC) //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::operator = (const char* inString) +void nsFileSpec::operator = (const char* inString) //---------------------------------------------------------------------------------------- { mPath = nsFileSpecHelpers::StringAssign(mPath, inString); // Make canonical and absolute. - nsFileSpecHelpers::Canonify(mPath, true /* XXX? */); + nsFileSpecHelpers::Canonify(mPath, PR_TRUE /* XXX? */); + mError = NS_OK; } #endif //XP_UNIX +#if DEBUG #if (defined(XP_UNIX) || defined(XP_PC)) //---------------------------------------------------------------------------------------- -nsBasicOutStream& operator << (nsBasicOutStream& s, const nsNativeFileSpec& spec) +nsOutputStream& operator << (nsOutputStream& s, const nsFileSpec& spec) //---------------------------------------------------------------------------------------- { return (s << (const char*)spec.mPath); } #endif // DEBUG && XP_UNIX +#endif //---------------------------------------------------------------------------------------- -nsNativeFileSpec nsNativeFileSpec::operator + (const char* inRelativePath) const +nsFileSpec nsFileSpec::operator + (const char* inRelativePath) const //---------------------------------------------------------------------------------------- { - nsNativeFileSpec result = *this; + nsFileSpec result = *this; result += inRelativePath; return result; -} // nsNativeFileSpec::operator + +} // nsFileSpec::operator + + +//======================================================================================== +// class nsPersistentFileDescriptor +//======================================================================================== + +//---------------------------------------------------------------------------------------- +nsPersistentFileDescriptor::nsPersistentFileDescriptor(const nsPersistentFileDescriptor& inDesc) +//---------------------------------------------------------------------------------------- + : mDescriptorString(nsFileSpecHelpers::StringDup(inDesc.mDescriptorString)) +{ +} // nsPersistentFileDescriptor::nsPersistentFileDescriptor + +//---------------------------------------------------------------------------------------- +void nsPersistentFileDescriptor::operator = (const nsPersistentFileDescriptor& inDesc) +//---------------------------------------------------------------------------------------- +{ + nsFileSpecHelpers::StringAssign(mDescriptorString, inDesc.mDescriptorString); +} // nsPersistentFileDescriptor::operator = + +//---------------------------------------------------------------------------------------- +nsPersistentFileDescriptor::nsPersistentFileDescriptor(const nsFileSpec& inSpec) +//---------------------------------------------------------------------------------------- + : mDescriptorString(nsnull) +{ + *this = inSpec; +} // nsPersistentFileDescriptor::nsPersistentFileDescriptor + +//---------------------------------------------------------------------------------------- +void nsPersistentFileDescriptor::operator = (const nsFileSpec& inSpec) +//---------------------------------------------------------------------------------------- +{ +#ifdef XP_MAC + if (inSpec.Error()) + return; + AliasHandle aliasH; + OSErr err = NewAlias(nil, inSpec.operator const FSSpec* const (), &aliasH); + if (err != noErr) + return; + + PRUint32 bytes = GetHandleSize((Handle) aliasH); + HLock((Handle) aliasH); + char* buf = PL_Base64Encode((const char*)*aliasH, bytes, nsnull); + DisposeHandle((Handle) aliasH); + + nsFileSpecHelpers::StringAssign(mDescriptorString, buf); + PR_Free(buf); +#else + nsFileSpecHelpers::StringAssign(mDescriptorString, inSpec); +#endif // XP_MAC +} // nsPersistentFileDescriptor::operator = + +//---------------------------------------------------------------------------------------- +nsPersistentFileDescriptor::~nsPersistentFileDescriptor() +//---------------------------------------------------------------------------------------- +{ + delete [] mDescriptorString; +} // nsPersistentFileDescriptor::~nsPersistentFileDescriptor + +//---------------------------------------------------------------------------------------- +void nsPersistentFileDescriptor::GetData(void*& outData, PRInt32& outSize) const +//---------------------------------------------------------------------------------------- +{ + outSize = PL_strlen(mDescriptorString); + outData = mDescriptorString; +} + +//---------------------------------------------------------------------------------------- +void nsPersistentFileDescriptor::SetData(const void* inData, PRInt32 inSize) +//---------------------------------------------------------------------------------------- +{ + delete [] mDescriptorString; + mDescriptorString = new char[1 + inSize]; + if (!mDescriptorString) + return; + memcpy(mDescriptorString, inData, inSize); + mDescriptorString[inSize] = '\0'; +} + +#define MAX_PERSISTENT_DATA_SIZE 1000 + +//---------------------------------------------------------------------------------------- +nsInputStream& operator >> (nsInputStream& s, nsPersistentFileDescriptor& d) +// reads the data from a file +//---------------------------------------------------------------------------------------- +{ + char bigBuffer[MAX_PERSISTENT_DATA_SIZE + 1]; + // The first 8 bytes of the data should be a hex version of the data size to follow. + PRInt32 bytesRead = 8; + bytesRead = s.read(bigBuffer, bytesRead); + if (bytesRead != 8) + return (nsInputFileStream&)s; + bigBuffer[8] = '\0'; + sscanf(bigBuffer, "%lx", &bytesRead); + if (bytesRead > MAX_PERSISTENT_DATA_SIZE) + return (nsInputFileStream&)s; // preposterous. + // Now we know how many bytes to read, do it. + s.read(bigBuffer, bytesRead); + d.SetData(bigBuffer, bytesRead); + return (nsInputFileStream&)s; +} + +//---------------------------------------------------------------------------------------- +nsOutputStream& operator << (nsOutputStream& s, const nsPersistentFileDescriptor& d) +// writes the data to a file +//---------------------------------------------------------------------------------------- +{ + char littleBuf[9]; + PRInt32 dataSize; + void* data; + d.GetData(data, dataSize); + // First write (in hex) the length of the data to follow. Exactly 8 bytes + sprintf(littleBuf, "%0.8x", dataSize); + s << littleBuf; + // Now write the data itself + s << d.mDescriptorString; + return s; +} diff --git a/mozilla/base/src/nsFileStream.cpp b/mozilla/base/src/nsFileStream.cpp index 50f2b780e85..2950894ec3b 100644 --- a/mozilla/base/src/nsFileStream.cpp +++ b/mozilla/base/src/nsFileStream.cpp @@ -22,332 +22,78 @@ #include "nsFileStream.h" + #include #include -#ifdef XP_MAC -#include -#endif //======================================================================================== -// nsBasicFileStream +// nsInputStream //======================================================================================== //---------------------------------------------------------------------------------------- -nsBasicFileStream::nsBasicFileStream() +nsInputStream::~nsInputStream() //---------------------------------------------------------------------------------------- - : mFileDesc(0) - , mNSPRMode(0) - , mFailed(false) - , mEOF(false) { + mInputStream->Close(); } //---------------------------------------------------------------------------------------- -nsBasicFileStream::nsBasicFileStream( - const nsFilePath& inFile, - int nsprMode, - PRIntn accessMode) +char nsInputStream::get() //---------------------------------------------------------------------------------------- - : mFileDesc(0) - , mNSPRMode(0) - , mFailed(false) - , mEOF(false) { - open(inFile, nsprMode, accessMode); + char c; + read(&c, sizeof(c)); + return c; } //---------------------------------------------------------------------------------------- -nsBasicFileStream::nsBasicFileStream(PRFileDesc* desc, int nsprMode) +static void TidyEndOfLine(char*& cp) +// Assumes that cp is pointing at \n or \r. Nulls out the character, checks for +// a second terminator (of the opposite persuasion), and returns cp pointing past the +// entire eol construct (one or two characters). //---------------------------------------------------------------------------------------- - : mFileDesc(desc) - , mNSPRMode(nsprMode) - , mFailed(false) - , mEOF(false) { + char ch = *cp; + *cp++ = '\0'; // terminate at the newline, then skip past it + if ((ch == '\n' && *cp == '\r') || (ch == '\r' && *cp == '\n')) + cp++; // possibly a pair. } //---------------------------------------------------------------------------------------- -nsBasicFileStream::~nsBasicFileStream() +nsInputStream& nsInputStream::operator >> (char& c) //---------------------------------------------------------------------------------------- { - close(); -} - -//---------------------------------------------------------------------------------------- -void nsBasicFileStream::open( - const nsFilePath& inFile, - int nsprMode, - PRIntn accessMode) -//---------------------------------------------------------------------------------------- -{ - if (mFileDesc) - return; - - const int nspr_modes[]={ - PR_WRONLY | PR_CREATE_FILE, - PR_WRONLY | PR_CREATE_FILE | PR_APPEND, - PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, - PR_RDONLY, - PR_RDONLY | PR_APPEND, - PR_RDWR | PR_CREATE_FILE, - PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE, -// "wb", -// "ab", -// "wb", -// "rb", -// "r+b", -// "w+b", - 0 }; - const int* currentLegalMode = nspr_modes; - while (*currentLegalMode && nsprMode != *currentLegalMode) - ++currentLegalMode; - if (!*currentLegalMode) - return; - -#ifdef XP_MAC - // Use the file spec to open the file, because one path can be common to - // several files on the Macintosh (you can have several volumes with the - // same name, see). - mFileDesc = 0; - if (inFile.GetNativeSpec().Error() != noErr) - return; - OSErr err = noErr; -#if DEBUG - const OSType kCreator = 'CWIE'; -#else - const OSType kCreator = 'MOSS'; -#endif - nsNativeFileSpec nativeSpec = inFile.GetNativeSpec(); - FSSpec* spec = (FSSpec*)nativeSpec; - if (nsprMode & PR_CREATE_FILE) - err = FSpCreate(spec, kCreator, 'TEXT', 0); - if (err == dupFNErr) - err = noErr; - if (err != noErr) - return; - - SInt8 perm; - if (nsprMode & PR_RDWR) - perm = fsRdWrPerm; - else if (nsprMode & PR_WRONLY) - perm = fsWrPerm; - else - perm = fsRdPerm; - - short refnum; - err = FSpOpenDF(spec, perm, &refnum); - - if (err == noErr && (nsprMode & PR_TRUNCATE)) - err = SetEOF(refnum, 0); - if (err == noErr && (nsprMode & PR_APPEND)) - err = SetFPos(refnum, fsFromLEOF, 0); - if (err != noErr) - return; - - if ((mFileDesc = PR_ImportFile(refnum)) == 0) - return; -#else - // Platforms other than Macintosh... - // Another bug in NSPR: Mac PR_Open assumes a unix style path, but Win PR_Open assumes - // a windows path. - if ((mFileDesc = PR_Open((const char*)nsNativeFileSpec(inFile), nsprMode, accessMode)) == 0) - return; -#endif - mNSPRMode = nsprMode; -} // nsFileStreamHelpers::open - -//---------------------------------------------------------------------------------------- -void nsBasicFileStream::close() -// Must precede the destructor because both are inline. -//---------------------------------------------------------------------------------------- -{ - if (mFileDesc==PR_STDIN || mFileDesc==PR_STDOUT || mFileDesc==PR_STDERR || mFileDesc == 0) - return; - if (PR_Close(mFileDesc) == PR_SUCCESS) - mFileDesc = 0; -} // nsBasicFileStream::close - -//---------------------------------------------------------------------------------------- -void nsBasicFileStream::seek(PRSeekWhence whence, PRInt32 offset) -// Must precede the destructor because both are inline. -//---------------------------------------------------------------------------------------- -{ - if (mFileDesc==PR_STDIN || mFileDesc==PR_STDOUT || mFileDesc==PR_STDERR || mFileDesc == 0) - return; - mFailed = false; // reset on a seek. - mEOF = false; // reset on a seek. - PRInt32 position = PR_Seek(mFileDesc, 0, PR_SEEK_CUR); - PRInt32 available = PR_Available(mFileDesc); - PRInt32 fileSize = position + available; - PRInt32 newPosition; - switch (whence) - { - case PR_SEEK_CUR: newPosition = position + offset; break; - case PR_SEEK_SET: newPosition = offset; break; - case PR_SEEK_END: newPosition = fileSize + offset; break; - } - if (newPosition < 0) - { - newPosition = 0; - mFailed = true; - } - else if (newPosition >= fileSize) - { - newPosition = fileSize; - mEOF = true; - } - if (PR_Seek(mFileDesc, newPosition, PR_SEEK_SET) < 0) - mFailed = true; -} // nsBasicFileStream::seek - -//---------------------------------------------------------------------------------------- -PRIntn nsBasicFileStream::tell() const -// Must precede the destructor because both are inline. -//---------------------------------------------------------------------------------------- -{ - if (mFileDesc==PR_STDIN || mFileDesc==PR_STDOUT || mFileDesc==PR_STDERR || mFileDesc == 0) - return -1; - return PR_Seek(mFileDesc, 0, PR_SEEK_CUR); -} // nsBasicFileStream::tell - -//======================================================================================== -// nsBasicInStream -//======================================================================================== - -//---------------------------------------------------------------------------------------- -nsBasicInStream::nsBasicInStream(nsBasicFileStream& inBasicStream, istream* inStream) -//---------------------------------------------------------------------------------------- - : mBase(inBasicStream) - , mStdStream(inStream) -{ -} -//---------------------------------------------------------------------------------------- -void nsBasicInStream::get(char& c) -//---------------------------------------------------------------------------------------- -{ - read(&c, sizeof(char)); -} - -//---------------------------------------------------------------------------------------- -PRBool nsBasicInStream::readline(char* s, PRInt32 n) -// This will truncate if the buffer is too small. Result will always be null-terminated. -//---------------------------------------------------------------------------------------- -{ - PRBool bufferLargeEnough = true; // result - if (!s || !n) - return true; - PRIntn position = mBase.tell(); - if (position < 0) - return false; - PRInt32 bytesRead = read(s, n - 1); - if (mBase.failed()) - return false; - s[bytesRead] = '\0'; // always terminate at the end of the buffer - char* tp = strpbrk(s, "\n\r"); - if (tp) - { - char ch = *tp; - *tp++ = '\0'; // terminate at the newline, then skip past it - if ((ch == '\n' && *tp == '\r') || (ch == '\r' && *tp == '\n')) - tp++; // possibly a pair. - bytesRead = (tp - s); - } - else if (!mBase.eof()) - bufferLargeEnough = false; - position += bytesRead; - mBase.seek(position); - return bufferLargeEnough; -} // nsBasicInStream::getline - -//---------------------------------------------------------------------------------------- -PRInt32 nsBasicInStream::read(void* s, PRInt32 n) -//---------------------------------------------------------------------------------------- -{ -#ifndef NS_USE_PR_STDIO - // Calling PR_Read on stdin is sure suicide on Macintosh. - if (GetStandardStream()) - { - GetStandardStream()->read((char*)s, n); - return n; - } -#endif - if (!mBase.is_open() || mBase.failed()) - return -1; - PRInt32 bytesRead = PR_Read(mBase.GetFileDescriptor(), s, n); - if (bytesRead < 0) - mBase.mFailed = true; - else if (bytesRead < n) - mBase.mEOF = true; - return bytesRead; -} - -//---------------------------------------------------------------------------------------- -nsBasicInStream& nsBasicInStream::operator >> (char& c) -//---------------------------------------------------------------------------------------- -{ - get(c); + c = get(); return *this; } //======================================================================================== -// nsInputFileStream +// nsOutputStream //======================================================================================== //---------------------------------------------------------------------------------------- -nsInputFileStream::nsInputFileStream(istream* stream) +nsOutputStream::~nsOutputStream() //---------------------------------------------------------------------------------------- -#ifndef NS_USE_PR_STDIO - : nsBasicFileStream(0, kDefaultMode) - , nsBasicInStream(*this, stream) -#else - : nsBasicFileStream(PR_STDIN, kDefaultMode) - , nsBasicInStream(*this, 0) -#endif -{ -} - -//======================================================================================== -// nsBasicOutStream -//======================================================================================== - -//---------------------------------------------------------------------------------------- -nsBasicOutStream::nsBasicOutStream(nsBasicFileStream& inBase, ostream* stream) -//---------------------------------------------------------------------------------------- - : mBase(inBase) - , mStdStream(stream) { + mOutputStream->Close(); } //---------------------------------------------------------------------------------------- -void nsBasicOutStream::put(char c) +void nsOutputStream::put(char c) //---------------------------------------------------------------------------------------- { write(&c, sizeof(c)); } //---------------------------------------------------------------------------------------- -PRInt32 nsBasicOutStream::write(const void* s, PRInt32 n) +void nsOutputStream::flush() //---------------------------------------------------------------------------------------- { -#ifndef NS_USE_PR_STDIO - // Calling PR_Write on stdout is sure suicide. - if (mStdStream) - { - mStdStream->write((const char*)s, n); - return n; - } -#endif - if (!mBase.mFileDesc || mBase.failed()) - return -1; - PRInt32 bytesWrit = PR_Write(mBase.mFileDesc, s, n); - if (bytesWrit != n) - mBase.mFailed = true; - return bytesWrit; } //---------------------------------------------------------------------------------------- -nsBasicOutStream& nsBasicOutStream::operator << (char c) +nsOutputStream& nsOutputStream::operator << (char c) //---------------------------------------------------------------------------------------- { put(c); @@ -355,7 +101,7 @@ nsBasicOutStream& nsBasicOutStream::operator << (char c) } //---------------------------------------------------------------------------------------- -nsBasicOutStream& nsBasicOutStream::operator << (const char* s) +nsOutputStream& nsOutputStream::operator << (const char* s) //---------------------------------------------------------------------------------------- { write(s, strlen(s)); @@ -363,78 +109,84 @@ nsBasicOutStream& nsBasicOutStream::operator << (const char* s) } //---------------------------------------------------------------------------------------- -nsBasicOutStream& nsBasicOutStream::operator << (short val) +nsOutputStream& nsOutputStream::operator << (short val) //---------------------------------------------------------------------------------------- { char buf[30]; sprintf(buf, "%d", val); - return *this << buf; + return (*this << buf); } //---------------------------------------------------------------------------------------- -nsBasicOutStream& nsBasicOutStream::operator << (unsigned short val) +nsOutputStream& nsOutputStream::operator << (unsigned short val) //---------------------------------------------------------------------------------------- { char buf[30]; sprintf(buf, "%ud", val); - return *this << buf; + return (*this << buf); } //---------------------------------------------------------------------------------------- -nsBasicOutStream& nsBasicOutStream::operator << (long val) +nsOutputStream& nsOutputStream::operator << (long val) //---------------------------------------------------------------------------------------- { char buf[30]; sprintf(buf, "%ld", val); - return *this << buf; + return (*this << buf); } //---------------------------------------------------------------------------------------- -nsBasicOutStream& nsBasicOutStream::operator << (unsigned long val) +nsOutputStream& nsOutputStream::operator << (unsigned long val) //---------------------------------------------------------------------------------------- { char buf[30]; sprintf(buf, "%uld", val); - return *this << buf; + return (*this << buf); } +//======================================================================================== +// nsInputFileStream +//======================================================================================== + //---------------------------------------------------------------------------------------- -void nsBasicOutStream::flush() -// Must precede the destructor because both are inline. +PRBool nsInputFileStream::readline(char* s, PRInt32 n) +// This will truncate if the buffer is too small. Result will always be null-terminated. //---------------------------------------------------------------------------------------- { -#ifndef NS_USE_PR_STDIO - if (mStdStream) + PRBool bufferLargeEnough = PR_TRUE; // result + if (!s || !n) + return PR_TRUE; + + PRIntn position = tell(); + if (position < 0) + return PR_FALSE; + PRInt32 bytesRead = read(s, n - 1); + if (failed()) + return PR_FALSE; + s[bytesRead] = '\0'; // always terminate at the end of the buffer + char* tp = strpbrk(s, "\n\r"); + if (tp) { - mStdStream->flush(); - return; + TidyEndOfLine(tp); + bytesRead = (tp - s); } -#endif - if (mBase.mFileDesc == 0) - return; - PRBool itFailed = PR_Sync(mBase.mFileDesc) != PR_SUCCESS; -#ifdef XP_MAC - // On unix, it seems to fail always. - if (itFailed) - mBase.mFailed = true; -#endif -} // nsBasicOutStream::flush + else if (!eof()) + bufferLargeEnough = PR_FALSE; + position += bytesRead; + seek(position); + return bufferLargeEnough; +} // nsInputStream::readline //======================================================================================== // nsOutputFileStream //======================================================================================== //---------------------------------------------------------------------------------------- -nsOutputFileStream::nsOutputFileStream(ostream* stream) +void nsOutputFileStream::flush() //---------------------------------------------------------------------------------------- -#ifndef NS_USE_PR_STDIO - : nsBasicFileStream(0, kDefaultMode) - , nsBasicOutStream(*this, stream) -#else - : nsBasicFileStream(PR_STDOUT, kDefaultMode) - , nsBasicOutStream(*this, 0) -#endif { + if (mFileOutputStream) + mFileOutputStream->Flush(); } //======================================================================================== @@ -442,19 +194,10 @@ nsOutputFileStream::nsOutputFileStream(ostream* stream) //======================================================================================== //---------------------------------------------------------------------------------------- -nsBasicOutStream& nsEndl(nsBasicOutStream& os) +nsOutputStream& nsEndl(nsOutputStream& os) //---------------------------------------------------------------------------------------- { -#ifndef NS_USE_PR_STDIO - // Calling PR_Write on stdout is sure suicide on Macintosh. - ostream* stream = os.GetStandardStream(); - if (stream) - { - *stream << std::endl; - return os; - } -#endif - os.put('\n'); - os.flush(); - return os; -} \ No newline at end of file + os.put('\n'); + os.flush(); + return os; +} // nsEndl \ No newline at end of file diff --git a/mozilla/base/src/nsIBaseStream.h b/mozilla/base/src/nsIBaseStream.h index 1b716332f4a..a360cfee093 100644 --- a/mozilla/base/src/nsIBaseStream.h +++ b/mozilla/base/src/nsIBaseStream.h @@ -31,6 +31,8 @@ class nsIBaseStream : public nsISupports { public: + static const nsIID& IID() { static nsIID iid = NS_IBASESTREAM_IID; return iid; } + /** Close the stream. */ NS_IMETHOD Close(void) = 0; diff --git a/mozilla/base/src/nsIFileStream.cpp b/mozilla/base/src/nsIFileStream.cpp new file mode 100644 index 00000000000..f21549a7ecd --- /dev/null +++ b/mozilla/base/src/nsIFileStream.cpp @@ -0,0 +1,451 @@ +#include "nsIFileStream.h" +#include "nsFileSpec.h" + +#include "prerror.h" + +#ifdef XP_MAC +#include "pprio.h" // To get PR_ImportFile +#else +#include "prio.h" +#endif + +#ifdef XP_MAC +#include +#include +#endif + +//======================================================================================== +class FileImpl + : public nsIOutputStream + , public nsIInputStream + , public nsIFileOutputStream + , public nsIFileInputStream + , public nsIFile +//======================================================================================== +{ + public: + FileImpl(PRFileDesc* inDesc) + : mFileDesc(inDesc) + , mFailed(PR_FALSE) + , mEOF(PR_FALSE) + , mLength(-1) + { + NS_INIT_REFCNT(); + } + FileImpl( + const nsFileSpec& inFile, + int nsprMode, + PRIntn accessMode) + : mFileDesc(nsnull) + , mFailed(PR_FALSE) + , mEOF(PR_FALSE) + { + NS_INIT_REFCNT(); + Open(inFile, nsprMode, accessMode); + } + virtual ~FileImpl() + { + Close(); + } + + // nsISupports interface + NS_DECL_ISUPPORTS + + // nsIFile interface + NS_IMETHOD Open( + const nsFileSpec& inFile, + int nsprMode, + PRIntn accessMode); + NS_IMETHOD Close(); + NS_IMETHOD Seek(PRSeekWhence whence, PRInt32 offset); + + NS_IMETHOD GetIsOpen(PRBool* outOpen) + { + *outOpen = (mFileDesc != nsnull); + return NS_OK; + } + NS_IMETHOD Tell(PRIntn* outWhere); + + // nsIInputStream interface + NS_IMETHOD GetLength(PRUint32 *aLength) + { + NS_PRECONDITION(aLength != nsnull, "null ptr"); + if (!aLength) + return NS_ERROR_NULL_POINTER; + if (mLength < 0) + return NS_FILE_RESULT(NS_ERROR_UNEXPECTED); + *aLength = mLength; + return NS_OK; + } + NS_IMETHOD Read(char* aBuf, + PRUint32 aOffset, + PRUint32 aCount, + PRUint32 *aReadCount) + { + NS_PRECONDITION(aBuf != nsnull, "null ptr"); + if (!aBuf) + return NS_ERROR_NULL_POINTER; + NS_PRECONDITION(aReadCount != nsnull, "null ptr"); + if (!aReadCount) + return NS_ERROR_NULL_POINTER; + if (!mFileDesc) + return NS_FILE_RESULT(PR_BAD_DESCRIPTOR_ERROR); + if (mFailed) + return NS_ERROR_FAILURE; + if (aOffset) + PR_Seek(mFileDesc, aOffset, PR_SEEK_CUR); + PRInt32 bytesRead = PR_Read(mFileDesc, aBuf, aCount); + if (bytesRead < 0) + { + *aReadCount = 0; + mFailed = PR_TRUE; + return NS_FILE_RESULT(PR_GetError()); + } + *aReadCount = bytesRead; + return NS_OK; + } + // nsIOutputStream interface + NS_IMETHOD Write(const char* aBuf, + PRUint32 aOffset, + PRUint32 aCount, + PRUint32 *aWriteCount) + { + NS_PRECONDITION(aBuf != nsnull, "null ptr"); + NS_PRECONDITION(aWriteCount != nsnull, "null ptr"); + + + #ifdef XP_MAC + // Calling PR_Write on stdout is sure suicide. + if (mFileDesc == PR_STDOUT || mFileDesc == PR_STDERR) + { + cout.write(aBuf, aCount); + *aWriteCount = aCount; + return NS_OK; + } + #endif + if (!mFileDesc) + return NS_FILE_RESULT(PR_BAD_DESCRIPTOR_ERROR); + if (mFailed) + return NS_ERROR_FAILURE; + if (aOffset) + PR_Seek(mFileDesc, aOffset, PR_SEEK_CUR); + PRInt32 bytesWrit = PR_Write(mFileDesc, aBuf, aCount); + if (bytesWrit != aCount) + { + mFailed = PR_TRUE; + *aWriteCount = 0; + return NS_FILE_RESULT(PR_GetError()); + } + *aWriteCount = bytesWrit; + return NS_OK; + } + NS_IMETHOD Flush(); + + protected: + + PRFileDesc* mFileDesc; + int mNSPRMode; + PRBool mFailed; + PRBool mEOF; + PRInt32 mLength; +}; // class FileImpl + +#define SAY_I_IMPLEMENT(classname) \ + if (aIID.Equals(classname::IID())) \ + { \ + *aInstancePtr = (void*)((classname*)this); \ + NS_ADDREF_THIS(); \ + return NS_OK; \ + } + +NS_IMPL_RELEASE(FileImpl) +NS_IMPL_ADDREF(FileImpl) + +//---------------------------------------------------------------------------------------- +NS_IMETHODIMP FileImpl::QueryInterface(REFNSIID aIID, void** aInstancePtr) +//---------------------------------------------------------------------------------------- +{ + if (!aInstancePtr) + return NS_ERROR_NULL_POINTER; + + *aInstancePtr = nsnull; + + SAY_I_IMPLEMENT(nsIFile) + SAY_I_IMPLEMENT(nsIOutputStream) + SAY_I_IMPLEMENT(nsIInputStream) + SAY_I_IMPLEMENT(nsIFileInputStream) + SAY_I_IMPLEMENT(nsIFileOutputStream) + // Note that we derive from two copies of nsIBaseStream (and hence + // of nsISupports), one through + // nsIOutputStream, the other through nsIInputStream. Resolve this + // by giving them a specific one + if (aIID.Equals(((nsIBaseStream*)(nsIOutputStream*)this)->IID())) + { + *aInstancePtr = (void*)((nsIBaseStream*)(nsIOutputStream*)this); + NS_ADDREF_THIS(); + return NS_OK; + } + if (aIID.Equals(((nsISupports*)(nsIOutputStream*)this)->IID())) + { + *aInstancePtr = (void*)((nsISupports*)(nsIOutputStream*)this); + NS_ADDREF_THIS(); + return NS_OK; + } + return NS_NOINTERFACE; +} // FileImpl::QueryInterface + +//---------------------------------------------------------------------------------------- +NS_IMETHODIMP FileImpl::Open( + const nsFileSpec& inFile, + int nsprMode, + PRIntn accessMode) +//---------------------------------------------------------------------------------------- +{ + if (mFileDesc) + if ((nsprMode & mNSPRMode) == nsprMode) + return NS_OK; + else + return NS_FILE_RESULT(PR_ILLEGAL_ACCESS_ERROR); + + const int nspr_modes[]={ + PR_WRONLY | PR_CREATE_FILE, + PR_WRONLY | PR_CREATE_FILE | PR_APPEND, + PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, + PR_RDONLY, + PR_RDONLY | PR_APPEND, + PR_RDWR | PR_CREATE_FILE, + PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE, +// "wb", +// "ab", +// "wb", +// "rb", +// "r+b", +// "w+b", + 0 }; + const int* currentLegalMode = nspr_modes; + while (*currentLegalMode && nsprMode != *currentLegalMode) + ++currentLegalMode; + if (!*currentLegalMode) + return NS_FILE_RESULT(PR_ILLEGAL_ACCESS_ERROR); + +#ifdef XP_MAC + // Use the file spec to open the file, because one path can be common to + // several files on the Macintosh (you can have several volumes with the + // same name, see). + mFileDesc = 0; + if (inFile.Error() != noErr) + return NS_FILE_RESULT(inFile.Error()); + OSErr err = noErr; +#if DEBUG + const OSType kCreator = 'CWIE'; +#else + const OSType kCreator = 'MOSS'; +#endif + // Resolve the alias to the original file. + nsFileSpec original = inFile; + PRBool ignoredResult; + original.ResolveAlias(ignoredResult); + const FSSpec& spec = original.operator const FSSpec&(); + if (nsprMode & PR_CREATE_FILE) + err = FSpCreate(&spec, kCreator, 'TEXT', 0); + if (err == dupFNErr) + err = noErr; + if (err != noErr) + return NS_FILE_RESULT(err); + + SInt8 perm; + if (nsprMode & PR_RDWR) + perm = fsRdWrPerm; + else if (nsprMode & PR_WRONLY) + perm = fsWrPerm; + else + perm = fsRdPerm; + + short refnum; + err = FSpOpenDF(&spec, perm, &refnum); + + if (err == noErr && (nsprMode & PR_TRUNCATE)) + err = SetEOF(refnum, 0); + if (err == noErr && (nsprMode & PR_APPEND)) + err = SetFPos(refnum, fsFromLEOF, 0); + if (err != noErr) + return NS_FILE_RESULT(err); + + if ((mFileDesc = PR_ImportFile(refnum)) == 0) + return NS_FILE_RESULT(PR_GetError()); +#else + // Platforms other than Macintosh... + // Another bug in NSPR: Mac PR_Open assumes a unix style path, but Win PR_Open assumes + // a windows path. + if ((mFileDesc = PR_Open((const char*)nsFileSpec(inFile), nsprMode, accessMode)) == 0) + return NS_FILE_RESULT(PR_GetError()); +#endif + mNSPRMode = nsprMode; + mLength = PR_Available(mFileDesc); + return NS_OK; +} // FileImpl::Open + +//---------------------------------------------------------------------------------------- +NS_IMETHODIMP FileImpl::Seek(PRSeekWhence whence, PRInt32 offset) +//---------------------------------------------------------------------------------------- +{ + if (mFileDesc==PR_STDIN || mFileDesc==PR_STDOUT || mFileDesc==PR_STDERR || !mFileDesc) + return NS_FILE_RESULT(PR_BAD_DESCRIPTOR_ERROR); + mFailed = PR_FALSE; // reset on a seek. + mEOF = PR_FALSE; // reset on a seek. + PRInt32 position = PR_Seek(mFileDesc, 0, PR_SEEK_CUR); + PRInt32 available = PR_Available(mFileDesc); + PRInt32 fileSize = position + available; + PRInt32 newPosition; + switch (whence) + { + case PR_SEEK_CUR: newPosition = position + offset; break; + case PR_SEEK_SET: newPosition = offset; break; + case PR_SEEK_END: newPosition = fileSize + offset; break; + } + if (newPosition < 0) + { + newPosition = 0; + mFailed = PR_TRUE; + } + else if (newPosition >= fileSize) + { + newPosition = fileSize; + mEOF = PR_TRUE; + } + if (PR_Seek(mFileDesc, newPosition, PR_SEEK_SET) < 0) + mFailed = PR_TRUE; + return NS_OK; +} // FileImpl::Seek + +//---------------------------------------------------------------------------------------- +NS_IMETHODIMP FileImpl::Tell(PRIntn* outWhere) +//---------------------------------------------------------------------------------------- +{ + if (mFileDesc==PR_STDIN || mFileDesc==PR_STDOUT || mFileDesc==PR_STDERR || !mFileDesc) + return NS_FILE_RESULT(PR_BAD_DESCRIPTOR_ERROR); + *outWhere = PR_Seek(mFileDesc, 0, PR_SEEK_CUR); + return NS_OK; +} // FileImpl::Tell + +//---------------------------------------------------------------------------------------- +NS_IMETHODIMP FileImpl::Close() +//---------------------------------------------------------------------------------------- +{ + if (mFileDesc==PR_STDIN || mFileDesc==PR_STDOUT || mFileDesc==PR_STDERR || !mFileDesc) + return NS_OK; + if (PR_Close(mFileDesc) == PR_SUCCESS) + mFileDesc = 0; + else + return NS_FILE_RESULT(PR_GetError()); + return NS_OK; +} // FileImpl::close + +//---------------------------------------------------------------------------------------- +NS_IMETHODIMP FileImpl::Flush() +//---------------------------------------------------------------------------------------- +{ +#ifdef XP_MAC + if (mFileDesc == PR_STDOUT || mFileDesc == PR_STDERR) + { + cout.flush(); + return NS_OK; + } +#endif + if (!mFileDesc) + return NS_FILE_RESULT(PR_BAD_DESCRIPTOR_ERROR); + PRBool itFailed = PR_Sync(mFileDesc) != PR_SUCCESS; +#ifdef XP_MAC + // On unix, it seems to fail always. + if (itFailed) + mFailed = PR_TRUE; +#endif + return NS_OK; +} // FileImpl::flush + +//---------------------------------------------------------------------------------------- +NS_BASE nsresult NS_NewTypicalInputFileStream( + nsISupports** aResult, + const nsFileSpec& inFile + /*Default nsprMode == PR_RDONLY*/ + /*Default accessmode = 0700 (octal)*/) +// Factory method to get an nsInputStream from a file, using most common options +//---------------------------------------------------------------------------------------- +{ + return NS_NewIOFileStream(aResult, inFile, PR_RDONLY, 0700); +} + +//---------------------------------------------------------------------------------------- +NS_BASE nsresult NS_NewOutputConsoleStream( + nsISupports** aResult) +// Factory method to get an nsOutputStream to the console. +//---------------------------------------------------------------------------------------- +{ + NS_PRECONDITION(aResult != nsnull, "null ptr"); + if (! aResult) + return NS_ERROR_NULL_POINTER; + + FileImpl* stream = new FileImpl(PR_STDOUT); + if (! stream) + return NS_ERROR_OUT_OF_MEMORY; + + NS_ADDREF(stream); + *aResult = (nsISupports*)(void*)stream; + return NS_OK; +} + +//---------------------------------------------------------------------------------------- +NS_BASE nsresult NS_NewTypicalOutputFileStream( + nsISupports** aResult, + const nsFileSpec& inFile + /*default nsprMode= (PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE)*/ + /*Default accessMode= 0700 (octal)*/) +// Factory method to get an nsOutputStream to a file - most common case. +//---------------------------------------------------------------------------------------- +{ + return NS_NewIOFileStream( + aResult, + inFile, + (PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE), + 0700); +} + +//---------------------------------------------------------------------------------------- +NS_BASE nsresult NS_NewIOFileStream( + nsISupports** aResult, + const nsFileSpec& inFile, + PRInt32 nsprMode /*default = (PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE)*/, + PRInt32 accessMode /*Default = 0700 (octal)*/) + // Factory method to get an object that implements both nsIInputStream + // and nsIOutputStream, associated with a file. +//---------------------------------------------------------------------------------------- +{ + NS_PRECONDITION(aResult != nsnull, "null ptr"); + if (!aResult) + return NS_ERROR_NULL_POINTER; + + FileImpl* stream = new FileImpl(inFile, nsprMode, accessMode); + if (! stream) + return NS_ERROR_OUT_OF_MEMORY; + + NS_ADDREF(stream); + *aResult = (nsISupports*)(void*)stream; + return NS_OK; +} + +//---------------------------------------------------------------------------------------- +NS_BASE nsresult NS_NewTypicalIOFileStream( + nsISupports** aResult, + const nsFileSpec& inFile + /*default nsprMode= (PR_RDWR | PR_CREATE_FILE)*/ + /*Default accessMode= 0700 (octal)*/) + // Factory method to get an object that implements both nsIInputStream + // and nsIOutputStream, associated with a single file. +//---------------------------------------------------------------------------------------- +{ + return NS_NewIOFileStream( + aResult, + inFile, + (PR_RDWR | PR_CREATE_FILE), + 0700); +} diff --git a/mozilla/base/src/nsIInputStream.h b/mozilla/base/src/nsIInputStream.h index a1c5b6167d5..67dac59561b 100644 --- a/mozilla/base/src/nsIInputStream.h +++ b/mozilla/base/src/nsIInputStream.h @@ -28,6 +28,8 @@ class nsIInputStream : public nsIBaseStream { public: + static const nsIID& IID() { static nsIID iid = NS_IINPUTSTREAM_IID; return iid; } + /** Return the number of bytes in the stream * @param aLength out parameter to hold the length * of the stream. if an error occurs, the length diff --git a/mozilla/base/src/nsIOutputStream.h b/mozilla/base/src/nsIOutputStream.h index 795416092d3..aa7d447b2ee 100644 --- a/mozilla/base/src/nsIOutputStream.h +++ b/mozilla/base/src/nsIOutputStream.h @@ -29,6 +29,8 @@ class nsIOutputStream : public nsIBaseStream { public: + static const nsIID& IID() { static nsIID iid = NS_IOUTPUTSTREAM_IID; return iid; } + /** Write data into the stream. * @param aBuf the buffer into which the data is read * @param aOffset the start offset of the data diff --git a/mozilla/base/src/unix/nsFileSpecUnix.cpp b/mozilla/base/src/unix/nsFileSpecUnix.cpp index d0e058dccbe..5fbeeb98107 100644 --- a/mozilla/base/src/unix/nsFileSpecUnix.cpp +++ b/mozilla/base/src/unix/nsFileSpecUnix.cpp @@ -25,9 +25,10 @@ #include #include #include +#include "nsError.h" //---------------------------------------------------------------------------------------- -void nsFileSpecHelpers::Canonify(char*& ioPath, bool inMakeDirs) +void nsFileSpecHelpers::Canonify(char*& ioPath, PRBool inMakeDirs) // Canonify, make absolute, and check whether directories exist //---------------------------------------------------------------------------------------- { @@ -76,75 +77,78 @@ void nsFileSpecHelpers::Canonify(char*& ioPath, bool inMakeDirs) } // nsFileSpecHelpers::Canonify //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::SetLeafName(const char* inLeafName) +void nsFileSpec::SetLeafName(const char* inLeafName) //---------------------------------------------------------------------------------------- { nsFileSpecHelpers::LeafReplace(mPath, '/', inLeafName); -} // nsNativeFileSpec::SetLeafName +} // nsFileSpec::SetLeafName //---------------------------------------------------------------------------------------- -char* nsNativeFileSpec::GetLeafName() const +char* nsFileSpec::GetLeafName() const //---------------------------------------------------------------------------------------- { return nsFileSpecHelpers::GetLeaf(mPath, '/'); -} // nsNativeFileSpec::GetLeafName +} // nsFileSpec::GetLeafName //---------------------------------------------------------------------------------------- -bool nsNativeFileSpec::Exists() const +PRBool nsFileSpec::Exists() const //---------------------------------------------------------------------------------------- { struct stat st; return 0 == stat(mPath, &st); -} // nsNativeFileSpec::Exists +} // nsFileSpec::Exists //---------------------------------------------------------------------------------------- -bool nsNativeFileSpec::IsFile() const +PRBool nsFileSpec::IsFile() const //---------------------------------------------------------------------------------------- { struct stat st; return 0 == stat(mPath, &st) && S_ISREG(st.st_mode); -} // nsNativeFileSpec::IsFile +} // nsFileSpec::IsFile //---------------------------------------------------------------------------------------- -bool nsNativeFileSpec::IsDirectory() const +PRBool nsFileSpec::IsDirectory() const //---------------------------------------------------------------------------------------- { struct stat st; return 0 == stat(mPath, &st) && S_ISDIR(st.st_mode); -} // nsNativeFileSpec::IsDirectory +} // nsFileSpec::IsDirectory //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::GetParent(nsNativeFileSpec& outSpec) const +void nsFileSpec::GetParent(nsFileSpec& outSpec) const //---------------------------------------------------------------------------------------- { nsFileSpecHelpers::StringAssign(outSpec.mPath, mPath); char* cp = strrchr(outSpec.mPath, '/'); if (cp) *cp = '\0'; -} // nsNativeFileSpec::GetParent +} // nsFileSpec::GetParent //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::operator += (const char* inRelativePath) +void nsFileSpec::operator += (const char* inRelativePath) //---------------------------------------------------------------------------------------- { if (!inRelativePath || !mPath) return; - if (mPath[strlen(mPath) - 1] != '/') - char* newPath = nsFileSpecHelpers::ReallocCat(mPath, "/"); + char endChar = mPath[strlen(mPath) - 1]; + if (endChar == '/') + nsFileSpecHelpers::ReallocCat(mPath, "x"); + else + nsFileSpecHelpers::ReallocCat(mPath, "/x"); SetLeafName(inRelativePath); -} // nsNativeFileSpec::operator += +} // nsFileSpec::operator += //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::CreateDirectory(int mode) +void nsFileSpec::CreateDirectory(int mode) //---------------------------------------------------------------------------------------- { // Note that mPath is canonical! mkdir(mPath, mode); -} // nsNativeFileSpec::CreateDirectory +} // nsFileSpec::CreateDirectory //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::Delete(bool inRecursive) +void nsFileSpec::Delete(PRBool inRecursive) // To check if this worked, call Exists() afterwards, see? //---------------------------------------------------------------------------------------- { @@ -152,9 +156,9 @@ void nsNativeFileSpec::Delete(bool inRecursive) { if (inRecursive) { - for (nsDirectoryIterator i(*this); i; i++) + for (nsDirectoryIterator i(*this); i.Exists(); i++) { - nsNativeFileSpec& child = (nsNativeFileSpec&)i; + nsFileSpec& child = (nsFileSpec&)i; child.Delete(inRecursive); } } @@ -162,7 +166,148 @@ void nsNativeFileSpec::Delete(bool inRecursive) } else remove(mPath); -} // nsNativeFileSpec::Delete +} // nsFileSpec::Delete + + + +//---------------------------------------------------------------------------------------- +nsresult nsFileSpec::Rename(const char* inNewName) +//---------------------------------------------------------------------------------------- +{ + // This function should not be used to move a file on disk. + if (strchr(inNewName, '/')) + return NS_FILE_FAILURE; + + if (PR_Rename(mPath, inNewName) != 0) + { + return NS_FILE_FAILURE; + } + SetLeafName(inNewName); + return NS_OK; +} // nsFileSpec::Rename + +static int CrudeFileCopy(const char* in, const char* out) +{ + struct stat in_stat; + int stat_result = -1; + + char buf [1024]; + FILE *ifp, *ofp; + int rbytes, wbytes; + + if (!in || !out) + return -1; + + stat_result = stat (in, &in_stat); + + ifp = fopen (in, "r"); + if (!ifp) + { + return -1; + } + + ofp = fopen (out, "w"); + if (!ofp) + { + fclose (ifp); + return -1; + } + + while ((rbytes = fread (buf, 1, sizeof(buf), ifp)) > 0) + { + while (rbytes > 0) + { + if ( (wbytes = fwrite (buf, 1, rbytes, ofp)) < 0 ) + { + fclose (ofp); + fclose (ifp); + unlink(out); + return -1; + } + rbytes -= wbytes; + } + } + fclose (ofp); + fclose (ifp); + + if (stat_result == 0) + { + chmod (out, in_stat.st_mode & 0777); + } + + return 0; +} // nsFileSpec::Rename + +//---------------------------------------------------------------------------------------- +nsresult nsFileSpec::Copy(const nsFileSpec& inParentDirectory) const +//---------------------------------------------------------------------------------------- +{ + // We can only copy into a directory, and (for now) can not copy entire directories + nsresult result = NS_FILE_FAILURE; + + if (inParentDirectory.IsDirectory() && (! IsDirectory() ) ) + { + char *leafname = GetLeafName(); + char* destPath = nsFileSpecHelpers::StringDup(inParentDirectory, ( strlen(inParentDirectory) + 1 + strlen(leafname) ) ); + strcat(destPath, "/"); + strcat(destPath, leafname); + delete [] leafname; + + result = NS_FILE_RESULT(CrudeFileCopy(*this, destPath)); + + delete [] destPath; + } + return result; +} // nsFileSpec::Copy + +//---------------------------------------------------------------------------------------- +nsresult nsFileSpec::Move(const nsFileSpec& inNewParentDirectory) const +//---------------------------------------------------------------------------------------- +{ + // We can only copy into a directory, and (for now) can not copy entire directories + nsresult result = NS_FILE_FAILURE; + + if (inNewParentDirectory.IsDirectory() && (! IsDirectory() ) ) + { + char *leafname = GetLeafName(); + char* destPath + = nsFileSpecHelpers::StringDup( + inNewParentDirectory, + strlen(inNewParentDirectory) + 1 + strlen(leafname)); + strcat(destPath, "/"); + strcat(destPath, leafname); + delete [] leafname; + + result = NS_FILE_RESULT(CrudeFileCopy(*this, destPath)); + if (result == NS_OK) + { + Delete(PR_FALSE); + } + delete [] destPath; + } + return result; +} + +//---------------------------------------------------------------------------------------- +nsresult nsFileSpec::Execute(const char* inArgs ) const +//---------------------------------------------------------------------------------------- +{ + nsresult result = NS_FILE_FAILURE; + + if (! IsDirectory()) + { + char* fileNameWithArgs + = nsFileSpecHelpers::StringDup(mPath, strlen(mPath) + 1 + strlen(inArgs)); + strcat(fileNameWithArgs, " "); + strcat(fileNameWithArgs, inArgs); + + result = NS_FILE_RESULT(system(fileNameWithArgs)); + delete [] fileNameWithArgs; + } + + return result; + +} // nsFileSpec::Execute //======================================================================================== // nsDirectoryIterator @@ -170,7 +315,7 @@ void nsNativeFileSpec::Delete(bool inRecursive) //---------------------------------------------------------------------------------------- nsDirectoryIterator::nsDirectoryIterator( - const nsNativeFileSpec& inDirectory + const nsFileSpec& inDirectory , int inIterateDirection) //---------------------------------------------------------------------------------------- : mCurrent(inDirectory) diff --git a/mozilla/base/src/windows/nsFileSpecWin.cpp b/mozilla/base/src/windows/nsFileSpecWin.cpp index 247d96a37e8..fb424c4616c 100644 --- a/mozilla/base/src/windows/nsFileSpecWin.cpp +++ b/mozilla/base/src/windows/nsFileSpecWin.cpp @@ -23,9 +23,18 @@ #include #include #include "prio.h" +#include "nsError.h" + +#include "windows.h" + +#ifdef UNICODE +#define CreateDirectoryW CreateDirectory +#else +#define CreateDirectoryA CreateDirectory +#endif //---------------------------------------------------------------------------------------- -void nsFileSpecHelpers::Canonify(char*& ioPath, bool inMakeDirs) +void nsFileSpecHelpers::Canonify(char*& ioPath, PRBool inMakeDirs) // Canonify, make absolute, and check whether directories exist. This // takes a (possibly relative) native path and converts it into a // fully qualified native path. @@ -125,7 +134,7 @@ void nsFileSpecHelpers::NativeToUnix(char*& ioPath) } //---------------------------------------------------------------------------------------- -nsNativeFileSpec::nsNativeFileSpec(const nsFilePath& inPath) +nsFileSpec::nsFileSpec(const nsFilePath& inPath) //---------------------------------------------------------------------------------------- : mPath(NULL) { @@ -133,15 +142,16 @@ nsNativeFileSpec::nsNativeFileSpec(const nsFilePath& inPath) } //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::operator = (const nsFilePath& inPath) +void nsFileSpec::operator = (const nsFilePath& inPath) //---------------------------------------------------------------------------------------- { nsFileSpecHelpers::StringAssign(mPath, (const char*)inPath); nsFileSpecHelpers::UnixToNative(mPath); -} // nsNativeFileSpec::operator = + mError = NS_OK; +} // nsFileSpec::operator = //---------------------------------------------------------------------------------------- -nsFilePath::nsFilePath(const nsNativeFileSpec& inSpec) +nsFilePath::nsFilePath(const nsFileSpec& inSpec) //---------------------------------------------------------------------------------------- : mPath(NULL) { @@ -149,7 +159,7 @@ nsFilePath::nsFilePath(const nsNativeFileSpec& inSpec) } // nsFilePath::nsFilePath //---------------------------------------------------------------------------------------- -void nsFilePath::operator = (const nsNativeFileSpec& inSpec) +void nsFilePath::operator = (const nsFileSpec& inSpec) //---------------------------------------------------------------------------------------- { nsFileSpecHelpers::StringAssign(mPath, inSpec.mPath); @@ -157,84 +167,86 @@ void nsFilePath::operator = (const nsNativeFileSpec& inSpec) } // nsFilePath::operator = //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::SetLeafName(const char* inLeafName) +void nsFileSpec::SetLeafName(const char* inLeafName) //---------------------------------------------------------------------------------------- { nsFileSpecHelpers::LeafReplace(mPath, '\\', inLeafName); -} // nsNativeFileSpec::SetLeafName +} // nsFileSpec::SetLeafName //---------------------------------------------------------------------------------------- -char* nsNativeFileSpec::GetLeafName() const +char* nsFileSpec::GetLeafName() const //---------------------------------------------------------------------------------------- { return nsFileSpecHelpers::GetLeaf(mPath, '\\'); -} // nsNativeFileSpec::GetLeafName +} // nsFileSpec::GetLeafName //---------------------------------------------------------------------------------------- -bool nsNativeFileSpec::Exists() const +PRBool nsFileSpec::Exists() const //---------------------------------------------------------------------------------------- { struct stat st; return 0 == stat(mPath, &st); -} // nsNativeFileSpec::Exists +} // nsFileSpec::Exists //---------------------------------------------------------------------------------------- -bool nsNativeFileSpec::IsFile() const +PRBool nsFileSpec::IsFile() const //---------------------------------------------------------------------------------------- { struct stat st; return 0 == stat(mPath, &st) && (_S_IFREG & st.st_mode); -} // nsNativeFileSpec::IsFile +} // nsFileSpec::IsFile //---------------------------------------------------------------------------------------- -bool nsNativeFileSpec::IsDirectory() const +PRBool nsFileSpec::IsDirectory() const //---------------------------------------------------------------------------------------- { struct stat st; return 0 == stat(mPath, &st) && (_S_IFDIR & st.st_mode); -} // nsNativeFileSpec::IsDirectory +} // nsFileSpec::IsDirectory //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::GetParent(nsNativeFileSpec& outSpec) const +void nsFileSpec::GetParent(nsFileSpec& outSpec) const //---------------------------------------------------------------------------------------- { nsFileSpecHelpers::StringAssign(outSpec.mPath, mPath); char* cp = strrchr(outSpec.mPath, '\\'); if (cp) *cp = '\0'; -} // nsNativeFileSpec::GetParent +} // nsFileSpec::GetParent //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::operator += (const char* inRelativePath) +void nsFileSpec::operator += (const char* inRelativePath) //---------------------------------------------------------------------------------------- { if (!inRelativePath || !mPath) return; - if (mPath[strlen(mPath) - 1] != '\\') - char* newPath = nsFileSpecHelpers::ReallocCat(mPath, "\\"); + if (mPath[strlen(mPath) - 1] == '\\') + nsFileSpecHelpers::ReallocCat(mPath, "x"); + else + nsFileSpecHelpers::ReallocCat(mPath, "\\x"); SetLeafName(inRelativePath); -} // nsNativeFileSpec::operator += +} // nsFileSpec::operator += //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::CreateDirectory(int /*mode*/) +void nsFileSpec::CreateDirectory(int /*mode*/) //---------------------------------------------------------------------------------------- { // Note that mPath is canonical! mkdir(mPath); -} // nsNativeFileSpec::CreateDirectory +} // nsFileSpec::CreateDirectory //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::Delete(bool inRecursive) +void nsFileSpec::Delete(PRBool inRecursive) //---------------------------------------------------------------------------------------- { if (IsDirectory()) { if (inRecursive) { - for (nsDirectoryIterator i(*this); i; i++) + for (nsDirectoryIterator i(*this); i.Exists(); i++) { - nsNativeFileSpec& child = (nsNativeFileSpec&)i; + nsFileSpec& child = (nsFileSpec&)i; child.Delete(inRecursive); } } @@ -244,7 +256,106 @@ void nsNativeFileSpec::Delete(bool inRecursive) { remove(mPath); } -} // nsNativeFileSpec::Delete +} // nsFileSpec::Delete + + +//---------------------------------------------------------------------------------------- +nsresult nsFileSpec::Rename(const char* inNewName) +//---------------------------------------------------------------------------------------- +{ + // This function should not be used to move a file on disk. + if (strchr(inNewName, '/')) + return NS_FILE_FAILURE; + + if (PR_Rename(*this, inNewName) != NS_OK) + { + return NS_FILE_FAILURE; + } + SetLeafName(inNewName); + return NS_OK; +} // nsFileSpec::Rename + +//---------------------------------------------------------------------------------------- +nsresult nsFileSpec::Copy(const nsFileSpec& inParentDirectory) const +//---------------------------------------------------------------------------------------- +{ + // We can only copy into a directory, and (for now) can not copy entire directories + + if (inParentDirectory.IsDirectory() && (! IsDirectory() ) ) + { + char *leafname = GetLeafName(); + char* destPath = nsFileSpecHelpers::StringDup(inParentDirectory, ( strlen(inParentDirectory) + 1 + strlen(leafname) ) ); + strcat(destPath, "\\"); + strcat(destPath, leafname); + delete [] leafname; + + // CopyFile returns non-zero if succeeds + int copyOK = CopyFile(*this, destPath, true); + + delete[] destPath; + + if (copyOK) + { + return NS_OK; + } + } + + return NS_FILE_FAILURE; +} // nsFileSpec::Copy + +//---------------------------------------------------------------------------------------- +nsresult nsFileSpec::Move(const nsFileSpec& nsNewParentDirectory) const +//---------------------------------------------------------------------------------------- +{ + // We can only copy into a directory, and (for now) can not copy entire directories + + if (nsNewParentDirectory.IsDirectory() && (! IsDirectory() ) ) + { + char *leafname = GetLeafName(); + char *destPath = nsFileSpecHelpers::StringDup(nsNewParentDirectory, ( strlen(nsNewParentDirectory) + 1 + strlen(leafname) )); + strcat(destPath, "\\"); + strcat(destPath, leafname); + delete [] leafname; + + // MoveFile returns non-zero if succeeds + int copyOK = MoveFile(*this, destPath); + + delete [] destPath; + + if (copyOK) + { + return NS_OK; + } + } + + return NS_FILE_FAILURE; +} // nsFileSpec::Move + +//---------------------------------------------------------------------------------------- +nsresult nsFileSpec::Execute(const char* inArgs ) const +//---------------------------------------------------------------------------------------- +{ + + if (! IsDirectory()) + { + char* fileNameWithArgs = NULL; + + fileNameWithArgs = nsFileSpecHelpers::StringDup(mPath, ( strlen(mPath) + 1 + strlen(inArgs) ) ); + strcat(fileNameWithArgs, " "); + strcat(fileNameWithArgs, inArgs); + + int execResult = WinExec( fileNameWithArgs, SW_NORMAL ); + + delete [] fileNameWithArgs; + + if (execResult > 31) + { + return NS_OK; + } + } + + return NS_FILE_FAILURE; +} // nsFileSpec::Execute //======================================================================================== // nsDirectoryIterator @@ -252,7 +363,7 @@ void nsNativeFileSpec::Delete(bool inRecursive) //---------------------------------------------------------------------------------------- nsDirectoryIterator::nsDirectoryIterator( - const nsNativeFileSpec& inDirectory + const nsFileSpec& inDirectory , int inIterateDirection) //---------------------------------------------------------------------------------------- : mCurrent(inDirectory) diff --git a/mozilla/base/tests/FilesTest.cpp b/mozilla/base/tests/FilesTest.cpp index 81b93b4ea1c..7d976dd7391 100644 --- a/mozilla/base/tests/FilesTest.cpp +++ b/mozilla/base/tests/FilesTest.cpp @@ -16,10 +16,11 @@ * Reserved. */ -#include "string.h" #include "nsFileSpec.h" #include "nsFileStream.h" +//#include "string.h" + struct FilesTest { FilesTest() : mConsole() {} @@ -30,18 +31,25 @@ struct FilesTest int InputStream(const char* relativePath); int OutputStream(const char* relativePath); int IOStream(const char* relativePath); - int Parent(const char* relativePath, nsNativeFileSpec& outParent); - int Delete(nsNativeFileSpec& victim); - int CreateDirectory(nsNativeFileSpec& victim); - int IterateDirectoryChildren(nsNativeFileSpec& startChild); + int Parent(const char* relativePath, nsFileSpec& outParent); + int Delete(nsFileSpec& victim); + int CreateDirectory(nsFileSpec& victim); + int IterateDirectoryChildren(nsFileSpec& startChild); int CanonicalPath(const char* relativePath); + int Persistence(const char* relativePath); + + int Copy(const char* sourceFile, const char* targDir); + int Move(const char* sourceFile, const char* targDir); + int Rename(const char* sourceFile, const char* newName); + + int Execute(const char* appName, const char* args); void Banner(const char* bannerString); void Passed(); void Failed(); void Inspect(); - nsOutputFileStream mConsole; + nsOutputConsoleStream mConsole; }; //---------------------------------------------------------------------------------------- @@ -59,7 +67,8 @@ void FilesTest::Banner(const char* bannerString) void FilesTest::Passed() //---------------------------------------------------------------------------------------- { - mConsole << "Test passed." << nsEndl; + ((nsOutputStream&)mConsole) << "Test passed."; + mConsole << nsEndl; } //---------------------------------------------------------------------------------------- @@ -89,7 +98,7 @@ void FilesTest::WriteStuff(nsOutputFileStream& s) s << "As a unix path: \"" << (const char*)filePath << "\""<< nsEndl; // Initialize a native file spec from a URL - nsNativeFileSpec fileSpec(fileURL); + nsFileSpec fileSpec(fileURL); s << "As a file spec: " << fileSpec << nsEndl; // Make the spec unique (this one has no suffix). @@ -119,10 +128,10 @@ int FilesTest::OutputStream(const char* relativePath) { nsFilePath myTextFilePath(relativePath, true); // relative path. const char* pathAsString = (const char*)myTextFilePath; - nsNativeFileSpec mySpec(myTextFilePath); + nsFileSpec mySpec(myTextFilePath); { mConsole << "WRITING IDENTICAL OUTPUT TO " << pathAsString << nsEndl << nsEndl; - nsOutputFileStream testStream(myTextFilePath); + nsOutputFileStream testStream(mySpec); if (!testStream.is_open()) { mConsole @@ -154,9 +163,10 @@ int FilesTest::IOStream(const char* relativePath) { nsFilePath myTextFilePath(relativePath, true); // relative path. const char* pathAsString = (const char*)myTextFilePath; + nsFileSpec mySpec(myTextFilePath); mConsole << "Replacing \"path\" by \"ZUUL\" in " << pathAsString << nsEndl << nsEndl; - nsIOFileStream testStream(myTextFilePath); + nsIOFileStream testStream(mySpec); if (!testStream.is_open()) { mConsole @@ -183,6 +193,57 @@ int FilesTest::IOStream(const char* relativePath) return 0; } +//---------------------------------------------------------------------------------------- +int FilesTest::Persistence( + const char* relativePathToWrite) +//---------------------------------------------------------------------------------------- +{ + nsFilePath myTextFilePath(relativePathToWrite, true); + const char* pathAsString = (const char*)myTextFilePath; + nsFileSpec mySpec(myTextFilePath); + + nsIOFileStream testStream(mySpec, (PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE)); + if (!testStream.is_open()) + { + mConsole + << "ERROR: File " + << pathAsString + << " could not be opened for input+output" + << nsEndl; + return -1; + } + + nsPersistentFileDescriptor myPersistent(mySpec); + mConsole + << "Writing persistent file data " << pathAsString << nsEndl << nsEndl; + + testStream.seek(0); // check that the seek compiles + testStream << myPersistent; + + testStream.seek(0); + + nsPersistentFileDescriptor mySecondPersistent; + testStream >> mySecondPersistent; + + mySpec = mySecondPersistent; +#ifdef XP_MAC + if (mySpec.Error()) + { + Failed(); + return -1; + } +#endif + + if (!mySpec.Exists()) + { + Failed(); + return -1; + } + + Passed(); + return 0; +} + //---------------------------------------------------------------------------------------- int FilesTest::InputStream(const char* relativePath) //---------------------------------------------------------------------------------------- @@ -190,7 +251,8 @@ int FilesTest::InputStream(const char* relativePath) nsFilePath myTextFilePath(relativePath, true); const char* pathAsString = (const char*)myTextFilePath; mConsole << "READING BACK DATA FROM " << pathAsString << nsEndl << nsEndl; - nsInputFileStream testStream2(myTextFilePath); + nsFileSpec mySpec(myTextFilePath); + nsInputFileStream testStream2(mySpec); if (!testStream2.is_open()) { mConsole @@ -215,12 +277,12 @@ int FilesTest::InputStream(const char* relativePath) //---------------------------------------------------------------------------------------- int FilesTest::Parent( const char* relativePath, - nsNativeFileSpec& outParent) + nsFileSpec& outParent) //---------------------------------------------------------------------------------------- { nsFilePath myTextFilePath(relativePath, true); const char* pathAsString = (const char*)myTextFilePath; - nsNativeFileSpec mySpec(myTextFilePath); + nsFileSpec mySpec(myTextFilePath); mySpec.GetParent(outParent); nsFilePath parentPath(outParent); @@ -235,7 +297,7 @@ int FilesTest::Parent( } //---------------------------------------------------------------------------------------- -int FilesTest::Delete(nsNativeFileSpec& victim) +int FilesTest::Delete(nsFileSpec& victim) //---------------------------------------------------------------------------------------- { // - Test of non-recursive delete @@ -284,7 +346,7 @@ int FilesTest::Delete(nsNativeFileSpec& victim) } //---------------------------------------------------------------------------------------- -int FilesTest::CreateDirectory(nsNativeFileSpec& dirSpec) +int FilesTest::CreateDirectory(nsFileSpec& dirSpec) //---------------------------------------------------------------------------------------- { nsFilePath dirPath(dirSpec); @@ -306,27 +368,27 @@ int FilesTest::CreateDirectory(nsNativeFileSpec& dirSpec) } //---------------------------------------------------------------------------------------- -int FilesTest::IterateDirectoryChildren(nsNativeFileSpec& startChild) +int FilesTest::IterateDirectoryChildren(nsFileSpec& startChild) //---------------------------------------------------------------------------------------- { // - Test of directory iterator - nsNativeFileSpec grandparent; + nsFileSpec grandparent; startChild.GetParent(grandparent); // should be the original default directory. nsFilePath grandparentPath(grandparent); mConsole << "Forwards listing of " << (const char*)grandparentPath << ":" << nsEndl; - for (nsDirectoryIterator i(grandparent, +1); i; i++) + for (nsDirectoryIterator i(grandparent, +1); i.Exists(); i++) { - char* itemName = ((nsNativeFileSpec&)i).GetLeafName(); + char* itemName = ((nsFileSpec&)i).GetLeafName(); mConsole << '\t' << itemName << nsEndl; delete [] itemName; } mConsole << "Backwards listing of " << (const char*)grandparentPath << ":" << nsEndl; - for (nsDirectoryIterator j(grandparent, -1); j; j--) + for (nsDirectoryIterator j(grandparent, -1); j.Exists(); j--) { - char* itemName = ((nsNativeFileSpec&)j).GetLeafName(); + char* itemName = ((nsFileSpec&)j).GetLeafName(); mConsole << '\t' << itemName << nsEndl; delete [] itemName; } @@ -355,6 +417,110 @@ int FilesTest::CanonicalPath( return 0; } +//---------------------------------------------------------------------------------------- +int FilesTest::Copy(const char* file, const char* dir) +//---------------------------------------------------------------------------------------- +{ + nsFileSpec dirPath(dir, true); + + dirPath.CreateDirectory(); + if (! dirPath.Exists()) + { + Failed(); + return -1; + } + + + nsFileSpec mySpec(file, true); // relative path. + { + nsIOFileStream testStream(mySpec); // creates the file + // Scope ends here, file gets closed + } + + nsFileSpec filePath(file); + if (! filePath.Exists()) + { + Failed(); + return -1; + } + + nsresult error = filePath.Copy(dirPath); + + dirPath += filePath.GetLeafName(); + if (! dirPath.Exists() || ! filePath.Exists() || NS_FAILED(error)) + { + Failed(); + return -1; + } + + Passed(); + + return 0; +} + +//---------------------------------------------------------------------------------------- +int FilesTest::Move(const char* file, const char* dir) +//---------------------------------------------------------------------------------------- +{ + nsFileSpec dirPath(dir, true); + + dirPath.CreateDirectory(); + if (! dirPath.Exists()) + { + Failed(); + return -1; + } + + + nsFileSpec srcSpec(file, true); // relative path. + { + nsIOFileStream testStream(srcSpec); // creates the file + // file gets closed here because scope ends here. + }; + + if (! srcSpec.Exists()) + { + Failed(); + return -1; + } + + nsresult error = srcSpec.Move(dirPath); + + + dirPath += srcSpec.GetLeafName(); + if (! dirPath.Exists() || srcSpec.Exists() || NS_FAILED(error)) + { + Failed(); + return -1; + } + + Passed(); + return 0; +} + +//---------------------------------------------------------------------------------------- +int FilesTest::Execute(const char* appName, const char* args) +//---------------------------------------------------------------------------------------- +{ + nsFileSpec appPath(appName, false); + if (!appPath.Exists()) + { + Failed(); + return -1; + } + + nsresult error = appPath.Execute(args); + if (NS_FAILED(error)) + { + Failed(); + return -1; + } + + Passed(); + + return 0; +} + //---------------------------------------------------------------------------------------- int FilesTest::RunAllTests() // For use with DEBUG defined. @@ -389,7 +555,7 @@ int FilesTest::RunAllTests() return -1; Banner("Parent"); - nsNativeFileSpec parent; + nsFileSpec parent; if (Parent("mumble/iotest.txt", parent) != 0) return -1; @@ -405,6 +571,36 @@ int FilesTest::RunAllTests() if (IterateDirectoryChildren(parent) != 0) return -1; + Banner("Copy"); + if (Copy("mumble/copyfile.txt", "mumble/copy") != 0) + return -1; + + Banner("Move"); + if (Move("mumble/moveFile.txt", "mumble/move") != 0) + return -1; + + Banner("Execute"); +#ifdef XP_MAC + // This path is hard-coded to test on jrm's machine. Finding an app + // on an arbitrary Macintosh would cost more trouble than it's worth. + // Change path to suit. + if NS_FAILED(Execute("/Projects/Nav45_BRANCH/ns/cmd/macfe/"\ + "projects/client45/Client45PPC", "")) +#elif XP_PC + if NS_FAILED(Execute("c:\\windows\\notepad.exe", "")) +#else + if NS_FAILED(Execute("/bin/ls", "/")) +#endif + return -1; + + Banner("Persistence"); + if (Persistence("mumble/filedesc.dat") != 0) + return -1; + + Banner("Delete again (to clean up our mess)"); + if (Delete(parent) != 0) + return -1; + return 0; } @@ -413,7 +609,6 @@ int main() // For use with DEBUG defined. //---------------------------------------------------------------------------------------- { - FilesTest tester; return tester.RunAllTests(); } // main diff --git a/mozilla/xpcom/io/nsFileSpec.cpp b/mozilla/xpcom/io/nsFileSpec.cpp index cf591af221f..9b0d62fb174 100644 --- a/mozilla/xpcom/io/nsFileSpec.cpp +++ b/mozilla/xpcom/io/nsFileSpec.cpp @@ -22,6 +22,9 @@ #include "nsDebug.h" #include "prtypes.h" +#include "plstr.h" +#include "plbase64.h" +#include "prmem.h" #include #include @@ -40,7 +43,7 @@ NS_NAMESPACE nsFileSpecHelpers char inSeparator, const char* inLeafName); #ifndef XP_MAC - NS_NAMESPACE_PROTOTYPE void Canonify(char*& ioPath, bool inMakeDirs); + NS_NAMESPACE_PROTOTYPE void Canonify(char*& ioPath, PRBool inMakeDirs); NS_NAMESPACE_PROTOTYPE void MakeAllDirectories(const char* inPath, int mode); #endif NS_NAMESPACE_PROTOTYPE char* GetLeaf(const char* inPath, char inSeparator); // allocated @@ -54,6 +57,14 @@ NS_NAMESPACE nsFileSpecHelpers #endif } NS_NAMESPACE_END +//---------------------------------------------------------------------------------------- +nsresult ns_file_convert_result(PRInt32 nativeErr) +//---------------------------------------------------------------------------------------- +{ + return nativeErr ? + NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES,((nativeErr)&0xFFFF)) + : NS_OK; +} //---------------------------------------------------------------------------------------- char* nsFileSpecHelpers::StringDup( @@ -65,7 +76,7 @@ char* nsFileSpecHelpers::StringDup( allocLength = strlen(inString); char* newPath = inString || allocLength ? new char[allocLength + 1] : nsnull; if (!newPath) - return NULL; + return nsnull; strcpy(newPath, inString); return newPath; } // nsFileSpecHelpers::StringDup @@ -77,7 +88,7 @@ char* nsFileSpecHelpers::AllocCat( //---------------------------------------------------------------------------------------- { if (!inString1) - return inString2 ? StringDup(inString2) : (char*)NULL; + return inString2 ? StringDup(inString2) : (char*)nsnull; if (!inString2) return StringDup(inString1); char* outString = StringDup(inString1, strlen(inString1) + strlen(inString2)); @@ -95,7 +106,7 @@ char* nsFileSpecHelpers::StringAssign( if (!inString2) { delete [] ioString; - ioString = (char*)NULL; + ioString = (char*)nsnull; return ioString; } if (!ioString || (strlen(inString2) > strlen(ioString))) @@ -125,8 +136,19 @@ void nsFileSpecHelpers::LeafReplace( } char* lastSeparator = strrchr(ioPath, inSeparator); int oldLength = strlen(ioPath); - *(++lastSeparator) = '\0'; // strip the current leaf name - int newLength = lastSeparator - ioPath + strlen(inLeafName); + PRBool trailingSeparator = (lastSeparator + 1 == ioPath + oldLength); + if (trailingSeparator) + { + *lastSeparator = '\0'; + lastSeparator = strrchr(ioPath, inSeparator); + } + if (lastSeparator) + lastSeparator++; // point at the trailing string + else + lastSeparator = ioPath; // the full monty + *lastSeparator = '\0'; // strip the current leaf name + + int newLength = (lastSeparator - ioPath) + strlen(inLeafName) + int(trailingSeparator); if (newLength > oldLength) { char* newPath = StringDup(ioPath, newLength + 1); @@ -134,7 +156,14 @@ void nsFileSpecHelpers::LeafReplace( ioPath = newPath; } strcat(ioPath, inLeafName); -} // nsNativeFileSpec::LeafReplace + if (trailingSeparator) + { + // If the original ended in a slash, then the new one should, too. + char sepStr[2] = "/"; + *sepStr = inSeparator; + strcat(ioPath, sepStr); + } +} // nsFileSpecHelpers::LeafReplace //---------------------------------------------------------------------------------------- char* nsFileSpecHelpers::GetLeaf(const char* inPath, char inSeparator) @@ -142,12 +171,32 @@ char* nsFileSpecHelpers::GetLeaf(const char* inPath, char inSeparator) //---------------------------------------------------------------------------------------- { if (!inPath) - return NULL; - char* lastSeparator = strrchr(inPath, inSeparator); - if (lastSeparator) - return StringDup(++lastSeparator); - return StringDup(inPath); -} // nsNativeFileSpec::GetLeaf + return nsnull; + const char* lastSeparator = strrchr(inPath, inSeparator); + + // If there was no separator, then return a copy of the caller's path. + if (!lastSeparator) + return StringDup(inPath); + + // So there's at least one separator. What's just after it? + // If the separator was not the last character, return the trailing string. + const char* leafPointer = lastSeparator + 1; + if (*leafPointer) + return StringDup(leafPointer); + + // So now, separator was the last character. Poke in a null instead. + *(char*)lastSeparator = '\0'; // Should use const_cast, but Unix has old compiler. + leafPointer = strrchr(inPath, inSeparator); + char* result = leafPointer ? StringDup(leafPointer++) : StringDup(inPath); + // Restore the poked null before returning. + *(char*)lastSeparator = inSeparator; +#ifdef XP_PC + // If it's a drive letter use the colon notation. + if (!leafPointer && strlen(result) == 2 && result[1] == '|') + result[1] = ':'; +#endif + return result; +} // nsFileSpecHelpers::GetLeaf #if defined(XP_UNIX) || defined(XP_PC) @@ -177,7 +226,7 @@ void nsFileSpecHelpers::MakeAllDirectories(const char* inPath, int mode) if (currentEnd) { *currentEnd = '\0'; - nsNativeFileSpec spec(nsFilePath(pathCopy, false)); + nsFileSpec spec(nsFilePath(pathCopy, PR_FALSE)); do { // If the node doesn't exist, and it is not the initial node in a full path, @@ -209,7 +258,7 @@ char* nsFileSpecHelpers::ReallocCat(char*& ioString, const char* inString1) delete [] ioString; ioString = newString; return ioString; -} // nsNativeFileSpec::ReallocCat +} // nsFileSpecHelpers::ReallocCat #if defined(XP_PC) #include "windows/nsFileSpecWin.cpp" // Windows-specific implementations @@ -225,7 +274,7 @@ char* nsFileSpecHelpers::ReallocCat(char*& ioString, const char* inString1) #ifndef XP_MAC //---------------------------------------------------------------------------------------- -nsFileURL::nsFileURL(const char* inString, bool inCreateDirs) +nsFileURL::nsFileURL(const char* inString, PRBool inCreateDirs) //---------------------------------------------------------------------------------------- : mURL(nsnull) { @@ -243,7 +292,7 @@ nsFileURL::nsFileURL(const nsFileURL& inOther) //---------------------------------------------------------------------------------------- : mURL(nsFileSpecHelpers::StringDup(inOther.mURL)) #ifdef XP_MAC -, mNativeFileSpec(inOther.GetNativeSpec()) +, mFileSpec(inOther.GetFileSpec()) #endif { } // nsFileURL::nsFileURL @@ -253,16 +302,16 @@ nsFileURL::nsFileURL(const nsFilePath& inOther) //---------------------------------------------------------------------------------------- : mURL(nsFileSpecHelpers::AllocCat(kFileURLPrefix, (const char*)inOther)) #ifdef XP_MAC -, mNativeFileSpec(inOther.GetNativeSpec()) +, mFileSpec(inOther.GetFileSpec()) #endif { } // nsFileURL::nsFileURL //---------------------------------------------------------------------------------------- -nsFileURL::nsFileURL(const nsNativeFileSpec& inOther) +nsFileURL::nsFileURL(const nsFileSpec& inOther) : mURL(nsFileSpecHelpers::AllocCat(kFileURLPrefix, (const char*)nsFilePath(inOther))) #ifdef XP_MAC -, mNativeFileSpec(inOther) +, mFileSpec(inOther) #endif //---------------------------------------------------------------------------------------- { @@ -282,7 +331,7 @@ void nsFileURL::operator = (const char* inString) nsFileSpecHelpers::StringAssign(mURL, inString); NS_ASSERTION(strstr(inString, kFileURLPrefix) == inString, "Not a URL!"); #ifdef XP_MAC - mNativeFileSpec = inString + kFileURLPrefixLength; + mFileSpec = inString + kFileURLPrefixLength; #endif } // nsFileURL::operator = @@ -292,7 +341,7 @@ void nsFileURL::operator = (const nsFileURL& inOther) { mURL = nsFileSpecHelpers::StringAssign(mURL, inOther.mURL); #ifdef XP_MAC - mNativeFileSpec = inOther.GetNativeSpec(); + mFileSpec = inOther.GetFileSpec(); #endif } // nsFileURL::operator = @@ -303,27 +352,29 @@ void nsFileURL::operator = (const nsFilePath& inOther) delete [] mURL; mURL = nsFileSpecHelpers::AllocCat(kFileURLPrefix, (const char*)inOther); #ifdef XP_MAC - mNativeFileSpec = inOther.GetNativeSpec(); + mFileSpec = inOther.GetFileSpec(); #endif } // nsFileURL::operator = //---------------------------------------------------------------------------------------- -void nsFileURL::operator = (const nsNativeFileSpec& inOther) +void nsFileURL::operator = (const nsFileSpec& inOther) //---------------------------------------------------------------------------------------- { delete [] mURL; mURL = nsFileSpecHelpers::AllocCat(kFileURLPrefix, (const char*)nsFilePath(inOther)); #ifdef XP_MAC - mNativeFileSpec = inOther; + mFileSpec = inOther; #endif } // nsFileURL::operator = +#if DEBUG //---------------------------------------------------------------------------------------- -nsBasicOutStream& operator << (nsBasicOutStream& s, const nsFileURL& url) +nsOutputStream& operator << (nsOutputStream& s, const nsFileURL& url) //---------------------------------------------------------------------------------------- { return (s << url.mURL); } +#endif //======================================================================================== // nsFilePath implementation @@ -332,14 +383,14 @@ nsBasicOutStream& operator << (nsBasicOutStream& s, const nsFileURL& url) nsFilePath::nsFilePath(const nsFilePath& inPath) : mPath(nsFileSpecHelpers::StringDup(inPath.mPath)) #ifdef XP_MAC - , mNativeFileSpec(inPath.mNativeFileSpec) + , mFileSpec(inPath.mFileSpec) #endif { } #ifndef XP_MAC //---------------------------------------------------------------------------------------- -nsFilePath::nsFilePath(const char* inString, bool inCreateDirs) +nsFilePath::nsFilePath(const char* inString, PRBool inCreateDirs) //---------------------------------------------------------------------------------------- : mPath(nsFileSpecHelpers::StringDup(inString)) { @@ -362,14 +413,14 @@ nsFilePath::nsFilePath(const nsFileURL& inOther) //---------------------------------------------------------------------------------------- : mPath(nsFileSpecHelpers::StringDup(inOther.mURL + kFileURLPrefixLength)) #ifdef XP_MAC -, mNativeFileSpec(inOther.GetNativeSpec()) +, mFileSpec(inOther.GetFileSpec()) #endif { } #ifdef XP_UNIX //---------------------------------------------------------------------------------------- -nsFilePath::nsFilePath(const nsNativeFileSpec& inOther) +nsFilePath::nsFilePath(const nsFileSpec& inOther) //---------------------------------------------------------------------------------------- : mPath(nsFileSpecHelpers::StringDup(inOther.mPath)) { @@ -385,7 +436,7 @@ nsFilePath::~nsFilePath() #ifdef XP_UNIX //---------------------------------------------------------------------------------------- -void nsFilePath::operator = (const nsNativeFileSpec& inOther) +void nsFilePath::operator = (const nsFileSpec& inOther) //---------------------------------------------------------------------------------------- { mPath = nsFileSpecHelpers::StringAssign(mPath, inOther.mPath); @@ -398,14 +449,14 @@ void nsFilePath::operator = (const char* inString) { NS_ASSERTION(strstr(inString, kFileURLPrefix) != inString, "URL passed as path"); #ifdef XP_MAC - mNativeFileSpec = inString; - nsFileSpecHelpers::StringAssign(mPath, (const char*)nsFilePath(mNativeFileSpec)); + mFileSpec = inString; + nsFileSpecHelpers::StringAssign(mPath, (const char*)nsFilePath(mFileSpec)); #else #ifdef XP_PC nsFileSpecHelpers::UnixToNative(mPath); #endif // Make canonical and absolute. - nsFileSpecHelpers::Canonify(mPath, false /* XXX? */); + nsFileSpecHelpers::Canonify(mPath, PR_FALSE /* XXX? */); #ifdef XP_PC nsFileSpecHelpers::NativeToUnix(mPath); #endif @@ -418,7 +469,7 @@ void nsFilePath::operator = (const nsFileURL& inOther) { nsFileSpecHelpers::StringAssign(mPath, (const char*)nsFilePath(inOther)); #ifdef XP_MAC - mNativeFileSpec = inOther.GetNativeSpec(); + mFileSpec = inOther.GetFileSpec(); #endif } @@ -433,40 +484,51 @@ void nsFilePath::operator = (const nsFilePath& inOther) } //======================================================================================== -// nsNativeFileSpec implementation +// nsFileSpec implementation //======================================================================================== #ifndef XP_MAC //---------------------------------------------------------------------------------------- -nsNativeFileSpec::nsNativeFileSpec() +nsFileSpec::nsFileSpec() //---------------------------------------------------------------------------------------- -: mPath(NULL) +: mPath(nsnull) +, mError(NS_OK) { } #endif //---------------------------------------------------------------------------------------- -nsNativeFileSpec::nsNativeFileSpec(const nsFileURL& inURL) +nsFileSpec::nsFileSpec(const nsPersistentFileDescriptor& inDescriptor) //---------------------------------------------------------------------------------------- #ifndef XP_MAC -: mPath(NULL) +: mPath(nsnull) +#endif +{ + *this = inDescriptor; +} + +//---------------------------------------------------------------------------------------- +nsFileSpec::nsFileSpec(const nsFileURL& inURL) +//---------------------------------------------------------------------------------------- +#ifndef XP_MAC +: mPath(nsnull) #endif { *this = nsFilePath(inURL); // convert to unix path first } //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::MakeUnique(const char* inSuggestedLeafName) +void nsFileSpec::MakeUnique(const char* inSuggestedLeafName) //---------------------------------------------------------------------------------------- { if (inSuggestedLeafName && *inSuggestedLeafName) SetLeafName(inSuggestedLeafName); MakeUnique(); -} // nsNativeFileSpec::MakeUnique +} // nsFileSpec::MakeUnique //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::MakeUnique() +void nsFileSpec::MakeUnique() //---------------------------------------------------------------------------------------- { if (!Exists()) @@ -497,51 +559,82 @@ void nsNativeFileSpec::MakeUnique() if (*suffix) delete [] suffix; delete [] leafName; -} // nsNativeFileSpec::MakeUnique +} // nsFileSpec::MakeUnique //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::operator = (const nsFileURL& inURL) +void nsFileSpec::operator = (const nsFileURL& inURL) //---------------------------------------------------------------------------------------- { *this = nsFilePath(inURL); // convert to unix path first } +//---------------------------------------------------------------------------------------- +void nsFileSpec::operator = (const nsPersistentFileDescriptor& inDescriptor) +//---------------------------------------------------------------------------------------- +{ + + void* data; + PRInt32 dataSize; + inDescriptor.GetData(data, dataSize); + +#ifdef XP_MAC + char* decodedData = PL_Base64Decode((const char*)data, (int)dataSize, nsnull); + // Cast to an alias record and resolve. + AliasHandle aliasH = nsnull; + mError = NS_FILE_RESULT(PtrToHand(decodedData, &(Handle)aliasH, (dataSize * 3) / 4)); + PR_Free(decodedData); + if (NS_SUCCEEDED(mError)) + return; // not enough memory? + + Boolean changed; + mError = NS_FILE_RESULT(::ResolveAlias(nsnull, aliasH, &mSpec, &changed)); + DisposeHandle((Handle) aliasH); +#else + nsFileSpecHelpers::StringAssign(mPath, (char*)data); + mError = NS_OK; +#endif +} + //======================================================================================== -// UNIX & WIN nsNativeFileSpec implementation +// UNIX & WIN nsFileSpec implementation //======================================================================================== #ifdef XP_UNIX //---------------------------------------------------------------------------------------- -nsNativeFileSpec::nsNativeFileSpec(const nsFilePath& inPath) +nsFileSpec::nsFileSpec(const nsFilePath& inPath) //---------------------------------------------------------------------------------------- : mPath(nsFileSpecHelpers::StringDup((const char*)inPath)) +, mError(NS_OK) { } #endif // XP_UNIX #ifdef XP_UNIX //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::operator = (const nsFilePath& inPath) +void nsFileSpec::operator = (const nsFilePath& inPath) //---------------------------------------------------------------------------------------- { nsFileSpecHelpers::StringAssign(mPath, (const char*)inPath); + mError = NS_OK; } #endif //XP_UNIX #if defined(XP_UNIX) || defined(XP_PC) //---------------------------------------------------------------------------------------- -nsNativeFileSpec::nsNativeFileSpec(const nsNativeFileSpec& inSpec) +nsFileSpec::nsFileSpec(const nsFileSpec& inSpec) //---------------------------------------------------------------------------------------- : mPath(nsFileSpecHelpers::StringDup(inSpec.mPath)) +, mError(NS_OK) { } #endif //XP_UNIX #if defined(XP_UNIX) || defined(XP_PC) //---------------------------------------------------------------------------------------- -nsNativeFileSpec::nsNativeFileSpec(const char* inString, bool inCreateDirs) +nsFileSpec::nsFileSpec(const char* inString, PRBool inCreateDirs) //---------------------------------------------------------------------------------------- : mPath(nsFileSpecHelpers::StringDup(inString)) +, mError(NS_OK) { // Make canonical and absolute. nsFileSpecHelpers::Canonify(mPath, inCreateDirs); @@ -549,7 +642,7 @@ nsNativeFileSpec::nsNativeFileSpec(const char* inString, bool inCreateDirs) #endif //XP_UNIX,PC //---------------------------------------------------------------------------------------- -nsNativeFileSpec::~nsNativeFileSpec() +nsFileSpec::~nsFileSpec() //---------------------------------------------------------------------------------------- { #ifndef XP_MAC @@ -559,39 +652,160 @@ nsNativeFileSpec::~nsNativeFileSpec() #if defined(XP_UNIX) || defined(XP_PC) //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::operator = (const nsNativeFileSpec& inSpec) +void nsFileSpec::operator = (const nsFileSpec& inSpec) //---------------------------------------------------------------------------------------- { mPath = nsFileSpecHelpers::StringAssign(mPath, inSpec.mPath); + mError = inSpec.Error(); } #endif //XP_UNIX #if defined(XP_UNIX) || defined(XP_PC) //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::operator = (const char* inString) +void nsFileSpec::operator = (const char* inString) //---------------------------------------------------------------------------------------- { mPath = nsFileSpecHelpers::StringAssign(mPath, inString); // Make canonical and absolute. - nsFileSpecHelpers::Canonify(mPath, true /* XXX? */); + nsFileSpecHelpers::Canonify(mPath, PR_TRUE /* XXX? */); + mError = NS_OK; } #endif //XP_UNIX +#if DEBUG #if (defined(XP_UNIX) || defined(XP_PC)) //---------------------------------------------------------------------------------------- -nsBasicOutStream& operator << (nsBasicOutStream& s, const nsNativeFileSpec& spec) +nsOutputStream& operator << (nsOutputStream& s, const nsFileSpec& spec) //---------------------------------------------------------------------------------------- { return (s << (const char*)spec.mPath); } #endif // DEBUG && XP_UNIX +#endif //---------------------------------------------------------------------------------------- -nsNativeFileSpec nsNativeFileSpec::operator + (const char* inRelativePath) const +nsFileSpec nsFileSpec::operator + (const char* inRelativePath) const //---------------------------------------------------------------------------------------- { - nsNativeFileSpec result = *this; + nsFileSpec result = *this; result += inRelativePath; return result; -} // nsNativeFileSpec::operator + +} // nsFileSpec::operator + + +//======================================================================================== +// class nsPersistentFileDescriptor +//======================================================================================== + +//---------------------------------------------------------------------------------------- +nsPersistentFileDescriptor::nsPersistentFileDescriptor(const nsPersistentFileDescriptor& inDesc) +//---------------------------------------------------------------------------------------- + : mDescriptorString(nsFileSpecHelpers::StringDup(inDesc.mDescriptorString)) +{ +} // nsPersistentFileDescriptor::nsPersistentFileDescriptor + +//---------------------------------------------------------------------------------------- +void nsPersistentFileDescriptor::operator = (const nsPersistentFileDescriptor& inDesc) +//---------------------------------------------------------------------------------------- +{ + nsFileSpecHelpers::StringAssign(mDescriptorString, inDesc.mDescriptorString); +} // nsPersistentFileDescriptor::operator = + +//---------------------------------------------------------------------------------------- +nsPersistentFileDescriptor::nsPersistentFileDescriptor(const nsFileSpec& inSpec) +//---------------------------------------------------------------------------------------- + : mDescriptorString(nsnull) +{ + *this = inSpec; +} // nsPersistentFileDescriptor::nsPersistentFileDescriptor + +//---------------------------------------------------------------------------------------- +void nsPersistentFileDescriptor::operator = (const nsFileSpec& inSpec) +//---------------------------------------------------------------------------------------- +{ +#ifdef XP_MAC + if (inSpec.Error()) + return; + AliasHandle aliasH; + OSErr err = NewAlias(nil, inSpec.operator const FSSpec* const (), &aliasH); + if (err != noErr) + return; + + PRUint32 bytes = GetHandleSize((Handle) aliasH); + HLock((Handle) aliasH); + char* buf = PL_Base64Encode((const char*)*aliasH, bytes, nsnull); + DisposeHandle((Handle) aliasH); + + nsFileSpecHelpers::StringAssign(mDescriptorString, buf); + PR_Free(buf); +#else + nsFileSpecHelpers::StringAssign(mDescriptorString, inSpec); +#endif // XP_MAC +} // nsPersistentFileDescriptor::operator = + +//---------------------------------------------------------------------------------------- +nsPersistentFileDescriptor::~nsPersistentFileDescriptor() +//---------------------------------------------------------------------------------------- +{ + delete [] mDescriptorString; +} // nsPersistentFileDescriptor::~nsPersistentFileDescriptor + +//---------------------------------------------------------------------------------------- +void nsPersistentFileDescriptor::GetData(void*& outData, PRInt32& outSize) const +//---------------------------------------------------------------------------------------- +{ + outSize = PL_strlen(mDescriptorString); + outData = mDescriptorString; +} + +//---------------------------------------------------------------------------------------- +void nsPersistentFileDescriptor::SetData(const void* inData, PRInt32 inSize) +//---------------------------------------------------------------------------------------- +{ + delete [] mDescriptorString; + mDescriptorString = new char[1 + inSize]; + if (!mDescriptorString) + return; + memcpy(mDescriptorString, inData, inSize); + mDescriptorString[inSize] = '\0'; +} + +#define MAX_PERSISTENT_DATA_SIZE 1000 + +//---------------------------------------------------------------------------------------- +nsInputStream& operator >> (nsInputStream& s, nsPersistentFileDescriptor& d) +// reads the data from a file +//---------------------------------------------------------------------------------------- +{ + char bigBuffer[MAX_PERSISTENT_DATA_SIZE + 1]; + // The first 8 bytes of the data should be a hex version of the data size to follow. + PRInt32 bytesRead = 8; + bytesRead = s.read(bigBuffer, bytesRead); + if (bytesRead != 8) + return (nsInputFileStream&)s; + bigBuffer[8] = '\0'; + sscanf(bigBuffer, "%lx", &bytesRead); + if (bytesRead > MAX_PERSISTENT_DATA_SIZE) + return (nsInputFileStream&)s; // preposterous. + // Now we know how many bytes to read, do it. + s.read(bigBuffer, bytesRead); + d.SetData(bigBuffer, bytesRead); + return (nsInputFileStream&)s; +} + +//---------------------------------------------------------------------------------------- +nsOutputStream& operator << (nsOutputStream& s, const nsPersistentFileDescriptor& d) +// writes the data to a file +//---------------------------------------------------------------------------------------- +{ + char littleBuf[9]; + PRInt32 dataSize; + void* data; + d.GetData(data, dataSize); + // First write (in hex) the length of the data to follow. Exactly 8 bytes + sprintf(littleBuf, "%0.8x", dataSize); + s << littleBuf; + // Now write the data itself + s << d.mDescriptorString; + return s; +} diff --git a/mozilla/xpcom/io/nsFileSpec.h b/mozilla/xpcom/io/nsFileSpec.h index 2cdce813668..78c30012f0f 100644 --- a/mozilla/xpcom/io/nsFileSpec.h +++ b/mozilla/xpcom/io/nsFileSpec.h @@ -24,7 +24,16 @@ // // Classes defined: // -// nsFilePath, nsFileURL, nsNativeFileSpec. +// nsFilePath, nsFileURL, nsFileSpec, nsPersistentFileDescriptor. +// +// Q. How should I represent files at run time? +// A. Use nsFileSpec. Using char* will lose information on some platforms. +// +// Q. Then what are nsFilePath and nsFileURL for? +// A. Only when you need a char* parameter for legacy code. +// +// Q. How should I represent files in a persistent way (eg, in a disk file)? +// A. Use nsPersistentFileDescriptor. Convert to and from nsFileSpec at run time. // // This suite provides the following services: // @@ -63,7 +72,7 @@ // // Initialize a native file spec from a URL // -// nsNativeFileSpec fileSpec(fileURL); +// nsFileSpec fileSpec(fileURL); // // Make the spec unique (this one has no suffix). // @@ -103,6 +112,7 @@ #define _FILESPEC_H_ #include "nscore.h" +#include "nsError.h" //======================================================================================== // Compiler-specific macros, as needed @@ -116,11 +126,13 @@ #define NS_NAMESPACE_PROTOTYPE #define NS_NAMESPACE namespace #define NS_NAMESPACE_END +#define NS_EXPLICIT explicit #else #define NS_NAMESPACE_PROTOTYPE static #define NS_NAMESPACE struct #define NS_NAMESPACE_END ; +#define NS_EXPLICIT #endif //=========================== End Compiler-specific macros =============================== @@ -137,33 +149,50 @@ // Here are the allowable ways to describe a file. //======================================================================================== -class nsFilePath; // This can be passed to NSPR file I/O routines. +class nsFileSpec; // Preferred. For i/o use nsInputFileStream, nsOutputFileStream +class nsFilePath; // This can be passed to NSPR file I/O routines, if you must. class nsFileURL; -class nsNativeFileSpec; +class nsPersistentFileDescriptor; // Used for storage across program launches. #define kFileURLPrefix "file://" #define kFileURLPrefixLength (7) -class nsBasicOutStream; +class nsOutputStream; +class nsInputStream; +class nsOutputFileStream; +class nsInputFileStream; //======================================================================================== -class NS_BASE nsNativeFileSpec +// Conversion of native file errors to nsresult values. These are really only for use +// in the file module, clients of this interface shouldn't really need them. +// Error results returned from this interface have, in the low-order 16 bits, +// native errors that are masked to 16 bits. Assumption: a native error of 0 is success +// on all platforms. Note the way we define this using an inline function. This +// avoids multiple evaluation if people go NS_FILE_RESULT(function_call()). +#define NS_FILE_RESULT(x) ns_file_convert_result((PRInt32)x) +nsresult ns_file_convert_result(PRInt32 nativeErr); +#define NS_FILE_FAILURE NS_FILE_RESULT(-1) + +//======================================================================================== +class NS_BASE nsFileSpec // This is whatever each platform really prefers to describe files as. Declared first -// because the other two types have an embeded nsNativeFileSpec object. +// because the other two types have an embeded nsFileSpec object. //======================================================================================== { public: - nsNativeFileSpec(); - explicit nsNativeFileSpec(const char* inString, bool inCreateDirs = false); - explicit nsNativeFileSpec(const nsFilePath& inPath); - explicit nsNativeFileSpec(const nsFileURL& inURL); - nsNativeFileSpec(const nsNativeFileSpec& inPath); - virtual ~nsNativeFileSpec(); + nsFileSpec(); + NS_EXPLICIT nsFileSpec(const char* inString, PRBool inCreateDirs = PR_FALSE); + NS_EXPLICIT nsFileSpec(const nsFilePath& inPath); + NS_EXPLICIT nsFileSpec(const nsFileURL& inURL); + NS_EXPLICIT nsFileSpec(const nsPersistentFileDescriptor& inURL); + nsFileSpec(const nsFileSpec& inPath); + virtual ~nsFileSpec(); void operator = (const char* inPath); void operator = (const nsFilePath& inPath); void operator = (const nsFileURL& inURL); - void operator = (const nsNativeFileSpec& inOther); + void operator = (const nsFileSpec& inOther); + void operator = (const nsPersistentFileDescriptor& inOther); #ifndef XP_MAC operator const char* () const { return mPath; } @@ -175,23 +204,22 @@ class NS_BASE nsNativeFileSpec #ifdef XP_MAC // For Macintosh people, this is meant to be useful in its own right as a C++ version // of the FSSpec struct. - nsNativeFileSpec( + nsFileSpec( short vRefNum, long parID, ConstStr255Param name); - nsNativeFileSpec(const FSSpec& inSpec) - : mSpec(inSpec), mError(noErr) {} + nsFileSpec(const FSSpec& inSpec) + : mSpec(inSpec), mError(NS_OK) {} operator FSSpec* () { return &mSpec; } operator const FSSpec* const () { return &mSpec; } operator FSSpec& () { return mSpec; } operator const FSSpec& () const { return mSpec; } - OSErr Error() const { return mError; } void MakeAliasSafe(); // Called for the spec of an alias. Copies the alias to // a secret temp directory and modifies the spec to point // to it. Sets mError. - void ResolveAlias(bool& wasAliased); + void ResolveAlias(PRBool& wasAliased); // Called for the spec of an alias. Modifies the spec to // point to the original. Sets mError. void MakeUnique(ConstStr255Param inSuggestedLeafName); @@ -199,15 +227,15 @@ class NS_BASE nsNativeFileSpec ConstStr255Param GetLeafPName() const { return mSpec.name; } #endif // end of Macintosh utility methods. -#ifdef XP_MAC - bool Valid() const { return mError == noErr; } -#else - bool Valid() const { return true; } // Fixme. -#endif // XP_MAC + PRBool Valid() const { return NS_SUCCEEDED(Error()); } + nsresult Error() const { return mError; } - friend NS_BASE nsBasicOutStream& operator << ( - nsBasicOutStream& s, - const nsNativeFileSpec& spec); +#if DEBUG + friend NS_BASE nsOutputStream& operator << ( + nsOutputStream& s, + const nsFileSpec& spec); // THIS IS FOR DEBUGGING ONLY. + // see PersistentFileDescriptor for the real deal. +#endif //-------------------------------------------------- // Queries and path algebra. These do not modify the disk. @@ -218,7 +246,7 @@ class NS_BASE nsNativeFileSpec // inLeafName can be a relative path, so this allows // one kind of concatenation of "paths". - void GetParent(nsNativeFileSpec& outSpec) const; + void GetParent(nsFileSpec& outSpec) const; // Return the filespec of the parent directory. Used // in conjunction with GetLeafName(), this lets you // parse a path into a list of node names. Beware, @@ -226,7 +254,7 @@ class NS_BASE nsNativeFileSpec // but a spec. Volumes on Macintosh can have identical // names. Perhaps could be used for an operator --() ? - nsNativeFileSpec operator + (const char* inRelativePath) const; + nsFileSpec operator + (const char* inRelativePath) const; void operator += (const char* inRelativePath); // Concatenate the relative path to this directory. // Used for constructing the filespec of a descendant. @@ -240,19 +268,24 @@ class NS_BASE nsNativeFileSpec void MakeUnique(); void MakeUnique(const char* inSuggestedLeafName); - bool IsDirectory() const; + PRBool IsDirectory() const; // More stringent than Exists() - bool IsFile() const; + PRBool IsFile() const; // More stringent than Exists() - bool Exists() const; + PRBool Exists() const; //-------------------------------------------------- // Creation and deletion of objects. These can modify the disk. //-------------------------------------------------- void CreateDirectory(int mode = 0700 /* for unix */); - void Delete(bool inRecursive); + void Delete(PRBool inRecursive); + nsresult Rename(const char* inNewName); // not const: gets updated + nsresult Copy(const nsFileSpec& inNewParentDirectory) const; + nsresult Move(const nsFileSpec& inNewParentDirectory) const; + nsresult Execute(const char* args) const; + //-------------------------------------------------- // Data //-------------------------------------------------- @@ -261,11 +294,15 @@ class NS_BASE nsNativeFileSpec friend class nsFilePath; #ifdef XP_MAC FSSpec mSpec; - OSErr mError; #else char* mPath; #endif -}; // class nsNativeFileSpec + nsresult mError; +}; // class nsFileSpec + +// FOR HISTORICAL REASONS: + +typedef nsFileSpec nsNativeFileSpec; //======================================================================================== class NS_BASE nsFileURL @@ -276,9 +313,9 @@ class NS_BASE nsFileURL { public: nsFileURL(const nsFileURL& inURL); - explicit nsFileURL(const char* inString, bool inCreateDirs = false); - explicit nsFileURL(const nsFilePath& inPath); - explicit nsFileURL(const nsNativeFileSpec& inPath); + NS_EXPLICIT nsFileURL(const char* inString, PRBool inCreateDirs = PR_FALSE); + NS_EXPLICIT nsFileURL(const nsFilePath& inPath); + NS_EXPLICIT nsFileURL(const nsFileSpec& inPath); virtual ~nsFileURL(); // nsString GetString() const { return mPath; } @@ -288,14 +325,14 @@ class NS_BASE nsFileURL void operator = (const nsFileURL& inURL); void operator = (const char* inString); void operator = (const nsFilePath& inOther); - void operator = (const nsNativeFileSpec& inOther); + void operator = (const nsFileSpec& inOther); - friend NS_BASE nsBasicOutStream& operator << ( - nsBasicOutStream& s, const nsFileURL& spec); + friend NS_BASE nsOutputStream& operator << ( + nsOutputStream& s, const nsFileURL& spec); #ifdef XP_MAC - // Accessor to allow quick assignment to a mNativeFileSpec - const nsNativeFileSpec& GetNativeSpec() const { return mNativeFileSpec; } + // Accessor to allow quick assignment to a mFileSpec + const nsFileSpec& GetFileSpec() const { return mFileSpec; } #endif private: // Should not be defined (only nsFilePath is to be treated as strings. @@ -306,8 +343,8 @@ class NS_BASE nsFileURL char* mURL; #ifdef XP_MAC // Since the path on the macintosh does not uniquely specify a file (volumes - // can have the same name), stash the secret nsNativeFileSpec, too. - nsNativeFileSpec mNativeFileSpec; + // can have the same name), stash the secret nsFileSpec, too. + nsFileSpec mFileSpec; #endif }; // class nsFileURL @@ -319,9 +356,9 @@ class NS_BASE nsFilePath { public: nsFilePath(const nsFilePath& inPath); - explicit nsFilePath(const char* inString, bool inCreateDirs = false); - explicit nsFilePath(const nsFileURL& inURL); - explicit nsFilePath(const nsNativeFileSpec& inPath); + NS_EXPLICIT nsFilePath(const char* inString, PRBool inCreateDirs = PR_FALSE); + NS_EXPLICIT nsFilePath(const nsFileURL& inURL); + NS_EXPLICIT nsFilePath(const nsFileSpec& inPath); virtual ~nsFilePath(); @@ -337,12 +374,12 @@ class NS_BASE nsFilePath void operator = (const nsFilePath& inPath); void operator = (const char* inString); void operator = (const nsFileURL& inURL); - void operator = (const nsNativeFileSpec& inOther); + void operator = (const nsFileSpec& inOther); #ifdef XP_MAC public: - // Accessor to allow quick assignment to a mNativeFileSpec - const nsNativeFileSpec& GetNativeSpec() const { return mNativeFileSpec; } + // Accessor to allow quick assignment to a mFileSpec + const nsFileSpec& GetFileSpec() const { return mFileSpec; } #endif private: @@ -350,26 +387,59 @@ class NS_BASE nsFilePath char* mPath; #ifdef XP_MAC // Since the path on the macintosh does not uniquely specify a file (volumes - // can have the same name), stash the secret nsNativeFileSpec, too. - nsNativeFileSpec mNativeFileSpec; + // can have the same name), stash the secret nsFileSpec, too. + nsFileSpec mFileSpec; #endif }; // class nsFilePath +//======================================================================================== +class NS_BASE nsPersistentFileDescriptor +//======================================================================================== +{ + public: + nsPersistentFileDescriptor() : mDescriptorString(nsnull) {} + // For use prior to reading in from a stream + nsPersistentFileDescriptor(const nsPersistentFileDescriptor& inPath); + virtual ~nsPersistentFileDescriptor(); + void operator = (const nsPersistentFileDescriptor& inPath); + + // Conversions + nsPersistentFileDescriptor(const nsFileSpec& inPath); + void operator = (const nsFileSpec& inPath); + + friend NS_BASE nsInputStream& operator >> (nsInputStream&, nsPersistentFileDescriptor&); + // reads the data from a file + friend NS_BASE nsOutputStream& operator << (nsOutputStream&, const nsPersistentFileDescriptor&); + // writes the data to a file + friend class nsFileSpec; + + private: + // Here are the ways to get data in and out of a file. + void GetData(void*& outData, PRInt32& outSize) const; + // DON'T FREE the returned data! + void SetData(const void* inData, PRInt32 inSize); + + private: + + char* mDescriptorString; + +}; // class nsPersistentFileDescriptor + //======================================================================================== class NS_BASE nsDirectoryIterator // Example: // -// nsNativeFileSpec parentDir(...); // directory over whose children we shall iterate +// nsFileSpec parentDir(...); // directory over whose children we shall iterate // for (nsDirectoryIterator i(parentDir); i; i++) // { -// // do something with (const nsNativeFileSpec&)i +// // do something with (const nsFileSpec&)i // } // // or: // -// for (nsDirectoryIterator i(parentDir, false); i; i--) +// for (nsDirectoryIterator i(parentDir, PR_FALSE); i; i--) // { -// // do something with (const nsNativeFileSpec&)i +// // do something with (const nsFileSpec&)i // } // // Currently, the only platform on which backwards iteration actually goes backwards @@ -378,21 +448,21 @@ class NS_BASE nsDirectoryIterator { public: nsDirectoryIterator( - const nsNativeFileSpec& parent, + const nsFileSpec& parent, int iterateDirection = +1); #ifndef XP_MAC // Macintosh currently doesn't allocate, so needn't clean up. virtual ~nsDirectoryIterator(); #endif - operator bool() const { return mExists; } + PRBool Exists() const { return mExists; } nsDirectoryIterator& operator ++(); // moves to the next item, if any. nsDirectoryIterator& operator ++(int) { return ++(*this); } // post-increment. nsDirectoryIterator& operator --(); // moves to the previous item, if any. nsDirectoryIterator& operator --(int) { return --(*this); } // post-decrement. - operator nsNativeFileSpec&() { return mCurrent; } + operator nsFileSpec&() { return mCurrent; } private: - nsNativeFileSpec mCurrent; - bool mExists; + nsFileSpec mCurrent; + bool mExists; // MUST be bool. #if defined(XP_UNIX) DIR* mDir; diff --git a/mozilla/xpcom/io/nsFileSpecMac.cpp b/mozilla/xpcom/io/nsFileSpecMac.cpp index dfa4da0ec28..a403ccb19a6 100644 --- a/mozilla/xpcom/io/nsFileSpecMac.cpp +++ b/mozilla/xpcom/io/nsFileSpecMac.cpp @@ -28,6 +28,7 @@ #include #include #include +#include const unsigned char* kAliasHavenFolderName = "\pnsAliasHaven"; @@ -74,7 +75,7 @@ namespace MacFileHelpers // to support attaching of aliases in mail. void EnsureAliasHaven(); void SetNoResolve(Boolean inResolve); - bool IsAliasSafe(const FSSpec& inSpec); + PRBool IsAliasSafe(const FSSpec& inSpec); OSErr MakeAliasSafe(FSSpec& inOutSpec); OSErr ResolveAliasFile(FSSpec& inOutSpec, Boolean& wasAliased); @@ -131,8 +132,8 @@ char* MacFileHelpers::EncodeMacPath( // Method: Swap ':' and '/', hex escape the result //----------------------------------- { - if (inPath == NULL) - return NULL; + if (inPath == nsnull) + return nsnull; int pathSize = strlen(inPath); // XP code sometimes chokes if there's a final slash in the unix path. @@ -145,8 +146,8 @@ char* MacFileHelpers::EncodeMacPath( pathSize--; } - char * newPath = NULL; - char * finalPath = NULL; + char * newPath = nsnull; + char * finalPath = nsnull; if (prependSlash) { @@ -188,10 +189,10 @@ OSErr MacFileHelpers::MakeAliasSafe(FSSpec& inOutSpec) //---------------------------------------------------------------------------------------- { EnsureAliasHaven(); - nsNativeFileSpec dstDirSpec(sAliasHavenVRefNum, sAliasHavenDirID, "\p"); + nsFileSpec dstDirSpec(sAliasHavenVRefNum, sAliasHavenDirID, "\p"); // Make sure its name is unique - nsNativeFileSpec havenSpec(sAliasHavenVRefNum, sAliasHavenDirID, "\pG'day"); + nsFileSpec havenSpec(sAliasHavenVRefNum, sAliasHavenDirID, "\pG'day"); if (havenSpec.Valid()) havenSpec.MakeUnique(inOutSpec.name); // Copy the file into the haven directory @@ -221,9 +222,9 @@ char* MacFileHelpers::MacPathFromUnixPath(const char* unixPath) { char* dst = result; const char* src = unixPath; - if (*src == '/') // ¥ full path + if (*src == '/') // * full path src++; - else if (strchr(src, '/')) // ¥ partial path, and not just a leaf name + else if (strchr(src, '/')) // * partial path, and not just a leaf name *dst++ = ':'; strcpy(dst, src); nsUnescape(dst); // Hex Decode @@ -346,7 +347,7 @@ void MacFileHelpers::EnsureAliasHaven() } // MacFileHelpers::EnsureAliasHaven //---------------------------------------------------------------------------------------- -bool MacFileHelpers::IsAliasSafe(const FSSpec& inSpec) +PRBool MacFileHelpers::IsAliasSafe(const FSSpec& inSpec) // Returns true if the alias is in the alias haven directory, or if alias resolution // has been turned off. //---------------------------------------------------------------------------------------- @@ -379,7 +380,7 @@ OSErr MacFileHelpers::FSSpecFromFullUnixPath( // then it is combined with inOutSpec's vRefNum and parID to form a new spec. //----------------------------------- { - if (unixPath == NULL) + if (unixPath == nsnull) return badFidErr; char* macPath = MacPathFromUnixPath(unixPath); if (!macPath) @@ -413,7 +414,7 @@ char* MacFileHelpers::PathNameFromFSSpec( const FSSpec& inSpec, Boolean wantLeaf OSErr err = noErr; short fullPathLength = 0; - Handle fullPath = NULL; + Handle fullPath = nsnull; FSSpec tempSpec = inSpec; if ( tempSpec.parID == fsRtParID ) @@ -471,7 +472,7 @@ char* MacFileHelpers::PathNameFromFSSpec( const FSSpec& inSpec, Boolean wantLeaf tempSpec.name[tempSpec.name[0]] = ':'; /* Add directory name to beginning of fullPath */ - (void) Munger(fullPath, 0, NULL, 0, &tempSpec.name[1], tempSpec.name[0]); + (void) Munger(fullPath, 0, nsnull, 0, &tempSpec.name[1], tempSpec.name[0]); err = MemError(); } } while ( err == noErr && pb.dirInfo.ioDrDirID != fsRtDirID ); @@ -500,19 +501,19 @@ Clean: } // MacFileHelpers::PathNameFromFSSpec //======================================================================================== -// Macintosh nsNativeFileSpec implementation +// Macintosh nsFileSpec implementation //======================================================================================== //---------------------------------------------------------------------------------------- -nsNativeFileSpec::nsNativeFileSpec() +nsFileSpec::nsFileSpec() //---------------------------------------------------------------------------------------- -: mError(noErr) +: mError(NS_OK) { mSpec.name[0] = '\0'; } //---------------------------------------------------------------------------------------- -nsNativeFileSpec::nsNativeFileSpec(const nsNativeFileSpec& inSpec) +nsFileSpec::nsFileSpec(const nsFileSpec& inSpec) //---------------------------------------------------------------------------------------- : mSpec(inSpec.mSpec) , mError(inSpec.Error()) @@ -520,87 +521,90 @@ nsNativeFileSpec::nsNativeFileSpec(const nsNativeFileSpec& inSpec) } //---------------------------------------------------------------------------------------- -nsNativeFileSpec::nsNativeFileSpec(const char* inString, bool inCreateDirs) +nsFileSpec::nsFileSpec(const char* inString, PRBool inCreateDirs) //---------------------------------------------------------------------------------------- { - mError = MacFileHelpers::FSSpecFromFullUnixPath( - inString, mSpec, true, true, inCreateDirs); + mError = NS_FILE_RESULT(MacFileHelpers::FSSpecFromFullUnixPath( + inString, mSpec, false, true, inCreateDirs)); // allow a partial path, create as necessary - if (mError == fnfErr) - mError = noErr; -} // nsNativeFileSpec::nsNativeFileSpec + if (mError == NS_FILE_RESULT(fnfErr)) + mError = NS_OK; +} // nsFileSpec::nsFileSpec //---------------------------------------------------------------------------------------- -nsNativeFileSpec::nsNativeFileSpec( +nsFileSpec::nsFileSpec( short vRefNum, long parID, ConstStr255Param name) //---------------------------------------------------------------------------------------- { - mError = ::FSMakeFSSpec(vRefNum, parID, name, &mSpec); - if (mError == fnfErr) + mError = NS_FILE_RESULT(::FSMakeFSSpec(vRefNum, parID, name, &mSpec)); + if (mError == NS_FILE_RESULT(fnfErr)) mError = noErr; } //---------------------------------------------------------------------------------------- -nsNativeFileSpec::nsNativeFileSpec(const nsFilePath& inPath) +nsFileSpec::nsFileSpec(const nsFilePath& inPath) //---------------------------------------------------------------------------------------- { - *this = inPath.GetNativeSpec(); + *this = inPath.GetFileSpec(); } +#if DEBUG //---------------------------------------------------------------------------------------- -nsBasicOutStream& operator << (nsBasicOutStream& s, const nsNativeFileSpec& spec) +nsOutputStream& operator << (nsOutputStream& s, const nsFileSpec& spec) //---------------------------------------------------------------------------------------- { s << spec.mSpec.vRefNum << ", " << spec.mSpec.parID << ", \""; s.write((const char*)&spec.mSpec.name[1], spec.mSpec.name[0]); return s << "\""; -} // nsOutputFileStream& operator << (nsOutputFileStream&, const nsNativeFileSpec&) +} // nsOutputStream& operator << (nsOutputStream&, const nsFileSpec&) +#endif //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::operator = (const char* inString) +void nsFileSpec::operator = (const char* inString) //---------------------------------------------------------------------------------------- { - mError = MacFileHelpers::FSSpecFromFullUnixPath(inString, mSpec, true); -} // nsNativeFileSpec::operator = + mError = NS_FILE_RESULT(MacFileHelpers::FSSpecFromFullUnixPath(inString, mSpec, false)); +} // nsFileSpec::operator = //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::operator = (const nsNativeFileSpec& inSpec) +void nsFileSpec::operator = (const nsFileSpec& inSpec) //---------------------------------------------------------------------------------------- { mSpec = inSpec.mSpec; mError = inSpec.Error(); -} // nsNativeFileSpec::operator = +} // nsFileSpec::operator = //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::operator = (const nsFilePath& inPath) +void nsFileSpec::operator = (const nsFilePath& inPath) //---------------------------------------------------------------------------------------- { - *this = inPath.GetNativeSpec(); -} // nsNativeFileSpec::operator = + *this = inPath.GetFileSpec(); +} // nsFileSpec::operator = //---------------------------------------------------------------------------------------- -bool nsNativeFileSpec::Exists() const +PRBool nsFileSpec::Exists() const //---------------------------------------------------------------------------------------- { FSSpec temp; return ::FSMakeFSSpec(mSpec.vRefNum, mSpec.parID, mSpec.name, &temp) == noErr; -} // nsNativeFileSpec::operator = +} // nsFileSpec::operator = //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::SetLeafName(const char* inLeafName) +void nsFileSpec::SetLeafName(const char* inLeafName) // In leaf name can actually be a partial path... //---------------------------------------------------------------------------------------- { // what about long relative paths? Hmm? Str255 partialPath; MacFileHelpers::PLstrcpy(partialPath, inLeafName); - mError = FSMakeFSSpec(mSpec.vRefNum, mSpec.parID, partialPath, &mSpec); -} // nsNativeFileSpec::SetLeafName + mError = NS_FILE_RESULT( + ::FSMakeFSSpec(mSpec.vRefNum, mSpec.parID, partialPath, &mSpec)); +} // nsFileSpec::SetLeafName //---------------------------------------------------------------------------------------- -char* nsNativeFileSpec::GetLeafName() const +char* nsFileSpec::GetLeafName() const // Result needs to be delete[]ed. //---------------------------------------------------------------------------------------- { @@ -608,133 +612,206 @@ char* nsNativeFileSpec::GetLeafName() const memcpy(leaf, &mSpec.name[1], mSpec.name[0]); leaf[mSpec.name[0]] = '\0'; return nsFileSpecHelpers::StringDup(leaf); -} // nsNativeFileSpec::GetLeafName +} // nsFileSpec::GetLeafName //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::MakeAliasSafe() +void nsFileSpec::MakeAliasSafe() //---------------------------------------------------------------------------------------- { - mError = MacFileHelpers::MakeAliasSafe(mSpec); -} // nsNativeFileSpec::MakeAliasSafe + mError = NS_FILE_RESULT(MacFileHelpers::MakeAliasSafe(mSpec)); +} // nsFileSpec::MakeAliasSafe //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::MakeUnique(ConstStr255Param inSuggestedLeafName) +void nsFileSpec::MakeUnique(ConstStr255Param inSuggestedLeafName) //---------------------------------------------------------------------------------------- { if (inSuggestedLeafName[0] > 0) MacFileHelpers::PLstrcpy(mSpec.name, inSuggestedLeafName); MakeUnique(); -} // nsNativeFileSpec::MakeUnique +} // nsFileSpec::MakeUnique //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::ResolveAlias(bool& wasAliased) +void nsFileSpec::ResolveAlias(PRBool& wasAliased) //---------------------------------------------------------------------------------------- { Boolean wasAliased2; - mError = MacFileHelpers::ResolveAliasFile(mSpec, wasAliased2); + mError = NS_FILE_RESULT(MacFileHelpers::ResolveAliasFile(mSpec, wasAliased2)); wasAliased = (wasAliased2 != false); -} // nsNativeFileSpec::ResolveAlias +} // nsFileSpec::ResolveAlias //---------------------------------------------------------------------------------------- -bool nsNativeFileSpec::IsFile() const +PRBool nsFileSpec::IsFile() const //---------------------------------------------------------------------------------------- { long dirID; Boolean isDirectory; return (noErr == FSpGetDirectoryID(&mSpec, &dirID, &isDirectory) && !isDirectory); -} // nsNativeFileSpec::IsFile +} // nsFileSpec::IsFile //---------------------------------------------------------------------------------------- -bool nsNativeFileSpec::IsDirectory() const +PRBool nsFileSpec::IsDirectory() const //---------------------------------------------------------------------------------------- { long dirID; Boolean isDirectory; return (noErr == FSpGetDirectoryID(&mSpec, &dirID, &isDirectory) && isDirectory); -} // nsNativeFileSpec::IsDirectory +} // nsFileSpec::IsDirectory //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::GetParent(nsNativeFileSpec& outSpec) const +void nsFileSpec::GetParent(nsFileSpec& outSpec) const //---------------------------------------------------------------------------------------- { - if (mError == noErr) - outSpec.mError = FSMakeFSSpec(mSpec.vRefNum, mSpec.parID, NULL, outSpec); -} // nsNativeFileSpec::GetParent + if (NS_SUCCEEDED(mError)) + outSpec.mError + = NS_FILE_RESULT(::FSMakeFSSpec(mSpec.vRefNum, mSpec.parID, nsnull, outSpec)); +} // nsFileSpec::GetParent //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::operator += (const char* inRelativePath) +void nsFileSpec::operator += (const char* inRelativePath) //---------------------------------------------------------------------------------------- { long dirID; Boolean isDirectory; - mError = FSpGetDirectoryID(&mSpec, &dirID, &isDirectory); - if (mError == noErr && isDirectory) + mError = NS_FILE_RESULT(::FSpGetDirectoryID(&mSpec, &dirID, &isDirectory)); + if (NS_SUCCEEDED(mError) && isDirectory) { Str255 partialPath; MacFileHelpers::PLstrcpy(partialPath, inRelativePath); - mError = FSMakeFSSpec(mSpec.vRefNum, dirID, partialPath, *this); - //if (mError == noErr) + mError = NS_FILE_RESULT(::FSMakeFSSpec(mSpec.vRefNum, dirID, partialPath, *this)); + //if (NS_SUCCEEDED(mError)) // SetLeafName(inRelativePath); } -} // nsNativeFileSpec::operator += +} // nsFileSpec::operator += //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::CreateDirectory(int /* unix mode */) +void nsFileSpec::CreateDirectory(int /* unix mode */) //---------------------------------------------------------------------------------------- { long ignoredDirID; FSpDirCreate(&mSpec, smCurrentScript, &ignoredDirID); -} // nsNativeFileSpec::CreateDirectory +} // nsFileSpec::CreateDirectory //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::Delete(bool inRecursive) +void nsFileSpec::Delete(PRBool inRecursive) //---------------------------------------------------------------------------------------- { if (inRecursive) { // MoreFilesExtras - mError = DeleteDirectory( + mError = NS_FILE_RESULT(::DeleteDirectory( mSpec.vRefNum, mSpec.parID, - const_cast(mSpec.name)); + const_cast(mSpec.name))); } else - mError = FSpDelete(&mSpec); -} // nsNativeFileSpec::Delete + mError = NS_FILE_RESULT(FSpDelete(&mSpec)); +} // nsFileSpec::Delete +//---------------------------------------------------------------------------------------- +nsresult nsFileSpec::Rename(const char* inNewName) +//---------------------------------------------------------------------------------------- +{ + if (strchr(inNewName, '/')) + return -1; // no relative paths here! + Str255 pName; + MacFileHelpers::PLstrcpy(pName, inNewName); + if (FSpRename(&mSpec, pName) != noErr) + return -1; + SetLeafName(inNewName); + return 0; +} // nsFileSpec::Rename + +//---------------------------------------------------------------------------------------- +nsresult nsFileSpec::Copy(const nsFileSpec& newParentDir) const +//---------------------------------------------------------------------------------------- +{ + // We can only copy into a directory, and (for now) can not copy entire directories + + if (!newParentDir.IsDirectory() || (IsDirectory() ) ) + return NS_FILE_FAILURE; + + + nsresult result = NS_FILE_RESULT(::FSpFileCopy( &mSpec, + &newParentDir.mSpec, + const_cast(GetLeafPName()), + nsnull, + 0, + true)); + + return result; + +} // nsFileSpec::Copy + +//---------------------------------------------------------------------------------------- +nsresult nsFileSpec::Move(const nsFileSpec& newParentDir) const +//---------------------------------------------------------------------------------------- +{ + // We can only move into a directory + + if (!newParentDir.IsDirectory()) + return NS_FILE_FAILURE; + + nsresult result = NS_FILE_RESULT(::FSpMoveRenameCompat(&mSpec, + &newParentDir.mSpec, + const_cast(GetLeafPName()))); + + return result; +} // nsFileSpec::Move + +//---------------------------------------------------------------------------------------- +nsresult nsFileSpec::Execute(const char* /*args - how can this be cross-platform? problem! */ ) const +//---------------------------------------------------------------------------------------- +{ + if (IsDirectory()) + return NS_FILE_FAILURE; + + LaunchParamBlockRec launchThis; + launchThis.launchAppSpec = const_cast(&mSpec); + launchThis.launchAppParameters = nsnull; // args; + /* launch the thing */ + launchThis.launchBlockID = extendedBlock; + launchThis.launchEPBLength = extendedBlockLen; + launchThis.launchFileFlags = nsnull; + launchThis.launchControlFlags = launchContinue + launchNoFileFlags + launchUseMinimum; + launchThis.launchControlFlags += launchDontSwitch; + + nsresult result = NS_FILE_RESULT(::LaunchApplication(&launchThis)); + return result; + +} // nsFileSpec::Execute //======================================================================================== // Macintosh nsFilePath implementation //======================================================================================== //---------------------------------------------------------------------------------------- -nsFilePath::nsFilePath(const char* inString, bool inCreateDirs) +nsFilePath::nsFilePath(const char* inString, PRBool inCreateDirs) //---------------------------------------------------------------------------------------- : mPath(nsnull) -, mNativeFileSpec(inString, inCreateDirs) +, mFileSpec(inString, inCreateDirs) { // Make canonical and absolute. - char * path = MacFileHelpers::PathNameFromFSSpec( mNativeFileSpec, TRUE ); + char * path = MacFileHelpers::PathNameFromFSSpec( mFileSpec, TRUE ); mPath = MacFileHelpers::EncodeMacPath(path, true, true); } //---------------------------------------------------------------------------------------- -nsFilePath::nsFilePath(const nsNativeFileSpec& inSpec) +nsFilePath::nsFilePath(const nsFileSpec& inSpec) //---------------------------------------------------------------------------------------- -: mNativeFileSpec(inSpec) +: mFileSpec(inSpec) { char * path = MacFileHelpers::PathNameFromFSSpec( inSpec.mSpec, TRUE ); mPath = MacFileHelpers::EncodeMacPath(path, true, true); } //---------------------------------------------------------------------------------------- -void nsFilePath::operator = (const nsNativeFileSpec& inSpec) +void nsFilePath::operator = (const nsFileSpec& inSpec) //---------------------------------------------------------------------------------------- { delete [] mPath; char * path = MacFileHelpers::PathNameFromFSSpec( inSpec.mSpec, TRUE ); mPath = MacFileHelpers::EncodeMacPath(path, true, true); - mNativeFileSpec = inSpec; + mFileSpec = inSpec; } // nsFilePath::operator = //======================================================================================== @@ -742,14 +819,14 @@ void nsFilePath::operator = (const nsNativeFileSpec& inSpec) //======================================================================================== //---------------------------------------------------------------------------------------- -nsFileURL::nsFileURL(const char* inString, bool inCreateDirs) +nsFileURL::nsFileURL(const char* inString, PRBool inCreateDirs) //---------------------------------------------------------------------------------------- : mURL(nsnull) -, mNativeFileSpec(inString + kFileURLPrefixLength, inCreateDirs) +, mFileSpec(inString + kFileURLPrefixLength, inCreateDirs) { NS_ASSERTION(strstr(inString, kFileURLPrefix) == inString, "Not a URL!"); // Make canonical and absolute. - char* path = MacFileHelpers::PathNameFromFSSpec( mNativeFileSpec, TRUE ); + char* path = MacFileHelpers::PathNameFromFSSpec( mFileSpec, TRUE ); char* escapedPath = MacFileHelpers::EncodeMacPath(path, true, true); mURL = nsFileSpecHelpers::StringDup(kFileURLPrefix, kFileURLPrefixLength + strlen(escapedPath)); strcat(mURL, escapedPath); @@ -762,7 +839,7 @@ nsFileURL::nsFileURL(const char* inString, bool inCreateDirs) //---------------------------------------------------------------------------------------- nsDirectoryIterator::nsDirectoryIterator( - const nsNativeFileSpec& inDirectory + const nsFileSpec& inDirectory , int inIterateDirection) //---------------------------------------------------------------------------------------- : mCurrent(inDirectory) @@ -772,7 +849,7 @@ nsDirectoryIterator::nsDirectoryIterator( CInfoPBRec pb; DirInfo* dipb = (DirInfo*)&pb; // Sorry about this, there seems to be a bug in CWPro 4: - const FSSpec& inSpec = inDirectory.nsNativeFileSpec::operator const FSSpec&(); + const FSSpec& inSpec = inDirectory.nsFileSpec::operator const FSSpec&(); Str255 outName; MacFileHelpers::PLstrcpy(outName, inSpec.name); pb.hFileInfo.ioNamePtr = outName; @@ -786,7 +863,7 @@ nsDirectoryIterator::nsDirectoryIterator( if ( (err != noErr ) || !( dipb->ioFlAttrib & 0x0010 ) ) return; // Sorry about this, there seems to be a bug in CWPro 4: - FSSpec& currentSpec = mCurrent.nsNativeFileSpec::operator FSSpec&(); + FSSpec& currentSpec = mCurrent.nsFileSpec::operator FSSpec&(); currentSpec.vRefNum = inSpec.vRefNum; currentSpec.parID = dipb->ioDrDirID; mMaxIndex = pb.dirInfo.ioDrNmFls; @@ -809,10 +886,10 @@ OSErr nsDirectoryIterator::SetToIndex() CInfoPBRec cipb; DirInfo *dipb=(DirInfo *)&cipb; Str255 objectName; - dipb->ioCompletion = NULL; + dipb->ioCompletion = nsnull; dipb->ioFDirIndex = mIndex; // Sorry about this, there seems to be a bug in CWPro 4: - FSSpec& currentSpec = mCurrent.nsNativeFileSpec::operator FSSpec&(); + FSSpec& currentSpec = mCurrent.nsFileSpec::operator FSSpec&(); dipb->ioVRefNum = currentSpec.vRefNum; /* Might need to use vRefNum, not sure*/ dipb->ioDrDirID = currentSpec.parID; dipb->ioNamePtr = objectName; diff --git a/mozilla/xpcom/io/nsFileSpecUnix.cpp b/mozilla/xpcom/io/nsFileSpecUnix.cpp index d0e058dccbe..5fbeeb98107 100644 --- a/mozilla/xpcom/io/nsFileSpecUnix.cpp +++ b/mozilla/xpcom/io/nsFileSpecUnix.cpp @@ -25,9 +25,10 @@ #include #include #include +#include "nsError.h" //---------------------------------------------------------------------------------------- -void nsFileSpecHelpers::Canonify(char*& ioPath, bool inMakeDirs) +void nsFileSpecHelpers::Canonify(char*& ioPath, PRBool inMakeDirs) // Canonify, make absolute, and check whether directories exist //---------------------------------------------------------------------------------------- { @@ -76,75 +77,78 @@ void nsFileSpecHelpers::Canonify(char*& ioPath, bool inMakeDirs) } // nsFileSpecHelpers::Canonify //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::SetLeafName(const char* inLeafName) +void nsFileSpec::SetLeafName(const char* inLeafName) //---------------------------------------------------------------------------------------- { nsFileSpecHelpers::LeafReplace(mPath, '/', inLeafName); -} // nsNativeFileSpec::SetLeafName +} // nsFileSpec::SetLeafName //---------------------------------------------------------------------------------------- -char* nsNativeFileSpec::GetLeafName() const +char* nsFileSpec::GetLeafName() const //---------------------------------------------------------------------------------------- { return nsFileSpecHelpers::GetLeaf(mPath, '/'); -} // nsNativeFileSpec::GetLeafName +} // nsFileSpec::GetLeafName //---------------------------------------------------------------------------------------- -bool nsNativeFileSpec::Exists() const +PRBool nsFileSpec::Exists() const //---------------------------------------------------------------------------------------- { struct stat st; return 0 == stat(mPath, &st); -} // nsNativeFileSpec::Exists +} // nsFileSpec::Exists //---------------------------------------------------------------------------------------- -bool nsNativeFileSpec::IsFile() const +PRBool nsFileSpec::IsFile() const //---------------------------------------------------------------------------------------- { struct stat st; return 0 == stat(mPath, &st) && S_ISREG(st.st_mode); -} // nsNativeFileSpec::IsFile +} // nsFileSpec::IsFile //---------------------------------------------------------------------------------------- -bool nsNativeFileSpec::IsDirectory() const +PRBool nsFileSpec::IsDirectory() const //---------------------------------------------------------------------------------------- { struct stat st; return 0 == stat(mPath, &st) && S_ISDIR(st.st_mode); -} // nsNativeFileSpec::IsDirectory +} // nsFileSpec::IsDirectory //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::GetParent(nsNativeFileSpec& outSpec) const +void nsFileSpec::GetParent(nsFileSpec& outSpec) const //---------------------------------------------------------------------------------------- { nsFileSpecHelpers::StringAssign(outSpec.mPath, mPath); char* cp = strrchr(outSpec.mPath, '/'); if (cp) *cp = '\0'; -} // nsNativeFileSpec::GetParent +} // nsFileSpec::GetParent //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::operator += (const char* inRelativePath) +void nsFileSpec::operator += (const char* inRelativePath) //---------------------------------------------------------------------------------------- { if (!inRelativePath || !mPath) return; - if (mPath[strlen(mPath) - 1] != '/') - char* newPath = nsFileSpecHelpers::ReallocCat(mPath, "/"); + char endChar = mPath[strlen(mPath) - 1]; + if (endChar == '/') + nsFileSpecHelpers::ReallocCat(mPath, "x"); + else + nsFileSpecHelpers::ReallocCat(mPath, "/x"); SetLeafName(inRelativePath); -} // nsNativeFileSpec::operator += +} // nsFileSpec::operator += //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::CreateDirectory(int mode) +void nsFileSpec::CreateDirectory(int mode) //---------------------------------------------------------------------------------------- { // Note that mPath is canonical! mkdir(mPath, mode); -} // nsNativeFileSpec::CreateDirectory +} // nsFileSpec::CreateDirectory //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::Delete(bool inRecursive) +void nsFileSpec::Delete(PRBool inRecursive) // To check if this worked, call Exists() afterwards, see? //---------------------------------------------------------------------------------------- { @@ -152,9 +156,9 @@ void nsNativeFileSpec::Delete(bool inRecursive) { if (inRecursive) { - for (nsDirectoryIterator i(*this); i; i++) + for (nsDirectoryIterator i(*this); i.Exists(); i++) { - nsNativeFileSpec& child = (nsNativeFileSpec&)i; + nsFileSpec& child = (nsFileSpec&)i; child.Delete(inRecursive); } } @@ -162,7 +166,148 @@ void nsNativeFileSpec::Delete(bool inRecursive) } else remove(mPath); -} // nsNativeFileSpec::Delete +} // nsFileSpec::Delete + + + +//---------------------------------------------------------------------------------------- +nsresult nsFileSpec::Rename(const char* inNewName) +//---------------------------------------------------------------------------------------- +{ + // This function should not be used to move a file on disk. + if (strchr(inNewName, '/')) + return NS_FILE_FAILURE; + + if (PR_Rename(mPath, inNewName) != 0) + { + return NS_FILE_FAILURE; + } + SetLeafName(inNewName); + return NS_OK; +} // nsFileSpec::Rename + +static int CrudeFileCopy(const char* in, const char* out) +{ + struct stat in_stat; + int stat_result = -1; + + char buf [1024]; + FILE *ifp, *ofp; + int rbytes, wbytes; + + if (!in || !out) + return -1; + + stat_result = stat (in, &in_stat); + + ifp = fopen (in, "r"); + if (!ifp) + { + return -1; + } + + ofp = fopen (out, "w"); + if (!ofp) + { + fclose (ifp); + return -1; + } + + while ((rbytes = fread (buf, 1, sizeof(buf), ifp)) > 0) + { + while (rbytes > 0) + { + if ( (wbytes = fwrite (buf, 1, rbytes, ofp)) < 0 ) + { + fclose (ofp); + fclose (ifp); + unlink(out); + return -1; + } + rbytes -= wbytes; + } + } + fclose (ofp); + fclose (ifp); + + if (stat_result == 0) + { + chmod (out, in_stat.st_mode & 0777); + } + + return 0; +} // nsFileSpec::Rename + +//---------------------------------------------------------------------------------------- +nsresult nsFileSpec::Copy(const nsFileSpec& inParentDirectory) const +//---------------------------------------------------------------------------------------- +{ + // We can only copy into a directory, and (for now) can not copy entire directories + nsresult result = NS_FILE_FAILURE; + + if (inParentDirectory.IsDirectory() && (! IsDirectory() ) ) + { + char *leafname = GetLeafName(); + char* destPath = nsFileSpecHelpers::StringDup(inParentDirectory, ( strlen(inParentDirectory) + 1 + strlen(leafname) ) ); + strcat(destPath, "/"); + strcat(destPath, leafname); + delete [] leafname; + + result = NS_FILE_RESULT(CrudeFileCopy(*this, destPath)); + + delete [] destPath; + } + return result; +} // nsFileSpec::Copy + +//---------------------------------------------------------------------------------------- +nsresult nsFileSpec::Move(const nsFileSpec& inNewParentDirectory) const +//---------------------------------------------------------------------------------------- +{ + // We can only copy into a directory, and (for now) can not copy entire directories + nsresult result = NS_FILE_FAILURE; + + if (inNewParentDirectory.IsDirectory() && (! IsDirectory() ) ) + { + char *leafname = GetLeafName(); + char* destPath + = nsFileSpecHelpers::StringDup( + inNewParentDirectory, + strlen(inNewParentDirectory) + 1 + strlen(leafname)); + strcat(destPath, "/"); + strcat(destPath, leafname); + delete [] leafname; + + result = NS_FILE_RESULT(CrudeFileCopy(*this, destPath)); + if (result == NS_OK) + { + Delete(PR_FALSE); + } + delete [] destPath; + } + return result; +} + +//---------------------------------------------------------------------------------------- +nsresult nsFileSpec::Execute(const char* inArgs ) const +//---------------------------------------------------------------------------------------- +{ + nsresult result = NS_FILE_FAILURE; + + if (! IsDirectory()) + { + char* fileNameWithArgs + = nsFileSpecHelpers::StringDup(mPath, strlen(mPath) + 1 + strlen(inArgs)); + strcat(fileNameWithArgs, " "); + strcat(fileNameWithArgs, inArgs); + + result = NS_FILE_RESULT(system(fileNameWithArgs)); + delete [] fileNameWithArgs; + } + + return result; + +} // nsFileSpec::Execute //======================================================================================== // nsDirectoryIterator @@ -170,7 +315,7 @@ void nsNativeFileSpec::Delete(bool inRecursive) //---------------------------------------------------------------------------------------- nsDirectoryIterator::nsDirectoryIterator( - const nsNativeFileSpec& inDirectory + const nsFileSpec& inDirectory , int inIterateDirection) //---------------------------------------------------------------------------------------- : mCurrent(inDirectory) diff --git a/mozilla/xpcom/io/nsFileSpecWin.cpp b/mozilla/xpcom/io/nsFileSpecWin.cpp index 247d96a37e8..fb424c4616c 100644 --- a/mozilla/xpcom/io/nsFileSpecWin.cpp +++ b/mozilla/xpcom/io/nsFileSpecWin.cpp @@ -23,9 +23,18 @@ #include #include #include "prio.h" +#include "nsError.h" + +#include "windows.h" + +#ifdef UNICODE +#define CreateDirectoryW CreateDirectory +#else +#define CreateDirectoryA CreateDirectory +#endif //---------------------------------------------------------------------------------------- -void nsFileSpecHelpers::Canonify(char*& ioPath, bool inMakeDirs) +void nsFileSpecHelpers::Canonify(char*& ioPath, PRBool inMakeDirs) // Canonify, make absolute, and check whether directories exist. This // takes a (possibly relative) native path and converts it into a // fully qualified native path. @@ -125,7 +134,7 @@ void nsFileSpecHelpers::NativeToUnix(char*& ioPath) } //---------------------------------------------------------------------------------------- -nsNativeFileSpec::nsNativeFileSpec(const nsFilePath& inPath) +nsFileSpec::nsFileSpec(const nsFilePath& inPath) //---------------------------------------------------------------------------------------- : mPath(NULL) { @@ -133,15 +142,16 @@ nsNativeFileSpec::nsNativeFileSpec(const nsFilePath& inPath) } //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::operator = (const nsFilePath& inPath) +void nsFileSpec::operator = (const nsFilePath& inPath) //---------------------------------------------------------------------------------------- { nsFileSpecHelpers::StringAssign(mPath, (const char*)inPath); nsFileSpecHelpers::UnixToNative(mPath); -} // nsNativeFileSpec::operator = + mError = NS_OK; +} // nsFileSpec::operator = //---------------------------------------------------------------------------------------- -nsFilePath::nsFilePath(const nsNativeFileSpec& inSpec) +nsFilePath::nsFilePath(const nsFileSpec& inSpec) //---------------------------------------------------------------------------------------- : mPath(NULL) { @@ -149,7 +159,7 @@ nsFilePath::nsFilePath(const nsNativeFileSpec& inSpec) } // nsFilePath::nsFilePath //---------------------------------------------------------------------------------------- -void nsFilePath::operator = (const nsNativeFileSpec& inSpec) +void nsFilePath::operator = (const nsFileSpec& inSpec) //---------------------------------------------------------------------------------------- { nsFileSpecHelpers::StringAssign(mPath, inSpec.mPath); @@ -157,84 +167,86 @@ void nsFilePath::operator = (const nsNativeFileSpec& inSpec) } // nsFilePath::operator = //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::SetLeafName(const char* inLeafName) +void nsFileSpec::SetLeafName(const char* inLeafName) //---------------------------------------------------------------------------------------- { nsFileSpecHelpers::LeafReplace(mPath, '\\', inLeafName); -} // nsNativeFileSpec::SetLeafName +} // nsFileSpec::SetLeafName //---------------------------------------------------------------------------------------- -char* nsNativeFileSpec::GetLeafName() const +char* nsFileSpec::GetLeafName() const //---------------------------------------------------------------------------------------- { return nsFileSpecHelpers::GetLeaf(mPath, '\\'); -} // nsNativeFileSpec::GetLeafName +} // nsFileSpec::GetLeafName //---------------------------------------------------------------------------------------- -bool nsNativeFileSpec::Exists() const +PRBool nsFileSpec::Exists() const //---------------------------------------------------------------------------------------- { struct stat st; return 0 == stat(mPath, &st); -} // nsNativeFileSpec::Exists +} // nsFileSpec::Exists //---------------------------------------------------------------------------------------- -bool nsNativeFileSpec::IsFile() const +PRBool nsFileSpec::IsFile() const //---------------------------------------------------------------------------------------- { struct stat st; return 0 == stat(mPath, &st) && (_S_IFREG & st.st_mode); -} // nsNativeFileSpec::IsFile +} // nsFileSpec::IsFile //---------------------------------------------------------------------------------------- -bool nsNativeFileSpec::IsDirectory() const +PRBool nsFileSpec::IsDirectory() const //---------------------------------------------------------------------------------------- { struct stat st; return 0 == stat(mPath, &st) && (_S_IFDIR & st.st_mode); -} // nsNativeFileSpec::IsDirectory +} // nsFileSpec::IsDirectory //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::GetParent(nsNativeFileSpec& outSpec) const +void nsFileSpec::GetParent(nsFileSpec& outSpec) const //---------------------------------------------------------------------------------------- { nsFileSpecHelpers::StringAssign(outSpec.mPath, mPath); char* cp = strrchr(outSpec.mPath, '\\'); if (cp) *cp = '\0'; -} // nsNativeFileSpec::GetParent +} // nsFileSpec::GetParent //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::operator += (const char* inRelativePath) +void nsFileSpec::operator += (const char* inRelativePath) //---------------------------------------------------------------------------------------- { if (!inRelativePath || !mPath) return; - if (mPath[strlen(mPath) - 1] != '\\') - char* newPath = nsFileSpecHelpers::ReallocCat(mPath, "\\"); + if (mPath[strlen(mPath) - 1] == '\\') + nsFileSpecHelpers::ReallocCat(mPath, "x"); + else + nsFileSpecHelpers::ReallocCat(mPath, "\\x"); SetLeafName(inRelativePath); -} // nsNativeFileSpec::operator += +} // nsFileSpec::operator += //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::CreateDirectory(int /*mode*/) +void nsFileSpec::CreateDirectory(int /*mode*/) //---------------------------------------------------------------------------------------- { // Note that mPath is canonical! mkdir(mPath); -} // nsNativeFileSpec::CreateDirectory +} // nsFileSpec::CreateDirectory //---------------------------------------------------------------------------------------- -void nsNativeFileSpec::Delete(bool inRecursive) +void nsFileSpec::Delete(PRBool inRecursive) //---------------------------------------------------------------------------------------- { if (IsDirectory()) { if (inRecursive) { - for (nsDirectoryIterator i(*this); i; i++) + for (nsDirectoryIterator i(*this); i.Exists(); i++) { - nsNativeFileSpec& child = (nsNativeFileSpec&)i; + nsFileSpec& child = (nsFileSpec&)i; child.Delete(inRecursive); } } @@ -244,7 +256,106 @@ void nsNativeFileSpec::Delete(bool inRecursive) { remove(mPath); } -} // nsNativeFileSpec::Delete +} // nsFileSpec::Delete + + +//---------------------------------------------------------------------------------------- +nsresult nsFileSpec::Rename(const char* inNewName) +//---------------------------------------------------------------------------------------- +{ + // This function should not be used to move a file on disk. + if (strchr(inNewName, '/')) + return NS_FILE_FAILURE; + + if (PR_Rename(*this, inNewName) != NS_OK) + { + return NS_FILE_FAILURE; + } + SetLeafName(inNewName); + return NS_OK; +} // nsFileSpec::Rename + +//---------------------------------------------------------------------------------------- +nsresult nsFileSpec::Copy(const nsFileSpec& inParentDirectory) const +//---------------------------------------------------------------------------------------- +{ + // We can only copy into a directory, and (for now) can not copy entire directories + + if (inParentDirectory.IsDirectory() && (! IsDirectory() ) ) + { + char *leafname = GetLeafName(); + char* destPath = nsFileSpecHelpers::StringDup(inParentDirectory, ( strlen(inParentDirectory) + 1 + strlen(leafname) ) ); + strcat(destPath, "\\"); + strcat(destPath, leafname); + delete [] leafname; + + // CopyFile returns non-zero if succeeds + int copyOK = CopyFile(*this, destPath, true); + + delete[] destPath; + + if (copyOK) + { + return NS_OK; + } + } + + return NS_FILE_FAILURE; +} // nsFileSpec::Copy + +//---------------------------------------------------------------------------------------- +nsresult nsFileSpec::Move(const nsFileSpec& nsNewParentDirectory) const +//---------------------------------------------------------------------------------------- +{ + // We can only copy into a directory, and (for now) can not copy entire directories + + if (nsNewParentDirectory.IsDirectory() && (! IsDirectory() ) ) + { + char *leafname = GetLeafName(); + char *destPath = nsFileSpecHelpers::StringDup(nsNewParentDirectory, ( strlen(nsNewParentDirectory) + 1 + strlen(leafname) )); + strcat(destPath, "\\"); + strcat(destPath, leafname); + delete [] leafname; + + // MoveFile returns non-zero if succeeds + int copyOK = MoveFile(*this, destPath); + + delete [] destPath; + + if (copyOK) + { + return NS_OK; + } + } + + return NS_FILE_FAILURE; +} // nsFileSpec::Move + +//---------------------------------------------------------------------------------------- +nsresult nsFileSpec::Execute(const char* inArgs ) const +//---------------------------------------------------------------------------------------- +{ + + if (! IsDirectory()) + { + char* fileNameWithArgs = NULL; + + fileNameWithArgs = nsFileSpecHelpers::StringDup(mPath, ( strlen(mPath) + 1 + strlen(inArgs) ) ); + strcat(fileNameWithArgs, " "); + strcat(fileNameWithArgs, inArgs); + + int execResult = WinExec( fileNameWithArgs, SW_NORMAL ); + + delete [] fileNameWithArgs; + + if (execResult > 31) + { + return NS_OK; + } + } + + return NS_FILE_FAILURE; +} // nsFileSpec::Execute //======================================================================================== // nsDirectoryIterator @@ -252,7 +363,7 @@ void nsNativeFileSpec::Delete(bool inRecursive) //---------------------------------------------------------------------------------------- nsDirectoryIterator::nsDirectoryIterator( - const nsNativeFileSpec& inDirectory + const nsFileSpec& inDirectory , int inIterateDirection) //---------------------------------------------------------------------------------------- : mCurrent(inDirectory) diff --git a/mozilla/xpcom/io/nsFileStream.cpp b/mozilla/xpcom/io/nsFileStream.cpp index 50f2b780e85..2950894ec3b 100644 --- a/mozilla/xpcom/io/nsFileStream.cpp +++ b/mozilla/xpcom/io/nsFileStream.cpp @@ -22,332 +22,78 @@ #include "nsFileStream.h" + #include #include -#ifdef XP_MAC -#include -#endif //======================================================================================== -// nsBasicFileStream +// nsInputStream //======================================================================================== //---------------------------------------------------------------------------------------- -nsBasicFileStream::nsBasicFileStream() +nsInputStream::~nsInputStream() //---------------------------------------------------------------------------------------- - : mFileDesc(0) - , mNSPRMode(0) - , mFailed(false) - , mEOF(false) { + mInputStream->Close(); } //---------------------------------------------------------------------------------------- -nsBasicFileStream::nsBasicFileStream( - const nsFilePath& inFile, - int nsprMode, - PRIntn accessMode) +char nsInputStream::get() //---------------------------------------------------------------------------------------- - : mFileDesc(0) - , mNSPRMode(0) - , mFailed(false) - , mEOF(false) { - open(inFile, nsprMode, accessMode); + char c; + read(&c, sizeof(c)); + return c; } //---------------------------------------------------------------------------------------- -nsBasicFileStream::nsBasicFileStream(PRFileDesc* desc, int nsprMode) +static void TidyEndOfLine(char*& cp) +// Assumes that cp is pointing at \n or \r. Nulls out the character, checks for +// a second terminator (of the opposite persuasion), and returns cp pointing past the +// entire eol construct (one or two characters). //---------------------------------------------------------------------------------------- - : mFileDesc(desc) - , mNSPRMode(nsprMode) - , mFailed(false) - , mEOF(false) { + char ch = *cp; + *cp++ = '\0'; // terminate at the newline, then skip past it + if ((ch == '\n' && *cp == '\r') || (ch == '\r' && *cp == '\n')) + cp++; // possibly a pair. } //---------------------------------------------------------------------------------------- -nsBasicFileStream::~nsBasicFileStream() +nsInputStream& nsInputStream::operator >> (char& c) //---------------------------------------------------------------------------------------- { - close(); -} - -//---------------------------------------------------------------------------------------- -void nsBasicFileStream::open( - const nsFilePath& inFile, - int nsprMode, - PRIntn accessMode) -//---------------------------------------------------------------------------------------- -{ - if (mFileDesc) - return; - - const int nspr_modes[]={ - PR_WRONLY | PR_CREATE_FILE, - PR_WRONLY | PR_CREATE_FILE | PR_APPEND, - PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, - PR_RDONLY, - PR_RDONLY | PR_APPEND, - PR_RDWR | PR_CREATE_FILE, - PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE, -// "wb", -// "ab", -// "wb", -// "rb", -// "r+b", -// "w+b", - 0 }; - const int* currentLegalMode = nspr_modes; - while (*currentLegalMode && nsprMode != *currentLegalMode) - ++currentLegalMode; - if (!*currentLegalMode) - return; - -#ifdef XP_MAC - // Use the file spec to open the file, because one path can be common to - // several files on the Macintosh (you can have several volumes with the - // same name, see). - mFileDesc = 0; - if (inFile.GetNativeSpec().Error() != noErr) - return; - OSErr err = noErr; -#if DEBUG - const OSType kCreator = 'CWIE'; -#else - const OSType kCreator = 'MOSS'; -#endif - nsNativeFileSpec nativeSpec = inFile.GetNativeSpec(); - FSSpec* spec = (FSSpec*)nativeSpec; - if (nsprMode & PR_CREATE_FILE) - err = FSpCreate(spec, kCreator, 'TEXT', 0); - if (err == dupFNErr) - err = noErr; - if (err != noErr) - return; - - SInt8 perm; - if (nsprMode & PR_RDWR) - perm = fsRdWrPerm; - else if (nsprMode & PR_WRONLY) - perm = fsWrPerm; - else - perm = fsRdPerm; - - short refnum; - err = FSpOpenDF(spec, perm, &refnum); - - if (err == noErr && (nsprMode & PR_TRUNCATE)) - err = SetEOF(refnum, 0); - if (err == noErr && (nsprMode & PR_APPEND)) - err = SetFPos(refnum, fsFromLEOF, 0); - if (err != noErr) - return; - - if ((mFileDesc = PR_ImportFile(refnum)) == 0) - return; -#else - // Platforms other than Macintosh... - // Another bug in NSPR: Mac PR_Open assumes a unix style path, but Win PR_Open assumes - // a windows path. - if ((mFileDesc = PR_Open((const char*)nsNativeFileSpec(inFile), nsprMode, accessMode)) == 0) - return; -#endif - mNSPRMode = nsprMode; -} // nsFileStreamHelpers::open - -//---------------------------------------------------------------------------------------- -void nsBasicFileStream::close() -// Must precede the destructor because both are inline. -//---------------------------------------------------------------------------------------- -{ - if (mFileDesc==PR_STDIN || mFileDesc==PR_STDOUT || mFileDesc==PR_STDERR || mFileDesc == 0) - return; - if (PR_Close(mFileDesc) == PR_SUCCESS) - mFileDesc = 0; -} // nsBasicFileStream::close - -//---------------------------------------------------------------------------------------- -void nsBasicFileStream::seek(PRSeekWhence whence, PRInt32 offset) -// Must precede the destructor because both are inline. -//---------------------------------------------------------------------------------------- -{ - if (mFileDesc==PR_STDIN || mFileDesc==PR_STDOUT || mFileDesc==PR_STDERR || mFileDesc == 0) - return; - mFailed = false; // reset on a seek. - mEOF = false; // reset on a seek. - PRInt32 position = PR_Seek(mFileDesc, 0, PR_SEEK_CUR); - PRInt32 available = PR_Available(mFileDesc); - PRInt32 fileSize = position + available; - PRInt32 newPosition; - switch (whence) - { - case PR_SEEK_CUR: newPosition = position + offset; break; - case PR_SEEK_SET: newPosition = offset; break; - case PR_SEEK_END: newPosition = fileSize + offset; break; - } - if (newPosition < 0) - { - newPosition = 0; - mFailed = true; - } - else if (newPosition >= fileSize) - { - newPosition = fileSize; - mEOF = true; - } - if (PR_Seek(mFileDesc, newPosition, PR_SEEK_SET) < 0) - mFailed = true; -} // nsBasicFileStream::seek - -//---------------------------------------------------------------------------------------- -PRIntn nsBasicFileStream::tell() const -// Must precede the destructor because both are inline. -//---------------------------------------------------------------------------------------- -{ - if (mFileDesc==PR_STDIN || mFileDesc==PR_STDOUT || mFileDesc==PR_STDERR || mFileDesc == 0) - return -1; - return PR_Seek(mFileDesc, 0, PR_SEEK_CUR); -} // nsBasicFileStream::tell - -//======================================================================================== -// nsBasicInStream -//======================================================================================== - -//---------------------------------------------------------------------------------------- -nsBasicInStream::nsBasicInStream(nsBasicFileStream& inBasicStream, istream* inStream) -//---------------------------------------------------------------------------------------- - : mBase(inBasicStream) - , mStdStream(inStream) -{ -} -//---------------------------------------------------------------------------------------- -void nsBasicInStream::get(char& c) -//---------------------------------------------------------------------------------------- -{ - read(&c, sizeof(char)); -} - -//---------------------------------------------------------------------------------------- -PRBool nsBasicInStream::readline(char* s, PRInt32 n) -// This will truncate if the buffer is too small. Result will always be null-terminated. -//---------------------------------------------------------------------------------------- -{ - PRBool bufferLargeEnough = true; // result - if (!s || !n) - return true; - PRIntn position = mBase.tell(); - if (position < 0) - return false; - PRInt32 bytesRead = read(s, n - 1); - if (mBase.failed()) - return false; - s[bytesRead] = '\0'; // always terminate at the end of the buffer - char* tp = strpbrk(s, "\n\r"); - if (tp) - { - char ch = *tp; - *tp++ = '\0'; // terminate at the newline, then skip past it - if ((ch == '\n' && *tp == '\r') || (ch == '\r' && *tp == '\n')) - tp++; // possibly a pair. - bytesRead = (tp - s); - } - else if (!mBase.eof()) - bufferLargeEnough = false; - position += bytesRead; - mBase.seek(position); - return bufferLargeEnough; -} // nsBasicInStream::getline - -//---------------------------------------------------------------------------------------- -PRInt32 nsBasicInStream::read(void* s, PRInt32 n) -//---------------------------------------------------------------------------------------- -{ -#ifndef NS_USE_PR_STDIO - // Calling PR_Read on stdin is sure suicide on Macintosh. - if (GetStandardStream()) - { - GetStandardStream()->read((char*)s, n); - return n; - } -#endif - if (!mBase.is_open() || mBase.failed()) - return -1; - PRInt32 bytesRead = PR_Read(mBase.GetFileDescriptor(), s, n); - if (bytesRead < 0) - mBase.mFailed = true; - else if (bytesRead < n) - mBase.mEOF = true; - return bytesRead; -} - -//---------------------------------------------------------------------------------------- -nsBasicInStream& nsBasicInStream::operator >> (char& c) -//---------------------------------------------------------------------------------------- -{ - get(c); + c = get(); return *this; } //======================================================================================== -// nsInputFileStream +// nsOutputStream //======================================================================================== //---------------------------------------------------------------------------------------- -nsInputFileStream::nsInputFileStream(istream* stream) +nsOutputStream::~nsOutputStream() //---------------------------------------------------------------------------------------- -#ifndef NS_USE_PR_STDIO - : nsBasicFileStream(0, kDefaultMode) - , nsBasicInStream(*this, stream) -#else - : nsBasicFileStream(PR_STDIN, kDefaultMode) - , nsBasicInStream(*this, 0) -#endif -{ -} - -//======================================================================================== -// nsBasicOutStream -//======================================================================================== - -//---------------------------------------------------------------------------------------- -nsBasicOutStream::nsBasicOutStream(nsBasicFileStream& inBase, ostream* stream) -//---------------------------------------------------------------------------------------- - : mBase(inBase) - , mStdStream(stream) { + mOutputStream->Close(); } //---------------------------------------------------------------------------------------- -void nsBasicOutStream::put(char c) +void nsOutputStream::put(char c) //---------------------------------------------------------------------------------------- { write(&c, sizeof(c)); } //---------------------------------------------------------------------------------------- -PRInt32 nsBasicOutStream::write(const void* s, PRInt32 n) +void nsOutputStream::flush() //---------------------------------------------------------------------------------------- { -#ifndef NS_USE_PR_STDIO - // Calling PR_Write on stdout is sure suicide. - if (mStdStream) - { - mStdStream->write((const char*)s, n); - return n; - } -#endif - if (!mBase.mFileDesc || mBase.failed()) - return -1; - PRInt32 bytesWrit = PR_Write(mBase.mFileDesc, s, n); - if (bytesWrit != n) - mBase.mFailed = true; - return bytesWrit; } //---------------------------------------------------------------------------------------- -nsBasicOutStream& nsBasicOutStream::operator << (char c) +nsOutputStream& nsOutputStream::operator << (char c) //---------------------------------------------------------------------------------------- { put(c); @@ -355,7 +101,7 @@ nsBasicOutStream& nsBasicOutStream::operator << (char c) } //---------------------------------------------------------------------------------------- -nsBasicOutStream& nsBasicOutStream::operator << (const char* s) +nsOutputStream& nsOutputStream::operator << (const char* s) //---------------------------------------------------------------------------------------- { write(s, strlen(s)); @@ -363,78 +109,84 @@ nsBasicOutStream& nsBasicOutStream::operator << (const char* s) } //---------------------------------------------------------------------------------------- -nsBasicOutStream& nsBasicOutStream::operator << (short val) +nsOutputStream& nsOutputStream::operator << (short val) //---------------------------------------------------------------------------------------- { char buf[30]; sprintf(buf, "%d", val); - return *this << buf; + return (*this << buf); } //---------------------------------------------------------------------------------------- -nsBasicOutStream& nsBasicOutStream::operator << (unsigned short val) +nsOutputStream& nsOutputStream::operator << (unsigned short val) //---------------------------------------------------------------------------------------- { char buf[30]; sprintf(buf, "%ud", val); - return *this << buf; + return (*this << buf); } //---------------------------------------------------------------------------------------- -nsBasicOutStream& nsBasicOutStream::operator << (long val) +nsOutputStream& nsOutputStream::operator << (long val) //---------------------------------------------------------------------------------------- { char buf[30]; sprintf(buf, "%ld", val); - return *this << buf; + return (*this << buf); } //---------------------------------------------------------------------------------------- -nsBasicOutStream& nsBasicOutStream::operator << (unsigned long val) +nsOutputStream& nsOutputStream::operator << (unsigned long val) //---------------------------------------------------------------------------------------- { char buf[30]; sprintf(buf, "%uld", val); - return *this << buf; + return (*this << buf); } +//======================================================================================== +// nsInputFileStream +//======================================================================================== + //---------------------------------------------------------------------------------------- -void nsBasicOutStream::flush() -// Must precede the destructor because both are inline. +PRBool nsInputFileStream::readline(char* s, PRInt32 n) +// This will truncate if the buffer is too small. Result will always be null-terminated. //---------------------------------------------------------------------------------------- { -#ifndef NS_USE_PR_STDIO - if (mStdStream) + PRBool bufferLargeEnough = PR_TRUE; // result + if (!s || !n) + return PR_TRUE; + + PRIntn position = tell(); + if (position < 0) + return PR_FALSE; + PRInt32 bytesRead = read(s, n - 1); + if (failed()) + return PR_FALSE; + s[bytesRead] = '\0'; // always terminate at the end of the buffer + char* tp = strpbrk(s, "\n\r"); + if (tp) { - mStdStream->flush(); - return; + TidyEndOfLine(tp); + bytesRead = (tp - s); } -#endif - if (mBase.mFileDesc == 0) - return; - PRBool itFailed = PR_Sync(mBase.mFileDesc) != PR_SUCCESS; -#ifdef XP_MAC - // On unix, it seems to fail always. - if (itFailed) - mBase.mFailed = true; -#endif -} // nsBasicOutStream::flush + else if (!eof()) + bufferLargeEnough = PR_FALSE; + position += bytesRead; + seek(position); + return bufferLargeEnough; +} // nsInputStream::readline //======================================================================================== // nsOutputFileStream //======================================================================================== //---------------------------------------------------------------------------------------- -nsOutputFileStream::nsOutputFileStream(ostream* stream) +void nsOutputFileStream::flush() //---------------------------------------------------------------------------------------- -#ifndef NS_USE_PR_STDIO - : nsBasicFileStream(0, kDefaultMode) - , nsBasicOutStream(*this, stream) -#else - : nsBasicFileStream(PR_STDOUT, kDefaultMode) - , nsBasicOutStream(*this, 0) -#endif { + if (mFileOutputStream) + mFileOutputStream->Flush(); } //======================================================================================== @@ -442,19 +194,10 @@ nsOutputFileStream::nsOutputFileStream(ostream* stream) //======================================================================================== //---------------------------------------------------------------------------------------- -nsBasicOutStream& nsEndl(nsBasicOutStream& os) +nsOutputStream& nsEndl(nsOutputStream& os) //---------------------------------------------------------------------------------------- { -#ifndef NS_USE_PR_STDIO - // Calling PR_Write on stdout is sure suicide on Macintosh. - ostream* stream = os.GetStandardStream(); - if (stream) - { - *stream << std::endl; - return os; - } -#endif - os.put('\n'); - os.flush(); - return os; -} \ No newline at end of file + os.put('\n'); + os.flush(); + return os; +} // nsEndl \ No newline at end of file diff --git a/mozilla/xpcom/io/nsFileStream.h b/mozilla/xpcom/io/nsFileStream.h index f56f25f772d..823a4c73c72 100644 --- a/mozilla/xpcom/io/nsFileStream.h +++ b/mozilla/xpcom/io/nsFileStream.h @@ -19,14 +19,31 @@ // First checked in on 98/11/20 by John R. McMullen in the wrong directory. // Checked in again 98/12/04. // Polished version 98/12/08. +// Completely rewritten to integrate with nsIInputStream and nsIOutputStream (the +// xpcom stream objects. //======================================================================================== // // Classes defined: // -// single-byte char: -// +// nsInputStream, nsOutputStream +// These are the lightweight STATICALLY LINKED wrappers for +// the xpcom objects nsIInputStream and nsIOutputstream. +// Possible uses: +// If you are implementing a function that accepts one of these xpcom +// streams, just make one of these little jobbies on the stack, and +// the handy << or >> notation can be yours. +// // nsInputFileStream, nsOutputFileStream +// These are the STATICALLY LINKED versions of the file i/o streams, +// which wrap the NSPR file i/o plus console i/o. +// +// Related files: +// prio.h the NSPR file i/o C API), which is wrapped by +// THIS FILE statically linked C++ wrappers, which in turn are wrapped by +// nsIFileStream.h COM wrappers for this file, which are wrapped by +// nsAutoFileStream.h more easily used, nicer syntax wrappers for the +// COMified ones. Wrapper of a wrapper of a wrapper. // // This suite provide the following services: // @@ -41,13 +58,13 @@ // // Basic example: // -// nsFilePath myPath("/Development/iotest.txt"); +// nsFileSpec myPath("/Development/iotest.txt"); // // nsOutputFileStream testStream(myPath); // testStream << "Hello World" << nsEndl; // -// 4. Requires streams to be constructed using typesafe nsFilePath specifier -// (not the notorious and bug prone const char*), namely nsFilePath. See +// 4. Requires streams to be constructed using typesafe nsFileSpec specifier +// (not the notorious and bug prone const char*), namely nsFileSpec. See // nsFileSpec.h for more details. // // 5. Fixes a bug that have been there for a long time, and @@ -73,7 +90,13 @@ #else #include "prio.h" #endif -#include "nsFileSpec.h" + +#include "nsIFileStream.h" +#include "nsCOMPtr.h" + +class nsFileSpec; +class nsInputFileStream; +class nsOutputFileStream; //======================================================================================== // Compiler-specific macros, as needed @@ -133,201 +156,392 @@ using std::ostream; //=========================== End Compiler-specific macros =============================== //======================================================================================== -class NS_BASE nsBasicFileStream +class NS_BASE nsInputStream +// This is a convenience class, for use on the STACK ("new" junkies: get detoxed first). +// Given a COM-style stream, this allows you to use the >> operators. It also acquires and +// reference counts its stream. +// Please read the comments at the top of this file //======================================================================================== { public: - nsBasicFileStream(); - nsBasicFileStream(PRFileDesc* desc, int nsprMode); - nsBasicFileStream( - const nsFilePath& inFile, - int nsprMode, - PRIntn accessMode); - virtual ~nsBasicFileStream(); + nsInputStream(nsIInputStream* inStream) + : mInputStream(do_QueryInterface(inStream)) + , mEOF(PR_FALSE) + {} + virtual ~nsInputStream(); + + nsCOMPtr GetIStream() const + { + return mInputStream; + } + char eof() const { return mEOF; } + char get(); + PRInt32 read(void* s, PRInt32 n) + { + if (!mInputStream) + return 0; + PRInt32 result = 0; + mInputStream->Read((char*)s, 0, n, (PRUint32*)&result); + if (result < n) + mEOF = PR_TRUE; + return result; + } + // Input streamers. Add more as needed (int&, unsigned int& etc). (but you have to + // add delegators to the derived classes, too, because these operators don't inherit). + nsInputStream& operator >> (char& ch); - inline PRBool is_open() const { return mFileDesc != 0; } - void open( - const nsFilePath& inFile, - int nsprMode, - PRIntn accessMode); - void close(); - PRIntn tell() const; - void seek(PRInt32 offset) { seek(PR_SEEK_SET, offset); } - void seek(PRSeekWhence whence, PRInt32 offset); - PRBool eof() const { return mEOF; } - PRBool failed() const { return mFailed; } - // call PR_GetError() for details -protected: - - PRFileDesc* GetFileDescriptor() const { return mFileDesc; } - -protected: - - friend class nsBasicInStream; - friend class nsBasicOutStream; - - PRFileDesc* mFileDesc; - int mNSPRMode; - PRBool mFailed; - PRBool mEOF; -}; // class nsBasicFileStream - -//======================================================================================== -class NS_BASE nsBasicInStream -//======================================================================================== -{ -protected: - nsBasicInStream(nsBasicFileStream& inStream, istream* stream); - -public: - - nsBasicInStream& operator >> (nsBasicInStream& (*pf)(nsBasicInStream&)) + // Support manipulators + nsInputStream& operator >> (nsInputStream& (*pf)(nsInputStream&)) { return pf(*this); - } - void get(char& c); - PRInt32 read(void* s, PRInt32 n); + } +private: + + nsInputStream& operator >> (char* buf); // TOO DANGEROUS. DON'T DEFINE. + +// DATA +protected: + nsCOMPtr mInputStream; + PRBool mEOF; +}; // class nsInputStream + +typedef nsInputStream nsBasicInStream; // historic support for this name + +//======================================================================================== +class NS_BASE nsOutputStream +// This is a convenience class, for use on the STACK ("new" junkies, get detoxed first). +// Given a COM-style stream, this allows you to use the << operators. It also acquires and +// reference counts its stream. +// Please read the comments at the top of this file +//======================================================================================== +{ +public: + nsOutputStream() {} + nsOutputStream(nsIOutputStream* inStream) + : mOutputStream(do_QueryInterface(inStream)) + {} + + virtual ~nsOutputStream(); + + nsCOMPtr GetIStream() const + { + return mOutputStream; + } + void put(char c); + PRInt32 write(const void* s, PRInt32 n) + { + if (!mOutputStream) + return 0; + PRInt32 result = 0; + mOutputStream->Write((char*)s, 0, n, (PRUint32*)&result); + return result; + } + virtual void flush(); + + // Output streamers. Add more as needed (but you have to add delegators to the derived + // classes, too, because these operators don't inherit). + nsOutputStream& operator << (const char* buf); + nsOutputStream& operator << (char ch); + nsOutputStream& operator << (short val); + nsOutputStream& operator << (unsigned short val); + nsOutputStream& operator << (long val); + nsOutputStream& operator << (unsigned long val); + + // Support manipulators + nsOutputStream& operator << (nsOutputStream& (*pf)(nsOutputStream&)) + { + return pf(*this); + } + +// DATA +protected: + nsCOMPtr mOutputStream; +}; // class nsOutputStream + +typedef nsOutputStream nsBasicOutStream; // Historic support for this name + +//======================================================================================== +class NS_BASE nsFileClient +// Because COM does not allow us to write functions which return a boolean value etc, +// this class is here to take care of the tedious "declare variable then call with +// the address of the variable" chores. +//======================================================================================== +{ +public: + nsFileClient() // for delayed opening + : mResult(NS_OK) + { + } + nsFileClient(const nsCOMPtr& inFile) + : mFile(do_QueryInterface(inFile)) + , mResult(NS_OK) + { + } + + PRBool is_file() const + { + return mFile ? PR_TRUE : PR_FALSE; + } + void open( + const nsFileSpec& inFile, + int nsprMode, + PRIntn accessMode) + { + if (mFile) + mResult = mFile->Open(inFile, nsprMode, accessMode); + } + PRBool is_open() const + { + PRBool result = PR_FALSE; + if (mFile) + mFile->GetIsOpen(&result); + return result; + } + PRBool failed() const + { + return NS_FAILED(mResult); + } + void seek(PRInt32 offset) + { + seek(PR_SEEK_SET, offset); + } + + void seek(PRSeekWhence whence, PRInt32 offset) + { + if (mFile) + mResult = mFile->Seek(whence, offset); + } + PRIntn tell() + { + PRIntn result = -1; + if (mFile) + mResult = mFile->Tell(&result); + return result; + } + +// DATA +protected: + nsCOMPtr mFile; + PRBool mResult; +}; // class nsFileClient + +//======================================================================================== +class NS_BASE nsInputFileStream +// Please read the comments at the top of this file +//======================================================================================== +: public nsInputStream +, public nsFileClient +{ +public: + enum { kDefaultMode = PR_RDONLY }; + nsInputFileStream(nsIInputStream* inStream) + : nsInputStream(inStream) + , nsFileClient(do_QueryInterface(inStream)) + , mFileInputStream(do_QueryInterface(inStream)) + { + } + nsInputFileStream( + const nsFileSpec& inFile, + int nsprMode = kDefaultMode, + PRIntn accessMode = 00700) // <- OCTAL + : nsInputStream(nsnull) + { + nsISupports* stream; + NS_NewIOFileStream( + &stream, + inFile, nsprMode, accessMode); + mFile = nsQueryInterface(stream); + mInputStream = nsQueryInterface(stream); + mFileInputStream = nsQueryInterface(stream); + } + PRBool readline(char* s, PRInt32 n); // Result always null-terminated. // Check eof() before each call. // CAUTION: false result only indicates line was truncated // to fit buffer, or an error occurred (OTHER THAN eof). - // Input streamers. Add more as needed - nsBasicInStream& operator >> (char& ch); - - istream* GetStandardStream() const { return mStdStream; } - -protected: - - nsBasicFileStream& mBase; - istream* mStdStream; -}; // class nsBasicInStream - -//======================================================================================== -class NS_BASE nsBasicOutStream -//======================================================================================== -{ -protected: - - nsBasicOutStream(nsBasicFileStream& inStream, ostream* stream); - -public: - - nsBasicOutStream& operator << (nsBasicOutStream& (*pf)(nsBasicOutStream&)) - { - return pf(*this); - } - void put(char c); - PRInt32 write(const void* s, PRInt32 n); - void flush(); - - // Output streamers. Add more as needed - nsBasicOutStream& operator << (const char* buf); - nsBasicOutStream& operator << (char ch); - nsBasicOutStream& operator << (short val); - nsBasicOutStream& operator << (unsigned short val); - nsBasicOutStream& operator << (long val); - nsBasicOutStream& operator << (unsigned long val); - - ostream* GetStandardStream() const { return mStdStream; } - -protected: - - nsBasicFileStream& mBase; - ostream* mStdStream; -}; // class nsBasicOutStream - -//======================================================================================== -class NS_BASE nsInputFileStream -//======================================================================================== -: public nsBasicFileStream -, public nsBasicInStream -{ -public: - enum { kDefaultMode = PR_RDONLY }; - nsInputFileStream(istream* stream = CONSOLE_IN); - nsInputFileStream( - const nsFilePath& inFile, - int nsprMode = kDefaultMode, - PRIntn accessMode = 00700) // <- OCTAL - : nsBasicFileStream(inFile, nsprMode, accessMode) - , nsBasicInStream(*this, 0) - {} - - void open( - const nsFilePath& inFile, + void Open( + const nsFileSpec& inFile, int nsprMode = kDefaultMode, PRIntn accessMode = 00700) // <- OCTAL { - nsBasicFileStream::open(inFile, nsprMode, accessMode); + if (mFile) + mFile->Open(inFile, nsprMode, accessMode); } -private: - nsInputFileStream& operator >> (char* buf); // TOO DANGEROUS. DON'T DEFINE. + // Input streamers. Unfortunately, they don't inherit! + nsInputStream& operator >> (char& ch) + { return nsInputStream::operator >>(ch); } + nsInputStream& operator >> (nsInputStream& (*pf)(nsInputStream&)) + { return nsInputStream::operator >>(pf); } +// DATA +protected: + nsCOMPtr mFileInputStream; }; // class nsInputFileStream //======================================================================================== class NS_BASE nsOutputFileStream +// Please read the comments at the top of this file //======================================================================================== -: public nsBasicFileStream -, public nsBasicOutStream +: public nsOutputStream +, public nsFileClient { public: enum { kDefaultMode = (PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE) }; - nsOutputFileStream(ostream* stream = CONSOLE_OUT); + nsOutputFileStream() {} + nsOutputFileStream(nsIOutputStream* inStream) + : nsOutputStream(inStream) + , nsFileClient(do_QueryInterface(inStream)) + , mFileOutputStream(do_QueryInterface(inStream)) + { + } nsOutputFileStream( - const nsFilePath& inFile, + const nsFileSpec& inFile, int nsprMode = kDefaultMode, PRIntn accessMode = 00700) // <- OCTAL - : nsBasicFileStream(inFile, nsprMode, accessMode) - , nsBasicOutStream(*this, 0) - {} - - inline void open( - const nsFilePath& inFile, - int nsprMode = kDefaultMode, - PRIntn accessMode = 00700) // <- OCTAL + : nsOutputStream(nsnull) { - nsBasicFileStream::open(inFile, nsprMode, accessMode); + nsISupports* stream; + if (NS_FAILED(NS_NewIOFileStream( + &stream, + inFile, nsprMode, accessMode))) + return; + mFile = nsQueryInterface(stream); + mOutputStream = nsQueryInterface(stream); + mFileOutputStream = nsQueryInterface(stream); } + + virtual void flush(); + + // Output streamers. Unfortunately, they don't inherit! + nsOutputStream& operator << (const char* buf) + { return nsOutputStream::operator << (buf); } + nsOutputStream& operator << (char ch) + { return nsOutputStream::operator << (ch); } + nsOutputStream& operator << (short val) + { return nsOutputStream::operator << (val); } + nsOutputStream& operator << (unsigned short val) + { return nsOutputStream::operator << (val); } + nsOutputStream& operator << (long val) + { return nsOutputStream::operator << (val); } + nsOutputStream& operator << (unsigned long val) + { return nsOutputStream::operator << (val); } + nsOutputStream& operator << (nsOutputStream& (*pf)(nsOutputStream&)) + { return nsOutputStream::operator << (pf); } + +// DATA +protected: + nsCOMPtr mFileOutputStream; }; // class nsOutputFileStream //======================================================================================== -class NS_BASE nsIOFileStream +class NS_BASE nsOutputConsoleStream +// Please read the comments at the top of this file //======================================================================================== -: public nsBasicFileStream -, public nsBasicOutStream -, public nsBasicInStream +: public nsOutputFileStream +{ +public: + + nsOutputConsoleStream() + { + nsISupports* stream; + if (NS_FAILED(NS_NewOutputConsoleStream(&stream))) + return; + mFile = nsQueryInterface(stream); + mOutputStream = nsQueryInterface(stream); + mFileOutputStream = nsQueryInterface(stream); + } + + // Output streamers. Unfortunately, they don't inherit! + nsOutputStream& operator << (const char* buf) + { return nsOutputStream::operator << (buf); } + nsOutputStream& operator << (char ch) + { return nsOutputStream::operator << (ch); } + nsOutputStream& operator << (short val) + { return nsOutputStream::operator << (val); } + nsOutputStream& operator << (unsigned short val) + { return nsOutputStream::operator << (val); } + nsOutputStream& operator << (long val) + { return nsOutputStream::operator << (val); } + nsOutputStream& operator << (unsigned long val) + { return nsOutputStream::operator << (val); } + nsOutputStream& operator << (nsOutputStream& (*pf)(nsOutputStream&)) + { return nsOutputStream::operator << (pf); } + +}; // class nsOutputConsoleStream + +//======================================================================================== +class NS_BASE nsIOFileStream +// Please read the comments at the top of this file +//======================================================================================== +: public nsInputFileStream +, public nsOutputStream { public: enum { kDefaultMode = (PR_RDWR | PR_CREATE_FILE) }; nsIOFileStream( - const nsFilePath& inFile, + nsIInputStream* inInputStream + , nsIOutputStream* inOutputStream) + : nsInputFileStream(inInputStream) + , nsOutputStream(inOutputStream) + , mFileOutputStream(do_QueryInterface(inOutputStream)) + { + } + nsIOFileStream( + const nsFileSpec& inFile, int nsprMode = kDefaultMode, PRIntn accessMode = 00700) // <- OCTAL - : nsBasicFileStream(inFile, nsprMode, accessMode) - , nsBasicInStream(*this, 0) - , nsBasicOutStream(*this, 0) - {} - - inline void open( - const nsFilePath& inFile, - int nsprMode = kDefaultMode, - PRIntn accessMode = 00700) // <- OCTAL + : nsInputFileStream(nsnull) + , nsOutputStream(nsnull) { - nsBasicFileStream::open(inFile, nsprMode, accessMode); + nsISupports* stream; + if (NS_FAILED(NS_NewIOFileStream( + &stream, + inFile, nsprMode, accessMode))) + return; + mFile = nsQueryInterface(stream); + mInputStream = nsQueryInterface(stream); + mOutputStream = nsQueryInterface(stream); + mFileInputStream = nsQueryInterface(stream); + mFileOutputStream = nsQueryInterface(stream); } -}; // class nsIOFileStream + + // Output streamers. Unfortunately, they don't inherit! + nsOutputStream& operator << (const char* buf) + { return nsOutputStream::operator << (buf); } + nsOutputStream& operator << (char ch) + { return nsOutputStream::operator << (ch); } + nsOutputStream& operator << (short val) + { return nsOutputStream::operator << (val); } + nsOutputStream& operator << (unsigned short val) + { return nsOutputStream::operator << (val); } + nsOutputStream& operator << (long val) + { return nsOutputStream::operator << (val); } + nsOutputStream& operator << (unsigned long val) + { return nsOutputStream::operator << (val); } + nsOutputStream& operator << (nsOutputStream& (*pf)(nsOutputStream&)) + { return nsOutputStream::operator << (pf); } + // Input streamers. Unfortunately, they don't inherit! + nsInputStream& operator >> (char& ch) + { return nsInputStream::operator >>(ch); } + nsInputStream& operator >> (nsInputStream& (*pf)(nsInputStream&)) + { return nsInputStream::operator >>(pf); } + // DATA +protected: + nsCOMPtr mFileOutputStream; +}; // class nsIOFileStream + //======================================================================================== // Manipulators //======================================================================================== -NS_BASE nsBasicOutStream& nsEndl(nsBasicOutStream& os); - + +NS_BASE nsOutputStream& nsEndl(nsOutputStream& os); // outputs and FLUSHES. + #endif /* _FILESTREAM_H_ */ diff --git a/mozilla/xpcom/io/nsIBaseStream.h b/mozilla/xpcom/io/nsIBaseStream.h index 1b716332f4a..a360cfee093 100644 --- a/mozilla/xpcom/io/nsIBaseStream.h +++ b/mozilla/xpcom/io/nsIBaseStream.h @@ -31,6 +31,8 @@ class nsIBaseStream : public nsISupports { public: + static const nsIID& IID() { static nsIID iid = NS_IBASESTREAM_IID; return iid; } + /** Close the stream. */ NS_IMETHOD Close(void) = 0; diff --git a/mozilla/xpcom/io/nsIFileStream.cpp b/mozilla/xpcom/io/nsIFileStream.cpp new file mode 100644 index 00000000000..f21549a7ecd --- /dev/null +++ b/mozilla/xpcom/io/nsIFileStream.cpp @@ -0,0 +1,451 @@ +#include "nsIFileStream.h" +#include "nsFileSpec.h" + +#include "prerror.h" + +#ifdef XP_MAC +#include "pprio.h" // To get PR_ImportFile +#else +#include "prio.h" +#endif + +#ifdef XP_MAC +#include +#include +#endif + +//======================================================================================== +class FileImpl + : public nsIOutputStream + , public nsIInputStream + , public nsIFileOutputStream + , public nsIFileInputStream + , public nsIFile +//======================================================================================== +{ + public: + FileImpl(PRFileDesc* inDesc) + : mFileDesc(inDesc) + , mFailed(PR_FALSE) + , mEOF(PR_FALSE) + , mLength(-1) + { + NS_INIT_REFCNT(); + } + FileImpl( + const nsFileSpec& inFile, + int nsprMode, + PRIntn accessMode) + : mFileDesc(nsnull) + , mFailed(PR_FALSE) + , mEOF(PR_FALSE) + { + NS_INIT_REFCNT(); + Open(inFile, nsprMode, accessMode); + } + virtual ~FileImpl() + { + Close(); + } + + // nsISupports interface + NS_DECL_ISUPPORTS + + // nsIFile interface + NS_IMETHOD Open( + const nsFileSpec& inFile, + int nsprMode, + PRIntn accessMode); + NS_IMETHOD Close(); + NS_IMETHOD Seek(PRSeekWhence whence, PRInt32 offset); + + NS_IMETHOD GetIsOpen(PRBool* outOpen) + { + *outOpen = (mFileDesc != nsnull); + return NS_OK; + } + NS_IMETHOD Tell(PRIntn* outWhere); + + // nsIInputStream interface + NS_IMETHOD GetLength(PRUint32 *aLength) + { + NS_PRECONDITION(aLength != nsnull, "null ptr"); + if (!aLength) + return NS_ERROR_NULL_POINTER; + if (mLength < 0) + return NS_FILE_RESULT(NS_ERROR_UNEXPECTED); + *aLength = mLength; + return NS_OK; + } + NS_IMETHOD Read(char* aBuf, + PRUint32 aOffset, + PRUint32 aCount, + PRUint32 *aReadCount) + { + NS_PRECONDITION(aBuf != nsnull, "null ptr"); + if (!aBuf) + return NS_ERROR_NULL_POINTER; + NS_PRECONDITION(aReadCount != nsnull, "null ptr"); + if (!aReadCount) + return NS_ERROR_NULL_POINTER; + if (!mFileDesc) + return NS_FILE_RESULT(PR_BAD_DESCRIPTOR_ERROR); + if (mFailed) + return NS_ERROR_FAILURE; + if (aOffset) + PR_Seek(mFileDesc, aOffset, PR_SEEK_CUR); + PRInt32 bytesRead = PR_Read(mFileDesc, aBuf, aCount); + if (bytesRead < 0) + { + *aReadCount = 0; + mFailed = PR_TRUE; + return NS_FILE_RESULT(PR_GetError()); + } + *aReadCount = bytesRead; + return NS_OK; + } + // nsIOutputStream interface + NS_IMETHOD Write(const char* aBuf, + PRUint32 aOffset, + PRUint32 aCount, + PRUint32 *aWriteCount) + { + NS_PRECONDITION(aBuf != nsnull, "null ptr"); + NS_PRECONDITION(aWriteCount != nsnull, "null ptr"); + + + #ifdef XP_MAC + // Calling PR_Write on stdout is sure suicide. + if (mFileDesc == PR_STDOUT || mFileDesc == PR_STDERR) + { + cout.write(aBuf, aCount); + *aWriteCount = aCount; + return NS_OK; + } + #endif + if (!mFileDesc) + return NS_FILE_RESULT(PR_BAD_DESCRIPTOR_ERROR); + if (mFailed) + return NS_ERROR_FAILURE; + if (aOffset) + PR_Seek(mFileDesc, aOffset, PR_SEEK_CUR); + PRInt32 bytesWrit = PR_Write(mFileDesc, aBuf, aCount); + if (bytesWrit != aCount) + { + mFailed = PR_TRUE; + *aWriteCount = 0; + return NS_FILE_RESULT(PR_GetError()); + } + *aWriteCount = bytesWrit; + return NS_OK; + } + NS_IMETHOD Flush(); + + protected: + + PRFileDesc* mFileDesc; + int mNSPRMode; + PRBool mFailed; + PRBool mEOF; + PRInt32 mLength; +}; // class FileImpl + +#define SAY_I_IMPLEMENT(classname) \ + if (aIID.Equals(classname::IID())) \ + { \ + *aInstancePtr = (void*)((classname*)this); \ + NS_ADDREF_THIS(); \ + return NS_OK; \ + } + +NS_IMPL_RELEASE(FileImpl) +NS_IMPL_ADDREF(FileImpl) + +//---------------------------------------------------------------------------------------- +NS_IMETHODIMP FileImpl::QueryInterface(REFNSIID aIID, void** aInstancePtr) +//---------------------------------------------------------------------------------------- +{ + if (!aInstancePtr) + return NS_ERROR_NULL_POINTER; + + *aInstancePtr = nsnull; + + SAY_I_IMPLEMENT(nsIFile) + SAY_I_IMPLEMENT(nsIOutputStream) + SAY_I_IMPLEMENT(nsIInputStream) + SAY_I_IMPLEMENT(nsIFileInputStream) + SAY_I_IMPLEMENT(nsIFileOutputStream) + // Note that we derive from two copies of nsIBaseStream (and hence + // of nsISupports), one through + // nsIOutputStream, the other through nsIInputStream. Resolve this + // by giving them a specific one + if (aIID.Equals(((nsIBaseStream*)(nsIOutputStream*)this)->IID())) + { + *aInstancePtr = (void*)((nsIBaseStream*)(nsIOutputStream*)this); + NS_ADDREF_THIS(); + return NS_OK; + } + if (aIID.Equals(((nsISupports*)(nsIOutputStream*)this)->IID())) + { + *aInstancePtr = (void*)((nsISupports*)(nsIOutputStream*)this); + NS_ADDREF_THIS(); + return NS_OK; + } + return NS_NOINTERFACE; +} // FileImpl::QueryInterface + +//---------------------------------------------------------------------------------------- +NS_IMETHODIMP FileImpl::Open( + const nsFileSpec& inFile, + int nsprMode, + PRIntn accessMode) +//---------------------------------------------------------------------------------------- +{ + if (mFileDesc) + if ((nsprMode & mNSPRMode) == nsprMode) + return NS_OK; + else + return NS_FILE_RESULT(PR_ILLEGAL_ACCESS_ERROR); + + const int nspr_modes[]={ + PR_WRONLY | PR_CREATE_FILE, + PR_WRONLY | PR_CREATE_FILE | PR_APPEND, + PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, + PR_RDONLY, + PR_RDONLY | PR_APPEND, + PR_RDWR | PR_CREATE_FILE, + PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE, +// "wb", +// "ab", +// "wb", +// "rb", +// "r+b", +// "w+b", + 0 }; + const int* currentLegalMode = nspr_modes; + while (*currentLegalMode && nsprMode != *currentLegalMode) + ++currentLegalMode; + if (!*currentLegalMode) + return NS_FILE_RESULT(PR_ILLEGAL_ACCESS_ERROR); + +#ifdef XP_MAC + // Use the file spec to open the file, because one path can be common to + // several files on the Macintosh (you can have several volumes with the + // same name, see). + mFileDesc = 0; + if (inFile.Error() != noErr) + return NS_FILE_RESULT(inFile.Error()); + OSErr err = noErr; +#if DEBUG + const OSType kCreator = 'CWIE'; +#else + const OSType kCreator = 'MOSS'; +#endif + // Resolve the alias to the original file. + nsFileSpec original = inFile; + PRBool ignoredResult; + original.ResolveAlias(ignoredResult); + const FSSpec& spec = original.operator const FSSpec&(); + if (nsprMode & PR_CREATE_FILE) + err = FSpCreate(&spec, kCreator, 'TEXT', 0); + if (err == dupFNErr) + err = noErr; + if (err != noErr) + return NS_FILE_RESULT(err); + + SInt8 perm; + if (nsprMode & PR_RDWR) + perm = fsRdWrPerm; + else if (nsprMode & PR_WRONLY) + perm = fsWrPerm; + else + perm = fsRdPerm; + + short refnum; + err = FSpOpenDF(&spec, perm, &refnum); + + if (err == noErr && (nsprMode & PR_TRUNCATE)) + err = SetEOF(refnum, 0); + if (err == noErr && (nsprMode & PR_APPEND)) + err = SetFPos(refnum, fsFromLEOF, 0); + if (err != noErr) + return NS_FILE_RESULT(err); + + if ((mFileDesc = PR_ImportFile(refnum)) == 0) + return NS_FILE_RESULT(PR_GetError()); +#else + // Platforms other than Macintosh... + // Another bug in NSPR: Mac PR_Open assumes a unix style path, but Win PR_Open assumes + // a windows path. + if ((mFileDesc = PR_Open((const char*)nsFileSpec(inFile), nsprMode, accessMode)) == 0) + return NS_FILE_RESULT(PR_GetError()); +#endif + mNSPRMode = nsprMode; + mLength = PR_Available(mFileDesc); + return NS_OK; +} // FileImpl::Open + +//---------------------------------------------------------------------------------------- +NS_IMETHODIMP FileImpl::Seek(PRSeekWhence whence, PRInt32 offset) +//---------------------------------------------------------------------------------------- +{ + if (mFileDesc==PR_STDIN || mFileDesc==PR_STDOUT || mFileDesc==PR_STDERR || !mFileDesc) + return NS_FILE_RESULT(PR_BAD_DESCRIPTOR_ERROR); + mFailed = PR_FALSE; // reset on a seek. + mEOF = PR_FALSE; // reset on a seek. + PRInt32 position = PR_Seek(mFileDesc, 0, PR_SEEK_CUR); + PRInt32 available = PR_Available(mFileDesc); + PRInt32 fileSize = position + available; + PRInt32 newPosition; + switch (whence) + { + case PR_SEEK_CUR: newPosition = position + offset; break; + case PR_SEEK_SET: newPosition = offset; break; + case PR_SEEK_END: newPosition = fileSize + offset; break; + } + if (newPosition < 0) + { + newPosition = 0; + mFailed = PR_TRUE; + } + else if (newPosition >= fileSize) + { + newPosition = fileSize; + mEOF = PR_TRUE; + } + if (PR_Seek(mFileDesc, newPosition, PR_SEEK_SET) < 0) + mFailed = PR_TRUE; + return NS_OK; +} // FileImpl::Seek + +//---------------------------------------------------------------------------------------- +NS_IMETHODIMP FileImpl::Tell(PRIntn* outWhere) +//---------------------------------------------------------------------------------------- +{ + if (mFileDesc==PR_STDIN || mFileDesc==PR_STDOUT || mFileDesc==PR_STDERR || !mFileDesc) + return NS_FILE_RESULT(PR_BAD_DESCRIPTOR_ERROR); + *outWhere = PR_Seek(mFileDesc, 0, PR_SEEK_CUR); + return NS_OK; +} // FileImpl::Tell + +//---------------------------------------------------------------------------------------- +NS_IMETHODIMP FileImpl::Close() +//---------------------------------------------------------------------------------------- +{ + if (mFileDesc==PR_STDIN || mFileDesc==PR_STDOUT || mFileDesc==PR_STDERR || !mFileDesc) + return NS_OK; + if (PR_Close(mFileDesc) == PR_SUCCESS) + mFileDesc = 0; + else + return NS_FILE_RESULT(PR_GetError()); + return NS_OK; +} // FileImpl::close + +//---------------------------------------------------------------------------------------- +NS_IMETHODIMP FileImpl::Flush() +//---------------------------------------------------------------------------------------- +{ +#ifdef XP_MAC + if (mFileDesc == PR_STDOUT || mFileDesc == PR_STDERR) + { + cout.flush(); + return NS_OK; + } +#endif + if (!mFileDesc) + return NS_FILE_RESULT(PR_BAD_DESCRIPTOR_ERROR); + PRBool itFailed = PR_Sync(mFileDesc) != PR_SUCCESS; +#ifdef XP_MAC + // On unix, it seems to fail always. + if (itFailed) + mFailed = PR_TRUE; +#endif + return NS_OK; +} // FileImpl::flush + +//---------------------------------------------------------------------------------------- +NS_BASE nsresult NS_NewTypicalInputFileStream( + nsISupports** aResult, + const nsFileSpec& inFile + /*Default nsprMode == PR_RDONLY*/ + /*Default accessmode = 0700 (octal)*/) +// Factory method to get an nsInputStream from a file, using most common options +//---------------------------------------------------------------------------------------- +{ + return NS_NewIOFileStream(aResult, inFile, PR_RDONLY, 0700); +} + +//---------------------------------------------------------------------------------------- +NS_BASE nsresult NS_NewOutputConsoleStream( + nsISupports** aResult) +// Factory method to get an nsOutputStream to the console. +//---------------------------------------------------------------------------------------- +{ + NS_PRECONDITION(aResult != nsnull, "null ptr"); + if (! aResult) + return NS_ERROR_NULL_POINTER; + + FileImpl* stream = new FileImpl(PR_STDOUT); + if (! stream) + return NS_ERROR_OUT_OF_MEMORY; + + NS_ADDREF(stream); + *aResult = (nsISupports*)(void*)stream; + return NS_OK; +} + +//---------------------------------------------------------------------------------------- +NS_BASE nsresult NS_NewTypicalOutputFileStream( + nsISupports** aResult, + const nsFileSpec& inFile + /*default nsprMode= (PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE)*/ + /*Default accessMode= 0700 (octal)*/) +// Factory method to get an nsOutputStream to a file - most common case. +//---------------------------------------------------------------------------------------- +{ + return NS_NewIOFileStream( + aResult, + inFile, + (PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE), + 0700); +} + +//---------------------------------------------------------------------------------------- +NS_BASE nsresult NS_NewIOFileStream( + nsISupports** aResult, + const nsFileSpec& inFile, + PRInt32 nsprMode /*default = (PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE)*/, + PRInt32 accessMode /*Default = 0700 (octal)*/) + // Factory method to get an object that implements both nsIInputStream + // and nsIOutputStream, associated with a file. +//---------------------------------------------------------------------------------------- +{ + NS_PRECONDITION(aResult != nsnull, "null ptr"); + if (!aResult) + return NS_ERROR_NULL_POINTER; + + FileImpl* stream = new FileImpl(inFile, nsprMode, accessMode); + if (! stream) + return NS_ERROR_OUT_OF_MEMORY; + + NS_ADDREF(stream); + *aResult = (nsISupports*)(void*)stream; + return NS_OK; +} + +//---------------------------------------------------------------------------------------- +NS_BASE nsresult NS_NewTypicalIOFileStream( + nsISupports** aResult, + const nsFileSpec& inFile + /*default nsprMode= (PR_RDWR | PR_CREATE_FILE)*/ + /*Default accessMode= 0700 (octal)*/) + // Factory method to get an object that implements both nsIInputStream + // and nsIOutputStream, associated with a single file. +//---------------------------------------------------------------------------------------- +{ + return NS_NewIOFileStream( + aResult, + inFile, + (PR_RDWR | PR_CREATE_FILE), + 0700); +} diff --git a/mozilla/xpcom/io/nsIFileStream.h b/mozilla/xpcom/io/nsIFileStream.h new file mode 100644 index 00000000000..da731e4f494 --- /dev/null +++ b/mozilla/xpcom/io/nsIFileStream.h @@ -0,0 +1,127 @@ +/* -*- 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.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ +#ifndef nsIFileStream_h___ +#define nsIFileStream_h___ + +#include "nsIInputStream.h" +#include "nsIOutputStream.h" +#include "prio.h" + +class nsFileSpec; + +/* a6cf90e8-15b3-11d2-932e-00805f8add32 */ +#define NS_IFILE_IID \ +{ 0xa6cf90e8, 0x15b3, 0x11d2, \ + {0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32} } + +//======================================================================================== +class nsIFile +// Represents a file, and supports Open, Tell etc. +//======================================================================================== +: public nsISupports +{ +public: + static const nsIID& IID() { static nsIID iid = NS_IFILE_IID; return iid; } + NS_IMETHOD Open( + const nsFileSpec& inFile, + int nsprMode, + PRIntn accessMode) = 0; + // Note: Open() is only needed after + // an explicit Close(). All file streams + // are automatically opened on construction. + NS_IMETHOD Seek(PRSeekWhence whence, PRInt32 offset) = 0; + NS_IMETHOD GetIsOpen(PRBool* outOpen) = 0; + NS_IMETHOD Tell(PRIntn* outWhere) = 0; +}; // class nsIFile + +/* a6cf90e6-15b3-11d2-932e-00805f8add32 */ +#define NS_IFILEINPUTSTREAM_IID \ +{ 0xa6cf90e6, 0x15b3, 0x11d2, \ + {0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32} } + +//======================================================================================== +class nsIFileInputStream +// These are additional file-specific methods that files have, above what +// nsIInputStream supports. The current implementation supports both +// interfaces. +//======================================================================================== +: public nsISupports +{ +public: + static const nsIID& IID() { static nsIID iid = NS_IFILEINPUTSTREAM_IID; return iid; } +}; // class nsIFileInputStream + +/* a6cf90e7-15b3-11d2-932e-00805f8add32 */ +#define NS_IFILEOUTPUTSTREAM_IID \ +{ 0xa6cf90e7, 0x15b3, 0x11d2, \ + {0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32} } + +//======================================================================================== +class nsIFileOutputStream +// These are additional file-specific methods that files have, above what +// nsIOutputStream supports. The current implementation supports both +// interfaces. +//======================================================================================== +: public nsISupports +{ +public: + static const nsIID& IID() { static nsIID iid = NS_IFILEOUTPUTSTREAM_IID; return iid; } + NS_IMETHOD Flush() = 0; + // Forces a write to disk. +}; // class nsIFileOutputStream + +//---------------------------------------------------------------------------------------- +NS_BASE nsresult NS_NewTypicalInputFileStream( + nsISupports** aStreamResult, + const nsFileSpec& inFile + /*Default nsprMode == PR_RDONLY*/ + /*Default accessmode = 0700 (octal)*/); +// Factory method to get an nsInputStream from a file, using most common options + +//---------------------------------------------------------------------------------------- +extern "C" NS_BASE nsresult NS_NewOutputConsoleStream( + nsISupports** aStreamResult); + // Factory method to get an nsOutputStream to the console. + +//---------------------------------------------------------------------------------------- +extern "C" NS_BASE nsresult NS_NewTypicalOutputFileStream( + nsISupports** aStreamResult, // will implement all the above interfaces + const nsFileSpec& inFile + /*default nsprMode= (PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE)*/ + /*Default accessMode= 0700 (octal)*/); + // Factory method to get an nsOutputStream to a file - most common case. + +//---------------------------------------------------------------------------------------- +extern "C" NS_BASE nsresult NS_NewTypicalIOFileStream( + nsISupports** aStreamResult, // will implement all the above interfaces + const nsFileSpec& inFile + /*default nsprMode = (PR_RDWR | PR_CREATE_FILE)*/ + /*Default accessMode = 0700 (octal)*/); + // Factory method to get an object that implements both nsIInputStream + // and nsIOutputStream, associated with a single file. + +//---------------------------------------------------------------------------------------- +extern "C" NS_BASE nsresult NS_NewIOFileStream( + nsISupports** aStreamResult, // will implement all the above interfaces + const nsFileSpec& inFile, + PRInt32 nsprMode, + PRInt32 accessMode); + // Factory method to get an object that implements both nsIInputStream + // and nsIOutputStream, associated with a single file. + +#endif /* nsIFileStream_h___ */ diff --git a/mozilla/xpcom/io/nsIInputStream.h b/mozilla/xpcom/io/nsIInputStream.h index a1c5b6167d5..67dac59561b 100644 --- a/mozilla/xpcom/io/nsIInputStream.h +++ b/mozilla/xpcom/io/nsIInputStream.h @@ -28,6 +28,8 @@ class nsIInputStream : public nsIBaseStream { public: + static const nsIID& IID() { static nsIID iid = NS_IINPUTSTREAM_IID; return iid; } + /** Return the number of bytes in the stream * @param aLength out parameter to hold the length * of the stream. if an error occurs, the length diff --git a/mozilla/xpcom/io/nsIOutputStream.h b/mozilla/xpcom/io/nsIOutputStream.h index 795416092d3..aa7d447b2ee 100644 --- a/mozilla/xpcom/io/nsIOutputStream.h +++ b/mozilla/xpcom/io/nsIOutputStream.h @@ -29,6 +29,8 @@ class nsIOutputStream : public nsIBaseStream { public: + static const nsIID& IID() { static nsIID iid = NS_IOUTPUTSTREAM_IID; return iid; } + /** Write data into the stream. * @param aBuf the buffer into which the data is read * @param aOffset the start offset of the data diff --git a/mozilla/xpcom/tests/FilesTest.cpp b/mozilla/xpcom/tests/FilesTest.cpp index 81b93b4ea1c..7d976dd7391 100644 --- a/mozilla/xpcom/tests/FilesTest.cpp +++ b/mozilla/xpcom/tests/FilesTest.cpp @@ -16,10 +16,11 @@ * Reserved. */ -#include "string.h" #include "nsFileSpec.h" #include "nsFileStream.h" +//#include "string.h" + struct FilesTest { FilesTest() : mConsole() {} @@ -30,18 +31,25 @@ struct FilesTest int InputStream(const char* relativePath); int OutputStream(const char* relativePath); int IOStream(const char* relativePath); - int Parent(const char* relativePath, nsNativeFileSpec& outParent); - int Delete(nsNativeFileSpec& victim); - int CreateDirectory(nsNativeFileSpec& victim); - int IterateDirectoryChildren(nsNativeFileSpec& startChild); + int Parent(const char* relativePath, nsFileSpec& outParent); + int Delete(nsFileSpec& victim); + int CreateDirectory(nsFileSpec& victim); + int IterateDirectoryChildren(nsFileSpec& startChild); int CanonicalPath(const char* relativePath); + int Persistence(const char* relativePath); + + int Copy(const char* sourceFile, const char* targDir); + int Move(const char* sourceFile, const char* targDir); + int Rename(const char* sourceFile, const char* newName); + + int Execute(const char* appName, const char* args); void Banner(const char* bannerString); void Passed(); void Failed(); void Inspect(); - nsOutputFileStream mConsole; + nsOutputConsoleStream mConsole; }; //---------------------------------------------------------------------------------------- @@ -59,7 +67,8 @@ void FilesTest::Banner(const char* bannerString) void FilesTest::Passed() //---------------------------------------------------------------------------------------- { - mConsole << "Test passed." << nsEndl; + ((nsOutputStream&)mConsole) << "Test passed."; + mConsole << nsEndl; } //---------------------------------------------------------------------------------------- @@ -89,7 +98,7 @@ void FilesTest::WriteStuff(nsOutputFileStream& s) s << "As a unix path: \"" << (const char*)filePath << "\""<< nsEndl; // Initialize a native file spec from a URL - nsNativeFileSpec fileSpec(fileURL); + nsFileSpec fileSpec(fileURL); s << "As a file spec: " << fileSpec << nsEndl; // Make the spec unique (this one has no suffix). @@ -119,10 +128,10 @@ int FilesTest::OutputStream(const char* relativePath) { nsFilePath myTextFilePath(relativePath, true); // relative path. const char* pathAsString = (const char*)myTextFilePath; - nsNativeFileSpec mySpec(myTextFilePath); + nsFileSpec mySpec(myTextFilePath); { mConsole << "WRITING IDENTICAL OUTPUT TO " << pathAsString << nsEndl << nsEndl; - nsOutputFileStream testStream(myTextFilePath); + nsOutputFileStream testStream(mySpec); if (!testStream.is_open()) { mConsole @@ -154,9 +163,10 @@ int FilesTest::IOStream(const char* relativePath) { nsFilePath myTextFilePath(relativePath, true); // relative path. const char* pathAsString = (const char*)myTextFilePath; + nsFileSpec mySpec(myTextFilePath); mConsole << "Replacing \"path\" by \"ZUUL\" in " << pathAsString << nsEndl << nsEndl; - nsIOFileStream testStream(myTextFilePath); + nsIOFileStream testStream(mySpec); if (!testStream.is_open()) { mConsole @@ -183,6 +193,57 @@ int FilesTest::IOStream(const char* relativePath) return 0; } +//---------------------------------------------------------------------------------------- +int FilesTest::Persistence( + const char* relativePathToWrite) +//---------------------------------------------------------------------------------------- +{ + nsFilePath myTextFilePath(relativePathToWrite, true); + const char* pathAsString = (const char*)myTextFilePath; + nsFileSpec mySpec(myTextFilePath); + + nsIOFileStream testStream(mySpec, (PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE)); + if (!testStream.is_open()) + { + mConsole + << "ERROR: File " + << pathAsString + << " could not be opened for input+output" + << nsEndl; + return -1; + } + + nsPersistentFileDescriptor myPersistent(mySpec); + mConsole + << "Writing persistent file data " << pathAsString << nsEndl << nsEndl; + + testStream.seek(0); // check that the seek compiles + testStream << myPersistent; + + testStream.seek(0); + + nsPersistentFileDescriptor mySecondPersistent; + testStream >> mySecondPersistent; + + mySpec = mySecondPersistent; +#ifdef XP_MAC + if (mySpec.Error()) + { + Failed(); + return -1; + } +#endif + + if (!mySpec.Exists()) + { + Failed(); + return -1; + } + + Passed(); + return 0; +} + //---------------------------------------------------------------------------------------- int FilesTest::InputStream(const char* relativePath) //---------------------------------------------------------------------------------------- @@ -190,7 +251,8 @@ int FilesTest::InputStream(const char* relativePath) nsFilePath myTextFilePath(relativePath, true); const char* pathAsString = (const char*)myTextFilePath; mConsole << "READING BACK DATA FROM " << pathAsString << nsEndl << nsEndl; - nsInputFileStream testStream2(myTextFilePath); + nsFileSpec mySpec(myTextFilePath); + nsInputFileStream testStream2(mySpec); if (!testStream2.is_open()) { mConsole @@ -215,12 +277,12 @@ int FilesTest::InputStream(const char* relativePath) //---------------------------------------------------------------------------------------- int FilesTest::Parent( const char* relativePath, - nsNativeFileSpec& outParent) + nsFileSpec& outParent) //---------------------------------------------------------------------------------------- { nsFilePath myTextFilePath(relativePath, true); const char* pathAsString = (const char*)myTextFilePath; - nsNativeFileSpec mySpec(myTextFilePath); + nsFileSpec mySpec(myTextFilePath); mySpec.GetParent(outParent); nsFilePath parentPath(outParent); @@ -235,7 +297,7 @@ int FilesTest::Parent( } //---------------------------------------------------------------------------------------- -int FilesTest::Delete(nsNativeFileSpec& victim) +int FilesTest::Delete(nsFileSpec& victim) //---------------------------------------------------------------------------------------- { // - Test of non-recursive delete @@ -284,7 +346,7 @@ int FilesTest::Delete(nsNativeFileSpec& victim) } //---------------------------------------------------------------------------------------- -int FilesTest::CreateDirectory(nsNativeFileSpec& dirSpec) +int FilesTest::CreateDirectory(nsFileSpec& dirSpec) //---------------------------------------------------------------------------------------- { nsFilePath dirPath(dirSpec); @@ -306,27 +368,27 @@ int FilesTest::CreateDirectory(nsNativeFileSpec& dirSpec) } //---------------------------------------------------------------------------------------- -int FilesTest::IterateDirectoryChildren(nsNativeFileSpec& startChild) +int FilesTest::IterateDirectoryChildren(nsFileSpec& startChild) //---------------------------------------------------------------------------------------- { // - Test of directory iterator - nsNativeFileSpec grandparent; + nsFileSpec grandparent; startChild.GetParent(grandparent); // should be the original default directory. nsFilePath grandparentPath(grandparent); mConsole << "Forwards listing of " << (const char*)grandparentPath << ":" << nsEndl; - for (nsDirectoryIterator i(grandparent, +1); i; i++) + for (nsDirectoryIterator i(grandparent, +1); i.Exists(); i++) { - char* itemName = ((nsNativeFileSpec&)i).GetLeafName(); + char* itemName = ((nsFileSpec&)i).GetLeafName(); mConsole << '\t' << itemName << nsEndl; delete [] itemName; } mConsole << "Backwards listing of " << (const char*)grandparentPath << ":" << nsEndl; - for (nsDirectoryIterator j(grandparent, -1); j; j--) + for (nsDirectoryIterator j(grandparent, -1); j.Exists(); j--) { - char* itemName = ((nsNativeFileSpec&)j).GetLeafName(); + char* itemName = ((nsFileSpec&)j).GetLeafName(); mConsole << '\t' << itemName << nsEndl; delete [] itemName; } @@ -355,6 +417,110 @@ int FilesTest::CanonicalPath( return 0; } +//---------------------------------------------------------------------------------------- +int FilesTest::Copy(const char* file, const char* dir) +//---------------------------------------------------------------------------------------- +{ + nsFileSpec dirPath(dir, true); + + dirPath.CreateDirectory(); + if (! dirPath.Exists()) + { + Failed(); + return -1; + } + + + nsFileSpec mySpec(file, true); // relative path. + { + nsIOFileStream testStream(mySpec); // creates the file + // Scope ends here, file gets closed + } + + nsFileSpec filePath(file); + if (! filePath.Exists()) + { + Failed(); + return -1; + } + + nsresult error = filePath.Copy(dirPath); + + dirPath += filePath.GetLeafName(); + if (! dirPath.Exists() || ! filePath.Exists() || NS_FAILED(error)) + { + Failed(); + return -1; + } + + Passed(); + + return 0; +} + +//---------------------------------------------------------------------------------------- +int FilesTest::Move(const char* file, const char* dir) +//---------------------------------------------------------------------------------------- +{ + nsFileSpec dirPath(dir, true); + + dirPath.CreateDirectory(); + if (! dirPath.Exists()) + { + Failed(); + return -1; + } + + + nsFileSpec srcSpec(file, true); // relative path. + { + nsIOFileStream testStream(srcSpec); // creates the file + // file gets closed here because scope ends here. + }; + + if (! srcSpec.Exists()) + { + Failed(); + return -1; + } + + nsresult error = srcSpec.Move(dirPath); + + + dirPath += srcSpec.GetLeafName(); + if (! dirPath.Exists() || srcSpec.Exists() || NS_FAILED(error)) + { + Failed(); + return -1; + } + + Passed(); + return 0; +} + +//---------------------------------------------------------------------------------------- +int FilesTest::Execute(const char* appName, const char* args) +//---------------------------------------------------------------------------------------- +{ + nsFileSpec appPath(appName, false); + if (!appPath.Exists()) + { + Failed(); + return -1; + } + + nsresult error = appPath.Execute(args); + if (NS_FAILED(error)) + { + Failed(); + return -1; + } + + Passed(); + + return 0; +} + //---------------------------------------------------------------------------------------- int FilesTest::RunAllTests() // For use with DEBUG defined. @@ -389,7 +555,7 @@ int FilesTest::RunAllTests() return -1; Banner("Parent"); - nsNativeFileSpec parent; + nsFileSpec parent; if (Parent("mumble/iotest.txt", parent) != 0) return -1; @@ -405,6 +571,36 @@ int FilesTest::RunAllTests() if (IterateDirectoryChildren(parent) != 0) return -1; + Banner("Copy"); + if (Copy("mumble/copyfile.txt", "mumble/copy") != 0) + return -1; + + Banner("Move"); + if (Move("mumble/moveFile.txt", "mumble/move") != 0) + return -1; + + Banner("Execute"); +#ifdef XP_MAC + // This path is hard-coded to test on jrm's machine. Finding an app + // on an arbitrary Macintosh would cost more trouble than it's worth. + // Change path to suit. + if NS_FAILED(Execute("/Projects/Nav45_BRANCH/ns/cmd/macfe/"\ + "projects/client45/Client45PPC", "")) +#elif XP_PC + if NS_FAILED(Execute("c:\\windows\\notepad.exe", "")) +#else + if NS_FAILED(Execute("/bin/ls", "/")) +#endif + return -1; + + Banner("Persistence"); + if (Persistence("mumble/filedesc.dat") != 0) + return -1; + + Banner("Delete again (to clean up our mess)"); + if (Delete(parent) != 0) + return -1; + return 0; } @@ -413,7 +609,6 @@ int main() // For use with DEBUG defined. //---------------------------------------------------------------------------------------- { - FilesTest tester; return tester.RunAllTests(); } // main