From 83b1a68c52ba3e0e8796282759f694b7fdddf06d Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Mon, 17 Nov 2014 15:24:07 +0100 Subject: [PATCH] Move NetFS to a package This is based on Jalopeura's patch to #10191, however, there are some changes. From the patch: * Make userlandfs use separate "interface definition" files for each filesystem, so the netfs package can provide a configuration file * Add a short document on how to use NetFS * Various fixes to netfs to make it build again (volatile atomics) * The netfs_mount script for easier use of NetFS Additional fixes: * Move netfs_mount and the interface description file to data/ in the source tree * Use strlcat instead of strcat to avoid a buffer overflow * Some parts were already applied in previous commits --- build/jam/HaikuPackages | 1 + build/jam/OptionalPackages | 34 ---- build/jam/packages/NetFS | 27 +++ build/jam/repositories/Haiku | 1 + data/bin/netfs_mount | 3 + data/userlandfs/file_systems/netfs | 18 ++ docs/add-ons/NetFS.html | 146 ++++++++++++++++ .../netfs/server/ClientVolume.cpp | 2 +- .../netfs/server/InsecureConnectionListener.h | 2 +- .../file_systems/netfs/server/NetFSServer.cpp | 165 +++++++++--------- .../file_systems/netfs/server/NetFSServer.h | 4 +- .../userlandfs/kernel_add_on/Settings.cpp | 66 +++++-- src/data/package_infos/generic/netfs | 21 +++ 13 files changed, 355 insertions(+), 135 deletions(-) create mode 100644 build/jam/packages/NetFS create mode 100644 data/bin/netfs_mount create mode 100644 data/userlandfs/file_systems/netfs create mode 100644 docs/add-ons/NetFS.html create mode 100644 src/data/package_infos/generic/netfs diff --git a/build/jam/HaikuPackages b/build/jam/HaikuPackages index f207eec1b3..e8563e58de 100644 --- a/build/jam/HaikuPackages +++ b/build/jam/HaikuPackages @@ -6,6 +6,7 @@ local packages = HaikuUserguide HaikuWelcome MakefileEngine + NetFS UserlandFS ; diff --git a/build/jam/OptionalPackages b/build/jam/OptionalPackages index 9c389367e1..47cea27ce8 100644 --- a/build/jam/OptionalPackages +++ b/build/jam/OptionalPackages @@ -13,8 +13,6 @@ # FFMpeg - audio/video library # FFMpeg-devel - FFMpeg development files # Git - the distributed version control system -# NetFS - the native networked file system components -# UserlandFS - aids native file system development (like FUSE) # WebPositive - native, WebKit-based web browser # Welcome - introductory documentation to Haiku # WifiFirmwareScriptData - data files needed by install-wifi-firmwares.sh @@ -188,38 +186,6 @@ if [ IsOptionalHaikuImagePackageAdded Git ] { } -# NetFS network file system -if [ IsOptionalHaikuImagePackageAdded NetFS ] { -# TODO: Make this an actual package! -# # userlandfs module -# AddFilesToHaikuImage home config add-ons userlandfs -# : netfs ; -# -# # servers -# AddFilesToHaikuImage system servers : netfs_server ; -# AddFilesToHaikuImage system servers -# : authentication_server ; -# -# # tools -# AddFilesToHaikuImage system bin : netfs_config ; -# AddFilesToHaikuImage system bin : netfs_server_prefs ; -# -# #example settings for netfs_server -# local netfsServerSettingsFiles = netfs-server ; -# SEARCH on $(netfsServerSettingsFiles) -# = [ FDirName $(HAIKU_TOP) src add-ons kernel file_systems netfs ] ; -# AddFilesToHaikuImage home config settings kernel drivers -# : $(netfsServerSettingsFiles) ; -# -# #userlandfs settings are needed for netfs_config to work (ioctls) -# local userlandfsServerSettingsFiles = userlandfs ; -# SEARCH on $(userlandfsServerSettingsFiles) -# = [ FDirName $(HAIKU_TOP) src add-ons kernel file_systems userlandfs ] ; -# AddFilesToHaikuImage home config settings kernel drivers -# : $(userlandfsServerSettingsFiles) ; -} - - # WebPositive if [ IsOptionalHaikuImagePackageAdded WebPositive ] { local architectureObject ; diff --git a/build/jam/packages/NetFS b/build/jam/packages/NetFS new file mode 100644 index 0000000000..7a9e0b8e26 --- /dev/null +++ b/build/jam/packages/NetFS @@ -0,0 +1,27 @@ +local netfsPackage = netfs.hpkg ; +HaikuPackage $(netfsPackage) ; + +# userlandfs module +AddFilesToPackage add-ons userlandfs : netfs ; + +# servers +AddFilesToPackage servers : netfs_server ; +AddFilesToPackage servers : authentication_server ; + +# tools +AddFilesToPackage bin : netfs_config ; +AddFilesToPackage bin : netfs_server_prefs ; +AddFilesToPackage bin + : [ FDirName $(HAIKU_TOP) data bin netfs_mount ] ; + +# interface definition +AddFilesToPackage data userlandfs file_systems + : [ FDirName $(HAIKU_TOP) data userlandfs file_systems netfs ] + : netfs ; + +# docs +AddFilesToPackage documentation add-ons : + [ FDirName $(HAIKU_TOP) docs add-ons NetFS.html ] : NetFS.html ; + +BuildHaikuPackage $(netfsPackage) : netfs ; + diff --git a/build/jam/repositories/Haiku b/build/jam/repositories/Haiku index 24459716c2..aedc72da59 100644 --- a/build/jam/repositories/Haiku +++ b/build/jam/repositories/Haiku @@ -15,6 +15,7 @@ local packages = haiku_userguide haiku_welcome makefile_engine + netfs userland_fs haiku_$(secondaryArchs) diff --git a/data/bin/netfs_mount b/data/bin/netfs_mount new file mode 100644 index 0000000000..85d25a6347 --- /dev/null +++ b/data/bin/netfs_mount @@ -0,0 +1,3 @@ +/system/servers/authentication_server & +mkdir /network +mount -t userlandfs -p "netfs" /network diff --git a/data/userlandfs/file_systems/netfs b/data/userlandfs/file_systems/netfs new file mode 100644 index 0000000000..d10d788de3 --- /dev/null +++ b/data/userlandfs/file_systems/netfs @@ -0,0 +1,18 @@ +# NetFS interface definition for UserlandFS + +file_system netfs { + # NET_FS_IOCTL_ADD_SERVER + ioctl 11000 { + buffer_size 256 + write_buffer_size 0 + is_buffer true + } + + # NET_FS_IOCTL_REMOVE_SERVER + ioctl 11001 { + buffer_size 256 + write_buffer_size 0 + is_buffer true + } +} + diff --git a/docs/add-ons/NetFS.html b/docs/add-ons/NetFS.html new file mode 100644 index 0000000000..5c7b94d418 --- /dev/null +++ b/docs/add-ons/NetFS.html @@ -0,0 +1,146 @@ + + + +NetFS + + + + +

