aboutsummaryrefslogtreecommitdiff
path: root/Src/Wasabi/bfc/std_file.cpp
diff options
context:
space:
mode:
authorJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
committerJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
commit20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Wasabi/bfc/std_file.cpp
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/Wasabi/bfc/std_file.cpp')
-rw-r--r--Src/Wasabi/bfc/std_file.cpp428
1 files changed, 428 insertions, 0 deletions
diff --git a/Src/Wasabi/bfc/std_file.cpp b/Src/Wasabi/bfc/std_file.cpp
new file mode 100644
index 00000000..a1c7267a
--- /dev/null
+++ b/Src/Wasabi/bfc/std_file.cpp
@@ -0,0 +1,428 @@
+#include "precomp_wasabi_bfc.h"
+
+#include "std_file.h"
+#include <bfc/file/readdir.h>
+#include <bfc/platform/strcmp.h>
+
+#ifdef WIN32
+#include <shellapi.h> // for ShellExecute
+#endif
+
+#ifdef __APPLE__
+#include <unistd.h>
+#endif
+
+#define TMPNAME_PREFIX L"WTF"
+
+#ifndef _NOSTUDIO
+#include <bfc/parse/pathparse.h>
+
+#undef fopen
+#undef fclose
+#undef fseek
+#undef ftell
+#undef fread
+#undef fwrite
+#undef fgets
+#undef fprintf
+#undef unlink
+#undef access
+
+#ifdef WASABI_COMPILE_FILEREADER
+static PtrList<void> fileReaders;
+
+OSFILETYPE FileReaderOpen(const wchar_t *filename, OSFNCSTR mode)
+{
+ OSFILETYPE ret = NULL;
+
+ const wchar_t *rFilename = filename;
+ wchar_t str[WA_MAX_PATH] = L"";
+
+ if (wcsstr(filename, L".."))
+ {
+ PathParserW pp(filename);
+ for (int i = 0;i < pp.getNumStrings();i++)
+ {
+ if (!wcscmp(pp.enumString(i), L".."))
+ {
+ PathParserW pp2(str);
+ if (pp2.getNumStrings() <= 0)
+ return NULL;
+ ASSERTPR(pp2.getNumStrings() > 0, "we don't handle this right, and I'm not sure how to fix it because I'm not sure what the code should do with a leading .. --BU");
+ int l = (int)wcslen(pp2.enumString(pp2.getNumStrings() - 1));
+ str[wcslen(str) - l - 1] = 0;
+ continue;
+ }
+ if (!wcscmp(pp.enumString(i), L"."))
+ continue;
+ wcscat(str, pp.enumString(i));
+ wcscat(str, L"/");
+ }
+ str[wcslen(str) - 1] = 0;
+ rFilename = str;
+ }
+
+ if (WASABI_API_FILE && (ret = (OSFILETYPE )WASABI_API_FILE->fileOpen(rFilename, mode)))
+ {
+ fileReaders.addItem((void *)ret);
+ return ret;
+ }
+ return 0;
+}
+#endif
+
+static DWORD mode_to_access(const wchar_t *mode)
+{
+ DWORD access_flags=0;
+ if (mode)
+ {
+ if (mode[0]=='r')
+ access_flags|=GENERIC_READ;
+
+ if (mode[0]=='w' || mode[0] == 'a')
+ {
+ access_flags|=GENERIC_WRITE;
+ if (mode[1] == '+')
+ access_flags|=GENERIC_READ;
+ }
+ }
+ return access_flags;
+}
+
+static DWORD mode_to_create(const wchar_t *mode)
+{
+ if (mode[0]=='r')
+return OPEN_EXISTING;
+ if (mode[0] == 'w')
+ return CREATE_ALWAYS;
+ if (mode[0] == 'a')
+ return OPEN_ALWAYS;
+
+ return OPEN_ALWAYS;
+}
+
+OSFILETYPE WFOPEN(const wchar_t *filename, OSFNCSTR mode, bool useFileReaders)
+{
+ if (!filename || !*filename)
+ return OPEN_FAILED;
+
+ if (!mode)
+ mode = WF_WRITE_BINARY;
+
+ OSFILETYPE ret = OPEN_FAILED;
+
+ if (!WCSNICMP(filename, L"file:", 5))
+ filename += 5;
+
+#ifdef _WIN32
+ ret = CreateFileW(filename, mode_to_access(mode), FILE_SHARE_READ, 0, mode_to_create(mode), FILE_FLAG_SEQUENTIAL_SCAN, 0);
+ if (ret != OPEN_FAILED && mode[0]=='a')
+ SetFilePointer(ret, 0, 0, FILE_END);
+#elif defined(__APPLE__)
+ // this is kind of slow, but hopefully this function isn't called enough for a major performance impact
+ // maybe it'd be faster if we did -fshort-wchar and used CFStringCreateWithCharactersNoCopy
+ CFStringRef cfstr = CFStringCreateWithBytes(kCFAllocatorDefault, (UInt8 *)filename, wcslen(filename)*sizeof(wchar_t), kCFStringEncodingUTF32, false);
+ if (cfstr)
+ {
+ size_t len = CFStringGetMaximumSizeOfFileSystemRepresentation(cfstr);
+ if (len)
+ {
+ char *tmpfn = alloca(len);
+ if (tmpfn)
+ {
+ if (CFStringGetFileSystemRepresentation(cfstr, tmpfn, len))
+ ret = fopen(tmpfn, mode);
+ }
+ }
+ CFRelease(cfstr);
+ }
+#else
+#error port me
+#endif
+
+ if (ret != OPEN_FAILED)
+ return ret;
+
+ // File not found... try to open it with the file readers
+ // but before that, resolve ".." in path so zip can find it
+#ifdef WASABI_COMPILE_FILEREADER
+ if (useFileReaders)
+ {
+ if (ret = FileReaderOpen(filename, mode))
+ return ret;
+ else
+ return OPEN_FAILED;
+ }
+#endif
+ // File still not found ...
+
+ return OPEN_FAILED;
+}
+
+int FCLOSE(OSFILETYPE stream)
+{
+#ifdef WASABI_COMPILE_FILEREADER
+ if (fileReaders.searchItem((void *)stream) != -1)
+ {
+ fileReaders.removeItem((void *)stream);
+ WASABI_API_FILE->fileClose((void *)stream);
+ return 0;
+ }
+#endif
+ return !CloseHandle(stream);
+}
+
+static __int64 Seek64(HANDLE hf, __int64 distance, DWORD MoveMethod)
+{
+ LARGE_INTEGER li;
+
+ li.QuadPart = distance;
+
+ li.LowPart = SetFilePointer (hf, li.LowPart, &li.HighPart, MoveMethod);
+
+ if (li.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR)
+ {
+ li.QuadPart = -1;
+ }
+
+ return li.QuadPart;
+}
+
+int FSEEK(OSFILETYPE stream, long offset, int origin)
+{
+#ifdef WASABI_COMPILE_FILEREADER
+ if (fileReaders.searchItem((void *)stream) != -1)
+ return WASABI_API_FILE->fileSeek(offset, origin, (void *)stream);
+#endif
+ return (int)Seek64(stream, offset, origin);
+}
+
+uint64_t FTELL(OSFILETYPE stream)
+{
+#ifdef WASABI_COMPILE_FILEREADER
+ if (fileReaders.searchItem((void *)stream) != -1)
+ return WASABI_API_FILE->fileTell((void *)stream);
+#endif
+ return Seek64(stream, 0, FILE_CURRENT);
+}
+
+size_t FREAD(void *buffer, size_t size, size_t count, OSFILETYPE stream)
+{
+#ifdef WASABI_COMPILE_FILEREADER
+ if (fileReaders.searchItem((void *)stream) != -1)
+ return WASABI_API_FILE->fileRead(buffer, size*count, (void *)stream);
+#endif
+ DWORD bytesRead=0;
+ ReadFile(stream, buffer, (DWORD)(size*count), &bytesRead, NULL);
+ return bytesRead;
+}
+
+size_t FWRITE(const void *buffer, size_t size, size_t count, OSFILETYPE stream)
+{
+#ifdef WASABI_COMPILE_FILEREADER
+ if (fileReaders.searchItem((void *)stream) != -1)
+ return WASABI_API_FILE->fileWrite(buffer, (int)(size*count), (void *)stream);
+#endif
+
+ DWORD bytesWritten=0;
+ WriteFile(stream, buffer, (DWORD)(size*count), &bytesWritten, NULL);
+ return bytesWritten;
+}
+
+uint64_t FGETSIZE(OSFILETYPE stream)
+{
+#ifdef WASABI_COMPILE_FILEREADER
+ if (fileReaders.searchItem((void *)stream) != -1)
+ return WASABI_API_FILE->fileGetFileSize((void *)stream);
+#endif
+ LARGE_INTEGER position;
+ position.QuadPart=0;
+ position.LowPart = GetFileSize(stream, (LPDWORD)&position.HighPart);
+
+ if (position.LowPart == INVALID_FILE_SIZE && GetLastError() != NO_ERROR)
+ return INVALID_FILE_SIZE;
+ else
+ return position.QuadPart;
+}
+/*
+char *FGETS(char *string, int n, OSFILETYPE stream)
+{
+#ifdef WASABI_COMPILE_FILEREADER
+ if (fileReaders.searchItem((void *)stream) != -1)
+ {
+ char c;
+ char *p = string;
+ for (int i = 0;i < (n - 1);i++)
+ {
+ if (!WASABI_API_FILE->fileRead(&c, 1, stream))
+ {
+ if (!i) return NULL;
+ break;
+ }
+ if (c == 0x0d) continue;
+ if (c == 0x0a) break;
+ *p++ = c;
+ }
+ *p = 0;
+ return string;
+ }
+#endif
+ return fgets(string, n, stream);
+}
+*/
+/*
+int FPRINTF(OSFILETYPE stream, const char *format , ...)
+{
+ int ret;
+ va_list args;
+ va_start (args, format);
+#ifdef WASABI_COMPILE_FILEREADER
+ if (fileReaders.searchItem((void *)stream) != -1)
+ {
+ String p;
+ ret = p.vsprintf(format, args);
+ FWRITE(p.v(), p.len(), 1, stream);
+ }
+ else
+#endif
+ ret = vfprintf(stream, format, args); //real stdio
+ va_end (args);
+ return ret;
+}*/
+
+OSFNCSTR TMPNAM2(OSFNSTR str, int val)
+{
+#ifdef WIN32
+ wchar_t tempPath[MAX_PATH-14] = {0};
+ static wchar_t tempName[MAX_PATH];
+ GetTempPathW(MAX_PATH-14, tempPath);
+ GetTempFileNameW(tempPath, TMPNAME_PREFIX, val, tempName);
+
+ if (str)
+ {
+ wcsncpy(str, tempName, MAX_PATH);
+ return str;
+ }
+ else
+ {
+ return tempName;
+ }
+#elif defined(LINUX) || defined(__APPLE__)
+ mkstemp(StringPrintf("%sXXXXXX", str).getNonConstVal());
+ return (const char *)str;
+#endif
+}
+
+OSFNCSTR TMPNAM(OSFNSTR string)
+{
+ return TMPNAM2(string, 0);
+}
+
+int UNLINK(OSFNCSTR filename)
+{
+#ifdef WASABI_COMPILE_FILEREADER
+ return FDELETE(filename);
+#elif defined(_WIN32)
+ return _wunlink(filename);
+#else
+ return unlink(filename); // this has been undefed at the top of this file
+#endif
+}
+
+int ACCESS(const char *filename, int mode)
+{
+#ifdef WIN32
+ return _access(filename, mode);
+#else
+ return access(filename, mode); // this has been undefed at the top of this file
+#endif
+}
+
+int WACCESS(OSFNCSTR filename, int mode)
+{
+#ifdef WIN32
+ return _waccess(filename, mode);
+#elif defined(__APPLE__)
+ return access(filename, mode); // this has been undefed at the top of this file
+#endif
+}
+
+int FDELETE(const wchar_t *filename, int permanently)
+{
+#ifdef WASABI_COMPILE_FILEREADER
+ if (permanently)
+ return WASABI_API_FILE->fileRemove(filename);
+ else
+ return WASABI_API_FILE->fileRemoveUndoable(filename);
+#else
+ return UNLINK(filename);
+#endif
+}
+
+int MOVEFILE(const wchar_t * filename, const wchar_t *destfilename)
+{
+#ifdef WASABI_COMPILE_FILEREADER
+ return WASABI_API_FILE->fileMove(filename, destfilename);
+#elif defined(_WIN32)
+ return MoveFileW(filename, destfilename);
+#else
+ return rename(filename, destfilename);
+#endif
+}
+
+#ifdef WIN32
+#include <shlobj.h>
+#include <shellapi.h>
+
+static HRESULT ResolveShortCut(LPCWSTR pszShortcutFile, LPWSTR pszPath, int maxbuf)
+{
+ HRESULT hres;
+ IShellLinkW* psl;
+ wchar_t szGotPath[MAX_PATH] = {0};
+ WIN32_FIND_DATAW wfd;
+
+ *pszPath = 0; // assume failure
+
+ hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
+ IID_IShellLinkW, (void **) & psl);
+ if (SUCCEEDED(hres))
+ {
+ IPersistFile* ppf;
+
+ hres = psl->QueryInterface(IID_IPersistFile, (void **) & ppf); // OLE 2! Yay! --YO
+ if (SUCCEEDED(hres))
+ {
+ hres = ppf->Load(pszShortcutFile, STGM_READ);
+ if (SUCCEEDED(hres))
+ {
+ hres = psl->Resolve(HWND_DESKTOP, SLR_ANY_MATCH);
+ if (SUCCEEDED(hres))
+ {
+ wcsncpy(szGotPath, pszShortcutFile, MAX_PATH);
+ hres = psl->GetPath(szGotPath, MAX_PATH, (WIN32_FIND_DATAW *) & wfd,
+ SLGP_SHORTPATH );
+ wcsncpy(pszPath, szGotPath, maxbuf);
+ if (maxbuf) pszPath[maxbuf] = 0;
+ }
+ }
+ ppf->Release();
+ }
+ psl->Release();
+ }
+ return SUCCEEDED(hres);
+}
+#endif
+
+// ommitting a maxbuf param was just asking for trouble...
+int StdFile::resolveShortcut(OSFNCSTR filename, OSFNSTR destfilename, int maxbuf)
+{
+#ifdef WIN32
+ return ResolveShortCut(filename, destfilename, maxbuf);
+#elif defined(LINUX) || defined(__APPLE__)
+ return readlink(filename, destfilename, maxbuf);
+#else
+#error port me
+#endif
+}
+
+#endif // ndef _NOSTUDIO \ No newline at end of file