Subversion Repositories HelenOS

Rev

Rev 2678 | Rev 2750 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 2678 Rev 2747
Line 1... Line 1...
1
/*
1
/*
2
 * Copyright (c) 2007 Jakub Jermar
2
 * Copyright (c) 2008 Jakub Jermar
3
 * All rights reserved.
3
 * All rights reserved.
4
 *
4
 *
5
 * Redistribution and use in source and binary forms, with or without
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
6
 * modification, are permitted provided that the following conditions
7
 * are met:
7
 * are met:
Line 38... Line 38...
38
#include "../../srv/vfs/vfs.h"
38
#include "../../srv/vfs/vfs.h"
39
#include <errno.h>
39
#include <errno.h>
40
#include <async.h>
40
#include <async.h>
41
#include <ipc/ipc.h>
41
#include <ipc/ipc.h>
42
#include <as.h>
42
#include <as.h>
-
 
43
#include <assert.h>
-
 
44
#include <dirent.h>
43
 
45
 
44
/** Register file system server.
46
/** Register file system server.
45
 *
47
 *
46
 * This function abstracts away the tedious registration protocol from
48
 * This function abstracts away the tedious registration protocol from
47
 * file system implementations and lets them to reuse this registration glue
49
 * file system implementations and lets them to reuse this registration glue
Line 118... Line 120...
118
    async_set_client_connection(conn);
120
    async_set_client_connection(conn);
119
 
121
 
120
    return IPC_GET_RETVAL(answer);
122
    return IPC_GET_RETVAL(answer);
121
}
123
}
122
 
124
 
-
 
125
void libfs_lookup(libfs_ops_t *ops, int fs_handle, ipc_callid_t rid,
-
 
126
    ipc_call_t *request)
-
 
127
{
-
 
128
    unsigned next = IPC_GET_ARG1(*request);
-
 
129
    unsigned last = IPC_GET_ARG2(*request);
-
 
130
    int dev_handle = IPC_GET_ARG3(*request);
-
 
131
    int lflag = IPC_GET_ARG4(*request);
-
 
132
 
-
 
133
    if (last < next)
-
 
134
        last += PLB_SIZE;
-
 
135
 
-
 
136
    void *cur = ops->root_get();
-
 
137
    void *tmp = ops->child_get(cur);
-
 
138
 
-
 
139
    if (ops->plb_get_char(next) == '/')
-
 
140
        next++;     /* eat slash */
-
 
141
   
-
 
142
    char component[NAME_MAX + 1];
-
 
143
    int len = 0;
-
 
144
    while (tmp && next <= last) {
-
 
145
 
-
 
146
        /* collect the component */
-
 
147
        if (ops->plb_get_char(next) != '/') {
-
 
148
            if (len + 1 == NAME_MAX) {
-
 
149
                /* comopnent length overflow */
-
 
150
                ipc_answer_0(rid, ENAMETOOLONG);
-
 
151
                return;
-
 
152
            }
-
 
153
            component[len++] = ops->plb_get_char(next);
-
 
154
            next++; /* process next character */
-
 
155
            if (next <= last)
-
 
156
                continue;
-
 
157
        }
-
 
158
 
-
 
159
        assert(len);
-
 
160
        component[len] = '\0';
-
 
161
        next++;     /* eat slash */
-
 
162
        len = 0;
-
 
163
 
-
 
164
        /* match the component */
-
 
165
        while (tmp && !ops->match(tmp, component))
-
 
166
            tmp = ops->sibling_get(tmp);
-
 
167
 
-
 
168
        /* handle miss: match amongst siblings */
-
 
169
        if (!tmp) {
-
 
170
            if ((next > last) && (lflag & L_CREATE)) {
-
 
171
                /* no components left and L_CREATE specified */
-
 
172
                if (!ops->is_directory(cur)) {
-
 
173
                    ipc_answer_0(rid, ENOTDIR);
-
 
174
                    return;
-
 
175
                }
-
 
176
                void *nodep = ops->create(lflag);
-
 
177
                if (nodep) {
-
 
178
                    if (!ops->link(cur, nodep, component)) {
-
 
179
                        ops->destroy(nodep);
-
 
180
                        ipc_answer_0(rid, ENOSPC);
-
 
181
                    } else {
-
 
182
                        ipc_answer_5(rid, EOK,
-
 
183
                            fs_handle, dev_handle,
-
 
184
                            ops->index_get(nodep), 0,
-
 
185
                            ops->lnkcnt_get(nodep));
-
 
186
                    }
-
 
187
                } else {
-
 
188
                    ipc_answer_0(rid, ENOSPC);
-
 
189
                }
-
 
190
                return;
-
 
191
            }
-
 
192
            ipc_answer_0(rid, ENOENT);
-
 
193
            return;
-
 
194
        }
-
 
195
 
-
 
196
        /* descend one level */
-
 
197
        cur = tmp;
-
 
198
        tmp = ops->child_get(tmp);
-
 
199
    }