NetFS

+ +
+ +

Client

+ +

To run the client, execute the following at the command line:

+ +
+$ netfs_mount
+
+ +

A "Network" icon will appear on your desktop, containing remote servers +identified by host name. Inside the folder for each server are the shares on +that server.

+ +

You can also run the steps individually:

+ +
+$ /system/servers/authentication_server &
+$ mkdir /network
+$ mount -t userlandfs -p "netfs" /network
+
+ +
+ +

Server

+ +

To run the server:

+ +
+$ netfs_server_prefs launch
+
+ +

You can also start the server directly if you prefer.

+ +
+$ /system/servers/netfs_server &
+
+ +

The server will then run until you shut down your computer, but it is also +possible to stop it manually.

+ +
+$ netfs_server_prefs terminate
+
+ +

Once the server is running, you can define shared folders. The first step is +to create a user who can access those folders, optionally with a password.

+ +
+$ netfs_server_prefs add user <name> [<password>]
+
+ +

Next create a shared folder and assign a user some permissions on it.

+ +
+$ netfs_server_prefs add share <name> <path>
+$ netfs_server_prefs permissions <user> <share> 
+
+ +

name is the name that will appear to clients when +they connect to your server. flags is one or more of: +m = mount, r = read, w = write, q = query.

+ +

Don't forget to save your settings.

+ +
+$ netfs_server_prefs save
+
+ +

The netfs_server_prefs tool can also list and +remove users and shares. See the help for details.

+ +
+$ netfs_server_prefs --help
+
+ +
+ +

Fallback Settings File

+ +

The settings file is stored in a binary format, but if it is missing or +damaged, the server will use a fallback settings file, which has a text-based +format. This file must be located at /boot/home/config/settings/netfs/netfs_server_fallback. (If +neither the main settings file nor the fallback settings file can be loaded, the +server will have no users or shares defined.) + +

Here is an example of a fallback settings file.

