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
This commit is contained in:
Adrien Destugues 2014-11-17 15:24:07 +01:00
parent 28627b28aa
commit 83b1a68c52
13 changed files with 355 additions and 135 deletions

View File

@ -6,6 +6,7 @@ local packages =
HaikuUserguide
HaikuWelcome
MakefileEngine
NetFS
UserlandFS
;

View File

@ -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 = <driver-settings>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 = <driver-settings>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 ;

27
build/jam/packages/NetFS Normal file
View File

@ -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 ;

View File

@ -15,6 +15,7 @@ local packages =
haiku_userguide
haiku_welcome
makefile_engine
netfs
userland_fs
haiku_$(secondaryArchs)

3
data/bin/netfs_mount Normal file
View File

@ -0,0 +1,3 @@
/system/servers/authentication_server &
mkdir /network
mount -t userlandfs -p "netfs" /network

View File

@ -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
}
}

146
docs/add-ons/NetFS.html Normal file
View File

@ -0,0 +1,146 @@
<!--
If you move this file, you must update the package rules file at
build/jam/packages/NetFS to reflect the new location. Otherwise the package will
not build.
-->
<html>
<head>
<title>NetFS</title>
<style>
.code {
font-family: monospace;
background: #eee;
border: 1px solid black;
whitespace: pre;
padding: 1em;
}
span.code {
padding: 0;
border: 0;
}
</style>
</head>
<body>
<h1 align="center">NetFS</h1>
<hr />
<h2 align="center">Client</h2>
<p>To run the client, execute the following at the command line:</p>
<pre class="code">
$ netfs_mount
</pre>
<p>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.</p>
<p>You can also run the steps individually:</p>
<pre class="code">
$ /system/servers/authentication_server &amp;
$ mkdir /network
$ mount -t userlandfs -p "netfs" /network
</pre>
<hr />
<h2 align="center">Server</h2>
<p>To run the server:</p>
<pre class="code">
$ netfs_server_prefs launch
</pre>
<p>You can also start the server directly if you prefer.</p>
<pre class="code">
$ /system/servers/netfs_server &amp;
</pre>
<p>The server will then run until you shut down your computer, but it is also
possible to stop it manually.</p>
<pre class="code">
$ netfs_server_prefs terminate
</pre>
<p>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.</p>
<pre class="code">
$ netfs_server_prefs add user &lt;name&gt; [&lt;password&gt;]
</pre>
<p>Next create a shared folder and assign a user some permissions on it.</p>
<pre class="code">
$ netfs_server_prefs add share &lt;name&gt; &lt;path&gt;
$ netfs_server_prefs permissions &lt;user&gt; &lt;share&gt; <flags>
</pre>
<p><span class="code">name</span> is the name that will appear to clients when
they connect to your server. <span class="code">flags</span> is one or more of:
<span class="code">m</span> = mount, <span class="code">r</span> = read, <span
class="code">w</span> = write, <span class="code">q</span> = query.</p>
<p>Don't forget to save your settings.</p>
<pre class="code">
$ netfs_server_prefs save
</pre>
<p>The <span class="code">netfs_server_prefs</span> tool can also list and
remove users and shares. See the help for details.</p>
<pre class="code">
$ netfs_server_prefs --help
</pre>
<hr />
<h2 align="center">Fallback Settings File</h2>
<p>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 <span
class="code">/boot/home/config/settings/netfs/netfs_server_fallback</span>. (If
neither the main settings file nor the fallback settings file can be loaded, the
server will have no users or shares defined.)
<p>Here is an example of a fallback settings file.</p>
<pre class="code">
# 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
}
}
</pre>
</body>

View File

@ -520,7 +520,7 @@ ClientVolume::_NextVolumeID()
}
// sNextVolumeID
vint32 ClientVolume::sNextVolumeID = 0;
int32 ClientVolume::sNextVolumeID = 0;
// #pragma -

View File

@ -27,7 +27,7 @@ public:
User** user);
private:
vint32 fSocket;
int32 fSocket;
};
#endif // NET_FS_INSECURE_CONNECTION_LISTENER_H

View File

@ -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<SecurityContext> 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(&parameter);) {
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(&parameter);) {
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<Share> 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(&parameter);) {
const char* userName = parameter.ValueAt(0);
const char* password = parameter.GetParameterValue("password");
if (!userName) {
WARN("Skipping nameless user settings entry.\n");
continue;
}
BReference<User> 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(&parameter);) {
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<Share> 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<User> 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;
}

View File

@ -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;

View File

@ -2,6 +2,7 @@
#include <new>
#include <stdio.h>
#include <stdlib.h>
#include <driver_settings.h>
@ -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<HashKey32<int>, 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

View File

@ -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
}