diff --git a/src/frameworks/CoreServices/CMakeLists.txt b/src/frameworks/CoreServices/CMakeLists.txt
index 54fa69401..e5833615a 100644
--- a/src/frameworks/CoreServices/CMakeLists.txt
+++ b/src/frameworks/CoreServices/CMakeLists.txt
@@ -1,6 +1,6 @@
project(CoreServices)
-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-rtti -fno-exceptions")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
include_directories(BEFORE ${CMAKE_SOURCE_DIR}/src/external/libcxx/include)
include_directories(
@@ -35,6 +35,9 @@ set(CoreServices_SRCS
LSApplicationWorkspace.m
constants.m
ComponentManager.cpp
+ Files.cpp
+ Resources.cpp
+ ResourcesImpl.cpp
)
set(DYLIB_COMPAT_VERSION "1.0.0")
diff --git a/src/frameworks/CoreServices/Files.cpp b/src/frameworks/CoreServices/Files.cpp
new file mode 100644
index 000000000..f835b8e01
--- /dev/null
+++ b/src/frameworks/CoreServices/Files.cpp
@@ -0,0 +1,37 @@
+/*
+This file is part of Darling.
+
+Copyright (C) 2020 Lubos Dolezel
+
+Darling is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Darling is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Darling. If not, see .
+*/
+#include
+#include
+
+OSErr FSGetDataForkName(HFSUniStr255* dataForkName)
+{
+ dataForkName->length = 0;
+ return noErr;
+}
+
+OSErr FSGetResourceForkName(HFSUniStr255* rsrcForkName)
+{
+ const char name[] = "RESOURCE_FORK";
+ rsrcForkName->length = sizeof(name) - 1;
+
+ for (int i = 0; i < sizeof(name) - 1; i++)
+ rsrcForkName->unicode[i] = name[i];
+
+ return noErr;
+}
diff --git a/src/frameworks/CoreServices/Resources.cpp b/src/frameworks/CoreServices/Resources.cpp
index 03804e5c8..c22b58bd8 100644
--- a/src/frameworks/CoreServices/Resources.cpp
+++ b/src/frameworks/CoreServices/Resources.cpp
@@ -18,6 +18,106 @@ along with Darling. If not, see .
*/
#include
+#include
+#include
+#include
+#include "ResourcesImpl.h"
+
+// Documentation:
+// http://web.archive.org/web/20040603192835/http://developer.apple.com/documentation/Carbon/Reference/Resource_Manager/index.html
// Usage example:
// https://github.com/nathanday/ndalias/blob/master/Classes/NDResourceFork.m
+
+static std::unordered_map g_resources;
+static std::mutex g_resourcesLock;
+static ResFileRefNum g_currentResFile = kResFileNotOpened;
+static ResFileRefNum g_nextRefNum = 1;
+
+ResFileRefNum FSOpenResFile(const FSRef* ref, SInt8 permission)
+{
+ HFSUniStr255 forkName;
+ FSGetDataForkName(&forkName);
+
+ ResFileRefNum refNum;
+ OSErr err = FSOpenResourceFile(ref, forkName.length, forkName.unicode, permission, &refNum);
+
+ if (err != noErr)
+ return kResFileNotOpened;
+ return refNum;
+}
+
+// Should return eofErr if given fork doesn't exist / is empty
+OSErr FSOpenResourceFile(const FSRef* ref, UniCharCount forkNameLength, const UniChar* forkName, SInt8 permissions, ResFileRefNum* refNum)
+{
+ bool resourceFork = false;
+ const bool readOnly = permissions == fsRdPerm;
+
+ if (forkNameLength != 0)
+ {
+ HFSUniStr255 rsrcForkName;
+ FSGetResourceForkName(&rsrcForkName);
+
+ if (rsrcForkName.length == forkNameLength && memcmp(forkName, rsrcForkName.unicode, 2 * forkNameLength) == 0)
+ resourceFork = true;
+ }
+
+ try
+ {
+ char path[4096];
+
+ OSErr rv = FSRefMakePath(ref, (UInt8*) path, sizeof(path) - 1);
+ if (rv != noErr)
+ throw rv;
+
+ Resources* r = new Resources(path, readOnly, resourceFork);
+
+ std::unique_lock l(g_resourcesLock);
+ while (g_resources.find(g_nextRefNum) != g_resources.end())
+ {
+ if (g_nextRefNum == std::numeric_limits::max())
+ g_nextRefNum = 1;
+ else
+ g_nextRefNum++;
+ }
+
+ g_resources.insert(std::make_pair(g_nextRefNum, r));
+ *refNum = g_nextRefNum;
+ g_nextRefNum++;
+
+ return noErr;
+ }
+ catch (OSErr e)
+ {
+ *refNum = kResFileNotOpened;
+ return e;
+ }
+}
+
+ResFileRefNum CurResFile(void)
+{
+ return g_currentResFile;
+}
+
+void UseResFile(ResFileRefNum ref)
+{
+ std::unique_lock l(g_resourcesLock);
+
+ if (g_resources.find(ref) != g_resources.end())
+ g_currentResFile = ref;
+}
+
+void CloseResFile(ResFileRefNum refNum)
+{
+ if (g_currentResFile == refNum)
+ g_currentResFile = kResFileNotOpened;
+
+ std::unique_lock l(g_resourcesLock);
+ auto it = g_resources.find(refNum);
+
+ if (it != g_resources.end())
+ {
+ delete it->second;
+ g_resources.erase(it);
+ }
+}
diff --git a/src/frameworks/CoreServices/ResourcesImpl.cpp b/src/frameworks/CoreServices/ResourcesImpl.cpp
new file mode 100644
index 000000000..5f49ae09b
--- /dev/null
+++ b/src/frameworks/CoreServices/ResourcesImpl.cpp
@@ -0,0 +1,29 @@
+/*
+This file is part of Darling.
+
+Copyright (C) 2020 Lubos Dolezel
+
+Darling is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Darling is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Darling. If not, see .
+*/
+#include "ResourcesImpl.h"
+#include
+
+// File format documentation:
+// https://developer.apple.com/library/archive/documentation/mac/MoreToolbox/MoreToolbox-99.html
+
+Resources::Resources(const char* file, bool readOnly, bool resourceFork)
+: m_file(file), m_readOnly(readOnly), m_resourceFork(resourceFork)
+{
+
+}
diff --git a/src/frameworks/CoreServices/ResourcesImpl.h b/src/frameworks/CoreServices/ResourcesImpl.h
new file mode 100644
index 000000000..f9bf33b67
--- /dev/null
+++ b/src/frameworks/CoreServices/ResourcesImpl.h
@@ -0,0 +1,36 @@
+/*
+This file is part of Darling.
+
+Copyright (C) 2020 Lubos Dolezel
+
+Darling is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Darling is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Darling. If not, see .
+*/
+
+#ifndef _CS_RESOURCES_IMPL_H
+#define _CS_RESOURCES_IMPL_H
+#include
+#include
+
+class Resources
+{
+public:
+
+ Resources(const char* file, bool readOnly, bool resourceFork);
+private:
+ std::string m_file;
+ const bool m_readOnly, m_resourceFork;
+};
+
+#endif
+
diff --git a/src/frameworks/CoreServices/include/CoreServices/FileManager.h b/src/frameworks/CoreServices/include/CoreServices/FileManager.h
index 015b3e1e5..813894557 100644
--- a/src/frameworks/CoreServices/include/CoreServices/FileManager.h
+++ b/src/frameworks/CoreServices/include/CoreServices/FileManager.h
@@ -45,6 +45,7 @@ struct HFSUniStr255
uint16_t length;
uint16_t unicode[255];
};
+typedef struct HFSUniStr255 HFSUniStr255;
struct FSSpec;
typedef struct FSSpec* FSSpecPtr;
diff --git a/src/frameworks/CoreServices/include/CoreServices/Files.h b/src/frameworks/CoreServices/include/CoreServices/Files.h
index a08d44fc6..e4c366bcb 100644
--- a/src/frameworks/CoreServices/include/CoreServices/Files.h
+++ b/src/frameworks/CoreServices/include/CoreServices/Files.h
@@ -21,6 +21,11 @@ along with Darling. If not, see .
#ifndef _CS_FILES_H
#define _CS_FILES_H
#include
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
#if __LP64__
typedef int FSIORefNum;
@@ -28,4 +33,19 @@ along with Darling. If not, see .
typedef SInt16 FSIORefNum;
#endif
+enum {
+ fsCurPerm = 0,
+ fsRdPerm = 1,
+ fsWrPerm = 2,
+ fsRdWrPerm = 3,
+ dsRdWrShPerm = 4,
+};
+
+OSErr FSGetDataForkName(HFSUniStr255* dataForkName);
+OSErr FSGetResourceForkName(HFSUniStr255* rsrcForkName);
+
+#ifdef __cplusplus
+}
+#endif
+
#endif
diff --git a/src/frameworks/CoreServices/include/CoreServices/Resources.h b/src/frameworks/CoreServices/include/CoreServices/Resources.h
index e5498c576..279e3ea94 100644
--- a/src/frameworks/CoreServices/include/CoreServices/Resources.h
+++ b/src/frameworks/CoreServices/include/CoreServices/Resources.h
@@ -46,6 +46,10 @@ ResFileRefNum CurResFile(void);
ResFileRefNum HomeResFile(Handle resource);
void UseResFile(ResFileRefNum ref);
+// NOTE: What's the difference between CountTypes() and Count1Types()?
+// CountTypes() applies to *all* open resource files.
+// Count1Types() applies to CurResFile() only.
+
ResourceCount CountTypes(void);
ResourceCount Count1Types(void);