# HG changeset patch # User Paul Boddie # Date 1627597235 -7200 # Node ID 40729d5e6af2937595431f604721e50a56b7bbf6 # Parent 5be26f9f495e53972bae93ff14584c0738c7b727 Moved ext2 filesystem operations to a dedicated object. diff -r 5be26f9f495e -r 40729d5e6af2 libfsserver/include/fsserver/ext2_file_accessor.h --- a/libfsserver/include/fsserver/ext2_file_accessor.h Sun Jul 25 23:18:39 2021 +0200 +++ b/libfsserver/include/fsserver/ext2_file_accessor.h Fri Jul 30 00:20:35 2021 +0200 @@ -24,6 +24,7 @@ #include #include +#include @@ -32,6 +33,7 @@ class Ext2FileAccessor : public Accessor { protected: + Ext2FileOperations *_ops; ext2_file_t _file; /* Data transfer helper methods. */ @@ -41,7 +43,8 @@ virtual void flush_populated(Flexpage *flexpage); public: - explicit Ext2FileAccessor(ext2_file_t file, fileid_t fileid); + explicit Ext2FileAccessor(Ext2FileOperations *ops, ext2_file_t file, + fileid_t fileid); virtual void close(); diff -r 5be26f9f495e -r 40729d5e6af2 libfsserver/include/fsserver/ext2_file_opener.h --- a/libfsserver/include/fsserver/ext2_file_opener.h Sun Jul 25 23:18:39 2021 +0200 +++ b/libfsserver/include/fsserver/ext2_file_opener.h Fri Jul 30 00:20:35 2021 +0200 @@ -23,6 +23,7 @@ #include +#include #include #include @@ -33,12 +34,12 @@ class Ext2FileOpener : public OpenerResource { protected: - ext2_filsys _fs; + Ext2FileOperations *_ops; user_t _user; public: - explicit Ext2FileOpener(FilePaging *paging, ext2_filsys fs, user_t user) - : OpenerResource(paging), _fs(fs), _user(user) + explicit Ext2FileOpener(FilePaging *paging, Ext2FileOperations *ops, user_t user) + : OpenerResource(paging), _ops(ops), _user(user) { } diff -r 5be26f9f495e -r 40729d5e6af2 libfsserver/include/fsserver/ext2_file_operations.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/include/fsserver/ext2_file_operations.h Fri Jul 30 00:20:35 2021 +0200 @@ -0,0 +1,62 @@ +/* + * File operations supporting an Ext2-compatible filesystem. + * + * Copyright (C) 2021 Paul Boddie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + +#include + +#include +#include + + + +/* An Ext2 file operations collection. */ + +class Ext2FileOperations +{ +protected: + ext2_filsys _fs; + +public: + explicit Ext2FileOperations(ext2_filsys fs) + : _fs(fs) + { + } + + long create_file(ext2_ino_t ino_parent, const char *filename, user_t user, + ext2_ino_t *ino); + + long find_file(const char *path, ext2_ino_t *ino, const char **remaining); + + void close_file(ext2_file_t file); + + long open_file(ext2_ino_t ino, ext2_file_t *file); + + offset_t get_size(ext2_file_t file); + + void set_size(ext2_file_t file, offset_t size); + + offset_t read_file(ext2_file_t file, offset_t filepos, void *addr, offset_t size); + + void write_file(ext2_file_t file, offset_t filepos, const void *addr, offset_t size); +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r 5be26f9f495e -r 40729d5e6af2 libfsserver/include/fsserver/ext2_filesystem.h --- a/libfsserver/include/fsserver/ext2_filesystem.h Sun Jul 25 23:18:39 2021 +0200 +++ b/libfsserver/include/fsserver/ext2_filesystem.h Fri Jul 30 00:20:35 2021 +0200 @@ -24,6 +24,7 @@ #include +#include #include @@ -33,13 +34,12 @@ class Ext2Filesystem : public FilesystemResource { protected: - ext2_filsys _fs; + Ext2FileOperations *_ops; public: - explicit Ext2Filesystem(Pages *pages, ext2_filsys fs) - : FilesystemResource(pages), _fs(fs) - { - } + explicit Ext2Filesystem(Pages *pages, ext2_filsys fs); + + virtual ~Ext2Filesystem(); /* Filesystem interface methods. */ diff -r 5be26f9f495e -r 40729d5e6af2 libfsserver/lib/Makefile --- a/libfsserver/lib/Makefile Sun Jul 25 23:18:39 2021 +0200 +++ b/libfsserver/lib/Makefile Fri Jul 30 00:20:35 2021 +0200 @@ -43,6 +43,7 @@ files/block_file_opener.cc \ files/ext2_file_accessor.cc \ files/ext2_file_opener.cc \ + files/ext2_file_operations.cc \ files/ext2_filesystem.cc \ files/file_pager.cc \ files/file_paging.cc \ diff -r 5be26f9f495e -r 40729d5e6af2 libfsserver/lib/files/ext2_file_accessor.cc --- a/libfsserver/lib/files/ext2_file_accessor.cc Sun Jul 25 23:18:39 2021 +0200 +++ b/libfsserver/lib/files/ext2_file_accessor.cc Fri Jul 30 00:20:35 2021 +0200 @@ -21,8 +21,6 @@ #include #include -#include -#include #include @@ -32,8 +30,9 @@ -Ext2FileAccessor::Ext2FileAccessor(ext2_file_t file, fileid_t fileid) -: Accessor(fileid), _file(file) +Ext2FileAccessor::Ext2FileAccessor(Ext2FileOperations *ops, ext2_file_t file, + fileid_t fileid) +: Accessor(fileid), _ops(ops), _file(file) { } @@ -41,22 +40,21 @@ offset_t Ext2FileAccessor::get_size() { - return ext2fs_file_get_size(_file); + return _ops->get_size(_file); } /* Update the size of the file. */ void Ext2FileAccessor::set_size(offset_t size) { - ext2fs_file_set_size(_file, size); + _ops->set_size(_file, size); } /* Perform any closing operation on the file. */ void Ext2FileAccessor::close() { - ext2fs_file_flush(_file); - ext2fs_file_close(_file); + _ops->close_file(_file); } /* Data transfer helper methods. */ @@ -74,10 +72,7 @@ /* Fill the region with file content. */ - ext2fs_file_llseek(_file, filepos, SEEK_SET, NULL); - - unsigned int nread; - ext2fs_file_read(_file, (void *) addr, flexpage->size, &nread); + offset_t nread = _ops->read_file(_file, filepos, (void *) addr, flexpage->size); /* Pad the flexpage with zero. */ @@ -98,8 +93,7 @@ /* Copy the populated region to the file. */ - ext2fs_file_llseek(_file, filepos, SEEK_SET, NULL); - ext2fs_file_write(_file, (const void *) addr, populated_size, NULL); + _ops->write_file(_file, filepos, (const void *) addr, populated_size); } // vim: tabstop=4 expandtab shiftwidth=4 diff -r 5be26f9f495e -r 40729d5e6af2 libfsserver/lib/files/ext2_file_opener.cc --- a/libfsserver/lib/files/ext2_file_opener.cc Sun Jul 25 23:18:39 2021 +0200 +++ b/libfsserver/lib/files/ext2_file_opener.cc Fri Jul 30 00:20:35 2021 +0200 @@ -19,8 +19,6 @@ * Boston, MA 02110-1301, USA */ -#include -#include #include #include @@ -32,55 +30,39 @@ long Ext2FileOpener::get_fileid(const char *path, flags_t flags, fileid_t *fileid) { - const char *filename = path; - - /* Obtain the inode number. */ - ext2_ino_t ino; - errcode_t retval = image_find_path(_fs, &filename, &ino); - - /* Handle a missing file. */ - - if (retval) - { - /* Create a missing file if possible. */ - - if (flags & O_CREAT) - { - /* Determine whether only the leafname is left of the path, with - the inode number referring to the parent directory. */ - - if (path_is_leafname(filename)) - { - struct ext2_inode inode_parent; + const char *remaining; + long err = _ops->find_file(path, &ino, &remaining); - /* Determine write access in the directory. */ - - retval = ext2fs_read_inode(_fs, ino, &inode_parent); - - if (retval) - return -L4_EIO; - - if (!access_can_write(_user, &inode_parent)) - return -L4_EPERM; - - /* If so, use the parent directory inode to create a new file. */ + /* Return an existing file. */ - if (image_create_file(_fs, ino, filename, 0666 & ~_user.umask, - _user.uid, _user.gid, &ino)) - return -L4_EIO; - - *fileid = (fileid_t) ino; - return L4_EOK; - } - } - - *fileid = FILEID_INVALID; - return -L4_ENOENT; + if (!err) + { + *fileid = (fileid_t) ino; + return L4_EOK; } - *fileid = (fileid_t) ino; - return L4_EOK; + *fileid = FILEID_INVALID; + + /* Create a missing file if possible. */ + + if (flags & O_CREAT) + { + /* Determine whether only the leafname is left of the path, with + the inode number referring to the parent directory. */ + + if (path_is_leafname(remaining)) + { + err = _ops->create_file(ino, remaining, _user, &ino); + if (err) + return err; + + *fileid = (fileid_t) ino; + return L4_EOK; + } + } + + return -L4_ENOENT; } /* Return a new accessor for 'fileid'. */ @@ -90,14 +72,12 @@ (void) path; (void) flags; ext2_file_t file; - errcode_t retval = ext2fs_file_open(_fs, (ext2_ino_t) fileid, EXT2_FILE_WRITE, &file); - - // NOTE: Map error conditions. + long err = _ops->open_file((ext2_ino_t) fileid, &file); - if (retval) - return -L4_EIO; + if (err) + return err; - *accessor = new Ext2FileAccessor(file, fileid); + *accessor = new Ext2FileAccessor(_ops, file, fileid); return L4_EOK; } diff -r 5be26f9f495e -r 40729d5e6af2 libfsserver/lib/files/ext2_file_operations.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/lib/files/ext2_file_operations.cc Fri Jul 30 00:20:35 2021 +0200 @@ -0,0 +1,126 @@ +/* + * File operations performed by an Ext2-compatible filesystem. + * + * Copyright (C) 2021 Paul Boddie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include +#include +#include + +#include "ext2_file_operations.h" + +/* Create a file in the directory indicated by the given inode number with the + given filename. The file is created with the given user permissions. */ + +long Ext2FileOperations::create_file(ext2_ino_t ino_parent, const char *filename, + user_t user, ext2_ino_t *ino) +{ + if (!path_is_leafname(filename)) + return -L4_EINVAL; + + struct ext2_inode inode_parent; + errcode_t retval = ext2fs_read_inode(_fs, ino_parent, &inode_parent); + + if (retval) + return -L4_EIO; + + if (!access_can_write(user, &inode_parent)) + return -L4_EPERM; + + if (image_create_file(_fs, ino_parent, filename, 0666 & ~user.umask, + user.uid, user.gid, ino)) + return -L4_EIO; + + return L4_EOK; +} + +/* For the given 'path', return an inode number or indicate the 'remaining' + part of the path that cannot be resolved. */ + +long Ext2FileOperations::find_file(const char *path, ext2_ino_t *ino, + const char **remaining) +{ + *remaining = path; + errcode_t retval = image_find_path(_fs, remaining, ino); + + // NOTE: Map error conditions. + + if (retval) + return -L4_EIO; + + return L4_EOK; +} + +/* Perform closing operations on a file. */ + +void Ext2FileOperations::close_file(ext2_file_t file) +{ + ext2fs_file_flush(file); + ext2fs_file_close(file); +} + +/* Open the file associated with the indicated inode. */ + +long Ext2FileOperations::open_file(ext2_ino_t ino, ext2_file_t *file) +{ + errcode_t retval = ext2fs_file_open(_fs, ino, EXT2_FILE_WRITE, file); + + // NOTE: Map error conditions. + + if (retval) + return -L4_EIO; + + return L4_EOK; +} + +/* Obtain the size of a file. */ + +offset_t Ext2FileOperations::get_size(ext2_file_t file) +{ + return ext2fs_file_get_size(file); +} + +/* Update the size of a file. */ + +void Ext2FileOperations::set_size(ext2_file_t file, offset_t size) +{ + ext2fs_file_set_size(file, size); +} + +/* Populate the given memory region with file content. */ + +offset_t Ext2FileOperations::read_file(ext2_file_t file, offset_t filepos, void *addr, offset_t size) +{ + unsigned int nread; + + ext2fs_file_llseek(file, filepos, SEEK_SET, NULL); + ext2fs_file_read(file, (void *) addr, size, &nread); + + return (offset_t) nread; +} + +/* Transfer content from the given memory region to a file. */ + +void Ext2FileOperations::write_file(ext2_file_t file, offset_t filepos, const void *addr, offset_t size) +{ + ext2fs_file_llseek(file, filepos, SEEK_SET, NULL); + ext2fs_file_write(file, addr, size, NULL); +} + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r 5be26f9f495e -r 40729d5e6af2 libfsserver/lib/files/ext2_filesystem.cc --- a/libfsserver/lib/files/ext2_filesystem.cc Sun Jul 25 23:18:39 2021 +0200 +++ b/libfsserver/lib/files/ext2_filesystem.cc Fri Jul 30 00:20:35 2021 +0200 @@ -24,13 +24,24 @@ #include "ext2_filesystem.h" #include "resource_server.h" +Ext2Filesystem::Ext2Filesystem(Pages *pages, ext2_filsys fs) +: FilesystemResource(pages) +{ + _ops = new Ext2FileOperations(fs); +} + +Ext2Filesystem::~Ext2Filesystem() +{ + delete _ops; +} + /* Return a file opener object for the given user. */ long Ext2Filesystem::open_for_user(sys_uid_t uid, sys_gid_t gid, sys_mode_t umask, l4_cap_idx_t *ref) { user_t user = (user_t) {uid, gid, umask}; - Resource *resource = new Ext2FileOpener(this, _fs, user); + Resource *resource = new Ext2FileOpener(this, _ops, user); /* Complete the initialisation and start a server in a new thread. If the thread does not start, the resource will be finalised. */