-
 
200
 
-
 
201
    /* handle miss: excessive components */
-
 
202
    if (!tmp && next <= last) {
-
 
203
        if (lflag & L_CREATE) {
-
 
204
            if (!ops->is_directory(cur)) {
-
 
205
                ipc_answer_0(rid, ENOTDIR);
-
 
206
                return;
-
 
207
            }
-
 
208
 
-
 
209
            /* collect next component */
-
 
210
            while (next <= last) {
-
 
211
                if (ops->plb_get_char(next) == '/') {
-
 
212
                    /* more than one component */
-
 
213
                    ipc_answer_0(rid, ENOENT);
-
 
214
                    return;
-
 
215
                }
-
 
216
                if (len + 1 == NAME_MAX) {
-
 
217
                    /* component length overflow */
-
 
218
                    ipc_answer_0(rid, ENAMETOOLONG);
-
 
219
                    return;
-
 
220
                }
-
 
221
                component[len++] = ops->plb_get_char(next);
-
 
222
                next++; /* process next character */
-
 
223
            }
-
 
224
            assert(len);
-
 
225
            component[len] = '\0';
-
 
226
            len = 0;
-
 
227
               
-
 
228
            void *nodep = ops->create(lflag);
-
 
229
            if (nodep) {
-
 
230
                if (!ops->link(cur, nodep, component)) {
-
 
231
                    ops->destroy(nodep);
-
 
232
                    ipc_answer_0(rid, ENOSPC);
-
 
233
                } else {
-
 
234
                    ipc_answer_5(rid, EOK,
-
 
235
                        fs_handle, dev_handle,
-
 
236
                        ops->index_get(nodep), 0,
-
 
237
                        ops->lnkcnt_get(nodep));
-
 
238
                }
-
 
239
            } else {
-
 
240
                ipc_answer_0(rid, ENOSPC);
-
 
241
            }
-
 
242
            return;
-
 
243
        }
-
 
244
        ipc_answer_0(rid, ENOENT);
-
 
245
        return;
-
 
246
    }
-
 
247
 
-
 
248
    /* handle hit */
-
 
249
    if (lflag & L_DESTROY) {
-
 
250
        unsigned old_lnkcnt = ops->lnkcnt_get(cur);
-
 
251
        int res = ops->unlink(cur);
-
 
252
        ipc_answer_5(rid, (ipcarg_t)res, fs_handle, dev_handle,
-
 
253
            ops->index_get(cur), ops->size_get(cur), old_lnkcnt);
-
 
254
        return;
-
 
255
    }
-
 
256
    if ((lflag & (L_CREATE | L_EXCLUSIVE)) == (L_CREATE | L_EXCLUSIVE)) {
-
 
257
        ipc_answer_0(rid, EEXIST);
-
 
258
        return;
-
 
259
    }
-
 
260
    if ((lflag & L_FILE) && (ops->is_directory(cur))) {
-
 
261
        ipc_answer_0(rid, EISDIR);
-
 
262
        return;
-
 
263
    }
-
 
264
    if ((lflag & L_DIRECTORY) && (ops->is_file(cur))) {
-
 
265
        ipc_answer_0(rid, ENOTDIR);
-
 
266
        return;
-
 
267
    }
-
 
268
 
-
 
269
    ipc_answer_5(rid, EOK, fs_handle, dev_handle, ops->index_get(cur),
-
 
270
        ops->size_get(cur), ops->lnkcnt_get(cur));
-
 
271
}
-
 
272
 
123
/** @}
273
/** @}
124
 */
274
 */