1.1 --- a/server/src/main.cc Sat Jun 29 17:56:01 2019 +0200
1.2 +++ b/server/src/main.cc Sat Jun 29 22:32:04 2019 +0200
1.3 @@ -31,6 +31,8 @@
1.4 #include <string.h>
1.5 #include <unistd.h>
1.6
1.7 +#include <map>
1.8 +
1.9 #include <fsclient/fsdesc.h>
1.10 #include <fsclient/fs_ipc.h>
1.11 #include <fsclient/ops.h>
1.12 @@ -39,16 +41,20 @@
1.13
1.14
1.15
1.16 +/* Mountpoint-to-server mapping. */
1.17 +
1.18 +typedef std::map<const char *, l4_cap_idx_t> MountTable;
1.19 +typedef std::map<const char *, l4_cap_idx_t>::iterator MountTableIterator;
1.20 +typedef std::map<const char *, l4_cap_idx_t>::value_type MountTableEntry;
1.21 +
1.22 +
1.23 +
1.24 /* Virtual filesystem server. */
1.25
1.26 class Vfs_server : public OpeningServer
1.27 {
1.28 private:
1.29 - /* NOTE: Improvised structure! */
1.30 -
1.31 - l4_cap_idx_t _servers[10];
1.32 - const char *_mountpoints[10];
1.33 - int _mounted = 0;
1.34 + MountTable _servers;
1.35
1.36 public:
1.37 explicit Vfs_server()
1.38 @@ -109,9 +115,9 @@
1.39
1.40 /* Match the path to a mountpoint. */
1.41
1.42 - int selected = find_mountpoint(desc.obj.buffer);
1.43 + MountTableIterator entry = find_mountpoint(desc.obj.buffer);
1.44
1.45 - if (selected < 0)
1.46 + if (entry == _servers.end())
1.47 {
1.48 ipc_message_send_error(msg, -L4_ENOENT);
1.49 return;
1.50 @@ -119,7 +125,7 @@
1.51
1.52 /* Rewrite the path for the selected filesystem. */
1.53
1.54 - rewrite_path(desc.obj.buffer, _mountpoints[selected]);
1.55 + rewrite_path(desc.obj.buffer, entry->first);
1.56
1.57 /* Find the path within the selected filesystem. */
1.58
1.59 @@ -127,7 +133,7 @@
1.60 NOTE: The L4_MSGTAG_PROPAGATE flag is not supported by Fiasco.OC, so this
1.61 NOTE: object has to act as intermediary. */
1.62
1.63 - desc.server = _servers[selected];
1.64 + desc.server = entry->second;
1.65
1.66 err = fs_ipc_open(&desc, flags, op);
1.67 if (err)
1.68 @@ -191,53 +197,55 @@
1.69
1.70 void mount_at_path(l4_cap_idx_t server, const char *path)
1.71 {
1.72 - /* NOTE: Should return error, terminate with path separator if absent. */
1.73 -
1.74 - if (_mounted >= 10)
1.75 - return;
1.76 + /* NOTE: Should terminate with path separator if absent.
1.77 + NOTE: Should also ensure zero termination. */
1.78
1.79 - _servers[_mounted] = server;
1.80 - _mountpoints[_mounted] = strdup(path);
1.81 -
1.82 - _mounted++;
1.83 + _servers.insert(MountTableEntry(strdup(path), server));
1.84 }
1.85
1.86 - int find_mountpoint(const char *path)
1.87 + MountTableIterator find_mountpoint(const char *path)
1.88 {
1.89 - int i, matching;
1.90 - size_t length, longest;
1.91 + /* Search only until "later" paths are encountered. Such paths will either
1.92 + incorporate components that are themselves greater than those in the path
1.93 + or will be longer than the path. */
1.94
1.95 - if (!_mounted)
1.96 - return -1;
1.97 -
1.98 - matching = -1;
1.99 - longest = 0;
1.100 + MountTableIterator it, found = _servers.end(),
1.101 + limit = _servers.upper_bound(path);
1.102 + size_t length, longest = 0;
1.103
1.104 /* Find the largest matching path. */
1.105
1.106 - for (i = 0; i < _mounted; i++)
1.107 + for (it = _servers.begin(); it != limit; it++)
1.108 {
1.109 - length = strlen(_mountpoints[i]);
1.110 -
1.111 - /* The empty mountpoint always matches;
1.112 - suffixed mountpoints may match as prefixes;
1.113 - suffixed mountpoints may match unsuffixed paths;
1.114 - unsuffixed mountpoints must match exactly. */
1.115 + length = match_path(path, it->first);
1.116
1.117 - /* NOTE: Unsuffixed mountpoints might support subpaths by insisting on
1.118 - a path separator as the first subsequent character. */
1.119 -
1.120 - if (!length ||
1.121 - ((_mountpoints[i][length - 1] == '/') && !strncmp(_mountpoints[i], path, length)) ||
1.122 - ((_mountpoints[i][length - 1] == '/') && (strlen(path) == length - 1) && !strncmp(_mountpoints[i], path, length - 1)) ||
1.123 - !strcmp(_mountpoints[i], path))
1.124 - {
1.125 - if (length >= longest)
1.126 - matching = i;
1.127 - }
1.128 + if (length >= longest)
1.129 + found = it;
1.130 }
1.131
1.132 - return matching;
1.133 + return found;
1.134 + }
1.135 +
1.136 + ssize_t match_path(const char *path, const char *mountpoint)
1.137 + {
1.138 + size_t length = strlen(mountpoint);
1.139 + int suffixed = (mountpoint[length - 1] == '/');
1.140 +
1.141 + /* The empty mountpoint always matches;
1.142 + suffixed mountpoints may match as prefixes;
1.143 + suffixed mountpoints may match unsuffixed paths;
1.144 + unsuffixed mountpoints must match exactly. */
1.145 +
1.146 + /* NOTE: Unsuffixed mountpoints might support subpaths by insisting on
1.147 + a path separator as the first subsequent character. */
1.148 +
1.149 + if (!length ||
1.150 + (suffixed && !strncmp(mountpoint, path, length)) ||
1.151 + (suffixed && (strlen(path) == length - 1) && !strncmp(mountpoint, path, length - 1)) ||
1.152 + !strcmp(mountpoint, path))
1.153 + return length;
1.154 +
1.155 + return -1;
1.156 }
1.157 };
1.158