L4Re/departure

Annotated libfsserver/lib/files/opener_resource.cc

218:20d95266049c
2021-10-16 Paul Boddie Made the file registry responsible for looking up existing objects and obtaining resources through a single get_resource operation, simplifying the opener resource.
paul@93 1
/*
paul@93 2
 * A resource offering support for creating contexts and opening files.
paul@93 3
 *
paul@93 4
 * Copyright (C) 2021 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@211 22
#include <string.h>
paul@211 23
paul@10 24
#include "opener_server.h"
paul@10 25
#include "opener_resource.h"
paul@10 26
#include "resource_server.h"
paul@9 27
paul@9 28
/* Support for providing access to files. */
paul@9 29
paul@209 30
OpenerResource::OpenerResource(FileObjectRegistry *registry)
paul@209 31
: _registry(registry)
paul@9 32
{
paul@9 33
}
paul@9 34
paul@156 35
OpenerResource::~OpenerResource()
paul@156 36
{
paul@156 37
}
paul@156 38
paul@10 39
int OpenerResource::expected_items()
paul@9 40
{
paul@10 41
    return Opener_expected_items;
paul@9 42
}
paul@9 43
paul@10 44
ipc_server_handler_type OpenerResource::handler()
paul@10 45
{
paul@10 46
    return (ipc_server_handler_type) handle_Opener;
paul@10 47
}
paul@10 48
paul@10 49
paul@10 50
paul@214 51
/* Obtain the identifier for any active parent directory for a path. */
paul@211 52
paul@214 53
long OpenerResource::get_parent(const char *path, fileid_t *fileid)
paul@211 54
{
paul@211 55
    char *sep = strrchr(path, (int) '/');
paul@211 56
    long err;
paul@211 57
paul@211 58
    /* For top-level paths, use the empty string to get the root directory.
paul@211 59
       Otherwise, obtain the parent directory path to obtain the file
paul@211 60
       identifier. */
paul@211 61
paul@211 62
    if (sep == NULL)
paul@214 63
        err = get_fileid("", 0, fileid);
paul@211 64
    else
paul@211 65
    {
paul@211 66
        char *parent = strndup(path, sep - path + 1);
paul@211 67
paul@211 68
        parent[sep - path] = '\0';
paul@214 69
        err = get_fileid(parent, 0, fileid);
paul@211 70
        free(parent);
paul@211 71
    }
paul@211 72
paul@214 73
    return err;
paul@214 74
}
paul@214 75
paul@214 76
/* Obtain any active parent directory for a path, notifying its subscribers of
paul@214 77
   the file opening event. */
paul@214 78
paul@214 79
long OpenerResource::notify_parent(const char *path)
paul@214 80
{
paul@214 81
    DirectoryProvider *provider;
paul@214 82
    fileid_t fileid;
paul@214 83
    long err;
paul@214 84
paul@214 85
    err = get_parent(path, &fileid);
paul@214 86
paul@211 87
    if (err)
paul@211 88
        return err;
paul@211 89
paul@211 90
    /* Obtain the provider of the parent directory. */
paul@211 91
paul@211 92
    err = _registry->find_directory_provider(fileid, &provider);
paul@211 93
paul@211 94
    if (err)
paul@211 95
        return err;
paul@211 96
paul@211 97
    /* With any active provider, send a notification.
paul@211 98
       NOTE: This should also communicate which file was involved, probably
paul@211 99
       NOTE: using the file identifier of the opened file. */
paul@211 100
paul@211 101
    provider->notify_all(NOTIFY_FILE_OPENED);
paul@211 102
    return L4_EOK;
paul@211 103
}
paul@211 104
paul@211 105
paul@211 106
paul@205 107
/* Return an object for the given path and flags. */
paul@10 108
paul@171 109
long OpenerResource::open(const char *path, flags_t flags, offset_t *size,
paul@171 110
                          l4_cap_idx_t *cap, object_flags_t *object_flags)
paul@9 111
{
paul@218 112
    Resource *resource;
paul@218 113
    long err = _registry->get_resource(this, path, flags, size, object_flags, &resource);
paul@156 114
paul@156 115
    if (err)
paul@156 116
        return err;
paul@156 117
paul@211 118
    /* Notify listeners subscribed to the parent of the opened object. */
paul@211 119
paul@211 120
    notify_parent(path);
paul@211 121
paul@218 122
    /* Start a server for the resource. */
paul@202 123
paul@218 124
    return ResourceServer(resource).start_thread(cap);
paul@9 125
}
paul@9 126
paul@10 127
paul@10 128
paul@10 129
/* Opener interface methods. */
paul@10 130
paul@10 131
long OpenerResource::context(l4_cap_idx_t *context)
paul@10 132
{
paul@10 133
    OpenerContextResource *resource = new OpenerContextResource(this);
paul@10 134
paul@62 135
    /* Complete the initialisation and start a server in a new thread.
paul@120 136
       If the thread does not start, the resource will be finalised. */
paul@10 137
paul@120 138
    return ResourceServer(resource).start_thread(context);
paul@10 139
}
paul@10 140
paul@9 141
// vim: tabstop=4 expandtab shiftwidth=4