1,5 → 1,5 |
/* |
* Copyright (c) 2008 Jakub Jermar |
* Copyright (c) 2009 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
42,6 → 42,8 |
#include <as.h> |
#include <assert.h> |
#include <dirent.h> |
#include <mem.h> |
#include <sys/stat.h> |
|
/** Register file system server. |
* |
68,7 → 70,7 |
* out-of-order, when it knows that the operation succeeded or failed. |
*/ |
ipc_call_t answer; |
aid_t req = async_send_0(vfs_phone, VFS_REGISTER, &answer); |
aid_t req = async_send_0(vfs_phone, VFS_IN_REGISTER, &answer); |
|
/* |
* Send our VFS info structure to VFS. |
103,7 → 105,7 |
} |
|
/* |
* Pick up the answer for the request to the VFS_REQUEST call. |
* Pick up the answer for the request to the VFS_IN_REQUEST call. |
*/ |
async_wait_for(req, NULL); |
reg->fs_handle = (int) IPC_GET_ARG1(answer); |
122,6 → 124,87 |
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_OUT_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 |
131,14 → 214,16 |
* 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 rid Request ID of the VFS_OUT_LOOKUP request. |
* @param request VFS_OUT_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 next = IPC_GET_ARG1(*request); |
unsigned first = 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 */ |
152,6 → 237,14 |
fs_node_t *cur = ops->root_get(dev_handle); |
fs_node_t *tmp = NULL; |
|
if (cur->mp_data.mp_active) { |
ipc_forward_slow(rid, cur->mp_data.phone, VFS_OUT_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 */ |
|
174,7 → 267,22 |
|
/* 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_OUT_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) { |
if (next <= last) { |
321,5 → 429,62 |
ops->node_put(tmp); |
} |
|
void libfs_stat(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid, |
ipc_call_t *request) |
{ |
dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request); |
fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request); |
fs_node_t *fn = ops->node_get(dev_handle, index); |
|
ipc_callid_t callid; |
size_t size; |
if (!ipc_data_read_receive(&callid, &size) || |
size != sizeof(struct stat)) { |
ipc_answer_0(callid, EINVAL); |
ipc_answer_0(rid, EINVAL); |
return; |
} |
|
struct stat stat; |
memset(&stat, 0, sizeof(struct stat)); |
|
stat.fs_handle = fs_handle; |
stat.dev_handle = dev_handle; |
stat.index = index; |
stat.lnkcnt = ops->lnkcnt_get(fn); |
stat.is_file = ops->is_file(fn); |
stat.size = ops->size_get(fn); |
|
ipc_data_read_finalize(callid, &stat, sizeof(struct stat)); |
ipc_answer_0(rid, EOK); |
} |
|
/** Open VFS triplet. |
* |
* @param ops libfs operations structure with function pointers to |
* file system implementation |
* @param rid Request ID of the VFS_OUT_OPEN_NODE request. |
* @param request VFS_OUT_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); |
} |
|
/** @} |
*/ |