L4Re/departure

Annotated libfsserver/lib/files/ext2_file_opener.cc

645:3047b11cc814
7 months ago Paul Boddie Fixed the file_data_available result to return zero if the populated span has somehow become less than the current position in the memory region.
paul@102 1
/*
paul@106 2
 * An opener for a file provided by an Ext2-compatible filesystem.
paul@102 3
 *
paul@239 4
 * Copyright (C) 2021, 2022 Paul Boddie <paul@boddie.org.uk>
paul@102 5
 *
paul@102 6
 * This program is free software; you can redistribute it and/or
paul@102 7
 * modify it under the terms of the GNU General Public License as
paul@102 8
 * published by the Free Software Foundation; either version 2 of
paul@102 9
 * the License, or (at your option) any later version.
paul@102 10
 *
paul@102 11
 * This program is distributed in the hope that it will be useful,
paul@102 12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
paul@102 13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
paul@102 14
 * GNU General Public License for more details.
paul@102 15
 *
paul@102 16
 * You should have received a copy of the GNU General Public License
paul@102 17
 * along with this program; if not, write to the Free Software
paul@102 18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
paul@102 19
 * Boston, MA  02110-1301, USA
paul@102 20
 */
paul@102 21
paul@168 22
#include <string.h>
paul@168 23
paul@147 24
#include <e2access/path.h>
paul@168 25
#include <fsclient/client.h>
paul@535 26
#include <resource/resource_server.h>
paul@147 27
#include <systypes/fcntl.h>
paul@269 28
#include <systypes/stat.h>
paul@106 29
paul@202 30
#include "ext2_directory_accessor.h"
paul@106 31
#include "ext2_file_accessor.h"
paul@106 32
#include "ext2_file_opener.h"
paul@168 33
paul@168 34
paul@168 35
paul@156 36
Ext2FileOpener::~Ext2FileOpener()
paul@156 37
{
paul@156 38
}
paul@156 39
paul@156 40
/* Test if a directory is being accessed. */
paul@156 41
paul@240 42
bool Ext2FileOpener::accessing_directory(flags_t flags, fileid_t fileid)
paul@156 43
{
paul@240 44
    (void) flags;
paul@156 45
    return _ops->is_directory((ext2_ino_t) fileid);
paul@156 46
}
paul@156 47
paul@156 48
/* Test if a file is being accessed. */
paul@156 49
paul@240 50
bool Ext2FileOpener::accessing_file(flags_t flags, fileid_t fileid)
paul@156 51
{
paul@240 52
    (void) flags;
paul@156 53
    return _ops->is_file((ext2_ino_t) fileid);
paul@156 54
}
paul@156 55
paul@256 56
/* Test if a directory is empty. */
paul@256 57
paul@256 58
bool Ext2FileOpener::directory_is_empty(fileid_t fileid)
paul@256 59
{
paul@256 60
    return _ops->directory_is_empty(fileid);
paul@256 61
}
paul@256 62
paul@102 63
/* Return a file identifier for the given 'path'. */
paul@102 64
paul@146 65
long Ext2FileOpener::get_fileid(const char *path, flags_t flags, fileid_t *fileid)
paul@102 66
{
paul@106 67
    ext2_ino_t ino;
paul@148 68
    const char *remaining;
paul@148 69
    long err = _ops->find_file(path, &ino, &remaining);
paul@147 70
paul@148 71
    /* Return an existing file. */
paul@147 72
paul@148 73
    if (!err)
paul@148 74
    {
paul@239 75
        if (!_ops->can_access(_user, flags, ino))
paul@414 76
            return -L4_EACCESS;
paul@239 77
paul@148 78
        *fileid = (fileid_t) ino;
paul@148 79
        return L4_EOK;
paul@147 80
    }
paul@106 81
paul@148 82
    *fileid = FILEID_INVALID;
paul@148 83
paul@148 84
    /* Create a missing file if possible. */
paul@148 85
paul@156 86
    if ((flags & O_CREAT) && (flags & ~O_DIRECTORY))
paul@148 87
    {
paul@148 88
        /* Determine whether only the leafname is left of the path, with
paul@148 89
           the inode number referring to the parent directory. */
paul@148 90
paul@148 91
        if (path_is_leafname(remaining))
paul@148 92
        {
paul@148 93
            err = _ops->create_file(ino, remaining, _user, &ino);
paul@148 94
            if (err)
paul@148 95
                return err;
paul@148 96
paul@148 97
            *fileid = (fileid_t) ino;
paul@148 98
            return L4_EOK;
paul@148 99
        }
paul@148 100
    }
paul@148 101
paul@148 102
    return -L4_ENOENT;
paul@102 103
}
paul@102 104
paul@102 105
/* Return a new accessor for 'fileid'. */
paul@102 106
paul@240 107
long Ext2FileOpener::make_accessor(flags_t flags, fileid_t fileid,
paul@240 108
                                   Accessor **accessor)
