1.1 --- a/libfsclient/include/fsclient/client.h Sat Sep 18 18:51:43 2021 +0200 1.2 +++ b/libfsclient/include/fsclient/client.h Mon Sep 20 01:16:59 2021 +0200 1.3 @@ -39,8 +39,7 @@ 1.4 file_t *client_open(const char *name, flags_t flags); 1.5 file_t *client_open_using(const char *name, flags_t flags, l4_cap_idx_t server); 1.6 1.7 -file_t *client_opendir(const char *name); 1.8 -file_t *client_opendir_using(const char *name, l4_cap_idx_t server); 1.9 +file_t *client_opendir(file_t *file); 1.10 1.11 long client_pipe(file_t **reader, file_t **writer, flags_t flags); 1.12 long client_pipe_using(file_t **reader, file_t **writer, flags_t flags, l4_cap_idx_t server);
2.1 --- a/libfsclient/include/fsclient/file.h Sat Sep 18 18:51:43 2021 +0200 2.2 +++ b/libfsclient/include/fsclient/file.h Mon Sep 20 01:16:59 2021 +0200 2.3 @@ -145,6 +145,12 @@ 2.4 2.5 2.6 2.7 +/* Directory operations. */ 2.8 + 2.9 +long directory_opendir(file_t *file, file_t *reader); 2.10 + 2.11 + 2.12 + 2.13 EXTERN_C_END 2.14 2.15 // vim: tabstop=2 expandtab shiftwidth=2
3.1 --- a/libfsclient/lib/src/Makefile Sat Sep 18 18:51:43 2021 +0200 3.2 +++ b/libfsclient/lib/src/Makefile Mon Sep 20 01:16:59 2021 +0200 3.3 @@ -15,7 +15,9 @@ 3.4 3.5 # Individual interfaces. 3.6 3.7 -CLIENT_INTERFACES_CC = dataspace file filesystem flush mapped_file notification opener opener_context pipe pipe_opener 3.8 +CLIENT_INTERFACES_CC = dataspace directory file filesystem flush \ 3.9 + mapped_file notification opener \ 3.10 + opener_context pipe pipe_opener 3.11 3.12 # Generated and plain source files. 3.13
4.1 --- a/libfsclient/lib/src/client.cc Sat Sep 18 18:51:43 2021 +0200 4.2 +++ b/libfsclient/lib/src/client.cc Mon Sep 20 01:16:59 2021 +0200 4.3 @@ -247,34 +247,33 @@ 4.4 4.5 4.6 4.7 -/* Open a directory. */ 4.8 +/* Open a directory listing stream via the given directory. */ 4.9 4.10 -file_t *client_opendir(const char *name) 4.11 +file_t *client_opendir(file_t *file) 4.12 { 4.13 - l4_cap_idx_t server = l4re_env_get_cap("server"); 4.14 + if (file == NULL) 4.15 + return NULL; 4.16 4.17 - return client_opendir_using(name, server); 4.18 -} 4.19 - 4.20 -/* Open a directory using a named capability. */ 4.21 + file_t *reader = (file_t *) malloc(sizeof(file_t)); 4.22 4.23 -file_t *client_opendir_using(const char *name, l4_cap_idx_t server) 4.24 -{ 4.25 - file_t *file = client_open_using(name, O_DIRECTORY, server); 4.26 + if (reader == NULL) 4.27 + return NULL; 4.28 4.29 - if (file == NULL) 4.30 + long err = directory_opendir(file, reader); 4.31 + 4.32 + if (err) 4.33 return NULL; 4.34 4.35 /* Set blocking read mode to be able to conveniently read directory entries 4.36 from the stream. */ 4.37 4.38 - if (client_set_blocking(file, NOTIFY_CONTENT_AVAILABLE | NOTIFY_PEER_CLOSED)) 4.39 + if (client_set_blocking(reader, NOTIFY_CONTENT_AVAILABLE | NOTIFY_PEER_CLOSED)) 4.40 { 4.41 - client_close(file); 4.42 + client_close(reader); 4.43 return NULL; 4.44 } 4.45 4.46 - return file; 4.47 + return reader; 4.48 } 4.49 4.50
5.1 --- a/libfsclient/lib/src/file.cc Sat Sep 18 18:51:43 2021 +0200 5.2 +++ b/libfsclient/lib/src/file.cc Mon Sep 20 01:16:59 2021 +0200 5.3 @@ -25,6 +25,7 @@ 5.4 #include <string.h> 5.5 5.6 #include "dataspace_client.h" 5.7 +#include "directory_client.h" 5.8 #include "file_client.h" 5.9 #include "filesystem_client.h" 5.10 #include "flush_client.h" 5.11 @@ -545,4 +546,15 @@ 5.12 return -L4_EINVAL; 5.13 } 5.14 5.15 + 5.16 + 5.17 +/* Obtain a directory listing stream from a directory. */ 5.18 + 5.19 +long directory_opendir(file_t *file, file_t *reader) 5.20 +{ 5.21 + client_Directory directory(file->ref); 5.22 + file_init(reader); 5.23 + return directory.opendir(&reader->size, &reader->ref, &reader->object_flags); 5.24 +} 5.25 + 5.26 // vim: tabstop=2 expandtab shiftwidth=2
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/libfsserver/include/fsserver/directory_accessor.h Mon Sep 20 01:16:59 2021 +0200 6.3 @@ -0,0 +1,38 @@ 6.4 +/* 6.5 + * An object providing access to a filesystem directory. 6.6 + * 6.7 + * Copyright (C) 2021 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 +#include <fsclient/file.h> 6.28 + 6.29 + 6.30 + 6.31 +/* An object providing access to a directory. */ 6.32 + 6.33 +class DirectoryAccessor 6.34 +{ 6.35 +public: 6.36 + virtual ~DirectoryAccessor(); 6.37 + 6.38 + virtual void read_directory(file_t *writer) = 0; 6.39 +}; 6.40 + 6.41 +// vim: tabstop=4 expandtab shiftwidth=4
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/libfsserver/include/fsserver/directory_provider.h Mon Sep 20 01:16:59 2021 +0200 7.3 @@ -0,0 +1,44 @@ 7.4 +/* 7.5 + * An object providing a directory abstraction with notification facilities. 7.6 + * 7.7 + * Copyright (C) 2021 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 +#pragma once 7.26 + 7.27 +#include <fsserver/directory_accessor.h> 7.28 +#include <fsserver/file_notification.h> 7.29 + 7.30 + 7.31 + 7.32 +/* An object providing access to directory functionality. */ 7.33 + 7.34 +class DirectoryProvider : public FileNotification 7.35 +{ 7.36 +protected: 7.37 + DirectoryAccessor *_accessor; 7.38 + 7.39 +public: 7.40 + explicit DirectoryProvider(DirectoryAccessor *accessor); 7.41 + 7.42 + virtual ~DirectoryProvider(); 7.43 + 7.44 + virtual DirectoryAccessor *accessor(); 7.45 +}; 7.46 + 7.47 +// vim: tabstop=4 expandtab shiftwidth=4
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/libfsserver/include/fsserver/directory_resource.h Mon Sep 20 01:16:59 2021 +0200 8.3 @@ -0,0 +1,65 @@ 8.4 +/* 8.5 + * A resource offering support for directory operations. 8.6 + * 8.7 + * Copyright (C) 2021 Paul Boddie <paul@boddie.org.uk> 8.8 + * 8.9 + * This program is free software; you can redistribute it and/or 8.10 + * modify it under the terms of the GNU General Public License as 8.11 + * published by the Free Software Foundation; either version 2 of 8.12 + * the License, or (at your option) any later version. 8.13 + * 8.14 + * This program is distributed in the hope that it will be useful, 8.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 8.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 8.17 + * GNU General Public License for more details. 8.18 + * 8.19 + * You should have received a copy of the GNU General Public License 8.20 + * along with this program; if not, write to the Free Software 8.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, 8.22 + * Boston, MA 02110-1301, USA 8.23 + */ 8.24 + 8.25 +#pragma once 8.26 + 8.27 +#include <fsserver/directory_object_interface.h> 8.28 +#include <fsserver/directory_provider.h> 8.29 +#include <fsserver/file_registry.h> 8.30 +#include <fsserver/resource.h> 8.31 + 8.32 + 8.33 + 8.34 +/* Support for providing access to directories. 8.35 + NOTE: Notification methods to be added when DirectoryObject is extended. */ 8.36 + 8.37 +class DirectoryResource : public Resource, public DirectoryObject 8.38 +{ 8.39 +protected: 8.40 + FileRegistry *_registry; 8.41 + DirectoryProvider *_provider; 8.42 + 8.43 +public: 8.44 + fileid_t fileid; 8.45 + 8.46 + DirectoryResource(fileid_t fileid, DirectoryProvider *provider, 8.47 + FileRegistry *registry); 8.48 + 8.49 + virtual ~DirectoryResource(); 8.50 + 8.51 + virtual void close(); 8.52 + 8.53 + /* Server details. */ 8.54 + 8.55 + int expected_items(); 8.56 + 8.57 + ipc_server_handler_type handler(); 8.58 + 8.59 + void *interface() 8.60 + { return static_cast<DirectoryObject *>(this); } 8.61 + 8.62 + /* Directory reading methods. */ 8.63 + 8.64 + virtual long opendir(offset_t *size, l4_cap_idx_t *cap, 8.65 + object_flags_t *object_flags); 8.66 +}; 8.67 + 8.68 +// vim: tabstop=4 expandtab shiftwidth=4
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/libfsserver/include/fsserver/ext2_directory_accessor.h Mon Sep 20 01:16:59 2021 +0200 9.3 @@ -0,0 +1,72 @@ 9.4 +/* 9.5 + * An object for a directory provided by an Ext2-compatible filesystem. 9.6 + * 9.7 + * Copyright (C) 2021 Paul Boddie <paul@boddie.org.uk> 9.8 + * 9.9 + * This program is free software; you can redistribute it and/or 9.10 + * modify it under the terms of the GNU General Public License as 9.11 + * published by the Free Software Foundation; either version 2 of 9.12 + * the License, or (at your option) any later version. 9.13 + * 9.14 + * This program is distributed in the hope that it will be useful, 9.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 9.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 9.17 + * GNU General Public License for more details. 9.18 + * 9.19 + * You should have received a copy of the GNU General Public License 9.20 + * along with this program; if not, write to the Free Software 9.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, 9.22 + * Boston, MA 02110-1301, USA 9.23 + */ 9.24 + 9.25 +#pragma once 9.26 + 9.27 +#include <ext2fs/ext2fs.h> 9.28 + 9.29 +#include <mem/types.h> 9.30 +#include <fsserver/directory_accessor.h> 9.31 +#include <fsserver/ext2_file_operations.h> 9.32 + 9.33 + 9.34 + 9.35 +/* Forward declarations. */ 9.36 + 9.37 +struct Ext2DirectoryState; 9.38 + 9.39 + 9.40 + 9.41 +/* Support for providing access to files. */ 9.42 + 9.43 +class Ext2DirectoryAccessor : public DirectoryAccessor 9.44 +{ 9.45 +protected: 9.46 + Ext2FileOperations *_ops; 9.47 + fileid_t _fileid; 9.48 + 9.49 +public: 9.50 + explicit Ext2DirectoryAccessor(Ext2FileOperations *ops, fileid_t fileid); 9.51 + 9.52 + virtual ~Ext2DirectoryAccessor(); 9.53 + 9.54 + /* Accessor methods. */ 9.55 + 9.56 + virtual void read_directory(file_t *writer); 9.57 + 9.58 + /* Helper methods. */ 9.59 + 9.60 + int write_directory_entry(struct Ext2DirectoryState *dir); 9.61 +}; 9.62 + 9.63 + 9.64 + 9.65 +/* Helper structures. */ 9.66 + 9.67 +struct Ext2DirectoryState 9.68 +{ 9.69 + Ext2DirectoryAccessor *directory; 9.70 + file_t *writer; 9.71 + struct ext2_dir_entry *entry; 9.72 + long offset; 9.73 +}; 9.74 + 9.75 +// vim: tabstop=4 expandtab shiftwidth=4
10.1 --- a/libfsserver/include/fsserver/ext2_file_opener.h Sat Sep 18 18:51:43 2021 +0200 10.2 +++ b/libfsserver/include/fsserver/ext2_file_opener.h Mon Sep 20 01:16:59 2021 +0200 10.3 @@ -30,12 +30,6 @@ 10.4 10.5 10.6 10.7 -/* Forward declarations. */ 10.8 - 10.9 -struct Ext2FileOpenerDir; 10.10 - 10.11 - 10.12 - 10.13 /* Support for providing access to files. */ 10.14 10.15 class Ext2FileOpener : public OpenerResource 10.16 @@ -50,12 +44,6 @@ 10.17 10.18 virtual bool accessing_file(const char *path, flags_t flags, fileid_t fileid); 10.19 10.20 - /* Convenience methods obtaining different pager types. */ 10.21 - 10.22 - virtual long get_directory(const char *path, flags_t flags, fileid_t fileid, 10.23 - offset_t *size, l4_cap_idx_t *cap, 10.24 - object_flags_t *object_flags); 10.25 - 10.26 public: 10.27 explicit Ext2FileOpener(FilePaging *paging, Ext2FileOperations *ops, user_t user) 10.28 : OpenerResource(paging), _ops(ops), _user(user) 10.29 @@ -64,29 +52,16 @@ 10.30 10.31 virtual ~Ext2FileOpener(); 10.32 10.33 - /* Configurable methods. */ 10.34 + /* File opening methods. */ 10.35 10.36 virtual long get_fileid(const char *path, flags_t flags, fileid_t *fileid); 10.37 10.38 - virtual long make_accessor(const char *path, flags_t flags, fileid_t fileid, Accessor **accessor); 10.39 - 10.40 - /* Helper methods. */ 10.41 - 10.42 - void read_directory(fileid_t fileid, file_t *writer); 10.43 - 10.44 - int write_directory_entry(struct Ext2FileOpenerDir *dir); 10.45 -}; 10.46 - 10.47 + virtual long make_accessor(const char *path, flags_t flags, fileid_t fileid, 10.48 + Accessor **accessor); 10.49 10.50 - 10.51 -/* Helper structures. */ 10.52 - 10.53 -struct Ext2FileOpenerDir 10.54 -{ 10.55 - Ext2FileOpener *opener; 10.56 - file_t *writer; 10.57 - struct ext2_dir_entry *entry; 10.58 - long offset; 10.59 + virtual long make_directory_accessor(const char *path, flags_t flags, 10.60 + fileid_t fileid, 10.61 + DirectoryAccessor **accessor); 10.62 }; 10.63 10.64 // vim: tabstop=4 expandtab shiftwidth=4
11.1 --- a/libfsserver/include/fsserver/file_opening.h Sat Sep 18 18:51:43 2021 +0200 11.2 +++ b/libfsserver/include/fsserver/file_opening.h Mon Sep 20 01:16:59 2021 +0200 11.3 @@ -22,6 +22,7 @@ 11.4 #pragma once 11.5 11.6 #include <fsserver/accessor.h> 11.7 +#include <fsserver/directory_accessor.h> 11.8 11.9 11.10 11.11 @@ -32,7 +33,12 @@ 11.12 public: 11.13 virtual long get_fileid(const char *path, flags_t flags, fileid_t *fileid) = 0; 11.14 11.15 - virtual long make_accessor(const char *path, flags_t flags, fileid_t fileid, Accessor **accessor) = 0; 11.16 + virtual long make_accessor(const char *path, flags_t flags, fileid_t fileid, 11.17 + Accessor **accessor) = 0; 11.18 + 11.19 + virtual long make_directory_accessor(const char *path, flags_t flags, 11.20 + fileid_t fileid, 11.21 + DirectoryAccessor **accessor) = 0; 11.22 }; 11.23 11.24 // vim: tabstop=4 expandtab shiftwidth=4
12.1 --- a/libfsserver/include/fsserver/file_pager.h Sat Sep 18 18:51:43 2021 +0200 12.2 +++ b/libfsserver/include/fsserver/file_pager.h Mon Sep 20 01:16:59 2021 +0200 12.3 @@ -23,7 +23,8 @@ 12.4 12.5 #include <fsserver/mapped_file_object_interface.h> 12.6 #include <fsserver/pager.h> 12.7 -#include <fsserver/file_paging.h> 12.8 +#include <fsserver/file_provider.h> 12.9 +#include <fsserver/file_registry.h> 12.10 12.11 12.12 12.13 @@ -32,7 +33,7 @@ 12.14 class FilePager : public Pager, public MappedFileObject 12.15 { 12.16 protected: 12.17 - FilePaging *_paging; 12.18 + FileRegistry *_registry; 12.19 FileProvider *_provider; 12.20 12.21 /* Notification endpoint for event subscription. */ 12.22 @@ -47,7 +48,7 @@ 12.23 fileid_t fileid; 12.24 12.25 explicit FilePager(fileid_t fileid, FileProvider *provider, map_flags_t flags, 12.26 - FilePaging *paging); 12.27 + FileRegistry *registry); 12.28 12.29 virtual void close(); 12.30
13.1 --- a/libfsserver/include/fsserver/file_paging.h Sat Sep 18 18:51:43 2021 +0200 13.2 +++ b/libfsserver/include/fsserver/file_paging.h Mon Sep 20 01:16:59 2021 +0200 13.3 @@ -21,57 +21,44 @@ 13.4 13.5 #pragma once 13.6 13.7 -#include <map> 13.8 -#include <mutex> 13.9 - 13.10 -#include <fsserver/accountable.h> 13.11 +#include <fsserver/directory_provider.h> 13.12 #include <fsserver/file_opening.h> 13.13 #include <fsserver/file_provider.h> 13.14 +#include <fsserver/file_registry.h> 13.15 #include <fsserver/pager.h> 13.16 #include <fsserver/pages.h> 13.17 13.18 13.19 13.20 -/* Mapping type from file identifiers to page mappers. */ 13.21 - 13.22 -typedef std::map<fileid_t, Accountable *> FileMapping; 13.23 -typedef std::pair<fileid_t, Accountable *> FileMappingEntry; 13.24 - 13.25 - 13.26 - 13.27 /* A registry of filesystem objects. */ 13.28 13.29 -class FilePaging 13.30 +class FilePaging : public FileRegistry 13.31 { 13.32 protected: 13.33 Pages *_pages; 13.34 - FileMapping _providers; 13.35 - std::mutex _lock; 13.36 13.37 - /* Filesystem object access. */ 13.38 - 13.39 - Accountable *get(fileid_t fileid); 13.40 - 13.41 - void remove(fileid_t fileid, Accountable *obj); 13.42 - 13.43 - void set(fileid_t fileid, Accountable *obj); 13.44 - 13.45 - /* Pager initialisation methods. */ 13.46 + /* Resource initialisation methods. */ 13.47 13.48 map_flags_t get_flags(flags_t flags); 13.49 13.50 - long get_provider(FileOpening *opening, const char *path, flags_t flags, fileid_t fileid, FileProvider **file_provider); 13.51 + long get_directory_provider(FileOpening *opening, const char *path, 13.52 + flags_t flags, fileid_t fileid, 13.53 + DirectoryProvider **directory_provider); 13.54 + 13.55 + long get_file_provider(FileOpening *opening, const char *path, 13.56 + flags_t flags, fileid_t fileid, 13.57 + FileProvider **file_provider); 13.58 13.59 public: 13.60 explicit FilePaging(Pages *pages); 13.61 13.62 - /* Pager initialisation methods. */ 13.63 - 13.64 - long get_pager(FileOpening *opening, const char *path, flags_t flags, fileid_t fileid, Pager **pager); 13.65 + /* Resource initialisation methods. */ 13.66 13.67 - /* Methods for the pager. */ 13.68 + long get_directory(FileOpening *opening, const char *path, flags_t flags, 13.69 + fileid_t fileid, Resource **resource); 13.70 13.71 - void detach_pager(fileid_t fileid, Accountable *mapper); 13.72 + long get_pager(FileOpening *opening, const char *path, flags_t flags, 13.73 + fileid_t fileid, Pager **pager); 13.74 }; 13.75 13.76 // vim: tabstop=4 expandtab shiftwidth=4
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 14.2 +++ b/libfsserver/include/fsserver/file_registry.h Mon Sep 20 01:16:59 2021 +0200 14.3 @@ -0,0 +1,61 @@ 14.4 +/* 14.5 + * A registry of filesystem objects. 14.6 + * 14.7 + * Copyright (C) 2021 Paul Boddie <paul@boddie.org.uk> 14.8 + * 14.9 + * This program is free software; you can redistribute it and/or 14.10 + * modify it under the terms of the GNU General Public License as 14.11 + * published by the Free Software Foundation; either version 2 of 14.12 + * the License, or (at your option) any later version. 14.13 + * 14.14 + * This program is distributed in the hope that it will be useful, 14.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 14.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14.17 + * GNU General Public License for more details. 14.18 + * 14.19 + * You should have received a copy of the GNU General Public License 14.20 + * along with this program; if not, write to the Free Software 14.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, 14.22 + * Boston, MA 02110-1301, USA 14.23 + */ 14.24 + 14.25 +#pragma once 14.26 + 14.27 +#include <map> 14.28 +#include <mutex> 14.29 + 14.30 +#include <mem/types.h> 14.31 +#include <fsserver/accountable.h> 14.32 + 14.33 + 14.34 + 14.35 +/* Mapping type from file identifiers to page mappers. */ 14.36 + 14.37 +typedef std::map<fileid_t, Accountable *> FileMapping; 14.38 +typedef std::pair<fileid_t, Accountable *> FileMappingEntry; 14.39 + 14.40 + 14.41 + 14.42 +/* A registry of filesystem objects. */ 14.43 + 14.44 +class FileRegistry 14.45 +{ 14.46 +protected: 14.47 + FileMapping _providers; 14.48 + std::mutex _lock; 14.49 + 14.50 + /* Filesystem object access. */ 14.51 + 14.52 + Accountable *get(fileid_t fileid); 14.53 + 14.54 + void remove(fileid_t fileid, Accountable *obj); 14.55 + 14.56 + void set(fileid_t fileid, Accountable *obj); 14.57 + 14.58 +public: 14.59 + /* Methods for resources. */ 14.60 + 14.61 + void detach(fileid_t fileid, Accountable *mapper); 14.62 +}; 14.63 + 14.64 +// vim: tabstop=4 expandtab shiftwidth=4
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 15.2 +++ b/libfsserver/include/fsserver/host_directory_accessor.h Mon Sep 20 01:16:59 2021 +0200 15.3 @@ -0,0 +1,45 @@ 15.4 +/* 15.5 + * An object for a "host" directory provided via the C library. 15.6 + * 15.7 + * Copyright (C) 2021 Paul Boddie <paul@boddie.org.uk> 15.8 + * 15.9 + * This program is free software; you can redistribute it and/or 15.10 + * modify it under the terms of the GNU General Public License as 15.11 + * published by the Free Software Foundation; either version 2 of 15.12 + * the License, or (at your option) any later version. 15.13 + * 15.14 + * This program is distributed in the hope that it will be useful, 15.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 15.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15.17 + * GNU General Public License for more details. 15.18 + * 15.19 + * You should have received a copy of the GNU General Public License 15.20 + * along with this program; if not, write to the Free Software 15.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, 15.22 + * Boston, MA 02110-1301, USA 15.23 + */ 15.24 + 15.25 +#pragma once 15.26 + 15.27 +#include <fsserver/directory_accessor.h> 15.28 + 15.29 + 15.30 + 15.31 +/* Support for providing access to directories. */ 15.32 + 15.33 +class HostDirectoryAccessor : public DirectoryAccessor 15.34 +{ 15.35 +protected: 15.36 + const char *_path; 15.37 + 15.38 +public: 15.39 + explicit HostDirectoryAccessor(const char *path); 15.40 + 15.41 + virtual ~HostDirectoryAccessor(); 15.42 + 15.43 + /* Accessor methods. */ 15.44 + 15.45 + virtual void read_directory(file_t *writer); 15.46 +}; 15.47 + 15.48 +// vim: tabstop=4 expandtab shiftwidth=4
16.1 --- a/libfsserver/include/fsserver/host_file_opener.h Sat Sep 18 18:51:43 2021 +0200 16.2 +++ b/libfsserver/include/fsserver/host_file_opener.h Mon Sep 20 01:16:59 2021 +0200 16.3 @@ -54,12 +54,6 @@ 16.4 16.5 virtual bool accessing_file(const char *path, flags_t flags, fileid_t fileid); 16.6 16.7 - /* Convenience methods obtaining different pager types. */ 16.8 - 16.9 - virtual long get_directory(const char *path, flags_t flags, fileid_t fileid, 16.10 - offset_t *size, l4_cap_idx_t *cap, 16.11 - object_flags_t *object_flags); 16.12 - 16.13 public: 16.14 explicit HostFileOpener(FilePaging *paging) 16.15 : OpenerResource(paging) 16.16 @@ -68,11 +62,16 @@ 16.17 16.18 virtual ~HostFileOpener(); 16.19 16.20 - /* Configurable methods. */ 16.21 + /* File opening methods. */ 16.22 16.23 virtual long get_fileid(const char *path, flags_t flags, fileid_t *fileid); 16.24 16.25 - virtual long make_accessor(const char *path, flags_t flags, fileid_t fileid, Accessor **accessor); 16.26 + virtual long make_accessor(const char *path, flags_t flags, fileid_t fileid, 16.27 + Accessor **accessor); 16.28 + 16.29 + virtual long make_directory_accessor(const char *path, flags_t flags, 16.30 + fileid_t fileid, 16.31 + DirectoryAccessor **accessor); 16.32 }; 16.33 16.34 // vim: tabstop=4 expandtab shiftwidth=4
17.1 --- a/libfsserver/include/fsserver/opener_resource.h Sat Sep 18 18:51:43 2021 +0200 17.2 +++ b/libfsserver/include/fsserver/opener_resource.h Mon Sep 20 01:16:59 2021 +0200 17.3 @@ -42,7 +42,7 @@ 17.4 17.5 virtual bool accessing_file(const char *path, flags_t flags, fileid_t fileid) = 0; 17.6 17.7 - /* Convenience methods obtaining different pager types. */ 17.8 + /* Convenience methods obtaining different resource types. */ 17.9 17.10 virtual long get_directory(const char *path, flags_t flags, fileid_t fileid, 17.11 offset_t *size, l4_cap_idx_t *cap, 17.12 @@ -52,10 +52,6 @@ 17.13 offset_t *size, l4_cap_idx_t *cap, 17.14 object_flags_t *object_flags); 17.15 17.16 - /* Preparation of resources for pagers. */ 17.17 - 17.18 - long resource_for_pager(Pager *pager, offset_t *size, l4_cap_idx_t *cap); 17.19 - 17.20 public: 17.21 explicit OpenerResource(FilePaging *paging); 17.22
18.1 --- a/libfsserver/include/fsserver/test_file_opener.h Sat Sep 18 18:51:43 2021 +0200 18.2 +++ b/libfsserver/include/fsserver/test_file_opener.h Mon Sep 20 01:16:59 2021 +0200 18.3 @@ -47,7 +47,12 @@ 18.4 18.5 virtual long get_fileid(const char *path, flags_t flags, fileid_t *fileid); 18.6 18.7 - virtual long make_accessor(const char *path, flags_t flags, fileid_t fileid, Accessor **accessor); 18.8 + virtual long make_accessor(const char *path, flags_t flags, fileid_t fileid, 18.9 + Accessor **accessor); 18.10 + 18.11 + virtual long make_directory_accessor(const char *path, flags_t flags, 18.12 + fileid_t fileid, 18.13 + DirectoryAccessor **accessor); 18.14 }; 18.15 18.16 // vim: tabstop=4 expandtab shiftwidth=4
19.1 --- a/libfsserver/lib/Makefile Sat Sep 18 18:51:43 2021 +0200 19.2 +++ b/libfsserver/lib/Makefile Mon Sep 20 01:16:59 2021 +0200 19.3 @@ -15,6 +15,9 @@ 19.4 19.5 # Compound interfaces. 19.6 19.7 +directory_object_NAME = DirectoryObject 19.8 +directory_object_INTERFACES = directory # notification 19.9 + 19.10 filesystem_object_NAME = FilesystemObject 19.11 filesystem_object_INTERFACES = filesystem filesystem_factory 19.12 19.13 @@ -27,7 +30,7 @@ 19.14 pipe_object_NAME = PipeObject 19.15 pipe_object_INTERFACES = dataspace flush notification pipe 19.16 19.17 -COMP_INTERFACES_CC = filesystem_object mapped_file_object opener_context_object pipe_object 19.18 +COMP_INTERFACES_CC = directory_object filesystem_object mapped_file_object opener_context_object pipe_object 19.19 19.20 # Individual interfaces. 19.21 19.22 @@ -42,6 +45,11 @@ 19.23 SERVER_INTERFACES_SRC_CC = $(call interfaces_to_server_cc,$(SERVER_INTERFACES_CC) $(COMP_INTERFACES_CC)) 19.24 19.25 PLAIN_SRC_CC = \ 19.26 + directories/directory_accessor.cc \ 19.27 + directories/directory_provider.cc \ 19.28 + directories/directory_resource.cc \ 19.29 + directories/ext2_directory_accessor.cc \ 19.30 + directories/host_directory_accessor.cc \ 19.31 files/block_file_accessor.cc \ 19.32 files/block_file_opener.cc \ 19.33 files/ext2_file_accessor.cc \ 19.34 @@ -52,6 +60,7 @@ 19.35 files/file_pager.cc \ 19.36 files/file_paging.cc \ 19.37 files/file_provider.cc \ 19.38 + files/file_registry.cc \ 19.39 files/filesystem_resource.cc \ 19.40 files/host_file_accessor.cc \ 19.41 files/host_file_opener.cc \
20.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 20.2 +++ b/libfsserver/lib/directories/directory_accessor.cc Mon Sep 20 01:16:59 2021 +0200 20.3 @@ -0,0 +1,32 @@ 20.4 +/* 20.5 + * An object providing access to a filesystem directory. 20.6 + * 20.7 + * Copyright (C) 2021 Paul Boddie <paul@boddie.org.uk> 20.8 + * 20.9 + * This program is free software; you can redistribute it and/or 20.10 + * modify it under the terms of the GNU General Public License as 20.11 + * published by the Free Software Foundation; either version 2 of 20.12 + * the License, or (at your option) any later version. 20.13 + * 20.14 + * This program is distributed in the hope that it will be useful, 20.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 20.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20.17 + * GNU General Public License for more details. 20.18 + * 20.19 + * You should have received a copy of the GNU General Public License 20.20 + * along with this program; if not, write to the Free Software 20.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, 20.22 + * Boston, MA 02110-1301, USA 20.23 + */ 20.24 + 20.25 +#include "directory_accessor.h" 20.26 + 20.27 + 20.28 + 20.29 +/* Deallocate the accessor. */ 20.30 + 20.31 +DirectoryAccessor::~DirectoryAccessor() 20.32 +{ 20.33 +} 20.34 + 20.35 +// vim: tabstop=4 expandtab shiftwidth=4
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 21.2 +++ b/libfsserver/lib/directories/directory_provider.cc Mon Sep 20 01:16:59 2021 +0200 21.3 @@ -0,0 +1,46 @@ 21.4 +/* 21.5 + * An object providing access to directory functionality. 21.6 + * 21.7 + * Copyright (C) 2021 Paul Boddie <paul@boddie.org.uk> 21.8 + * 21.9 + * This program is free software; you can redistribute it and/or 21.10 + * modify it under the terms of the GNU General Public License as 21.11 + * published by the Free Software Foundation; either version 2 of 21.12 + * the License, or (at your option) any later version. 21.13 + * 21.14 + * This program is distributed in the hope that it will be useful, 21.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 21.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21.17 + * GNU General Public License for more details. 21.18 + * 21.19 + * You should have received a copy of the GNU General Public License 21.20 + * along with this program; if not, write to the Free Software 21.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, 21.22 + * Boston, MA 02110-1301, USA 21.23 + */ 21.24 + 21.25 +#include "directory_provider.h" 21.26 + 21.27 + 21.28 + 21.29 +/* Initialise the provider. */ 21.30 + 21.31 +DirectoryProvider::DirectoryProvider(DirectoryAccessor *accessor) 21.32 +: FileNotification(), _accessor(accessor) 21.33 +{ 21.34 +} 21.35 + 21.36 +/* Deallocate the provider's resources. */ 21.37 + 21.38 +DirectoryProvider::~DirectoryProvider() 21.39 +{ 21.40 +} 21.41 + 21.42 +/* Return the accessor. */ 21.43 + 21.44 +DirectoryAccessor *DirectoryProvider::accessor() 21.45 +{ 21.46 + return _accessor; 21.47 +} 21.48 + 21.49 +// vim: tabstop=4 expandtab shiftwidth=4
22.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 22.2 +++ b/libfsserver/lib/directories/directory_resource.cc Mon Sep 20 01:16:59 2021 +0200 22.3 @@ -0,0 +1,129 @@ 22.4 +/* 22.5 + * A resource offering support for accessing directories. 22.6 + * 22.7 + * Copyright (C) 2021 Paul Boddie <paul@boddie.org.uk> 22.8 + * 22.9 + * This program is free software; you can redistribute it and/or 22.10 + * modify it under the terms of the GNU General Public License as 22.11 + * published by the Free Software Foundation; either version 2 of 22.12 + * the License, or (at your option) any later version. 22.13 + * 22.14 + * This program is distributed in the hope that it will be useful, 22.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 22.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22.17 + * GNU General Public License for more details. 22.18 + * 22.19 + * You should have received a copy of the GNU General Public License 22.20 + * along with this program; if not, write to the Free Software 22.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, 22.22 + * Boston, MA 02110-1301, USA 22.23 + */ 22.24 + 22.25 +#include <thread> 22.26 + 22.27 +#include <fsclient/client.h> 22.28 +#include <ipc/cap_alloc.h> 22.29 + 22.30 +#include "directory_resource.h" 22.31 +#include "directory_object_server.h" 22.32 + 22.33 + 22.34 + 22.35 +DirectoryResource::DirectoryResource(fileid_t fileid, 22.36 + DirectoryProvider *provider, 22.37 + FileRegistry *registry) 22.38 +: _registry(registry), _provider(provider), fileid(fileid) 22.39 +{ 22.40 +} 22.41 + 22.42 +DirectoryResource::~DirectoryResource() 22.43 +{ 22.44 +} 22.45 + 22.46 + 22.47 + 22.48 +int DirectoryResource::expected_items() 22.49 +{ 22.50 + return DirectoryObject_expected_items; 22.51 +} 22.52 + 22.53 +ipc_server_handler_type DirectoryResource::handler() 22.54 +{ 22.55 + return (ipc_server_handler_type) handle_DirectoryObject; 22.56 +} 22.57 + 22.58 + 22.59 + 22.60 +/* Close the resource, removing the provider from the registry if 22.61 + appropriate. */ 22.62 + 22.63 +void DirectoryResource::close() 22.64 +{ 22.65 + /* Detach the resource, potentially removing the file provider. */ 22.66 + 22.67 + _registry->detach(fileid, _provider); 22.68 +} 22.69 + 22.70 + 22.71 + 22.72 +/* Thread payload for directory listing production. */ 22.73 + 22.74 +static void read_directory(FileRegistry *registry, DirectoryProvider *provider, 22.75 + fileid_t fileid, file_t *writer) 22.76 +{ 22.77 + DirectoryAccessor *accessor = provider->accessor(); 22.78 + 22.79 + /* Attach to the provider to keep it available, even if the directory 22.80 + resource is released. */ 22.81 + 22.82 + provider->attach(); 22.83 + 22.84 + /* Invoke the directory reading mechanism. */ 22.85 + 22.86 + accessor->read_directory(writer); 22.87 + 22.88 + /* Close and detach from the registry. */ 22.89 + 22.90 + client_close(writer); 22.91 + registry->detach(fileid, provider); 22.92 +} 22.93 + 22.94 + 22.95 + 22.96 +/* Open a directory to read the directory entries via a file-like object. */ 22.97 + 22.98 +long DirectoryResource::opendir(offset_t *size, l4_cap_idx_t *file, 22.99 + object_flags_t *object_flags) 22.100 +{ 22.101 + file_t *reader, *writer; 22.102 + 22.103 + /* Mapping of the reader's memory region should be avoided because no use 22.104 + of the reader will be made here. */ 22.105 + 22.106 + long err = client_pipe(&reader, &writer, 0); 22.107 + 22.108 + if (err) 22.109 + return err; 22.110 + 22.111 + *size = reader->size; 22.112 + *file = reader->ref; 22.113 + *object_flags = 0; /* does not support mmap, has no fixed size */ 22.114 + 22.115 + /* Discard the reader structure but preserve the capability. */ 22.116 + 22.117 + reader->ref = L4_INVALID_CAP; 22.118 + file_close(reader); 22.119 + 22.120 + /* Initiate the reading process. */ 22.121 + 22.122 + std::thread(read_directory, _registry, _provider, fileid, writer).detach(); 22.123 + 22.124 + /* Send the capability immediately, discarding it afterwards. */ 22.125 + 22.126 + complete_Directory_opendir(*size, *file, *object_flags); 22.127 + ipc_cap_free_um(*file); 22.128 + 22.129 + return IPC_MESSAGE_SENT; 22.130 +} 22.131 + 22.132 +// vim: tabstop=4 expandtab shiftwidth=4
23.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 23.2 +++ b/libfsserver/lib/directories/ext2_directory_accessor.cc Mon Sep 20 01:16:59 2021 +0200 23.3 @@ -0,0 +1,145 @@ 23.4 +/* 23.5 + * An object for a directory provided by an Ext2-compatible filesystem. 23.6 + * 23.7 + * Copyright (C) 2021 Paul Boddie <paul@boddie.org.uk> 23.8 + * 23.9 + * This program is free software; you can redistribute it and/or 23.10 + * modify it under the terms of the GNU General Public License as 23.11 + * published by the Free Software Foundation; either version 2 of 23.12 + * the License, or (at your option) any later version. 23.13 + * 23.14 + * This program is distributed in the hope that it will be useful, 23.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 23.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23.17 + * GNU General Public License for more details. 23.18 + * 23.19 + * You should have received a copy of the GNU General Public License 23.20 + * along with this program; if not, write to the Free Software 23.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, 23.22 + * Boston, MA 02110-1301, USA 23.23 + */ 23.24 + 23.25 +#include <dirent.h> 23.26 +#include <string.h> 23.27 + 23.28 +#include <fsclient/client.h> 23.29 + 23.30 +#include "ext2_directory_accessor.h" 23.31 + 23.32 + 23.33 + 23.34 +/* Common definitions. */ 23.35 + 23.36 +#define DIRENT_CORE_SIZE (sizeof(struct dirent) - sizeof(((struct dirent *) 0)->d_name)) 23.37 + 23.38 +/* File type conversion. */ 23.39 + 23.40 +static int convert_file_type(int type) 23.41 +{ 23.42 + switch (type) 23.43 + { 23.44 + case EXT2_FT_REG_FILE: return DT_REG; 23.45 + case EXT2_FT_DIR: return DT_DIR; 23.46 + case EXT2_FT_CHRDEV: return DT_CHR; 23.47 + case EXT2_FT_BLKDEV: return DT_BLK; 23.48 + case EXT2_FT_FIFO: return DT_FIFO; 23.49 + case EXT2_FT_SOCK: return DT_SOCK; 23.50 + case EXT2_FT_SYMLINK: return DT_LNK; 23.51 + default: return DT_UNKNOWN; 23.52 + } 23.53 +} 23.54 + 23.55 +/* Helper function to ensure alignment in generated entries. */ 23.56 + 23.57 +static int pad_align(int value) 23.58 +{ 23.59 + return value + (sizeof(unsigned int) - (value % sizeof(unsigned int))); 23.60 +} 23.61 + 23.62 +/* Callback function. */ 23.63 + 23.64 +static int read_directory_entry(struct ext2_dir_entry *dir_entry, int offset, 23.65 + int blocksize, char *buf, void *priv_data) 23.66 +{ 23.67 + (void) offset; (void) blocksize; (void) buf; 23.68 + 23.69 + struct Ext2DirectoryState *dir = reinterpret_cast<struct Ext2DirectoryState *>(priv_data); 23.70 + 23.71 + dir->entry = dir_entry; 23.72 + dir->offset = offset; 23.73 + return dir->directory->write_directory_entry(dir); 23.74 +} 23.75 + 23.76 + 23.77 + 23.78 +/* Accessor methods. */ 23.79 + 23.80 +Ext2DirectoryAccessor::Ext2DirectoryAccessor(Ext2FileOperations *ops, 23.81 + fileid_t fileid) 23.82 +: _ops(ops), _fileid(fileid) 23.83 +{ 23.84 +} 23.85 + 23.86 +Ext2DirectoryAccessor::~Ext2DirectoryAccessor() 23.87 +{ 23.88 +} 23.89 + 23.90 +/* Thread payload helper method. */ 23.91 + 23.92 +void Ext2DirectoryAccessor::read_directory(file_t *writer) 23.93 +{ 23.94 + /* Initialise directory reading state: directory, writer, entry, offset. */ 23.95 + 23.96 + struct Ext2DirectoryState dir = {this, writer, NULL, 0}; 23.97 + 23.98 + /* Call the handler function for each directory entry. */ 23.99 + 23.100 + _ops->directory_iterate((ext2_ino_t) _fileid, read_directory_entry, &dir); 23.101 +} 23.102 + 23.103 +/* Callback method for directory entry output. */ 23.104 + 23.105 +int Ext2DirectoryAccessor::write_directory_entry(struct Ext2DirectoryState *dir) 23.106 +{ 23.107 + struct ext2_inode inode; 23.108 + 23.109 + /* Obtain the inode details for metadata. */ 23.110 + 23.111 + if (_ops->read_inode(dir->entry->inode, &inode)) 23.112 + return DIRENT_ABORT; 23.113 + 23.114 + /* Align the size of the entry to avoid problems on architectures which 23.115 + require aligned accesses and where the compiler needs to assume an 23.116 + aligned structure. */ 23.117 + 23.118 + offset_t namelen = ext2fs_dirent_name_len(dir->entry); 23.119 + offset_t reclen = pad_align(DIRENT_CORE_SIZE + namelen); 23.120 + 23.121 + /* Construct a directory entry structure of the calculated size. */ 23.122 + 23.123 + char buffer[reclen]; 23.124 + struct dirent *dirent = (struct dirent *) buffer; 23.125 + 23.126 + dirent->d_ino = dir->entry->inode; 23.127 + dirent->d_off = dir->offset; 23.128 + dirent->d_reclen = reclen; 23.129 + dirent->d_type = convert_file_type(ext2fs_dirent_file_type(dir->entry)); 23.130 + 23.131 + /* Copy the name, padding the memory after it to the alignment boundary. */ 23.132 + 23.133 + memcpy(dirent->d_name, dir->entry->name, namelen); 23.134 + memset(dirent->d_name + namelen, 0, reclen - namelen); 23.135 + 23.136 + /* Write the structure to the pipe. */ 23.137 + 23.138 + offset_t nwritten = client_write(dir->writer, (const void *) dirent, reclen); 23.139 + 23.140 + /* Stop writing if the pipe is closed. */ 23.141 + 23.142 + if (nwritten < reclen) 23.143 + return DIRENT_ABORT; 23.144 + 23.145 + return 0; 23.146 +} 23.147 + 23.148 +// vim: tabstop=4 expandtab shiftwidth=4
24.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 24.2 +++ b/libfsserver/lib/directories/host_directory_accessor.cc Mon Sep 20 01:16:59 2021 +0200 24.3 @@ -0,0 +1,57 @@ 24.4 +/* 24.5 + * An object for a "host" directory provided via the C library. 24.6 + * 24.7 + * Copyright (C) 2021 Paul Boddie <paul@boddie.org.uk> 24.8 + * 24.9 + * This program is free software; you can redistribute it and/or 24.10 + * modify it under the terms of the GNU General Public License as 24.11 + * published by the Free Software Foundation; either version 2 of 24.12 + * the License, or (at your option) any later version. 24.13 + * 24.14 + * This program is distributed in the hope that it will be useful, 24.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 24.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24.17 + * GNU General Public License for more details. 24.18 + * 24.19 + * You should have received a copy of the GNU General Public License 24.20 + * along with this program; if not, write to the Free Software 24.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, 24.22 + * Boston, MA 02110-1301, USA 24.23 + */ 24.24 + 24.25 +#include <dirent.h> 24.26 + 24.27 +#include <fsclient/client.h> 24.28 + 24.29 +#include "host_directory_accessor.h" 24.30 + 24.31 + 24.32 + 24.33 +HostDirectoryAccessor::HostDirectoryAccessor(const char *path) 24.34 +: _path(path) 24.35 +{ 24.36 +} 24.37 + 24.38 +HostDirectoryAccessor::~HostDirectoryAccessor() 24.39 +{ 24.40 +} 24.41 + 24.42 +void HostDirectoryAccessor::read_directory(file_t *writer) 24.43 +{ 24.44 + DIR *dir = opendir(_path); 24.45 + struct dirent *dirent; 24.46 + 24.47 + /* Write directory entries to the pipe, closing the pipe when finished. */ 24.48 + 24.49 + while ((dirent = readdir(dir)) != NULL) 24.50 + { 24.51 + offset_t nwritten = client_write(writer, (const void *) dirent, dirent->d_reclen); 24.52 + 24.53 + /* Stop writing if the pipe is closed. */ 24.54 + 24.55 + if (nwritten < dirent->d_reclen) 24.56 + break; 24.57 + } 24.58 +} 24.59 + 24.60 +// vim: tabstop=4 expandtab shiftwidth=4
25.1 --- a/libfsserver/lib/files/ext2_file_opener.cc Sat Sep 18 18:51:43 2021 +0200 25.2 +++ b/libfsserver/lib/files/ext2_file_opener.cc Mon Sep 20 01:16:59 2021 +0200 25.3 @@ -19,70 +19,16 @@ 25.4 * Boston, MA 02110-1301, USA 25.5 */ 25.6 25.7 -#include <dirent.h> 25.8 #include <string.h> 25.9 25.10 -#include <thread> 25.11 - 25.12 #include <e2access/path.h> 25.13 #include <fsclient/client.h> 25.14 #include <systypes/fcntl.h> 25.15 25.16 +#include "ext2_directory_accessor.h" 25.17 #include "ext2_file_accessor.h" 25.18 #include "ext2_file_opener.h" 25.19 - 25.20 - 25.21 - 25.22 -/* Common definitions. */ 25.23 - 25.24 -#define DIRENT_CORE_SIZE (sizeof(struct dirent) - sizeof(((struct dirent *) 0)->d_name)) 25.25 - 25.26 -/* File type conversion. */ 25.27 - 25.28 -static int convert_file_type(int type) 25.29 -{ 25.30 - switch (type) 25.31 - { 25.32 - case EXT2_FT_REG_FILE: return DT_REG; 25.33 - case EXT2_FT_DIR: return DT_DIR; 25.34 - case EXT2_FT_CHRDEV: return DT_CHR; 25.35 - case EXT2_FT_BLKDEV: return DT_BLK; 25.36 - case EXT2_FT_FIFO: return DT_FIFO; 25.37 - case EXT2_FT_SOCK: return DT_SOCK; 25.38 - case EXT2_FT_SYMLINK: return DT_LNK; 25.39 - default: return DT_UNKNOWN; 25.40 - } 25.41 -} 25.42 - 25.43 -/* Helper function to ensure alignment in generated entries. */ 25.44 - 25.45 -static int pad_align(int value) 25.46 -{ 25.47 - return value + (sizeof(unsigned int) - (value % sizeof(unsigned int))); 25.48 -} 25.49 - 25.50 -/* Callback function. */ 25.51 - 25.52 -static int read_directory_entry(struct ext2_dir_entry *dir_entry, int offset, 25.53 - int blocksize, char *buf, void *priv_data) 25.54 -{ 25.55 - (void) offset; (void) blocksize; (void) buf; 25.56 - 25.57 - struct Ext2FileOpenerDir *dir = reinterpret_cast<struct Ext2FileOpenerDir *>(priv_data); 25.58 - 25.59 - dir->entry = dir_entry; 25.60 - dir->offset = offset; 25.61 - return dir->opener->write_directory_entry(dir); 25.62 -} 25.63 - 25.64 -/* Thread payload. */ 25.65 - 25.66 -static void _read_directory(Ext2FileOpener *opener, fileid_t fileid, file_t *writer) 25.67 -{ 25.68 - opener->read_directory(fileid, writer); 25.69 - 25.70 - client_close(writer); 25.71 -} 25.72 +#include "resource_server.h" 25.73 25.74 25.75 25.76 @@ -106,104 +52,6 @@ 25.77 return _ops->is_file((ext2_ino_t) fileid); 25.78 } 25.79 25.80 -// NOTE: This is mostly the same as the HostFileOpener implementation. 25.81 - 25.82 -long Ext2FileOpener::get_directory(const char *path, flags_t flags, 25.83 - fileid_t fileid, offset_t *size, 25.84 - l4_cap_idx_t *cap, object_flags_t *object_flags) 25.85 -{ 25.86 - /* The file identifier is used to obtain the directory. */ 25.87 - 25.88 - (void) path; (void) flags; 25.89 - 25.90 - file_t *reader, *writer; 25.91 - 25.92 - // Mapping of the reader's memory region should be avoided because no use 25.93 - // of the reader will be made here. 25.94 - 25.95 - long err = client_pipe(&reader, &writer, 0); 25.96 - 25.97 - if (err) 25.98 - return err; 25.99 - 25.100 - *size = reader->size; 25.101 - *cap = reader->ref; 25.102 - *object_flags = 0; /* does not support mmap, has no fixed size */ 25.103 - 25.104 - /* Spawn a independent thread for reading the directory details and writing 25.105 - them to the pipe. */ 25.106 - 25.107 - std::thread(_read_directory, this, fileid, writer).detach(); 25.108 - 25.109 - /* Discard the reader structure but preserve the capability. */ 25.110 - 25.111 - reader->ref = L4_INVALID_CAP; 25.112 - client_close(reader); 25.113 - 25.114 - /* Return an indication that the capability will be propagated and not 25.115 - retained. This is explicitly supported by the opener context. */ 25.116 - 25.117 - return IPC_MESSAGE_SENT; 25.118 -} 25.119 - 25.120 -/* Thread payload helper method. */ 25.121 - 25.122 -void Ext2FileOpener::read_directory(fileid_t fileid, file_t *writer) 25.123 -{ 25.124 - /* Initialise directory reading state: opener, writer, entry, offset. */ 25.125 - 25.126 - struct Ext2FileOpenerDir dir = {this, writer, NULL, 0}; 25.127 - 25.128 - /* Call the handler function for each directory entry. */ 25.129 - 25.130 - _ops->directory_iterate((ext2_ino_t) fileid, read_directory_entry, &dir); 25.131 -} 25.132 - 25.133 -/* Callback method for directory entry output. */ 25.134 - 25.135 -int Ext2FileOpener::write_directory_entry(struct Ext2FileOpenerDir *dir) 25.136 -{ 25.137 - struct ext2_inode inode; 25.138 - 25.139 - /* Obtain the inode details for metadata. */ 25.140 - 25.141 - if (_ops->read_inode(dir->entry->inode, &inode)) 25.142 - return DIRENT_ABORT; 25.143 - 25.144 - /* Align the size of the entry to avoid problems on architectures which 25.145 - require aligned accesses and where the compiler needs to assume an 25.146 - aligned structure. */ 25.147 - 25.148 - offset_t namelen = ext2fs_dirent_name_len(dir->entry); 25.149 - offset_t reclen = pad_align(DIRENT_CORE_SIZE + namelen); 25.150 - 25.151 - /* Construct a directory entry structure of the calculated size. */ 25.152 - 25.153 - char buffer[reclen]; 25.154 - struct dirent *dirent = (struct dirent *) buffer; 25.155 - 25.156 - dirent->d_ino = dir->entry->inode; 25.157 - dirent->d_off = dir->offset; 25.158 - dirent->d_reclen = reclen; 25.159 - dirent->d_type = convert_file_type(ext2fs_dirent_file_type(dir->entry)); 25.160 - 25.161 - /* Copy the name, padding the memory after it to the alignment boundary. */ 25.162 - 25.163 - memcpy(dirent->d_name, dir->entry->name, namelen); 25.164 - memset(dirent->d_name + namelen, 0, reclen - namelen); 25.165 - 25.166 - /* Write the structure to the pipe. */ 25.167 - 25.168 - offset_t nwritten = client_write(dir->writer, (const void *) dirent, reclen); 25.169 - 25.170 - /* Stop writing if the pipe is closed. */ 25.171 - 25.172 - if (nwritten < reclen) 25.173 - return DIRENT_ABORT; 25.174 - 25.175 - return 0; 25.176 -} 25.177 - 25.178 /* Return a file identifier for the given 'path'. */ 25.179 25.180 long Ext2FileOpener::get_fileid(const char *path, flags_t flags, fileid_t *fileid) 25.181 @@ -245,7 +93,8 @@ 25.182 25.183 /* Return a new accessor for 'fileid'. */ 25.184 25.185 -long Ext2FileOpener::make_accessor(const char *path, flags_t flags, fileid_t fileid, Accessor **accessor) 25.186 +long Ext2FileOpener::make_accessor(const char *path, flags_t flags, 25.187 + fileid_t fileid, Accessor **accessor) 25.188 { 25.189 (void) path; (void) flags; 25.190 25.191 @@ -259,4 +108,16 @@ 25.192 return L4_EOK; 25.193 } 25.194 25.195 +/* Return a directory object reference for the given file identifier. */ 25.196 + 25.197 +long Ext2FileOpener::make_directory_accessor(const char *path, flags_t flags, 25.198 + fileid_t fileid, 25.199 + DirectoryAccessor **accessor) 25.200 +{ 25.201 + (void) path; (void) flags; 25.202 + 25.203 + *accessor = new Ext2DirectoryAccessor(_ops, fileid); 25.204 + return L4_EOK; 25.205 +} 25.206 + 25.207 // vim: tabstop=4 expandtab shiftwidth=4
26.1 --- a/libfsserver/lib/files/file_pager.cc Sat Sep 18 18:51:43 2021 +0200 26.2 +++ b/libfsserver/lib/files/file_pager.cc Mon Sep 20 01:16:59 2021 +0200 26.3 @@ -25,13 +25,13 @@ 26.4 26.5 26.6 /* Initialise a pager for a file with a unique file identifier, file provider, 26.7 - mapping flags and a file paging coordinator. The provider offers a shared 26.8 - page mapper for moderating access to loaded pages. */ 26.9 + mapping flags and a file registry. The provider offers a shared page mapper 26.10 + for moderating access to loaded pages. */ 26.11 26.12 FilePager::FilePager(fileid_t fileid, FileProvider *provider, map_flags_t flags, 26.13 - FilePaging *paging) 26.14 + FileRegistry *registry) 26.15 : Pager(provider->mapper(), flags), 26.16 - _paging(paging), _provider(provider), fileid(fileid) 26.17 + _registry(registry), _provider(provider), fileid(fileid) 26.18 { 26.19 } 26.20 26.21 @@ -57,7 +57,7 @@ 26.22 26.23 /* Detach the pager, potentially removing the file provider. */ 26.24 26.25 - _paging->detach_pager(fileid, _provider); 26.26 + _registry->detach(fileid, _provider); 26.27 } 26.28 26.29
27.1 --- a/libfsserver/lib/files/file_paging.cc Sat Sep 18 18:51:43 2021 +0200 27.2 +++ b/libfsserver/lib/files/file_paging.cc Mon Sep 20 01:16:59 2021 +0200 27.3 @@ -1,5 +1,5 @@ 27.4 /* 27.5 - * General functionality supporting file paging. 27.6 + * File registry and opening functionality. 27.7 * 27.8 * Copyright (C) 2021 Paul Boddie <paul@boddie.org.uk> 27.9 * 27.10 @@ -19,6 +19,7 @@ 27.11 * Boston, MA 02110-1301, USA 27.12 */ 27.13 27.14 +#include "directory_resource.h" 27.15 #include "file_pager.h" 27.16 #include "file_paging.h" 27.17 27.18 @@ -36,44 +37,6 @@ 27.19 27.20 27.21 27.22 -/* Return any registered provider for the given 'fileid' or NULL if no such 27.23 - provider is registered. */ 27.24 - 27.25 -Accountable *FilePaging::get(fileid_t fileid) 27.26 -{ 27.27 - FileMapping::iterator entry = _providers.find(fileid); 27.28 - Accountable *provider; 27.29 - 27.30 - if (entry == _providers.end()) 27.31 - provider = NULL; 27.32 - else 27.33 - provider = entry->second; 27.34 - 27.35 - return provider; 27.36 -} 27.37 - 27.38 -/* Remove a provider and its resources for the given 'fileid'. */ 27.39 - 27.40 -void FilePaging::remove(fileid_t fileid, Accountable *provider) 27.41 -{ 27.42 - _providers.erase(fileid); 27.43 - delete provider; 27.44 -} 27.45 - 27.46 -/* Register a 'provider' for the given 'fileid'. */ 27.47 - 27.48 -void FilePaging::set(fileid_t fileid, Accountable *provider) 27.49 -{ 27.50 - FileMapping::iterator entry = _providers.find(fileid); 27.51 - 27.52 - if (entry != _providers.end()) 27.53 - return; 27.54 - 27.55 - _providers[fileid] = provider; 27.56 -} 27.57 - 27.58 - 27.59 - 27.60 /* Convert opening flags to map-compatible paging flags. */ 27.61 27.62 map_flags_t FilePaging::get_flags(flags_t flags) 27.63 @@ -83,10 +46,11 @@ 27.64 27.65 27.66 27.67 -/* Obtain a provider for the 'fileid' or register a new one in the 27.68 - paging object. */ 27.69 +/* Obtain a provider for the 'fileid' or register a new one. */ 27.70 27.71 -long FilePaging::get_provider(FileOpening *opening, const char *path, flags_t flags, fileid_t fileid, FileProvider **file_provider) 27.72 +long FilePaging::get_directory_provider(FileOpening *opening, const char *path, 27.73 + flags_t flags, fileid_t fileid, 27.74 + DirectoryProvider **directory_provider) 27.75 { 27.76 /* Obtain any registered provider. */ 27.77 27.78 @@ -94,10 +58,42 @@ 27.79 27.80 if (provider != NULL) 27.81 { 27.82 - /* Distinguish between file providers and other objects that may be 27.83 - registered. For files specifically, a file provider is needed 27.84 - because it will provide a page mapper. */ 27.85 + *directory_provider = dynamic_cast<DirectoryProvider *>(provider); 27.86 + 27.87 + if ((*directory_provider) != NULL) 27.88 + return L4_EOK; 27.89 + else 27.90 + return -L4_EIO; 27.91 + } 27.92 + 27.93 + /* Make an accessor and a provider to encapsulate it. */ 27.94 + 27.95 + DirectoryAccessor *accessor; 27.96 + long err = opening->make_directory_accessor(path, flags, fileid, &accessor); 27.97 + 27.98 + if (err) 27.99 + return err; 27.100 + 27.101 + *directory_provider = new DirectoryProvider(accessor); 27.102 27.103 + /* Register the provider. */ 27.104 + 27.105 + set(fileid, *directory_provider); 27.106 + return L4_EOK; 27.107 +} 27.108 + 27.109 +/* Obtain a provider for the 'fileid' or register a new one. */ 27.110 + 27.111 +long FilePaging::get_file_provider(FileOpening *opening, const char *path, 27.112 + flags_t flags, fileid_t fileid, 27.113 + FileProvider **file_provider) 27.114 +{ 27.115 + /* Obtain any registered provider. */ 27.116 + 27.117 + Accountable *provider = get(fileid); 27.118 + 27.119 + if (provider != NULL) 27.120 + { 27.121 *file_provider = dynamic_cast<FileProvider *>(provider); 27.122 27.123 if ((*file_provider) != NULL) 27.124 @@ -125,9 +121,35 @@ 27.125 27.126 27.127 27.128 +/* Return a directory resource initialised with a provider. */ 27.129 + 27.130 +long FilePaging::get_directory(FileOpening *opening, const char *path, 27.131 + flags_t flags, fileid_t fileid, 27.132 + Resource **resource) 27.133 +{ 27.134 + std::lock_guard<std::mutex> guard(_lock); 27.135 + 27.136 + /* Obtain any existing provider registered for the object, or make a new 27.137 + provider. */ 27.138 + 27.139 + DirectoryProvider *provider; 27.140 + long err = get_directory_provider(opening, path, flags, fileid, &provider); 27.141 + 27.142 + if (err) 27.143 + return err; 27.144 + 27.145 + /* Initialise the resource with the provider and a reference to this object 27.146 + for detaching from the provider. */ 27.147 + 27.148 + provider->attach(); 27.149 + *resource = new DirectoryResource(fileid, provider, this); 27.150 + return L4_EOK; 27.151 +} 27.152 + 27.153 /* Return a pager initialised with a provider, page mapper and accessor. */ 27.154 27.155 -long FilePaging::get_pager(FileOpening *opening, const char *path, flags_t flags, fileid_t fileid, Pager **pager) 27.156 +long FilePaging::get_pager(FileOpening *opening, const char *path, 27.157 + flags_t flags, fileid_t fileid, Pager **pager) 27.158 { 27.159 std::lock_guard<std::mutex> guard(_lock); 27.160 27.161 @@ -135,27 +157,17 @@ 27.162 provider. */ 27.163 27.164 FileProvider *provider; 27.165 - long err = get_provider(opening, path, flags, fileid, &provider); 27.166 + long err = get_file_provider(opening, path, flags, fileid, &provider); 27.167 27.168 if (err) 27.169 return err; 27.170 27.171 /* Initialise the pager with the provider and a reference to this object for 27.172 - closing the provider, mapper and accessor. */ 27.173 + detaching from the provider. */ 27.174 27.175 provider->attach(); 27.176 *pager = new FilePager(fileid, provider, get_flags(flags), this); 27.177 return L4_EOK; 27.178 } 27.179 27.180 -/* Detach a pager, potentially removing its resources. */ 27.181 - 27.182 -void FilePaging::detach_pager(fileid_t fileid, Accountable *provider) 27.183 -{ 27.184 - std::lock_guard<std::mutex> guard(_lock); 27.185 - 27.186 - if (!provider->detach()) 27.187 - remove(fileid, provider); 27.188 -} 27.189 - 27.190 // vim: tabstop=4 expandtab shiftwidth=4
28.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 28.2 +++ b/libfsserver/lib/files/file_registry.cc Mon Sep 20 01:16:59 2021 +0200 28.3 @@ -0,0 +1,76 @@ 28.4 +/* 28.5 + * File registry functionality. 28.6 + * 28.7 + * Copyright (C) 2021 Paul Boddie <paul@boddie.org.uk> 28.8 + * 28.9 + * This program is free software; you can redistribute it and/or 28.10 + * modify it under the terms of the GNU General Public License as 28.11 + * published by the Free Software Foundation; either version 2 of 28.12 + * the License, or (at your option) any later version. 28.13 + * 28.14 + * This program is distributed in the hope that it will be useful, 28.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 28.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28.17 + * GNU General Public License for more details. 28.18 + * 28.19 + * You should have received a copy of the GNU General Public License 28.20 + * along with this program; if not, write to the Free Software 28.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, 28.22 + * Boston, MA 02110-1301, USA 28.23 + */ 28.24 + 28.25 +#include "file_registry.h" 28.26 + 28.27 + 28.28 + 28.29 +/* Methods for use with the lock already acquired. */ 28.30 + 28.31 +/* Return any registered provider for the given 'fileid' or NULL if no such 28.32 + provider is registered. */ 28.33 + 28.34 +Accountable *FileRegistry::get(fileid_t fileid) 28.35 +{ 28.36 + FileMapping::iterator entry = _providers.find(fileid); 28.37 + Accountable *provider; 28.38 + 28.39 + if (entry == _providers.end()) 28.40 + provider = NULL; 28.41 + else 28.42 + provider = entry->second; 28.43 + 28.44 + return provider; 28.45 +} 28.46 + 28.47 +/* Remove a provider and its resources for the given 'fileid'. */ 28.48 + 28.49 +void FileRegistry::remove(fileid_t fileid, Accountable *provider) 28.50 +{ 28.51 + _providers.erase(fileid); 28.52 + delete provider; 28.53 +} 28.54 + 28.55 +/* Register a 'provider' for the given 'fileid'. */ 28.56 + 28.57 +void FileRegistry::set(fileid_t fileid, Accountable *provider) 28.58 +{ 28.59 + FileMapping::iterator entry = _providers.find(fileid); 28.60 + 28.61 + if (entry != _providers.end()) 28.62 + return; 28.63 + 28.64 + _providers[fileid] = provider; 28.65 +} 28.66 + 28.67 + 28.68 + 28.69 +/* Detach from a provider, potentially removing it from the registry. */ 28.70 + 28.71 +void FileRegistry::detach(fileid_t fileid, Accountable *provider) 28.72 +{ 28.73 + std::lock_guard<std::mutex> guard(_lock); 28.74 + 28.75 + if (!provider->detach()) 28.76 + remove(fileid, provider); 28.77 +} 28.78 + 28.79 +// vim: tabstop=4 expandtab shiftwidth=4
29.1 --- a/libfsserver/lib/files/host_file_opener.cc Sat Sep 18 18:51:43 2021 +0200 29.2 +++ b/libfsserver/lib/files/host_file_opener.cc Mon Sep 20 01:16:59 2021 +0200 29.3 @@ -19,40 +19,14 @@ 29.4 * Boston, MA 02110-1301, USA 29.5 */ 29.6 29.7 -#include <thread> 29.8 - 29.9 -#include <dirent.h> 29.10 #include <sys/stat.h> 29.11 29.12 #include <fsclient/client.h> 29.13 -#include <systypes/fcntl.h> 29.14 29.15 +#include "host_directory_accessor.h" 29.16 #include "host_file_accessor.h" 29.17 #include "host_file_opener.h" 29.18 - 29.19 - 29.20 - 29.21 -/* Thread payload. */ 29.22 - 29.23 -static void read_directory(const char *path, file_t *writer) 29.24 -{ 29.25 - DIR *dir = opendir(path); 29.26 - struct dirent *dirent; 29.27 - 29.28 - /* Write directory entries to the pipe, closing the pipe when finished. */ 29.29 - 29.30 - while ((dirent = readdir(dir)) != NULL) 29.31 - { 29.32 - offset_t nwritten = client_write(writer, (const void *) dirent, dirent->d_reclen); 29.33 - 29.34 - /* Stop writing if the pipe is closed. */ 29.35 - 29.36 - if (nwritten < dirent->d_reclen) 29.37 - break; 29.38 - } 29.39 - 29.40 - client_close(writer); 29.41 -} 29.42 +#include "resource_server.h" 29.43 29.44 29.45 29.46 @@ -82,41 +56,6 @@ 29.47 return (st.st_mode & S_IFREG) ? true : false; 29.48 } 29.49 29.50 -long HostFileOpener::get_directory(const char *path, flags_t flags, 29.51 - fileid_t fileid, offset_t *size, 29.52 - l4_cap_idx_t *cap, object_flags_t *object_flags) 29.53 -{ 29.54 - /* The path is used to obtain the directory. */ 29.55 - 29.56 - (void) flags; (void) fileid; 29.57 - 29.58 - file_t *reader, *writer; 29.59 - 29.60 - // Mapping of the reader's memory region should be avoided because no use 29.61 - // of the reader will be made here. 29.62 - 29.63 - long err = client_pipe(&reader, &writer, 0); 29.64 - 29.65 - if (err) 29.66 - return err; 29.67 - 29.68 - *size = reader->size; 29.69 - *cap = reader->ref; 29.70 - *object_flags = 0; /* does not support mmap, has no fixed size */ 29.71 - 29.72 - /* Discard the reader structure but preserve the capability. */ 29.73 - 29.74 - reader->ref = L4_INVALID_CAP; 29.75 - file_close(reader); 29.76 - 29.77 - /* Spawn a independent thread for reading the directory details and writing 29.78 - them to the pipe. */ 29.79 - 29.80 - std::thread(read_directory, path, writer).detach(); 29.81 - 29.82 - return L4_EOK; 29.83 -} 29.84 - 29.85 /* Return a file identifier for the given 'path'. */ 29.86 29.87 long HostFileOpener::get_fileid(const char *path, flags_t flags, fileid_t *fileid) 29.88 @@ -164,7 +103,8 @@ 29.89 29.90 /* Return a new accessor for 'fileid'. */ 29.91 29.92 -long HostFileOpener::make_accessor(const char *path, flags_t flags, fileid_t fileid, Accessor **accessor) 29.93 +long HostFileOpener::make_accessor(const char *path, flags_t flags, 29.94 + fileid_t fileid, Accessor **accessor) 29.95 { 29.96 // NOTE: Not testing for create or write flags. 29.97 29.98 @@ -179,4 +119,16 @@ 29.99 return L4_EOK; 29.100 } 29.101 29.102 +/* Return a directory accessor for 'fileid'. */ 29.103 + 29.104 +long HostFileOpener::make_directory_accessor(const char *path, flags_t flags, 29.105 + fileid_t fileid, 29.106 + DirectoryAccessor **accessor) 29.107 +{ 29.108 + (void) flags; (void) fileid; 29.109 + 29.110 + *accessor = new HostDirectoryAccessor(path); 29.111 + return L4_EOK; 29.112 +} 29.113 + 29.114 // vim: tabstop=4 expandtab shiftwidth=4
30.1 --- a/libfsserver/lib/files/opener_context_resource.cc Sat Sep 18 18:51:43 2021 +0200 30.2 +++ b/libfsserver/lib/files/opener_context_resource.cc Mon Sep 20 01:16:59 2021 +0200 30.3 @@ -75,19 +75,7 @@ 30.4 if (path == NULL) 30.5 return -L4_EINVAL; 30.6 30.7 - long err = _opener->open(path, flags, size, file, object_flags); 30.8 - 30.9 - /* Handle propagated capabilities. By indicating the special status, the 30.10 - operation is first completed and then the capability is discarded. */ 30.11 - 30.12 - if (err == IPC_MESSAGE_SENT) 30.13 - { 30.14 - complete_OpenerContext_open(*size, *file, *object_flags); 30.15 - ipc_cap_free_um(*file); 30.16 - return IPC_MESSAGE_SENT; 30.17 - } 30.18 - 30.19 - return err; 30.20 + return _opener->open(path, flags, size, file, object_flags); 30.21 } 30.22 30.23 // vim: tabstop=4 expandtab shiftwidth=4
31.1 --- a/libfsserver/lib/files/opener_resource.cc Sat Sep 18 18:51:43 2021 +0200 31.2 +++ b/libfsserver/lib/files/opener_resource.cc Mon Sep 20 01:16:59 2021 +0200 31.3 @@ -71,14 +71,25 @@ 31.4 31.5 31.6 31.7 -/* Return a directory pager. */ 31.8 +/* Return a directory object reference for the given file identifier. */ 31.9 31.10 long OpenerResource::get_directory(const char *path, flags_t flags, 31.11 fileid_t fileid, offset_t *size, 31.12 - l4_cap_idx_t *cap, object_flags_t *object_flags) 31.13 + l4_cap_idx_t *cap, 31.14 + object_flags_t *object_flags) 31.15 { 31.16 - (void) path; (void) flags; (void) fileid; (void) size; (void) cap; (void) object_flags; 31.17 - return -L4_EIO; 31.18 + Resource *directory; 31.19 + long err = _paging->get_directory(this, path, flags, fileid, &directory); 31.20 + 31.21 + if (err) 31.22 + return err; 31.23 + 31.24 + /* Provide non-file values for certain outputs. */ 31.25 + 31.26 + *size = 0; 31.27 + *object_flags = 0; 31.28 + 31.29 + return ResourceServer(directory).start_thread(cap); 31.30 } 31.31 31.32 /* Return a file pager. */ 31.33 @@ -93,20 +104,11 @@ 31.34 if (err) 31.35 return err; 31.36 31.37 - *object_flags = OBJECT_SUPPORTS_MMAP | OBJECT_HAS_SIZE; 31.38 - 31.39 - return resource_for_pager(pager, size, cap); 31.40 -} 31.41 - 31.42 -/* Return pager resource details. */ 31.43 + /* Obtain the size details from the pager, also providing appropriate 31.44 + flags. */ 31.45 31.46 -long OpenerResource::resource_for_pager(Pager *pager, offset_t *size, l4_cap_idx_t *cap) 31.47 -{ 31.48 *size = pager->get_data_size(); 31.49 - 31.50 - /* Complete the initialisation and start a server in a new thread. 31.51 - If the thread does not start, the resource (including pager) will be 31.52 - finalised. */ 31.53 + *object_flags = OBJECT_SUPPORTS_MMAP | OBJECT_HAS_SIZE; 31.54 31.55 return ResourceServer(pager).start_thread(cap); 31.56 }
32.1 --- a/libfsserver/lib/files/test_file_opener.cc Sat Sep 18 18:51:43 2021 +0200 32.2 +++ b/libfsserver/lib/files/test_file_opener.cc Mon Sep 20 01:16:59 2021 +0200 32.3 @@ -61,11 +61,22 @@ 32.4 32.5 /* Return a new accessor for 'fileid'. */ 32.6 32.7 -long TestFileOpener::make_accessor(const char *path, flags_t flags, fileid_t fileid, Accessor **accessor) 32.8 +long TestFileOpener::make_accessor(const char *path, flags_t flags, 32.9 + fileid_t fileid, Accessor **accessor) 32.10 { 32.11 (void) flags; (void) path; 32.12 *accessor = new TestFileAccessor(fileid, _file_size); 32.13 return L4_EOK; 32.14 } 32.15 32.16 +/* Return a new directory accessor for 'fileid'. */ 32.17 + 32.18 +long TestFileOpener::make_directory_accessor(const char *path, flags_t flags, 32.19 + fileid_t fileid, 32.20 + DirectoryAccessor **accessor) 32.21 +{ 32.22 + (void) flags; (void) path; (void) fileid; (void) accessor; 32.23 + return -L4_EIO; 32.24 +} 32.25 + 32.26 // vim: tabstop=4 expandtab shiftwidth=4
33.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 33.2 +++ b/libsystypes/idl/directory.idl Mon Sep 20 01:16:59 2021 +0200 33.3 @@ -0,0 +1,14 @@ 33.4 +#include <systypes/base.h> /* object_flags_t, offset_t */ 33.5 + 33.6 +/* An interface to a filesystem directory. */ 33.7 + 33.8 +interface Directory 33.9 +{ 33.10 + /* Obtain a file reference for reading directory entries. */ 33.11 + 33.12 + [opcode(26)] void opendir(out offset_t size, out cap file, 33.13 + out object_flags_t object_flags); 33.14 +}; 33.15 + 33.16 +/* vim: tabstop=2 expandtab shiftwidth=2 33.17 +*/
34.1 --- a/tests/dstest_file_readdir.cc Sat Sep 18 18:51:43 2021 +0200 34.2 +++ b/tests/dstest_file_readdir.cc Mon Sep 20 01:16:59 2021 +0200 34.3 @@ -47,11 +47,11 @@ 34.4 34.5 /* Invoke the open method to receive the file reference. */ 34.6 34.7 - return client_opendir_using(filename, opener); 34.8 + return client_open_using(filename, O_DIRECTORY, opener); 34.9 } 34.10 else 34.11 { 34.12 - return client_opendir(filename); 34.13 + return client_open(filename, O_DIRECTORY); 34.14 } 34.15 } 34.16 34.17 @@ -79,11 +79,19 @@ 34.18 return 1; 34.19 } 34.20 34.21 + file_t *reader = client_opendir(file); 34.22 + 34.23 + if (reader == NULL) 34.24 + { 34.25 + printf("Could not read from directory.\n"); 34.26 + return 1; 34.27 + } 34.28 + 34.29 printf("Reading...\n"); 34.30 34.31 struct dirent *dirent; 34.32 34.33 - while ((dirent = client_readdir(file)) != NULL) 34.34 + while ((dirent = client_readdir(reader)) != NULL) 34.35 { 34.36 printf("> %s\n", dirent->d_name); 34.37 free(dirent); 34.38 @@ -101,7 +109,15 @@ 34.39 return 1; 34.40 } 34.41 34.42 - dirent = client_readdir(file); 34.43 + reader = client_opendir(file); 34.44 + 34.45 + if (reader == NULL) 34.46 + { 34.47 + printf("Could not read from directory.\n"); 34.48 + return 1; 34.49 + } 34.50 + 34.51 + dirent = client_readdir(reader); 34.52 34.53 if (dirent != NULL) 34.54 {