Subversion Repositories HelenOS

Rev

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

Rev 2700 Rev 2705
Line 43... Line 43...
43
#include <errno.h>
43
#include <errno.h>
44
#include <atomic.h>
44
#include <atomic.h>
45
#include <stdlib.h>
45
#include <stdlib.h>
46
#include <string.h>
46
#include <string.h>
47
#include <stdio.h>
47
#include <stdio.h>
-
 
48
#include <dirent.h>
48
#include <assert.h>
49
#include <assert.h>
49
#include <sys/types.h>
50
#include <sys/types.h>
50
#include <libadt/hash_table.h>
51
#include <libadt/hash_table.h>
51
#include <as.h>
52
#include <as.h>
52
 
53
 
Line 196... Line 197...
196
}
197
}
197
 
198
 
198
/** Compare one component of path to a directory entry.
199
/** Compare one component of path to a directory entry.
199
 *
200
 *
200
 * @param dentry    Directory entry to compare the path component with.
201
 * @param dentry    Directory entry to compare the path component with.
201
 * @param start     Index into PLB where the path component starts.
202
 * @param component Array of characters holding component name.
202
 * @param last      Index of the last character of the path in PLB.
-
 
203
 *
203
 *
204
 * @return      Zero on failure or delta such that (index + delta) %
204
 * @return      True on match, false otherwise.
205
 *          PLB_SIZE points to the first unprocessed character in
-
 
206
 *          PLB which comprises the path.
-
 
207
 */
205
 */
208
static unsigned match_path_component(tmpfs_dentry_t *dentry, unsigned start,
206
static bool match_component(tmpfs_dentry_t *dentry, const char *component)
209
    unsigned last)
-
 
210
{
207
{
211
    int i, j;
-
 
212
    size_t namelen;
208
    return !strcmp(dentry->name, component);
213
 
209
}
214
    namelen = strlen(dentry->name);
-
 
215
 
210
 
-
 
211
static unsigned long create_node(tmpfs_dentry_t *dentry,
216
    if (last < start)
212
    const char *component, int lflag)
-
 
213
{
217
        last += PLB_SIZE;
214
    return 0;
-
 
215
}
218
 
216
 
219
    for (i = 0, j = start; i < namelen && j <= last; i++, j++) {
-
 
220
        if (dentry->name[i] != PLB_GET_CHAR(j))
217
static int destroy_component(tmpfs_dentry_t *dentry)
221
            return 0;
-
 
222
    }
-
 
223
   
218
{
224
    if (i != namelen)
-
 
225
        return 0;
-
 
226
    if (j < last && PLB_GET_CHAR(j) != '/')
-
 
227
        return 0;
219
    return EPERM;
228
    if (j == last)
-
 
229
            return 0;
-
 
230
   
-
 
231
    return (j - start);
-
 
232
}
220
}
233
 
221
 
