1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/Control Thu Feb 07 17:30:14 2019 +0100
1.3 @@ -0,0 +1,3 @@
1.4 +requires: libc libipc libfsclient libfsserver
1.5 +provides: vfsserver
1.6 +maintainer: paul@boddie.org.uk
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/Makefile Thu Feb 07 17:30:14 2019 +0100
2.3 @@ -0,0 +1,4 @@
2.4 +PKGDIR ?= .
2.5 +L4DIR ?= $(PKGDIR)/../..
2.6 +
2.7 +include $(L4DIR)/mk/subdir.mk
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/server/Makefile Thu Feb 07 17:30:14 2019 +0100
3.3 @@ -0,0 +1,4 @@
3.4 +PKGDIR ?= ..
3.5 +L4DIR ?= $(PKGDIR)/../..
3.6 +
3.7 +include $(L4DIR)/mk/subdir.mk
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/server/src/Makefile Thu Feb 07 17:30:14 2019 +0100
4.3 @@ -0,0 +1,11 @@
4.4 +PKGDIR ?= ../..
4.5 +L4DIR ?= $(PKGDIR)/../..
4.6 +
4.7 +TARGET = vfsserver
4.8 +MODE = shared
4.9 +
4.10 +SRC_CC = main.cc fspath.cc
4.11 +
4.12 +REQUIRES_LIBS = l4re_c l4re_c-util libipc libfsclient libfsserver
4.13 +
4.14 +include $(L4DIR)/mk/prog.mk
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/server/src/fspath.cc Thu Feb 07 17:30:14 2019 +0100
5.3 @@ -0,0 +1,42 @@
5.4 +/*
5.5 + * Filesystem path utilities.
5.6 + *
5.7 + * Copyright (C) 2018 Paul Boddie <paul@boddie.org.uk>
5.8 + *
5.9 + * This program is free software; you can redistribute it and/or
5.10 + * modify it under the terms of the GNU General Public License as
5.11 + * published by the Free Software Foundation; either version 2 of
5.12 + * the License, or (at your option) any later version.
5.13 + *
5.14 + * This program is distributed in the hope that it will be useful,
5.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
5.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5.17 + * GNU General Public License for more details.
5.18 + *
5.19 + * You should have received a copy of the GNU General Public License
5.20 + * along with this program; if not, write to the Free Software
5.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
5.22 + * Boston, MA 02110-1301, USA
5.23 + */
5.24 +
5.25 +#include <string.h>
5.26 +
5.27 +#include "fspath.h"
5.28 +
5.29 +void rewrite_path(char *path, const char *prefix)
5.30 +{
5.31 + size_t pathlen = strlen(path),
5.32 + prefixlen = strlen(prefix),
5.33 + newpathlen = pathlen - prefixlen;
5.34 + const char *newpath = path + prefixlen;
5.35 +
5.36 + /* Copy the new path (minus the prefix) to the base address. */
5.37 +
5.38 + memmove(path, newpath, strlen(newpath));
5.39 +
5.40 + /* Overwrite remaining traces of the old path. Since the new path has been
5.41 + relocated over the prefix, the remaining traces are as long as the
5.42 + prefix. */
5.43 +
5.44 + memset(path + newpathlen, 0, prefixlen);
5.45 +}
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/server/src/fspath.h Thu Feb 07 17:30:14 2019 +0100
6.3 @@ -0,0 +1,24 @@
6.4 +/*
6.5 + * Filesystem path utilities.
6.6 + *
6.7 + * Copyright (C) 2018 Paul Boddie <paul@boddie.org.uk>
6.8 + *
6.9 + * This program is free software; you can redistribute it and/or
6.10 + * modify it under the terms of the GNU General Public License as
6.11 + * published by the Free Software Foundation; either version 2 of
6.12 + * the License, or (at your option) any later version.
6.13 + *
6.14 + * This program is distributed in the hope that it will be useful,
6.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
6.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6.17 + * GNU General Public License for more details.
6.18 + *
6.19 + * You should have received a copy of the GNU General Public License
6.20 + * along with this program; if not, write to the Free Software
6.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
6.22 + * Boston, MA 02110-1301, USA
6.23 + */
6.24 +
6.25 +#pragma once
6.26 +
6.27 +void rewrite_path(char *path, const char *prefix);
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/server/src/main.cc Thu Feb 07 17:30:14 2019 +0100
7.3 @@ -0,0 +1,297 @@
7.4 +/*
7.5 + * Access several filesystems.
7.6 + *
7.7 + * Copyright (C) 2018, 2019 Paul Boddie <paul@boddie.org.uk>
7.8 + *
7.9 + * This program is free software; you can redistribute it and/or
7.10 + * modify it under the terms of the GNU General Public License as
7.11 + * published by the Free Software Foundation; either version 2 of
7.12 + * the License, or (at your option) any later version.
7.13 + *
7.14 + * This program is distributed in the hope that it will be useful,
7.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
7.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7.17 + * GNU General Public License for more details.
7.18 + *
7.19 + * You should have received a copy of the GNU General Public License
7.20 + * along with this program; if not, write to the Free Software
7.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
7.22 + * Boston, MA 02110-1301, USA
7.23 + */
7.24 +
7.25 +#include <l4/util/util.h>
7.26 +
7.27 +#include <l4/re/c/dataspace.h>
7.28 +#include <l4/re/env.h>
7.29 +#include <l4/re/c/util/cap_alloc.h>
7.30 +#include <l4/sys/err.h>
7.31 +#include <l4/sys/kernel_object.h>
7.32 +#include <l4/sys/types.h>
7.33 +
7.34 +#include <stdlib.h>
7.35 +#include <stdio.h>
7.36 +#include <string.h>
7.37 +#include <unistd.h>
7.38 +
7.39 +#include <fsclient/fs_client.h>
7.40 +#include <fsclient/fsdesc.h>
7.41 +#include <fsclient/fs_ipc.h>
7.42 +#include <fsserver/server.h>
7.43 +#include <ipc/util_ipc.h>
7.44 +#include "fspath.h"
7.45 +
7.46 +
7.47 +
7.48 +/* Virtual filesystem server. */
7.49 +
7.50 +class Vfs_server : public Server
7.51 +{
7.52 +private:
7.53 + /* NOTE: Improvised structure! */
7.54 +
7.55 + l4_cap_idx_t _servers[10];
7.56 + const char *_mountpoints[10];
7.57 + int _mounted = 0;
7.58 +
7.59 +public:
7.60 + explicit Vfs_server()
7.61 + {
7.62 + }
7.63 +
7.64 + void dispatch(ipc_message_t *msg)
7.65 + {
7.66 + switch (l4_msgtag_label(msg->tag))
7.67 + {
7.68 + case Fs_op_mount:
7.69 + mount(msg);
7.70 + break;
7.71 +
7.72 + case Fs_op_open:
7.73 + open(Fs_op_open, msg);
7.74 + break;
7.75 +
7.76 + case Fs_op_getfs:
7.77 + open(Fs_op_getfs, msg);
7.78 + break;
7.79 +
7.80 + default:
7.81 + error(msg, -L4_EBADPROTO);
7.82 + break;
7.83 + }
7.84 + }
7.85 +
7.86 + void open(int op, ipc_message_t *msg)
7.87 + {
7.88 + l4_cap_idx_t server;
7.89 + l4re_ds_t ds;
7.90 + size_t size;
7.91 + char *buffer;
7.92 + long err;
7.93 +
7.94 + /* Obtain the dataspace. */
7.95 +
7.96 + err = import_dataspace(msg, 0, &ds, (l4_addr_t *) &buffer);
7.97 + if (err)
7.98 + {
7.99 + error(msg, -L4_EIO);
7.100 + return;
7.101 + }
7.102 +
7.103 + /* Match the path to a mountpoint. */
7.104 +
7.105 + int selected = find_mountpoint(buffer);
7.106 +
7.107 + if (selected < 0)
7.108 + {
7.109 + error(msg, -L4_ENOENT);
7.110 + return;
7.111 + }
7.112 +
7.113 + /* Rewrite the path for the selected filesystem. */
7.114 +
7.115 + rewrite_path(buffer, _mountpoints[selected]);
7.116 +
7.117 + /* Find the path within the selected filesystem. */
7.118 +
7.119 + /* Propagate the message to the identified filesystem.
7.120 + NOTE: The L4_MSGTAG_PROPAGATE flag is not supported by Fiasco.OC, so this
7.121 + NOTE: object has to act as intermediary. */
7.122 +
7.123 + err = fs_ipc_open(_servers[selected], op, ds, &server, &size);
7.124 + if (err)
7.125 + {
7.126 + error(msg, -L4_EIO);
7.127 + return;
7.128 + }
7.129 +
7.130 + /* Free the capability and buffer from this task. */
7.131 +
7.132 + discard_dataspace(ds, (l4_addr_t) buffer);
7.133 +
7.134 + /* Return the file size. */
7.135 +
7.136 + ipc_message_add_word(msg, size);
7.137 +
7.138 + /* Export and eventually free the server reference from this task. */
7.139 +
7.140 + ipc_message_propagate_item(msg, server);
7.141 + }
7.142 +
7.143 + void mount(ipc_message_t *msg)
7.144 + {
7.145 + l4_cap_idx_t server;
7.146 + l4re_ds_t ds;
7.147 + char *buffer;
7.148 + long err;
7.149 +
7.150 + /* Obtain the filesystem capability. */
7.151 +
7.152 + err = import_capability(msg, 0, &server);
7.153 + if (err)
7.154 + {
7.155 + error(msg, -L4_EIO);
7.156 + return;
7.157 + }
7.158 +
7.159 + /* Obtain the dataspace. */
7.160 +
7.161 + err = import_dataspace(msg, 1, &ds, (l4_addr_t *) &buffer);
7.162 + if (err)
7.163 + {
7.164 + error(msg, -L4_EIO);
7.165 + return;
7.166 + }
7.167 +
7.168 + /* Obtain the object's path. */
7.169 +
7.170 + char *path = buffer;
7.171 +
7.172 + /* Mount the supplied capability. */
7.173 +
7.174 + mount_at_path(server, path);
7.175 +
7.176 + /* Free the capability and buffer from this task. */
7.177 +
7.178 + discard_dataspace(ds, (l4_addr_t) buffer);
7.179 + }
7.180 +
7.181 + /* Non-exported methods. */
7.182 +
7.183 + void mount_at_path(l4_cap_idx_t server, const char *path)
7.184 + {
7.185 + /* NOTE: Should return error, terminate with path separator if absent. */
7.186 +
7.187 + if (_mounted >= 10)
7.188 + return;
7.189 +
7.190 + _servers[_mounted] = server;
7.191 + _mountpoints[_mounted] = strdup(path);
7.192 +
7.193 + _mounted++;
7.194 + }
7.195 +
7.196 + int find_mountpoint(const char *path)
7.197 + {
7.198 + int i, matching;
7.199 + size_t length, longest;
7.200 +
7.201 + if (!_mounted)
7.202 + return -1;
7.203 +
7.204 + matching = -1;
7.205 + longest = 0;
7.206 +
7.207 + /* Find the largest matching path. */
7.208 +
7.209 + for (i = 0; i < _mounted; i++)
7.210 + {
7.211 + length = strlen(_mountpoints[i]);
7.212 +
7.213 + /* The empty mountpoint always matches;
7.214 + suffixed mountpoints may match as prefixes;
7.215 + suffixed mountpoints may match unsuffixed paths;
7.216 + unsuffixed mountpoints must match exactly. */
7.217 +
7.218 + /* NOTE: Unsuffixed mountpoints might support subpaths by insisting on
7.219 + a path separator as the first subsequent character. */
7.220 +
7.221 + if (!length ||
7.222 + ((_mountpoints[i][length - 1] == '/') && !strncmp(_mountpoints[i], path, length)) ||
7.223 + ((_mountpoints[i][length - 1] == '/') && (strlen(path) == length - 1) && !strncmp(_mountpoints[i], path, length - 1)) ||
7.224 + !strcmp(_mountpoints[i], path))
7.225 + {
7.226 + if (length >= longest)
7.227 + matching = i;
7.228 + }
7.229 + }
7.230 +
7.231 + return matching;
7.232 + }
7.233 +};
7.234 +
7.235 +
7.236 +
7.237 +int main(int argc, char *argv[])
7.238 +{
7.239 + FILE *fp;
7.240 + char buffer[256], *sep;
7.241 + l4_cap_idx_t fscap, server;
7.242 +
7.243 + if (argc < 2)
7.244 + {
7.245 + printf("Need a mount table.\n");
7.246 + return 1;
7.247 + }
7.248 +
7.249 + /* Initialise and register a new server object. */
7.250 +
7.251 + Vfs_server server_obj;
7.252 +
7.253 + if (bind_to_capability("export", l4_umword_t(&server_obj), &server))
7.254 + {
7.255 + printf("Could not bind thread.\n");
7.256 + return 1;
7.257 + }
7.258 +
7.259 + /* Mount filesystems. */
7.260 +
7.261 + fp = fopen(argv[1], "r");
7.262 + if (fp == NULL)
7.263 + {
7.264 + printf("Could not open %s.\n", argv[1]);
7.265 + return 1;
7.266 + }
7.267 +
7.268 + /* Obtain capabilities for mountpoints. */
7.269 +
7.270 + while (fgets(buffer, 256, fp) != NULL)
7.271 + {
7.272 + sep = strchr(buffer, (int) '\t');
7.273 + if (sep == NULL)
7.274 + continue;
7.275 +
7.276 + /* Terminate newline-suffixed strings. */
7.277 +
7.278 + if (sep[strlen(sep) - 1] == '\n')
7.279 + sep[strlen(sep) - 1] = '\0';
7.280 +
7.281 + /* Obtain the named capability. */
7.282 +
7.283 + fscap = l4re_env_get_cap(sep + 1);
7.284 +
7.285 + if (l4_is_invalid_cap(fscap))
7.286 + continue;
7.287 +
7.288 + /* Terminate the path and register the mountpoint. */
7.289 +
7.290 + *sep = '\0';
7.291 + server_obj.mount_at_path(fscap, buffer);
7.292 + }
7.293 +
7.294 + fclose(fp);
7.295 +
7.296 + /* Enter the IPC server loop expecting at most two items. */
7.297 +
7.298 + server_loop(2);
7.299 + return 0;
7.300 +}