# HG changeset patch # User Paul Boddie # Date 1561840324 -7200 # Node ID 0d36efa79efbe816842bd4040ead2bcff4b5c6e9 # Parent cd038cc826d8b1ce5fc6936c5bf26ef5fa028df6 Replaced fixed-length arrays with a map. diff -r cd038cc826d8 -r 0d36efa79efb server/src/main.cc --- a/server/src/main.cc Sat Jun 29 17:56:01 2019 +0200 +++ b/server/src/main.cc Sat Jun 29 22:32:04 2019 +0200 @@ -31,6 +31,8 @@ #include #include +#include + #include #include #include @@ -39,16 +41,20 @@ +/* Mountpoint-to-server mapping. */ + +typedef std::map MountTable; +typedef std::map::iterator MountTableIterator; +typedef std::map::value_type MountTableEntry; + + + /* Virtual filesystem server. */ class Vfs_server : public OpeningServer { private: - /* NOTE: Improvised structure! */ - - l4_cap_idx_t _servers[10]; - const char *_mountpoints[10]; - int _mounted = 0; + MountTable _servers; public: explicit Vfs_server() @@ -109,9 +115,9 @@ /* Match the path to a mountpoint. */ - int selected = find_mountpoint(desc.obj.buffer); + MountTableIterator entry = find_mountpoint(desc.obj.buffer); - if (selected < 0) + if (entry == _servers.end()) { ipc_message_send_error(msg, -L4_ENOENT); return; @@ -119,7 +125,7 @@ /* Rewrite the path for the selected filesystem. */ - rewrite_path(desc.obj.buffer, _mountpoints[selected]); + rewrite_path(desc.obj.buffer, entry->first); /* Find the path within the selected filesystem. */ @@ -127,7 +133,7 @@ NOTE: The L4_MSGTAG_PROPAGATE flag is not supported by Fiasco.OC, so this NOTE: object has to act as intermediary. */ - desc.server = _servers[selected]; + desc.server = entry->second; err = fs_ipc_open(&desc, flags, op); if (err) @@ -191,53 +197,55 @@ void mount_at_path(l4_cap_idx_t server, const char *path) { - /* NOTE: Should return error, terminate with path separator if absent. */ - - if (_mounted >= 10) - return; + /* NOTE: Should terminate with path separator if absent. + NOTE: Should also ensure zero termination. */ - _servers[_mounted] = server; - _mountpoints[_mounted] = strdup(path); - - _mounted++; + _servers.insert(MountTableEntry(strdup(path), server)); } - int find_mountpoint(const char *path) + MountTableIterator find_mountpoint(const char *path) { - int i, matching; - size_t length, longest; + /* Search only until "later" paths are encountered. Such paths will either + incorporate components that are themselves greater than those in the path + or will be longer than the path. */ - if (!_mounted) - return -1; - - matching = -1; - longest = 0; + MountTableIterator it, found = _servers.end(), + limit = _servers.upper_bound(path); + size_t length, longest = 0; /* Find the largest matching path. */ - for (i = 0; i < _mounted; i++) + for (it = _servers.begin(); it != limit; it++) { - length = strlen(_mountpoints[i]); - - /* The empty mountpoint always matches; - suffixed mountpoints may match as prefixes; - suffixed mountpoints may match unsuffixed paths; - unsuffixed mountpoints must match exactly. */ + length = match_path(path, it->first); - /* NOTE: Unsuffixed mountpoints might support subpaths by insisting on - a path separator as the first subsequent character. */ - - if (!length || - ((_mountpoints[i][length - 1] == '/') && !strncmp(_mountpoints[i], path, length)) || - ((_mountpoints[i][length - 1] == '/') && (strlen(path) == length - 1) && !strncmp(_mountpoints[i], path, length - 1)) || - !strcmp(_mountpoints[i], path)) - { - if (length >= longest) - matching = i; - } + if (length >= longest) + found = it; } - return matching; + return found; + } + + ssize_t match_path(const char *path, const char *mountpoint) + { + size_t length = strlen(mountpoint); + int suffixed = (mountpoint[length - 1] == '/'); + + /* The empty mountpoint always matches; + suffixed mountpoints may match as prefixes; + suffixed mountpoints may match unsuffixed paths; + unsuffixed mountpoints must match exactly. */ + + /* NOTE: Unsuffixed mountpoints might support subpaths by insisting on + a path separator as the first subsequent character. */ + + if (!length || + (suffixed && !strncmp(mountpoint, path, length)) || + (suffixed && (strlen(path) == length - 1) && !strncmp(mountpoint, path, length - 1)) || + !strcmp(mountpoint, path)) + return length; + + return -1; } };