1 /* 2 * File registry and opening functionality. 3 * 4 * Copyright (C) 2021 Paul Boddie <paul@boddie.org.uk> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation; either version 2 of 9 * the License, or (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 * Boston, MA 02110-1301, USA 20 */ 21 22 #include "directory_resource.h" 23 #include "file_pager.h" 24 #include "file_paging.h" 25 26 #include <systypes/fcntl.h> 27 28 29 30 /* The file paging coordinator provides a memory page collection to the page 31 mappers it creates. */ 32 33 FilePaging::FilePaging(Pages *pages) 34 : _pages(pages) 35 { 36 } 37 38 39 40 /* Convert opening flags to map-compatible paging flags. */ 41 42 map_flags_t FilePaging::get_flags(flags_t flags) 43 { 44 return flags & (O_WRONLY | O_RDWR) ? L4RE_DS_MAP_FLAG_RW : L4RE_DS_MAP_FLAG_RO; 45 } 46 47 48 49 /* Obtain a provider for the 'fileid' or register a new one. */ 50 51 long FilePaging::get_directory_provider(FileOpening *opening, const char *path, 52 flags_t flags, fileid_t fileid, 53 DirectoryProvider **directory_provider) 54 { 55 /* Obtain any registered provider. */ 56 57 Accountable *provider = get(fileid); 58 59 if (provider != NULL) 60 { 61 *directory_provider = dynamic_cast<DirectoryProvider *>(provider); 62 63 if ((*directory_provider) != NULL) 64 return L4_EOK; 65 else 66 return -L4_EIO; 67 } 68 69 /* Make an accessor and a provider to encapsulate it. */ 70 71 DirectoryAccessor *accessor; 72 long err = opening->make_directory_accessor(path, flags, fileid, &accessor); 73 74 if (err) 75 return err; 76 77 *directory_provider = new DirectoryProvider(accessor); 78 79 /* Register the provider. */ 80 81 set(fileid, *directory_provider); 82 return L4_EOK; 83 } 84 85 /* Obtain a provider for the 'fileid' or register a new one. */ 86 87 long FilePaging::get_file_provider(FileOpening *opening, const char *path, 88 flags_t flags, fileid_t fileid, 89 FileProvider **file_provider) 90 { 91 /* Obtain any registered provider. */ 92 93 Accountable *provider = get(fileid); 94 95 if (provider != NULL) 96 { 97 *file_provider = dynamic_cast<FileProvider *>(provider); 98 99 if ((*file_provider) != NULL) 100 return L4_EOK; 101 else 102 return -L4_EIO; 103 } 104 105 /* Make an accessor, page mapper, and a provider to encapsulate them. */ 106 107 Accessor *accessor; 108 long err = opening->make_accessor(path, flags, fileid, &accessor); 109 110 if (err) 111 return err; 112 113 PageMapper *mapper = new PageMapper(accessor, _pages); 114 *file_provider = new FileProvider(mapper); 115 116 /* Register the provider. */ 117 118 set(fileid, *file_provider); 119 return L4_EOK; 120 } 121 122 123 124 /* Return a directory resource initialised with a provider. */ 125 126 long FilePaging::get_directory(FileOpening *opening, const char *path, 127 flags_t flags, fileid_t fileid, 128 Resource **resource) 129 { 130 std::lock_guard<std::mutex> guard(_lock); 131 132 /* Obtain any existing provider registered for the object, or make a new 133 provider. */ 134 135 DirectoryProvider *provider; 136 long err = get_directory_provider(opening, path, flags, fileid, &provider); 137 138 if (err) 139 return err; 140 141 /* Initialise the resource with the provider and a reference to this object 142 for detaching from the provider. */ 143 144 provider->attach(); 145 *resource = new DirectoryResource(fileid, provider, this); 146 return L4_EOK; 147 } 148 149 /* Return a pager initialised with a provider, page mapper and accessor. */ 150 151 long FilePaging::get_pager(FileOpening *opening, const char *path, 152 flags_t flags, fileid_t fileid, Pager **pager) 153 { 154 std::lock_guard<std::mutex> guard(_lock); 155 156 /* Obtain any existing provider registered for the file, or make a new 157 provider. */ 158 159 FileProvider *provider; 160 long err = get_file_provider(opening, path, flags, fileid, &provider); 161 162 if (err) 163 return err; 164 165 /* Initialise the pager with the provider and a reference to this object for 166 detaching from the provider. */ 167 168 provider->attach(); 169 *pager = new FilePager(fileid, provider, get_flags(flags), this); 170 return L4_EOK; 171 } 172 173 // vim: tabstop=4 expandtab shiftwidth=4