diff --git a/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/NetFS.framework/Headers b/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/NetFS.framework/Headers
new file mode 120000
index 000000000..a177d2a6b
--- /dev/null
+++ b/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/NetFS.framework/Headers
@@ -0,0 +1 @@
+Versions/Current/Headers
\ No newline at end of file
diff --git a/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/NetFS.framework/Versions/A/Headers b/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/NetFS.framework/Versions/A/Headers
new file mode 120000
index 000000000..c430425d1
--- /dev/null
+++ b/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/NetFS.framework/Versions/A/Headers
@@ -0,0 +1 @@
+../../../../../../../../../../../../src/frameworks/NetFS/include/NetFS
\ No newline at end of file
diff --git a/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/NetFS.framework/Versions/Current b/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/NetFS.framework/Versions/Current
new file mode 120000
index 000000000..8c7e5a667
--- /dev/null
+++ b/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/NetFS.framework/Versions/Current
@@ -0,0 +1 @@
+A
\ No newline at end of file
diff --git a/framework-include/NetFS b/framework-include/NetFS
new file mode 120000
index 000000000..da82345f1
--- /dev/null
+++ b/framework-include/NetFS
@@ -0,0 +1 @@
+../Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/NetFS.framework/Headers
\ No newline at end of file
diff --git a/src/frameworks/CMakeLists.txt b/src/frameworks/CMakeLists.txt
index 8816e10f3..567e8be54 100644
--- a/src/frameworks/CMakeLists.txt
+++ b/src/frameworks/CMakeLists.txt
@@ -39,6 +39,7 @@ add_subdirectory(Metal)
add_subdirectory(MetalKit)
add_subdirectory(ModelIO)
add_subdirectory(MultipeerConnectivity)
+add_subdirectory(NetFS)
add_subdirectory(Network)
add_subdirectory(OpenAL)
add_subdirectory(OpenCL)
diff --git a/src/frameworks/NetFS/CMakeLists.txt b/src/frameworks/NetFS/CMakeLists.txt
new file mode 100644
index 000000000..741135f93
--- /dev/null
+++ b/src/frameworks/NetFS/CMakeLists.txt
@@ -0,0 +1,18 @@
+project(NetFS)
+
+set(DYLIB_COMPAT_VERSION "1.0.0")
+set(DYLIB_CURRENT_VERSION "1.0.0")
+
+add_framework(NetFS
+ FAT
+ CURRENT_VERSION
+ VERSION "A"
+
+ SOURCES
+ src/NetFS.m
+
+ DEPENDENCIES
+ system
+ objc
+ Foundation
+)
diff --git a/src/frameworks/NetFS/include/NetFS/NetFS.h b/src/frameworks/NetFS/include/NetFS/NetFS.h
new file mode 100644
index 000000000..ad969d05e
--- /dev/null
+++ b/src/frameworks/NetFS/include/NetFS/NetFS.h
@@ -0,0 +1,85 @@
+/*
+ This file is part of Darling.
+
+ Copyright (C) 2021 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 _NetFS_H_
+#define _NetFS_H_
+
+#include
+
+void* GetCompleteMountURL(void);
+void* GetURLFromURLRemountInfo(void);
+void* GetURLRemountInfo(void);
+void* GetURLRemountInfoSize(void);
+void* MountCompleteURL(void);
+void* MountServerURL(void);
+void* MountURLWithAuthentication(void);
+void* NetFSCFStringtoCString(void);
+void* NetFSClearAllURLApprovals(void);
+void* NetFSCopyHostAndPort(void);
+void* NetFSCopyNormalizedURLString(void);
+void* NetFSCopyURLForRemountingVolume(void);
+void* NetFSGetMountInfo(void);
+void* NetFSGetMountInfoByFSID(void);
+void* NetFSGetSupportedSchemes(void);
+void* NetFSGetURLApprovalState(void);
+void* NetFSInterface_AddRef(void);
+void* NetFSInterface_Release(void);
+void* NetFSLogToMessageTracer(void);
+void* NetFSMountURLAsync(void);
+void* NetFSMountURLCancel(void);
+void* NetFSMountURLProbe(void);
+void* NetFSMountURLSync(void);
+void* NetFSMountURLWithAuthenticationSync(void);
+void* NetFSQueryInterface(void);
+void* NetFSSetURLApprovalState(void);
+void* NetFS_CreateInterface(void);
+void* PremountHomeDirectoryWithAuthentication(void);
+void* RemountInfoQueryInterface(void);
+void* UnmountServerURL(void);
+void* netfs_Cancel(void);
+void* netfs_CancelAsyncMount(void);
+void* netfs_CloseSession(void);
+void* netfs_ConnectToServerAsync(void);
+void* netfs_ConnectToServerSync(void);
+void* netfs_CreateSessionRef(void);
+void* netfs_CreateURL(void);
+void* netfs_EnumerateShares(void);
+void* netfs_GetServerInfo(void);
+void* netfs_Mount(void);
+void* netfs_MountURLWithAuthenticationAsync(void);
+void* netfs_MountURLWithAuthenticationSync(void);
+void* netfs_OpenSession(void);
+void* netfs_ParseURL(void);
+void* netfs_log_message_tracer(void);
+void* netfs_log_message_tracer_auth_type(void);
+void* netfs_log_message_tracer_automounted(void);
+void* netfs_log_message_tracer_executable_name(void);
+void* netfs_log_message_tracer_result(void);
+void* netfs_log_message_tracer_result_on_fail(void);
+void* netfs_log_message_tracer_scheme(void);
+
+int NetFSUnmountHomeDirectory(const char* home, const char* path, uid_t uid, int flags /* unsure */);
+int NetFSMountHomeDirectoryWithAuthentication(const char* url, const char* home, const char* path, uid_t uid, size_t mount_dir_length, const char* mount_dir, const char* username, const char* authenticator, int flags, unsigned int* out_was_remounted);
+
+enum {
+ // no clue what the real value is
+ kNetFSAllowKerberos = 1,
+};
+
+#endif
diff --git a/src/frameworks/NetFS/include/NetFS/URLMount.h b/src/frameworks/NetFS/include/NetFS/URLMount.h
new file mode 100644
index 000000000..0cd81f6e7
--- /dev/null
+++ b/src/frameworks/NetFS/include/NetFS/URLMount.h
@@ -0,0 +1,25 @@
+/**
+ * This file is part of Darling.
+ *
+ * Copyright (C) 2021 Darling developers
+ *
+ * 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 _NETFS_URLMOUNT_H_
+#define _NETFS_URLMOUNT_H_
+
+#include
+
+#endif // _NETFS_URLMOUNT_H_
diff --git a/src/frameworks/NetFS/src/NetFS.m b/src/frameworks/NetFS/src/NetFS.m
new file mode 100644
index 000000000..5ddb6e7c0
--- /dev/null
+++ b/src/frameworks/NetFS/src/NetFS.m
@@ -0,0 +1,346 @@
+/*
+ This file is part of Darling.
+
+ Copyright (C) 2021 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
+#include
+
+static int verbose = 0;
+
+__attribute__((constructor))
+static void initme(void) {
+ verbose = getenv("STUB_VERBOSE") != NULL;
+}
+
+void* GetCompleteMountURL(void)
+{
+ if (verbose) puts("STUB: GetCompleteMountURL called");
+ return NULL;
+}
+
+void* GetURLFromURLRemountInfo(void)
+{
+ if (verbose) puts("STUB: GetURLFromURLRemountInfo called");
+ return NULL;
+}
+
+void* GetURLRemountInfo(void)
+{
+ if (verbose) puts("STUB: GetURLRemountInfo called");
+ return NULL;
+}
+
+void* GetURLRemountInfoSize(void)
+{
+ if (verbose) puts("STUB: GetURLRemountInfoSize called");
+ return NULL;
+}
+
+void* MountCompleteURL(void)
+{
+ if (verbose) puts("STUB: MountCompleteURL called");
+ return NULL;
+}
+
+void* MountServerURL(void)
+{
+ if (verbose) puts("STUB: MountServerURL called");
+ return NULL;
+}
+
+void* MountURLWithAuthentication(void)
+{
+ if (verbose) puts("STUB: MountURLWithAuthentication called");
+ return NULL;
+}
+
+void* NetFSCFStringtoCString(void)
+{
+ if (verbose) puts("STUB: NetFSCFStringtoCString called");
+ return NULL;
+}
+
+void* NetFSClearAllURLApprovals(void)
+{
+ if (verbose) puts("STUB: NetFSClearAllURLApprovals called");
+ return NULL;
+}
+
+void* NetFSCopyHostAndPort(void)
+{
+ if (verbose) puts("STUB: NetFSCopyHostAndPort called");
+ return NULL;
+}
+
+void* NetFSCopyNormalizedURLString(void)
+{
+ if (verbose) puts("STUB: NetFSCopyNormalizedURLString called");
+ return NULL;
+}
+
+void* NetFSCopyURLForRemountingVolume(void)
+{
+ if (verbose) puts("STUB: NetFSCopyURLForRemountingVolume called");
+ return NULL;
+}
+
+void* NetFSGetMountInfo(void)
+{
+ if (verbose) puts("STUB: NetFSGetMountInfo called");
+ return NULL;
+}
+
+void* NetFSGetMountInfoByFSID(void)
+{
+ if (verbose) puts("STUB: NetFSGetMountInfoByFSID called");
+ return NULL;
+}
+
+void* NetFSGetSupportedSchemes(void)
+{
+ if (verbose) puts("STUB: NetFSGetSupportedSchemes called");
+ return NULL;
+}
+
+void* NetFSGetURLApprovalState(void)
+{
+ if (verbose) puts("STUB: NetFSGetURLApprovalState called");
+ return NULL;
+}
+
+void* NetFSInterface_AddRef(void)
+{
+ if (verbose) puts("STUB: NetFSInterface_AddRef called");
+ return NULL;
+}
+
+void* NetFSInterface_Release(void)
+{
+ if (verbose) puts("STUB: NetFSInterface_Release called");
+ return NULL;
+}
+
+void* NetFSLogToMessageTracer(void)
+{
+ if (verbose) puts("STUB: NetFSLogToMessageTracer called");
+ return NULL;
+}
+
+void* NetFSMountURLAsync(void)
+{
+ if (verbose) puts("STUB: NetFSMountURLAsync called");
+ return NULL;
+}
+
+void* NetFSMountURLCancel(void)
+{
+ if (verbose) puts("STUB: NetFSMountURLCancel called");
+ return NULL;
+}
+
+void* NetFSMountURLProbe(void)
+{
+ if (verbose) puts("STUB: NetFSMountURLProbe called");
+ return NULL;
+}
+
+void* NetFSMountURLSync(void)
+{
+ if (verbose) puts("STUB: NetFSMountURLSync called");
+ return NULL;
+}
+
+void* NetFSMountURLWithAuthenticationSync(void)
+{
+ if (verbose) puts("STUB: NetFSMountURLWithAuthenticationSync called");
+ return NULL;
+}
+
+void* NetFSQueryInterface(void)
+{
+ if (verbose) puts("STUB: NetFSQueryInterface called");
+ return NULL;
+}
+
+void* NetFSSetURLApprovalState(void)
+{
+ if (verbose) puts("STUB: NetFSSetURLApprovalState called");
+ return NULL;
+}
+
+void* NetFS_CreateInterface(void)
+{
+ if (verbose) puts("STUB: NetFS_CreateInterface called");
+ return NULL;
+}
+
+void* PremountHomeDirectoryWithAuthentication(void)
+{
+ if (verbose) puts("STUB: PremountHomeDirectoryWithAuthentication called");
+ return NULL;
+}
+
+void* RemountInfoQueryInterface(void)
+{
+ if (verbose) puts("STUB: RemountInfoQueryInterface called");
+ return NULL;
+}
+
+void* UnmountServerURL(void)
+{
+ if (verbose) puts("STUB: UnmountServerURL called");
+ return NULL;
+}
+
+void* netfs_Cancel(void)
+{
+ if (verbose) puts("STUB: netfs_Cancel called");
+ return NULL;
+}
+
+void* netfs_CancelAsyncMount(void)
+{
+ if (verbose) puts("STUB: netfs_CancelAsyncMount called");
+ return NULL;
+}
+
+void* netfs_CloseSession(void)
+{
+ if (verbose) puts("STUB: netfs_CloseSession called");
+ return NULL;
+}
+
+void* netfs_ConnectToServerAsync(void)
+{
+ if (verbose) puts("STUB: netfs_ConnectToServerAsync called");
+ return NULL;
+}
+
+void* netfs_ConnectToServerSync(void)
+{
+ if (verbose) puts("STUB: netfs_ConnectToServerSync called");
+ return NULL;
+}
+
+void* netfs_CreateSessionRef(void)
+{
+ if (verbose) puts("STUB: netfs_CreateSessionRef called");
+ return NULL;
+}
+
+void* netfs_CreateURL(void)
+{
+ if (verbose) puts("STUB: netfs_CreateURL called");
+ return NULL;
+}
+
+void* netfs_EnumerateShares(void)
+{
+ if (verbose) puts("STUB: netfs_EnumerateShares called");
+ return NULL;
+}
+
+void* netfs_GetServerInfo(void)
+{
+ if (verbose) puts("STUB: netfs_GetServerInfo called");
+ return NULL;
+}
+
+void* netfs_Mount(void)
+{
+ if (verbose) puts("STUB: netfs_Mount called");
+ return NULL;
+}
+
+void* netfs_MountURLWithAuthenticationAsync(void)
+{
+ if (verbose) puts("STUB: netfs_MountURLWithAuthenticationAsync called");
+ return NULL;
+}
+
+void* netfs_MountURLWithAuthenticationSync(void)
+{
+ if (verbose) puts("STUB: netfs_MountURLWithAuthenticationSync called");
+ return NULL;
+}
+
+void* netfs_OpenSession(void)
+{
+ if (verbose) puts("STUB: netfs_OpenSession called");
+ return NULL;
+}
+
+void* netfs_ParseURL(void)
+{
+ if (verbose) puts("STUB: netfs_ParseURL called");
+ return NULL;
+}
+
+void* netfs_log_message_tracer(void)
+{
+ if (verbose) puts("STUB: netfs_log_message_tracer called");
+ return NULL;
+}
+
+void* netfs_log_message_tracer_auth_type(void)
+{
+ if (verbose) puts("STUB: netfs_log_message_tracer_auth_type called");
+ return NULL;
+}
+
+void* netfs_log_message_tracer_automounted(void)
+{
+ if (verbose) puts("STUB: netfs_log_message_tracer_automounted called");
+ return NULL;
+}
+
+void* netfs_log_message_tracer_executable_name(void)
+{
+ if (verbose) puts("STUB: netfs_log_message_tracer_executable_name called");
+ return NULL;
+}
+
+void* netfs_log_message_tracer_result(void)
+{
+ if (verbose) puts("STUB: netfs_log_message_tracer_result called");
+ return NULL;
+}
+
+void* netfs_log_message_tracer_result_on_fail(void)
+{
+ if (verbose) puts("STUB: netfs_log_message_tracer_result_on_fail called");
+ return NULL;
+}
+
+void* netfs_log_message_tracer_scheme(void)
+{
+ if (verbose) puts("STUB: netfs_log_message_tracer_scheme called");
+ return NULL;
+}
+
+int NetFSUnmountHomeDirectory(const char* home, const char* path, uid_t uid, int flags) {
+ if (verbose) puts("STUB: NetFSUnmountHomeDirectory called");
+ return -1;
+};
+
+int NetFSMountHomeDirectoryWithAuthentication(const char* url, const char* home, const char* path, uid_t uid, size_t mount_dir_length, const char* mount_dir, const char* username, const char* authenticator, int flags, unsigned int* out_was_remounted) {
+ if (verbose) puts("STUB: NetFSMountHomeDirectoryWithAuthentication called");
+ return -1;
+};