1/*
2 * Copyright 2016, Data61
3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO)
4 * ABN 41 687 119 230.
5 *
6 * This software may be distributed and modified according to the terms of
7 * the BSD 2-Clause license. Note that NO WARRANTY is provided.
8 * See "LICENSE_BSD2.txt" for details.
9 *
10 * @TAG(D61_BSD)
11 */
12
13#include <assert.h>
14#include <stdio.h>
15#include <stdlib.h>
16#include <string.h>
17#include <sel4/sel4.h>
18
19#include <refos-rpc/name_client.h>
20#include <refos-rpc/name_client_helper.h>
21#include <refos-rpc/proc_client.h>
22#include <refos-rpc/proc_client_helper.h>
23#include <refos-util/dprintf.h>
24
25static bool
26nsv_check_path_resolved(char* path)
27{
28    if (!path) {
29        return false;
30    }
31    if (path[0] == '/') {
32        path++;
33    }
34
35    int len = strlen(path);
36    for (int i = 0; i < len; i++) {
37        if (path[i] == '/') {
38            return false;
39        }
40    }
41
42    return true;
43}
44
45void
46nsv_mountpoint_release(nsv_mountpoint_t *m)
47{
48    if (!m || !m->success || !m->serverAnon) {
49        return;
50    }
51    m->success = false;
52    if (m->serverAnon != REFOS_PROCSERV_EP) {
53        proc_del_endpoint(m->serverAnon);
54    }
55    m->serverAnon = 0;
56    memset(m, 0, sizeof(nsv_mountpoint_t));
57}
58
59nsv_mountpoint_t
60nsv_resolve(char* path)
61{
62    nsv_mountpoint_t ret;
63    memset(&ret, 0, sizeof(nsv_mountpoint_t));
64
65    if (!path) {
66        REFOS_SET_ERRNO(EINVALIDPARAM);
67        return ret;
68    }
69
70    char *cpath = path;
71    seL4_CPtr nameServer = REFOS_NAMESERV_EP;
72
73    while (1) {
74        int resolvedBytes = 0;
75        seL4_CPtr nextNameServer = 0;
76
77        /* Check if path has already been resolved. */
78        bool resolved = nsv_check_path_resolved(cpath);
79        if (!resolved) {
80            nextNameServer = nsv_resolve_segment(nameServer, cpath, &resolvedBytes);
81        }
82
83        /* Have we reached the leaf of the path? */
84        if (resolved || resolvedBytes == NAMESERV_RESOLVED) {
85            ret.success = true;
86            ret.serverAnon = nameServer;
87            ret.nameservRoot = REFOS_NAMESERV_EP;
88            strcpy(ret.dspaceName, cpath);
89            strncpy(ret.nameservPathPrefix, path, cpath - path);
90            REFOS_SET_ERRNO(ESUCCESS);
91            return ret;
92        }
93
94        /* Delete the name server. */
95        if (nameServer != REFOS_NAMESERV_EP) {
96            assert(nameServer);
97            proc_del_endpoint(nameServer);
98            nameServer = 0;
99        }
100
101        /* Was resolve invalid? */
102        if (resolvedBytes == 0) {
103            ret.success = false;
104            REFOS_SET_ERRNO(ESERVERNOTFOUND);
105            return ret;
106        }
107
108        /* External resolve. */
109        assert(nextNameServer);
110        nameServer = nextNameServer;
111        cpath += resolvedBytes;
112        if (cpath[0] == '/') {
113            cpath++;
114        }
115    }
116}