From 970ad3e729043c4b078acad9414e6acf174120c0 Mon Sep 17 00:00:00 2001 From: Michael Hansen Date: Sat, 19 Jan 2013 21:46:40 -0800 Subject: [PATCH] Add additional functionality to plFileSystem as needed --- Sources/Plasma/CoreLib/plFileSystem.cpp | 100 ++++++++++++++++++ Sources/Plasma/CoreLib/plFileSystem.h | 45 ++++++++ Sources/Plasma/CoreLib/plString.cpp | 1 + Sources/Plasma/CoreLib/plString.h | 10 +- .../PubUtilLib/plFile/plEncryptedStream.cpp | 1 - .../PubUtilLib/plFile/plSecureStream.cpp | 2 - 6 files changed, 151 insertions(+), 8 deletions(-) diff --git a/Sources/Plasma/CoreLib/plFileSystem.cpp b/Sources/Plasma/CoreLib/plFileSystem.cpp index f0dfcd9a..75767121 100644 --- a/Sources/Plasma/CoreLib/plFileSystem.cpp +++ b/Sources/Plasma/CoreLib/plFileSystem.cpp @@ -40,6 +40,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com *==LICENSE==*/ +#include "HeadSpin.h" #include "plFileSystem.h" #if HS_BUILD_FOR_WIN32 @@ -250,6 +251,15 @@ plFileName plFileSystem::GetCWD() return cwd; } +bool plFileSystem::SetCWD(const plFileName &cwd) +{ +#if HS_BUILD_FOR_WIN32 + return SetCurrentDirectoryW(cwd.AsString().ToWchar()); +#else + return (chdir(cwd.AsString().c_str()) == 0); +#endif +} + FILE *plFileSystem::Open(const plFileName &filename, const char *mode) { #if HS_BUILD_FOR_WIN32 @@ -366,3 +376,93 @@ plFileName plFileSystem::GetLogPath() plFileSystem::CreateDir(_logPath); return _logPath; } + +#if !HS_BUILD_FOR_WIN32 +static plFileName _CheckReadlink(const char *link_path) +{ + plFileInfo info(link_path); + if (info.Exists()) { + char *path = new char[info.FileSize()]; + readlink(link_path, path, info.FileSize()); + plFileName appPath = plString::FromUtf8(path, info.FileSize()); + delete [] path; + return appPath; + } + + return ""; +} +#endif + +plFileName plFileSystem::GetCurrentAppPath() +{ + plFileName appPath; + + // Neither OS makes this one simple... +#if HS_BUILD_FOR_WIN32 + wchar_t path[MAX_PATH]; + size_t size = GetModuleFileNameW(nullptr, path, MAX_PATH); + if (size >= MAX_PATH) { + // Buffer not big enough + size_t bigger = MAX_PATH; + do { + bigger *= 2; + wchar_t *path_lg = new wchar_t[bigger]; + size = GetModuleFileNameW(nullptr, path_lg, bigger); + if (size < bigger) + appPath = plString::FromWchar(path_lg); + delete [] path_lg; + } while (!appPath.IsValid()); + } else { + appPath = plString::FromWchar(path); + } + + return appPath; +#else + // Look for /proc/self/exe (Linux), /proc/curproc/file (FreeBSD / Mac), + // then /proc/self/path/a.out (Solaris). If none were found, you're SOL + appPath = _CheckReadlink("/proc/self/exe"); + if (appPath.IsValid()) + return appPath; + + appPath = _CheckReadlink("/proc/curproc/file"); + if (appPath.IsValid()) + return appPath; + + appPath = _CheckReadlink("/proc/self/path/a.out"); + if (appPath.IsValid()) + return appPath; + + hsAssert(0, "Your OS doesn't make life easy, does it?"); +#endif +} + +plFileName plFileSystem::GetTempFilename(const char *prefix, const plFileName &path) +{ +#if HS_BUILD_FOR_WIN32 + // GetTempFileName() never uses more than 3 chars for the prefix + wchar_t wprefix[4]; + for (size_t i=0; i<4; ++i) + wprefix[i] = prefix[i]; + wprefix[3] = 0; + + wchar_t temp[MAX_PATH]; + if (GetTempFileNameW(path.AsString().ToWchar(), wprefix, 0, temp)) + return plString::FromWchar(temp); + + return ""; +#else + plFileName tmpdir = path; + if (!tmpdir.IsValid()) + tmpdir = "/tmp"; + + // "/tmp/prefixXXXXXX" + size_t temp_len = tmpdir.GetSize() + strlen(prefix) + 7; + char *temp = new char[temp_len + 1]; + snprintf(temp, temp_len + 1, "%s/%sXXXXXX", tmpdir.AsString().c_str(), prefix); + mktemp(temp); + plFileName result = temp; + delete [] temp; + + return result; +#endif +} diff --git a/Sources/Plasma/CoreLib/plFileSystem.h b/Sources/Plasma/CoreLib/plFileSystem.h index 2654bb0d..930624a7 100644 --- a/Sources/Plasma/CoreLib/plFileSystem.h +++ b/Sources/Plasma/CoreLib/plFileSystem.h @@ -45,6 +45,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "plString.h" #include +#include #if HS_BUILD_FOR_WIN32 # define PATH_SEPARATOR '\\' @@ -187,10 +188,42 @@ public: const plFileName& path2, const plFileName &path3) { return Join(Join(Join(base, path), path2), path3); } + /** Append UTF-8 data from a C-style string pointer to the end of this + * filename object. Not to be confused with Join() -- do not use this + * for joining path components, or you will be shot by Zrax. + */ + plFileName &operator+=(const char *cstr) { return operator=(fName + cstr); } + + /** Append the string \a str to the end of this filename object. + * Not to be confused with Join() -- do not use this for joining path + * components, or you will be shot by Zrax. + */ + plFileName &operator+=(const plString &str) { return operator=(fName + str); } + private: plString fName; + + // See the comments in plString's nullptr_t constructors for more info: + plFileName(std::nullptr_t) { } + void operator=(std::nullptr_t) { } + void operator==(std::nullptr_t) const { } + void operator!=(std::nullptr_t) const { } }; +/** Concatentate a plFileName with a string constant. Not to be confused with + * plFileName::Join() -- do not use this for joining path components, or you + * will be shot by Zrax. + */ +inline plFileName operator+(const plFileName &left, const char *right) +{ return left.AsString() + right; } + +/** Concatentate a plFileName with a string constant. Not to be confused with + * plFileName::Join() -- do not use this for joining path components, or you + * will be shot by Zrax. + */ +inline plFileName operator+(const char *left, const plFileName &right) +{ return left + right.AsString(); } + /** Structure to get information about a file by name. * \sa plFileName @@ -250,6 +283,9 @@ namespace plFileSystem /** Get the current working directory of the application. */ plFileName GetCWD(); + /** Change the current working directory. */ + bool SetCWD(const plFileName &cwd); + /** Open a file using the correct platform fopen API. */ FILE *Open(const plFileName &filename, const char *mode); @@ -279,6 +315,15 @@ namespace plFileSystem /** Get the Log output directory. If it doesn't exist, this will * create it. */ plFileName GetLogPath(); + + /** Get the full path and filename of the current process. */ + plFileName GetCurrentAppPath(); + + /** Create a temporary filename. If path is specified, the returned + * filename will be relative to the supplied path -- otherwise, the + * system temp path is used. + */ + plFileName GetTempFilename(const char *prefix = "tmp", const plFileName &path = ""); } #endif // plFileSystem_Defined diff --git a/Sources/Plasma/CoreLib/plString.cpp b/Sources/Plasma/CoreLib/plString.cpp index 573b4897..cde11972 100644 --- a/Sources/Plasma/CoreLib/plString.cpp +++ b/Sources/Plasma/CoreLib/plString.cpp @@ -40,6 +40,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com *==LICENSE==*/ +#include "HeadSpin.h" #include "plString.h" #include diff --git a/Sources/Plasma/CoreLib/plString.h b/Sources/Plasma/CoreLib/plString.h index 27b4352b..b4573245 100644 --- a/Sources/Plasma/CoreLib/plString.h +++ b/Sources/Plasma/CoreLib/plString.h @@ -43,7 +43,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #ifndef plString_Defined #define plString_Defined -#include "HeadSpin.h" +#include #include /** Single Unicode character code unit */ @@ -407,8 +407,8 @@ public: */ int Compare(const char *str, CaseSensitivity sense = kCaseSensitive) const { - return (sense == kCaseSensitive) ? strcmp(c_str(), str) - : stricmp(c_str(), str); + return (sense == kCaseSensitive) ? strcmp(c_str(), str ? str : "") + : stricmp(c_str(), str ? str : ""); } /** Compare up to but never exceeding the first \a count bytes of this @@ -427,8 +427,8 @@ public: */ int CompareN(const char *str, size_t count, CaseSensitivity sense = kCaseSensitive) const { - return (sense == kCaseSensitive) ? strncmp(c_str(), str, count) - : strnicmp(c_str(), str, count); + return (sense == kCaseSensitive) ? strncmp(c_str(), str ? str : "", count) + : strnicmp(c_str(), str ? str : "", count); } /** Shortcut for Compare(str, kCaseInsensitive). */ diff --git a/Sources/Plasma/PubUtilLib/plFile/plEncryptedStream.cpp b/Sources/Plasma/PubUtilLib/plFile/plEncryptedStream.cpp index 63cefc63..6a4bc7f4 100644 --- a/Sources/Plasma/PubUtilLib/plFile/plEncryptedStream.cpp +++ b/Sources/Plasma/PubUtilLib/plFile/plEncryptedStream.cpp @@ -63,7 +63,6 @@ plEncryptedStream::plEncryptedStream(uint32_t* key) : fActualFileSize(0), fBufferedStream(false), fRAMStream(nil), - fWriteFileName(nil), fOpenMode(kOpenFail) { if (key) diff --git a/Sources/Plasma/PubUtilLib/plFile/plSecureStream.cpp b/Sources/Plasma/PubUtilLib/plFile/plSecureStream.cpp index 8a43a260..4f751299 100644 --- a/Sources/Plasma/PubUtilLib/plFile/plSecureStream.cpp +++ b/Sources/Plasma/PubUtilLib/plFile/plSecureStream.cpp @@ -72,7 +72,6 @@ fRef(INVALID_HANDLE_VALUE), fActualFileSize(0), fBufferedStream(false), fRAMStream(nil), -fWriteFileName(nil), fOpenMode(kOpenFail), fDeleteOnExit(deleteOnExit) { @@ -87,7 +86,6 @@ fRef(INVALID_HANDLE_VALUE), fActualFileSize(0), fBufferedStream(false), fRAMStream(nil), -fWriteFileName(nil), fOpenMode(kOpenFail), fDeleteOnExit(false) {