234
void tmpfs_lookup(ipc_callid_t rid, ipc_call_t *request)
222
void tmpfs_lookup(ipc_callid_t rid, ipc_call_t *request)
235
{
223
{
236
    unsigned next = IPC_GET_ARG1(*request);
224
    unsigned next = IPC_GET_ARG1(*request);
Line 239... Line 227...
239
    int lflag = IPC_GET_ARG4(*request);
227
    int lflag = IPC_GET_ARG4(*request);
240
 
228
 
241
    if (last < next)
229
    if (last < next)
242
        last += PLB_SIZE;
230
        last += PLB_SIZE;
243
 
231
 
-
 
232
    /*
-
 
233
     * Initialize TMPFS.
-
 
234
     */
244
    if (!root && !tmpfs_init()) {
235
    if (!root && !tmpfs_init()) {
245
        ipc_answer_0(rid, ENOMEM);
236
        ipc_answer_0(rid, ENOMEM);
246
        return;
237
        return;
247
    }
238
    }
248
 
239
 
249
    tmpfs_dentry_t *dtmp = root->child;
240
    tmpfs_dentry_t *dtmp = root->child;
250
    tmpfs_dentry_t *dcur = root;
241
    tmpfs_dentry_t *dcur = root;
251
 
242
 
252
    bool hit = true;
-
 
253
   
-
 
254
    if (PLB_GET_CHAR(next) == '/')
243
    if (PLB_GET_CHAR(next) == '/')
255
        next++;     /* eat slash */
244
        next++;     /* eat slash */
256
   
245
   
-
 
246
    char component[NAME_MAX + 1];
-
 
247
    int len = 0;
257
    while (next <= last) {
248
    while (next <= last) {
-
 
249
 
-
 
250
        /* collect the component */
-
 
251
        if (PLB_GET_CHAR(next) != '/') {
-
 
252
            if (len + 1 == NAME_MAX) {
-
 
253
                /* comopnent length overflow */
-
 
254
                ipc_answer_0(rid, ENAMETOOLONG);
-
 
255
                return;
-
 
256
            }
-
 
257
            component[len++] = PLB_GET_CHAR(next);
-
 
258
            next++; /* process next character */
258
        unsigned delta;
259
            if (next <= last)
259
        hit = false;
260
                continue;
260
        do {
261
        }
-
 
262
 
-
 
263
        assert(len);
-
 
264
        component[len] = '\0';
-
 
265
        next++;     /* eat slash */
-
 
266
        len = 0;
-
 
267
 
-
 
268
        /* match the component */
261
            delta = match_path_component(dtmp, next, last);
269
        while (dtmp && !match_component(dtmp, component))
-
 
270
            dtmp = dtmp->sibling;
-
 
271
 
-
 
272
        /* handle miss: match amongst siblings */
262
            if (!delta) {
273
        if (!dtmp) {
-
 
274
            if ((next > last) && (lflag & L_CREATE)) {
-
 
275
                /* no components left and L_CREATE specified */
-
 
276
                if (dcur->type != TMPFS_DIRECTORY) {
-
 
277
                    ipc_answer_0(rid, ENOTDIR);
-
 
278
                    return;
-
 
279
                }
-
 
280
                unsigned long index = create_node(dcur,
263
                dtmp = dtmp->sibling;
281
                    component, lflag);
-
 
282
                if (index) {
-
 
283
                    ipc_answer_4(rid, EOK,
-
 
284
                        tmpfs_reg.fs_handle, dev_handle,
-
 
285
                        index, 0);
264
            } else {
286
                } else {
-
 
287
                    ipc_answer_0(rid, ENOSPC);
-
 
288
                }
265
                hit = true;
289
                return;
-
 
290
            }
-
 
291
            ipc_answer_0(rid, ENOENT);
266
                next += delta;
292
            return;
-
 
293
        }
-
 
294
 
267
                next++;     /* eat slash */
295
        /* descent one level */
268
                dcur = dtmp;
296
        dcur = dtmp;
269
                dtmp = dtmp->child;
297
        dtmp = dtmp->child;
-
 
298
 
-
 
299
        /* handle miss: excessive components */
-
 
300
        if (!dtmp && next <= last) {
-
 
301
            if (lflag & L_CREATE) {
-
 
302
                if (dcur->type != TMPFS_DIRECTORY) {
-
 
303
                    ipc_answer_0(rid, ENOTDIR);
-
 
304
                    return;
270
            }  
305
                }
-
 
306
 
-
 
307
                /* collect next component */
271
        } while (delta == 0 && dtmp);
308
                while (next <= last) {
-
 
309
                    if (PLB_GET_CHAR(next) == '/') {
-
 
310
                        /* more than one component */
-
 
311
                        ipc_answer_0(rid, ENOENT);
-
 
312
                        return;
-
 
313
                    }
-
 
314
                    if (len + 1 == NAME_MAX) {
-
 
315
                        /* component length overflow */
-
 
316
                        ipc_answer_0(rid, ENAMETOOLONG);
-
 
317
                        return;
-
 
318
                    }
-
 
319
                    component[len++] = PLB_GET_CHAR(next);
-
 
320
                    next++; /* process next character */
-
 
321
                }
-
 
322
                assert(len);
-
 
323
                component[len] = '\0';
-
 
324
                len = 0;
-
 
325
               
-
 
326
                unsigned long index;
-
 
327
                index = create_node(dcur, component, lflag);
272
        if (!hit) {
328
                if (index) {
273
            ipc_answer_3(rid, ENOENT, tmpfs_reg.fs_handle,
329
                    ipc_answer_4(rid, EOK,
274
                dev_handle, dcur->index);
330
                        tmpfs_reg.fs_handle, dev_handle,
-
 
331
                        index, 0);
-
 
332
                } else {
-
 
333
                    ipc_answer_0(rid, ENOSPC);
-
 
334
                }
-
 
335
                return;
-
 
336
            }
-
 
337
            ipc_answer_0(rid, ENOENT);
275
            return;
338
            return;
276
        }
339
        }
-
 
340
   
-
 
341
    }
-
 
342
 
-
 
343
    /* handle hit */
-
 
344
    if (lflag & L_DESTROY) {
-
 
345
        int res = destroy_component(dcur);
-
 
346
        ipc_answer_0(rid, res);
-
 
347
        return;
-
 
348
    }
-
 
349
    if ((lflag & (L_CREATE | L_EXCLUSIVE)) == (L_CREATE | L_EXCLUSIVE)) {
-
 
350
        ipc_answer_0(rid, EEXIST);
-
 
351
        return;
-
 
352
    }
-
 
353
    if ((lflag & L_FILE) && (dcur->type != TMPFS_FILE)) {
-
 
354
        ipc_answer_0(rid, EISDIR);
-
 
355
        return;
-
 
356
    }
-
 
357
    if ((lflag & L_DIRECTORY) && (dcur->type != TMPFS_DIRECTORY)) {
-
 
358
        ipc_answer_0(rid, ENOTDIR);
-
 
359
        return;
277
    }
360
    }
278
 
361
 
279
    ipc_answer_4(rid, EOK, tmpfs_reg.fs_handle, dev_handle, dcur->index,
362
    ipc_answer_4(rid, EOK, tmpfs_reg.fs_handle, dev_handle, dcur->index,
280
        dcur->size);
363
        dcur->size);
281
}
364
}