+ +
+# users
+user bonefish {
+	password	password
+}
+
+# user without a password
+user anonymous
+
+# shares
+share ttttt {
+	path /boot/home/Desktop/ttttt
+	user bonefish {
+		permissions	mount query read write
+	}
+}
+
+share sub-ttttt {
+	path /boot/home/Desktop/ttttt/rmessage
+	user bonefish {
+		permissions	mount query read write
+	}
+	user anonymous {
+		permissions	mount query read
+	}
+}
+
+ + + diff --git a/src/add-ons/kernel/file_systems/netfs/server/ClientVolume.cpp b/src/add-ons/kernel/file_systems/netfs/server/ClientVolume.cpp index f6af50a733..8874b7d056 100644 --- a/src/add-ons/kernel/file_systems/netfs/server/ClientVolume.cpp +++ b/src/add-ons/kernel/file_systems/netfs/server/ClientVolume.cpp @@ -520,7 +520,7 @@ ClientVolume::_NextVolumeID() } // sNextVolumeID -vint32 ClientVolume::sNextVolumeID = 0; +int32 ClientVolume::sNextVolumeID = 0; // #pragma - diff --git a/src/add-ons/kernel/file_systems/netfs/server/InsecureConnectionListener.h b/src/add-ons/kernel/file_systems/netfs/server/InsecureConnectionListener.h index e4e4471b84..738ab2d0f6 100644 --- a/src/add-ons/kernel/file_systems/netfs/server/InsecureConnectionListener.h +++ b/src/add-ons/kernel/file_systems/netfs/server/InsecureConnectionListener.h @@ -27,7 +27,7 @@ public: User** user); private: - vint32 fSocket; + int32 fSocket; }; #endif // NET_FS_INSECURE_CONNECTION_LISTENER_H diff --git a/src/add-ons/kernel/file_systems/netfs/server/NetFSServer.cpp b/src/add-ons/kernel/file_systems/netfs/server/NetFSServer.cpp index 4b067eba0d..49041d1cd5 100644 --- a/src/add-ons/kernel/file_systems/netfs/server/NetFSServer.cpp +++ b/src/add-ons/kernel/file_systems/netfs/server/NetFSServer.cpp @@ -40,8 +40,9 @@ #include "Utils.h" #include "VolumeManager.h" -static const char* kSettingsDirName = "netfs"; -static const char* kSettingsFileName = "netfs_server"; +static const char* kSettingsDirName = "netfs"; +static const char* kSettingsFileName = "netfs_server"; +static const char* kFallbackSettingsFileName = "netfs_server_fallback"; // usage static const char* kUsage = @@ -796,89 +797,91 @@ NetFSServer::_LoadSecurityContext(SecurityContext** _securityContext) } ObjectDeleter securityContextDeleter(securityContext); - // load from driver settings for the time being + // load the fallback settings, if present + BPath path; DriverSettings settings; - error = settings.Load("netfs-server"); - if (error != B_OK) - return error; - - // load users - DriverParameter parameter; - for (DriverParameterIterator it = settings.GetParameterIterator("user"); - it.GetNext(¶meter);) { - const char* userName = parameter.ValueAt(0); - const char* password = parameter.GetParameterValue("password"); - if (!userName) { - WARN("Skipping nameless user settings entry.\n"); - continue; - } -// PRINT(("user: %s, password: %s\n", parameter.ValueAt(0), -// parameter.GetParameterValue("password"))); - error = securityContext->AddUser(userName, password); - if (error != B_OK) - ERROR("ERROR: Failed to add user `%s'\n", userName); - } - - // load shares - for (DriverParameterIterator it = settings.GetParameterIterator("share"); - it.GetNext(¶meter);) { - const char* shareName = parameter.ValueAt(0); - const char* path = parameter.GetParameterValue("path"); - if (!shareName || !path) { - WARN("settings: Skipping invalid share settings entry (no name" - " or no path).\n"); - continue; - } -// PRINT(("share: %s, path: %s\n", parameter.ValueAt(0), -// parameter.GetParameterValue("path"))); - Share* share; - error = securityContext->AddShare(shareName, path, &share); - if (error != B_OK) { - ERROR("ERROR: Failed to add share `%s'\n", shareName); - continue; - } - BReference shareReference(share, true); - DriverParameter userParameter; - // iterate through the share users - for (DriverParameterIterator userIt - = parameter.GetParameterIterator("user"); - userIt.GetNext(&userParameter);) { - const char* userName = userParameter.ValueAt(0); -// PRINT((" user: %s\n", userName)); - User* user = securityContext->FindUser(userName); - if (!user) { - ERROR("ERROR: Undefined user `%s'.\n", userName); + + if (_GetSettingsDirPath(&path, false) == B_OK + && path.Append(kFallbackSettingsFileName) == B_OK + && settings.Load(path.Path()) == B_OK) { + // load users + DriverParameter parameter; + for (DriverParameterIterator it = settings.GetParameterIterator("user"); + it.GetNext(¶meter);) { + const char* userName = parameter.ValueAt(0); + const char* password = parameter.GetParameterValue("password"); + if (!userName) { + WARN("Skipping nameless user settings entry.\n"); continue; } - BReference userReference(user, true); - DriverParameter permissionsParameter; - if (!userParameter.FindParameter("permissions", - &permissionsParameter)) { +// PRINT(("user: %s, password: %s\n", parameter.ValueAt(0), +// parameter.GetParameterValue("password"))); + error = securityContext->AddUser(userName, password); + if (error != B_OK) + ERROR("ERROR: Failed to add user `%s'\n", userName); + } + + // load shares + for (DriverParameterIterator it = settings.GetParameterIterator("share"); + it.GetNext(¶meter);) { + const char* shareName = parameter.ValueAt(0); + const char* path = parameter.GetParameterValue("path"); + if (!shareName || !path) { + WARN("settings: Skipping invalid share settings entry (no name" + " or no path).\n"); continue; } - Permissions permissions; - for (int32 i = 0; i < permissionsParameter.CountValues(); i++) { - const char* permission = permissionsParameter.ValueAt(i); -// PRINT((" permission: %s\n", permission)); - if (strcmp(permission, "mount") == 0) { - permissions.AddPermissions(MOUNT_SHARE_PERMISSION); - } else if (strcmp(permission, "query") == 0) { - permissions.AddPermissions(QUERY_SHARE_PERMISSION); - } else if (strcmp(permission, "read") == 0) { - permissions.AddPermissions(READ_PERMISSION - | READ_DIR_PERMISSION | RESOLVE_DIR_ENTRY_PERMISSION); - } else if (strcmp(permission, "write") == 0) { - permissions.AddPermissions(WRITE_PERMISSION - | WRITE_DIR_PERMISSION); - } else if (strcmp(permission, "all") == 0) { - permissions.AddPermissions(ALL_PERMISSIONS); - } - } - error = securityContext->SetNodePermissions(share->GetPath(), user, - permissions); +// PRINT(("share: %s, path: %s\n", parameter.ValueAt(0), +// parameter.GetParameterValue("path"))); + Share* share; + error = securityContext->AddShare(shareName, path, &share); if (error != B_OK) { - ERROR("ERROR: Failed to set permissions for share `%s'\n", - share->GetName()); + ERROR("ERROR: Failed to add share `%s'\n", shareName); + continue; + } + BReference shareReference(share, true); + DriverParameter userParameter; + // iterate through the share users + for (DriverParameterIterator userIt + = parameter.GetParameterIterator("user"); + userIt.GetNext(&userParameter);) { + const char* userName = userParameter.ValueAt(0); +// PRINT((" user: %s\n", userName)); + User* user = securityContext->FindUser(userName); + if (!user) { + ERROR("ERROR: Undefined user `%s'.\n", userName); + continue; + } + BReference userReference(user, true); + DriverParameter permissionsParameter; + if (!userParameter.FindParameter("permissions", + &permissionsParameter)) { + continue; + } + Permissions permissions; + for (int32 i = 0; i < permissionsParameter.CountValues(); i++) { + const char* permission = permissionsParameter.ValueAt(i); +// PRINT((" permission: %s\n", permission)); + if (strcmp(permission, "mount") == 0) { + permissions.AddPermissions(MOUNT_SHARE_PERMISSION); + } else if (strcmp(permission, "query") == 0) { + permissions.AddPermissions(QUERY_SHARE_PERMISSION); + } else if (strcmp(permission, "read") == 0) { + permissions.AddPermissions(READ_PERMISSION + | READ_DIR_PERMISSION | RESOLVE_DIR_ENTRY_PERMISSION); + } else if (strcmp(permission, "write") == 0) { + permissions.AddPermissions(WRITE_PERMISSION + | WRITE_DIR_PERMISSION); + } else if (strcmp(permission, "all") == 0) { + permissions.AddPermissions(ALL_PERMISSIONS); + } + } + error = securityContext->SetNodePermissions(share->GetPath(), user, + permissions); + if (error != B_OK) { + ERROR("ERROR: Failed to set permissions for share `%s'\n", + share->GetName()); + } } } } @@ -929,8 +932,8 @@ NetFSServer::_LoadSettings() // if existing load the settings BEntry bEntry; - if (FDManager::SetEntry(&bEntry, filePath.Path()) == B_OK - && bEntry.Exists()) { + if (FDManager::SetEntry(&bEntry, filePath.Path()) != B_OK + || !bEntry.Exists()) { return B_ENTRY_NOT_FOUND; } diff --git a/src/add-ons/kernel/file_systems/netfs/server/NetFSServer.h b/src/add-ons/kernel/file_systems/netfs/server/NetFSServer.h index 0fa5dfbb38..c90b36c76b 100644 --- a/src/add-ons/kernel/file_systems/netfs/server/NetFSServer.h +++ b/src/add-ons/kernel/file_systems/netfs/server/NetFSServer.h @@ -87,10 +87,10 @@ private: thread_id fConnectionListenerThread; thread_id fConnectionDeleter; thread_id fBroadcaster; - vint32 fBroadcastingSocket; + int32 fBroadcastingSocket; sem_id fBroadcasterSemaphore; thread_id fServerInfoConnectionListener; - vint32 fServerInfoConnectionListenerSocket; + int32 fServerInfoConnectionListenerSocket; int32 fServerInfoUpdated; bool fUseBroadcasting; volatile bool fTerminating; diff --git a/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/Settings.cpp b/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/Settings.cpp index 7f675ad7de..be5da235c1 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/Settings.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/Settings.cpp @@ -2,6 +2,7 @@ #include +#include #include #include @@ -13,7 +14,13 @@ using std::nothrow; -static const char *kFSName = "userlandfs"; +static const directory_which kDirectories[] = { + B_USER_NONPACKAGED_DATA_DIRECTORY, + B_USER_DATA_DIRECTORY, + B_SYSTEM_NONPACKAGED_DATA_DIRECTORY, + B_SYSTEM_DATA_DIRECTORY +}; +static const char *kFSSubpath = "/userlandfs/file_systems/"; // IOCtlInfoMap struct Settings::IOCtlInfoMap : public HashMap, IOCtlInfo*> { @@ -163,21 +170,48 @@ Settings::SetTo(const char* fsName) fIOCtlInfos = new(nothrow) IOCtlInfoMap; if (!fIOCtlInfos) RETURN_ERROR(B_NO_MEMORY); - // load the driver settings and find the entry for the FS - void *settings = load_driver_settings(kFSName); - const driver_parameter *fsParameter = NULL; - const driver_settings *ds = get_driver_settings(settings); - if (!ds) - RETURN_ERROR(B_ENTRY_NOT_FOUND); - fsParameter = _FindFSParameter(ds, fsName); - // init the object and unload the settings - status_t error = B_OK; - if (fsParameter) - _Init(ds, fsParameter); - else - error = B_ENTRY_NOT_FOUND; - unload_driver_settings(settings); - return B_OK; + + // load the driver settings for the FS + char path[B_PATH_NAME_LENGTH]; + for (size_t i = 0; i < sizeof(kDirectories) / sizeof(kDirectories[0]); + i++) { + if (find_directory(kDirectories[i], -1, false, (char*)&path, + B_PATH_NAME_LENGTH) != B_OK) { + continue; + } + + // construct the path within the directory + strlcat(path, kFSSubpath, B_PATH_NAME_LENGTH); + strlcat(path, fsName, B_PATH_NAME_LENGTH); + + // load the file at the constructed path + void *settings = load_driver_settings((char*)&path); + if (!settings) + continue; + + // get the settings from the loaded file + const driver_settings *ds = get_driver_settings(settings); + if (!ds) { + unload_driver_settings(settings); + continue; + } + + // get the parameter from the settings + const driver_parameter *fsParameter = NULL; + fsParameter = _FindFSParameter(ds, fsName); + + // init the object and unload the settings + if (fsParameter) + _Init(ds, fsParameter); + unload_driver_settings(settings); + + // if we found the parameter, we're done + if (fsParameter) + return B_OK; + } + + // if we get here, we did not find the parameter + return B_ENTRY_NOT_FOUND; } // Unset diff --git a/src/data/package_infos/generic/netfs b/src/data/package_infos/generic/netfs new file mode 100644 index 0000000000..2775cdaeaf --- /dev/null +++ b/src/data/package_infos/generic/netfs @@ -0,0 +1,21 @@ +name netfs +version %HAIKU_VERSION% +architecture %HAIKU_PACKAGING_ARCH% +summary "NetFS" + +description "The package contains the NetFS add-on and servers." + +packager "The Haiku build system" +vendor "Haiku Project" + +copyrights "2001-2014 Haiku, Inc. et al" +licenses "MIT" + +provides { + netfs = %HAIKU_VERSION% compat >= R1~alpha1 +} + +requires { + userlandfs +} +