L4Re/departure

Annotated libfsserver/lib/files/host_file_opener.cc

240:ffd7b371fcfd
2022-02-10 Paul Boddie Removed file paths from various methods, instead relying on file identifiers. Some operations such as file renaming still need to be aware of file paths because they need to know the parent directories of renamed objects.
paul@93 1
/*
paul@93 2
 * An opener for a "host" file provided via the C library.
paul@93 3
 *
paul@236 4
 * Copyright (C) 2021, 2022 Paul Boddie <paul@boddie.org.uk>
paul@93 5
 *
paul@93 6
 * This program is free software; you can redistribute it and/or
paul@93 7
 * modify it under the terms of the GNU General Public License as
paul@93 8
 * published by the Free Software Foundation; either version 2 of
paul@93 9
 * the License, or (at your option) any later version.
paul@93 10
 *
paul@93 11
 * This program is distributed in the hope that it will be useful,
paul@93 12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
paul@93 13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
paul@93 14
 * GNU General Public License for more details.
paul@93 15
 *
paul@93 16
 * You should have received a copy of the GNU General Public License
paul@93 17
 * along with this program; if not, write to the Free Software
paul@93 18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
paul@93 19
 * Boston, MA  02110-1301, USA
paul@93 20
 */
paul@93 21
paul@236 22
#include <stdio.h>
paul@156 23
#include <sys/stat.h>
paul@232 24
#include <unistd.h>
paul@156 25
paul@160 26
#include <fsclient/client.h>
paul@160 27
paul@202 28
#include "host_directory_accessor.h"
paul@12 29
#include "host_file_accessor.h"
paul@12 30
#include "host_file_opener.h"
paul@202 31
#include "resource_server.h"
paul@160 32
paul@160 33
paul@160 34
paul@156 35
HostFileOpener::~HostFileOpener()
paul@156 36
{
paul@156 37
}
paul@156 38
paul@240 39
bool HostFileOpener::accessing_directory(flags_t flags, fileid_t fileid)
paul@156 40
{
paul@240 41
    (void) flags;
paul@240 42
paul@240 43
    const char *path = _get_path(fileid);
paul@240 44
paul@240 45
    if (path == NULL)
paul@240 46
        return false;
paul@240 47
paul@156 48
    struct stat st;
paul@156 49
paul@156 50
    if (stat(path, &st))
paul@156 51
        return false;
paul@156 52
paul@156 53
    return (st.st_mode & S_IFDIR) ? true : false;
paul@156 54
}
paul@156 55
paul@240 56
bool HostFileOpener::accessing_file(flags_t flags, fileid_t fileid)
paul@156 57
{
paul@240 58
    (void) flags;
paul@156 59
    struct stat st;
paul@156 60
paul@240 61
    const char *path = _get_path(fileid);
paul@240 62
paul@240 63
    if (path == NULL)
paul@240 64
        return false;
paul@240 65
paul@156 66
    if (stat(path, &st))
paul@156 67
        return false;
paul@156 68
paul@156 69
    return (st.st_mode & S_IFREG) ? true : false;
paul@156 70
}
paul@156 71
paul@12 72
/* Return a file identifier for the given 'path'. */
paul@12 73
paul@146 74
long HostFileOpener::get_fileid(const char *path, flags_t flags, fileid_t *fileid)
paul@143 75
{
paul@143 76
    (void) flags;
paul@143 77
paul@146 78
    /* Test for a valid file. */
paul@143 79
paul@143 80
    FILE *fp = fopen(path, "r");
paul@143 81
paul@143 82
    if (fp == NULL)
paul@146 83
        return -L4_ENOENT;
paul@143 84
paul@143 85
    fclose(fp);
paul@143 86
paul@146 87
    *fileid = _get_fileid(path, true);
paul@146 88
    return L4_EOK;
paul@143 89
}
paul@143 90
paul@143 91
fileid_t HostFileOpener::_get_fileid(const char *path, bool create)
paul@12 92
{
paul@139 93
    std::lock_guard<std::mutex> guard(_lock);
paul@139 94
paul@139 95
    /* The inode number would be a good choice, but the L4Re read-only file
paul@139 96
       implementation just provides the value of a counter!
paul@139 97
paul@139 98
       See: pkg/l4re-core/l4re_vfs/include/impl/ro_file_impl.h */
paul@139 99
paul@139 100
    std::string s(path);
paul@12 101
paul@139 102
    HostFileIdentifiers::iterator it = _fileids.find(s);
paul@139 103
paul@139 104
    if (it != _fileids.end())
paul@139 105
        return it->second;
paul@12 106
paul@143 107
    if (!create)
paul@143 108
        return FILEID_INVALID;
paul@143 109
paul@139 110
    fileid_t fileid = _fileids.size();
paul@12 111
paul@139 112
    _fileids[s] = fileid;
paul@240 113
    _paths[fileid] = s;
paul@139 114
paul@139 115
    return fileid;
paul@12 116
}
paul@12 117
paul@240 118
const char *HostFileOpener::_get_path(fileid_t fileid)
paul@240 119
{
paul@240 120
    std::lock_guard<std::mutex> guard(_lock);
paul@240 121
paul@240 122
    HostFilePaths::iterator it = _paths.find(fileid);
paul@240 123
paul@240 124
    if (it != _paths.end())
paul@240 125
        return it->second.c_str();
paul@240 126
    else
paul@240 127
        return NULL;
paul@240 128
}
paul@240 129
paul@12 130
/* Return a new accessor for 'fileid'. */
paul@12 131
paul@240 132
long HostFileOpener::make_accessor(flags_t flags, fileid_t fileid,
paul@240 133
                                   Accessor **accessor)