paul@102 109
{
paul@240 110
    (void) flags;
paul@102 111
paul@106 112
    ext2_file_t file;
paul@148 113
    long err = _ops->open_file((ext2_ino_t) fileid, &file);
paul@143 114
paul@148 115
    if (err)
paul@148 116
        return err;
paul@106 117
paul@148 118
    *accessor = new Ext2FileAccessor(_ops, file, fileid);
paul@143 119
    return L4_EOK;
paul@102 120
}
paul@102 121
paul@202 122
/* Return a directory object reference for the given file identifier. */
paul@202 123
paul@240 124
long Ext2FileOpener::make_directory_accessor(flags_t flags, fileid_t fileid,
paul@202 125
                                             DirectoryAccessor **accessor)
paul@202 126
{
paul@240 127
    (void) flags;
paul@202 128
paul@202 129
    *accessor = new Ext2DirectoryAccessor(_ops, fileid);
paul@202 130
    return L4_EOK;
paul@202 131
}
paul@202 132
paul@266 133
paul@266 134
paul@271 135
/* Make a new directory. */
paul@271 136
paul@271 137
long Ext2FileOpener::make_directory_object(const char *path, sys_mode_t mode)
paul@271 138
{
paul@271 139
    fileid_t fileid, parent;
paul@271 140
    long err;
paul@271 141
paul@271 142
    /* Test for an existing object. */
paul@271 143
paul@271 144
    err = get_fileid(path, 0, &fileid);
paul@271 145
paul@271 146
    if (!err)
paul@271 147
        return -L4_EEXIST;
paul@271 148
paul@271 149
    if (err != -L4_ENOENT)
paul@271 150
        return err;
paul@271 151
paul@271 152
    /* Obtain the parent of the new directory. */
paul@271 153
paul@271 154
    err = get_parent(path, &parent);
paul@271 155
paul@271 156
    if (err)
paul@271 157
        return err;
paul@271 158
paul@271 159
    return _ops->mkdir((ext2_ino_t) parent, path_basename(path),
paul@271 160
                       systypes_from_sys_mode(mode), _user);
paul@271 161
}
paul@271 162
paul@232 163
/* Remove a filesystem object. */
paul@232 164
paul@240 165
long Ext2FileOpener::remove_object(fileid_t fileid)
paul@232 166
{
paul@232 167
    return _ops->remove((ext2_ino_t) fileid);
paul@232 168
}
paul@232 169
paul@236 170
/* Rename a filesystem object, placing source inside the parent of target. */
paul@236 171
paul@240 172
long Ext2FileOpener::rename_object(const char *source, const char *target)
paul@236 173
{
paul@240 174
    fileid_t source_fileid, source_parent, target_parent;
paul@240 175
    long err;
paul@236 176
paul@240 177
    err = get_fileid(source, 0, &source_fileid);
paul@240 178
paul@240 179
    if (err)
paul@240 180
        return err;
paul@236 181
paul@236 182
    err = get_parent(source, &source_parent);
paul@236 183
paul@236 184
    if (err)
paul@236 185
        return err;
paul@236 186
paul@236 187
    err = get_parent(target, &target_parent);
paul@236 188
paul@236 189
    if (err)
paul@236 190
        return err;
paul@236 191
paul@236 192
    return _ops->rename((ext2_ino_t) source_fileid,
paul@236 193
                        (ext2_ino_t) source_parent, path_basename(source),
paul@236 194
                        (ext2_ino_t) target_parent, path_basename(target));
paul@236 195
}
paul@236 196
paul@269 197
/* Populate a memory region with statistics metadata for a filesystem object. */
paul@269 198
paul@269 199
long Ext2FileOpener::stat_object(const char *path, void *base, offset_t size)
paul@269 200
{
paul@269 201
    struct stat st;
paul@269 202
    fileid_t fileid;
paul@590 203
paul@590 204
    /* Find the object without access restrictions since the metadata is not
paul@590 205
       sensitive. */
paul@590 206
paul@590 207
    ext2_ino_t ino;
paul@590 208
    const char *remaining;
paul@590 209
    long err = _ops->find_file(path, &ino, &remaining);
paul@269 210
paul@269 211
    if (err)
paul@590 212
        return -L4_ENOENT;
paul@590 213
paul@590 214
    fileid = (fileid_t) ino;
paul@269 215
paul@269 216
    if (sizeof(struct stat) > size)
paul@269 217
        return -L4_ENOMEM;
paul@269 218
paul@269 219
    err = _ops->stat_inode((ext2_ino_t) fileid, &st);
paul@269 220
paul@269 221
    if (err)
paul@269 222
        return err;
paul@269 223
paul@269 224
    /* Use the systypes version of the structure to permit different library
paul@269 225
       implementations on the client and server sides of an IPC invocation. */
paul@269 226
paul@269 227
    systypes_copy_to_sys_stat(&st, (sys_stat_t *) base);
paul@269 228
paul@269 229
    return L4_EOK;
paul@269 230
}
paul@269 231
paul@232 232
/* Unlink a filesystem object. */
paul@232 233
paul@240 234
long Ext2FileOpener::unlink_object(fileid_t parent_fileid, fileid_t fileid)
paul@232 235
{
paul@240 236
    return _ops->unlink((ext2_ino_t) parent_fileid, (ext2_ino_t) fileid);
paul@232 237
}
paul@232 238
paul@102 239
// vim: tabstop=4 expandtab shiftwidth=4