1,5 → 1,5 |
/* |
* Copyright (c) 2009 Jakub Jermar |
* Copyright (c) 2008 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
42,7 → 42,6 |
#include <as.h> |
#include <assert.h> |
#include <dirent.h> |
#include <mem.h> |
|
/** Register file system server. |
* |
123,106 → 122,23 |
return IPC_GET_RETVAL(answer); |
} |
|
void fs_node_initialize(fs_node_t *fn) |
{ |
memset(fn, 0, sizeof(fs_node_t)); |
} |
|
void libfs_mount(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid, |
ipc_call_t *request) |
{ |
dev_handle_t mp_dev_handle = (dev_handle_t) IPC_GET_ARG1(*request); |
fs_index_t mp_fs_index = (fs_index_t) IPC_GET_ARG2(*request); |
fs_handle_t mr_fs_handle = (fs_handle_t) IPC_GET_ARG3(*request); |
dev_handle_t mr_dev_handle = (dev_handle_t) IPC_GET_ARG4(*request); |
int res; |
ipcarg_t rc; |
|
ipc_call_t call; |
ipc_callid_t callid; |
|
/* accept the phone */ |
callid = async_get_call(&call); |
int mountee_phone = (int)IPC_GET_ARG1(call); |
if ((IPC_GET_METHOD(call) != IPC_M_CONNECTION_CLONE) || |
mountee_phone < 0) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
ipc_answer_0(callid, EOK); /* acknowledge the mountee_phone */ |
|
res = ipc_data_write_receive(&callid, NULL); |
if (!res) { |
ipc_hangup(mountee_phone); |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
|
fs_node_t *fn = ops->node_get(mp_dev_handle, mp_fs_index); |
if (!fn) { |
ipc_hangup(mountee_phone); |
ipc_answer_0(callid, ENOENT); |
ipc_answer_0(rid, ENOENT); |
return; |
} |
|
if (fn->mp_data.mp_active) { |
ipc_hangup(mountee_phone); |
ops->node_put(fn); |
ipc_answer_0(callid, EBUSY); |
ipc_answer_0(rid, EBUSY); |
return; |
} |
|
rc = async_req_0_0(mountee_phone, IPC_M_CONNECT_ME); |
if (rc != 0) { |
ipc_hangup(mountee_phone); |
ops->node_put(fn); |
ipc_answer_0(callid, rc); |
ipc_answer_0(rid, rc); |
return; |
} |
|
ipc_call_t answer; |
aid_t msg = async_send_1(mountee_phone, VFS_MOUNTED, mr_dev_handle, |
&answer); |
ipc_forward_fast(callid, mountee_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME); |
async_wait_for(msg, &rc); |
|
if (rc == EOK) { |
fn->mp_data.mp_active = true; |
fn->mp_data.fs_handle = mr_fs_handle; |
fn->mp_data.dev_handle = mr_dev_handle; |
fn->mp_data.phone = mountee_phone; |
} |
/* |
* Do not release the FS node so that it stays in memory. |
*/ |
ipc_answer_3(rid, rc, IPC_GET_ARG1(answer), IPC_GET_ARG2(answer), |
IPC_GET_ARG3(answer)); |
} |
|
/** Lookup VFS triplet by name in the file system name space. |
* |
* The path passed in the PLB must be in the canonical file system path format |
* as returned by the canonify() function. |
* |
* @param ops libfs operations structure with function pointers to |
* file system implementation |
* @param fs_handle File system handle of the file system where to perform |
* the lookup. |
* @param rid Request ID of the VFS_LOOKUP request. |
* @param request VFS_LOOKUP request data itself. |
* |
* @param ops libfs operations structure with function pointers to |
* file system implementation |
* @param fs_handle File system handle of the file system where to perform |
* the lookup. |
* @param rid Request ID of the VFS_LOOKUP request. |
* @param request VFS_LOOKUP request data itself. |
*/ |
void libfs_lookup(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid, |
ipc_call_t *request) |
{ |
unsigned first = IPC_GET_ARG1(*request); |
unsigned next = IPC_GET_ARG1(*request); |
unsigned last = IPC_GET_ARG2(*request); |
unsigned next = first; |
dev_handle_t dev_handle = IPC_GET_ARG3(*request); |
int lflag = IPC_GET_ARG4(*request); |
fs_index_t index = IPC_GET_ARG5(*request); /* when L_LINK specified */ |
232,18 → 148,10 |
if (last < next) |
last += PLB_SIZE; |
|
fs_node_t *par = NULL; |
fs_node_t *cur = ops->root_get(dev_handle); |
fs_node_t *tmp = NULL; |
void *par = NULL; |
void *cur = ops->root_get(dev_handle); |
void *tmp = NULL; |
|
if (cur->mp_data.mp_active) { |
ipc_forward_slow(rid, cur->mp_data.phone, VFS_LOOKUP, |
next, last, cur->mp_data.dev_handle, lflag, index, |
IPC_FF_ROUTE_FROM_ME); |
ops->node_put(cur); |
return; |
} |
|
if (ops->plb_get_char(next) == '/') |
next++; /* eat slash */ |
|
266,21 → 174,6 |
|
/* match the component */ |
tmp = ops->match(cur, component); |
if (tmp && tmp->mp_data.mp_active) { |
if (next > last) |
next = last = first; |
else |
next--; |
|
ipc_forward_slow(rid, tmp->mp_data.phone, VFS_LOOKUP, |
next, last, tmp->mp_data.dev_handle, lflag, index, |
IPC_FF_ROUTE_FROM_ME); |
ops->node_put(cur); |
ops->node_put(tmp); |
if (par) |
ops->node_put(par); |
return; |
} |
|
/* handle miss: match amongst siblings */ |
if (!tmp) { |
296,33 → 189,39 |
ipc_answer_0(rid, ENOTDIR); |
goto out; |
} |
fs_node_t *fn; |
void *nodep; |
if (lflag & L_CREATE) |
fn = ops->create(dev_handle, lflag); |
nodep = ops->create(dev_handle, lflag); |
else |
fn = ops->node_get(dev_handle, |
nodep = ops->node_get(dev_handle, |
index); |
if (fn) { |
if (nodep) { |
int rc; |
|
rc = ops->link(cur, fn, component); |
rc = ops->link(cur, nodep, component); |
if (rc != EOK) { |
if (lflag & L_CREATE) { |
(void)ops->destroy(fn); |
(void)ops->destroy( |
nodep); |
} |
ipc_answer_0(rid, rc); |
} else { |
ipc_answer_5(rid, EOK, |
fs_handle, dev_handle, |
ops->index_get(fn), |
ops->size_get(fn), |
ops->lnkcnt_get(fn)); |
ops->node_put(fn); |
ops->index_get(nodep), |
ops->size_get(nodep), |
ops->lnkcnt_get(nodep)); |
ops->node_put(nodep); |
} |
} else { |
ipc_answer_0(rid, ENOSPC); |
} |
goto out; |
} else if (lflag & L_PARENT) { |
/* return parent */ |
ipc_answer_5(rid, EOK, fs_handle, dev_handle, |
ops->index_get(cur), ops->size_get(cur), |
ops->lnkcnt_get(cur)); |
} |
ipc_answer_0(rid, ENOENT); |
goto out; |
364,26 → 263,26 |
assert(len); |
component[len] = '\0'; |
|
fs_node_t *fn; |
void *nodep; |
if (lflag & L_CREATE) |
fn = ops->create(dev_handle, lflag); |
nodep = ops->create(dev_handle, lflag); |
else |
fn = ops->node_get(dev_handle, index); |
if (fn) { |
nodep = ops->node_get(dev_handle, index); |
if (nodep) { |
int rc; |
|
rc = ops->link(cur, fn, component); |
rc = ops->link(cur, nodep, component); |
if (rc != EOK) { |
if (lflag & L_CREATE) |
(void)ops->destroy(fn); |
(void)ops->destroy(nodep); |
ipc_answer_0(rid, rc); |
} else { |
ipc_answer_5(rid, EOK, |
fs_handle, dev_handle, |
ops->index_get(fn), |
ops->size_get(fn), |
ops->lnkcnt_get(fn)); |
ops->node_put(fn); |
ops->index_get(nodep), |
ops->size_get(nodep), |
ops->lnkcnt_get(nodep)); |
ops->node_put(nodep); |
} |
} else { |
ipc_answer_0(rid, ENOSPC); |
395,9 → 294,18 |
} |
|
/* handle hit */ |
if (lflag & L_PARENT) { |
ops->node_put(cur); |
cur = par; |
par = NULL; |
if (!cur) { |
ipc_answer_0(rid, ENOENT); |
goto out; |
} |
} |
if (lflag & L_UNLINK) { |
unsigned old_lnkcnt = ops->lnkcnt_get(cur); |
int res = ops->unlink(par, cur, component); |
int res = ops->unlink(par, cur); |
ipc_answer_5(rid, (ipcarg_t)res, fs_handle, dev_handle, |
ops->index_get(cur), ops->size_get(cur), old_lnkcnt); |
goto out; |
428,32 → 336,5 |
ops->node_put(tmp); |
} |
|
/** Open VFS triplet. |
* |
* @param ops libfs operations structure with function pointers to |
* file system implementation |
* @param rid Request ID of the VFS_OPEN_NODE request. |
* @param request VFS_OPEN_NODE request data itself. |
* |
*/ |
void libfs_open_node(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid, |
ipc_call_t *request) |
{ |
dev_handle_t dev_handle = IPC_GET_ARG1(*request); |
fs_index_t index = IPC_GET_ARG2(*request); |
|
fs_node_t *node = ops->node_get(dev_handle, index); |
|
if (node == NULL) { |
ipc_answer_0(rid, ENOENT); |
return; |
} |
|
ipc_answer_5(rid, EOK, fs_handle, dev_handle, index, |
ops->size_get(node), ops->lnkcnt_get(node)); |
|
ops->node_put(node); |
} |
|
/** @} |
*/ |