paul@12 134
{
paul@143 135
    // NOTE: Not testing for create or write flags.
paul@143 136
paul@143 137
    (void) flags;
paul@143 138
paul@240 139
    const char *path = _get_path(fileid);
paul@240 140
paul@240 141
    if (path == NULL)
paul@240 142
        return -L4_ENOENT;
paul@240 143
paul@106 144
    FILE *fp = fopen(path, "r");
paul@12 145
paul@106 146
    if (fp == NULL)
paul@143 147
        return -L4_ENOENT;
paul@106 148
paul@143 149
    *accessor = new HostFileAccessor(fp, fileid);
paul@143 150
    return L4_EOK;
paul@12 151
}
paul@12 152
paul@202 153
/* Return a directory accessor for 'fileid'. */
paul@202 154
paul@240 155
long HostFileOpener::make_directory_accessor(flags_t flags, fileid_t fileid,
paul@202 156
                                             DirectoryAccessor **accessor)
paul@202 157
{
paul@240 158
    (void) flags;
paul@240 159
paul@240 160
    const char *path = _get_path(fileid);
paul@240 161
paul@240 162
    if (path == NULL)
paul@240 163
        return -L4_ENOENT;
paul@202 164
paul@202 165
    *accessor = new HostDirectoryAccessor(path);
paul@202 166
    return L4_EOK;
paul@202 167
}
paul@202 168
paul@232 169
/* Remove a filesystem object. */
paul@232 170
paul@240 171
long HostFileOpener::remove_object(fileid_t fileid)
paul@232 172
{
paul@240 173
    (void) fileid;
paul@232 174
    return L4_EOK;
paul@232 175
}
paul@232 176
paul@236 177
/* Rename a filesystem object, placing source inside the parent of target. */
paul@236 178
paul@240 179
long HostFileOpener::rename_object(const char *source, const char *target)
paul@236 180
{
paul@236 181
    /* NOTE: Should propagate a more meaningful error. */
paul@236 182
paul@236 183
    if (rename(source, target))
paul@236 184
        return -L4_EIO;
paul@236 185
paul@236 186
    return L4_EOK;
paul@236 187
}
paul@236 188
paul@232 189
/* Unlink a filesystem object. */
paul@232 190
paul@240 191
long HostFileOpener::unlink_object(fileid_t parent_fileid, fileid_t fileid)
paul@232 192
{
paul@240 193
    /* Ignore the parent and always use the path. */
paul@240 194
paul@240 195
    (void) parent_fileid;
paul@232 196
paul@240 197
    const char *path = _get_path(fileid);
paul@240 198
paul@240 199
    if (path == NULL)
paul@240 200
        return -L4_ENOENT;
paul@232 201
paul@232 202
    // NOTE: Return code may need converting.
paul@232 203
paul@232 204
    int err = unlink(path);
paul@232 205
paul@232 206
    if (err)
paul@232 207
        return err;
paul@232 208
paul@232 209
    /* Remove the file identifier mapping. */
paul@232 210
paul@232 211
    std::string s(path);
paul@232 212
paul@232 213
    HostFileIdentifiers::iterator it = _fileids.find(s);
paul@232 214
paul@232 215
    if (it != _fileids.end())
paul@232 216
        _fileids.erase(it);
paul@232 217
paul@240 218
    HostFilePaths::iterator pit = _paths.find(fileid);
paul@240 219
paul@240 220
    if (pit != _paths.end())
paul@240 221
        _paths.erase(pit);
paul@240 222
paul@232 223
    return L4_EOK;
paul@232 224
}
paul@232 225
paul@12 226
// vim: tabstop=4 expandtab shiftwidth=4