1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/libfsserver/lib/files/file_object_registry.cc Mon Sep 27 01:30:05 2021 +0200
1.3 @@ -0,0 +1,189 @@
1.4 +/*
1.5 + * File registry and opening functionality.
1.6 + *
1.7 + * Copyright (C) 2021 Paul Boddie <paul@boddie.org.uk>
1.8 + *
1.9 + * This program is free software; you can redistribute it and/or
1.10 + * modify it under the terms of the GNU General Public License as
1.11 + * published by the Free Software Foundation; either version 2 of
1.12 + * the License, or (at your option) any later version.
1.13 + *
1.14 + * This program is distributed in the hope that it will be useful,
1.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.17 + * GNU General Public License for more details.
1.18 + *
1.19 + * You should have received a copy of the GNU General Public License
1.20 + * along with this program; if not, write to the Free Software
1.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
1.22 + * Boston, MA 02110-1301, USA
1.23 + */
1.24 +
1.25 +#include "directory_resource.h"
1.26 +#include "file_object_registry.h"
1.27 +#include "file_pager.h"
1.28 +
1.29 +#include <systypes/fcntl.h>
1.30 +
1.31 +
1.32 +
1.33 +/* The file object registry provides a memory page collection to the page
1.34 + mappers it creates. */
1.35 +
1.36 +FileObjectRegistry::FileObjectRegistry(Pages *pages)
1.37 +: _pages(pages)
1.38 +{
1.39 +}
1.40 +
1.41 +
1.42 +
1.43 +/* Convert opening flags to map-compatible paging flags. */
1.44 +
1.45 +map_flags_t FileObjectRegistry::get_flags(flags_t flags)
1.46 +{
1.47 + return flags & (O_WRONLY | O_RDWR) ? L4RE_DS_MAP_FLAG_RW : L4RE_DS_MAP_FLAG_RO;
1.48 +}
1.49 +
1.50 +
1.51 +
1.52 +/* Obtain any active provider for 'fileid'. */
1.53 +
1.54 +long FileObjectRegistry::find_directory_provider(fileid_t fileid,
1.55 + DirectoryProvider **directory_provider)
1.56 +{
1.57 + /* Obtain any registered provider. */
1.58 +
1.59 + Accountable *provider = get(fileid);
1.60 +
1.61 + if (provider != NULL)
1.62 + {
1.63 + *directory_provider = dynamic_cast<DirectoryProvider *>(provider);
1.64 +
1.65 + if ((*directory_provider) != NULL)
1.66 + return L4_EOK;
1.67 + else
1.68 + return -L4_EIO;
1.69 + }
1.70 +
1.71 + return -L4_ENOENT;
1.72 +}
1.73 +
1.74 +/* Obtain a provider for the 'fileid' or register a new one. */
1.75 +
1.76 +long FileObjectRegistry::get_directory_provider(FileOpening *opening,
1.77 + const char *path, flags_t flags,
1.78 + fileid_t fileid,
1.79 + DirectoryProvider **directory_provider)
1.80 +{
1.81 + long err = find_directory_provider(fileid, directory_provider);
1.82 +
1.83 + if (err != -L4_ENOENT)
1.84 + return err;
1.85 +
1.86 + /* Make an accessor and a provider to encapsulate it. */
1.87 +
1.88 + DirectoryAccessor *accessor;
1.89 + err = opening->make_directory_accessor(path, flags, fileid, &accessor);
1.90 +
1.91 + if (err)
1.92 + return err;
1.93 +
1.94 + *directory_provider = new DirectoryProvider(accessor);
1.95 +
1.96 + /* Register the provider. */
1.97 +
1.98 + set(fileid, *directory_provider);
1.99 + return L4_EOK;
1.100 +}
1.101 +
1.102 +/* Obtain a provider for the 'fileid' or register a new one. */
1.103 +
1.104 +long FileObjectRegistry::get_file_provider(FileOpening *opening,
1.105 + const char *path, flags_t flags,
1.106 + fileid_t fileid,
1.107 + FileProvider **file_provider)
1.108 +{
1.109 + /* Obtain any registered provider. */
1.110 +
1.111 + Accountable *provider = get(fileid);
1.112 +
1.113 + if (provider != NULL)
1.114 + {
1.115 + *file_provider = dynamic_cast<FileProvider *>(provider);
1.116 +
1.117 + if ((*file_provider) != NULL)
1.118 + return L4_EOK;
1.119 + else
1.120 + return -L4_EIO;
1.121 + }
1.122 +
1.123 + /* Make an accessor, page mapper, and a provider to encapsulate them. */
1.124 +
1.125 + Accessor *accessor;
1.126 + long err = opening->make_accessor(path, flags, fileid, &accessor);
1.127 +
1.128 + if (err)
1.129 + return err;
1.130 +
1.131 + PageMapper *mapper = new PageMapper(accessor, _pages);
1.132 + *file_provider = new FileProvider(mapper);
1.133 +
1.134 + /* Register the provider. */
1.135 +
1.136 + set(fileid, *file_provider);
1.137 + return L4_EOK;
1.138 +}
1.139 +
1.140 +
1.141 +
1.142 +/* Return a directory resource initialised with a provider. */
1.143 +
1.144 +long FileObjectRegistry::get_directory(FileOpening *opening, const char *path,
1.145 + flags_t flags, fileid_t fileid,
1.146 + Resource **resource)
1.147 +{
1.148 + std::lock_guard<std::mutex> guard(_lock);
1.149 +
1.150 + /* Obtain any existing provider registered for the object, or make a new
1.151 + provider. */
1.152 +
1.153 + DirectoryProvider *provider;
1.154 + long err = get_directory_provider(opening, path, flags, fileid, &provider);
1.155 +
1.156 + if (err)
1.157 + return err;
1.158 +
1.159 + /* Initialise the resource with the provider and a reference to this object
1.160 + for detaching from the provider. */
1.161 +
1.162 + provider->attach();
1.163 + *resource = new DirectoryResource(fileid, provider, this);
1.164 + return L4_EOK;
1.165 +}
1.166 +
1.167 +/* Return a pager initialised with a provider, page mapper and accessor. */
1.168 +
1.169 +long FileObjectRegistry::get_pager(FileOpening *opening, const char *path,
1.170 + flags_t flags, fileid_t fileid,
1.171 + Pager **pager)
1.172 +{
1.173 + std::lock_guard<std::mutex> guard(_lock);
1.174 +
1.175 + /* Obtain any existing provider registered for the file, or make a new
1.176 + provider. */
1.177 +
1.178 + FileProvider *provider;
1.179 + long err = get_file_provider(opening, path, flags, fileid, &provider);
1.180 +
1.181 + if (err)
1.182 + return err;
1.183 +
1.184 + /* Initialise the pager with the provider and a reference to this object for
1.185 + detaching from the provider. */
1.186 +
1.187 + provider->attach();
1.188 + *pager = new FilePager(fileid, provider, get_flags(flags), this);
1.189 + return L4_EOK;
1.190 +}
1.191 +
1.192 +// vim: tabstop=4 expandtab shiftwidth=4