Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 2657 → Rev 2658

/trunk/uspace/srv/fs/tmpfs/tmpfs_ops.c
45,9 → 45,46
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <libadt/hash_table.h>
#include <as.h>
 
#define min(a, b) ((a) < (b) ? (a) : (b))
#define max(a, b) ((a) > (b) ? (a) : (b))
 
#define PLB_GET_CHAR(i) (tmpfs_reg.plb_ro[(i) % PLB_SIZE])
 
#define DENTRIES_BUCKETS 256
 
/*
* Hash table of all directory entries.
*/
hash_table_t dentries;
 
static hash_index_t dentries_hash(unsigned long *key)
{
return *key % DENTRIES_BUCKETS;
}
 
static int dentries_compare(unsigned long *key, hash_count_t keys,
link_t *item)
{
tmpfs_dentry_t *dentry = hash_table_get_instance(item, tmpfs_dentry_t,
dh_link);
return dentry->index == *key;
}
 
static void dentries_remove_callback(link_t *item)
{
}
 
/** TMPFS dentries hash table operations. */
hash_table_operations_t dentries_ops = {
.hash = dentries_hash,
.compare = dentries_compare,
.remove_callback = dentries_remove_callback
};
 
unsigned tmpfs_next_index = 1;
 
static void tmpfs_dentry_initialize(tmpfs_dentry_t *dentry)
60,6 → 97,7
dentry->type = TMPFS_NONE;
dentry->size = 0;
dentry->data = NULL;
link_initialize(&dentry->dh_link);
}
 
/*
70,14 → 108,17
 
static bool tmpfs_init(void)
{
if (!hash_table_create(&dentries, DENTRIES_BUCKETS, 1, &dentries_ops))
return false;
 
root = (tmpfs_dentry_t *) malloc(sizeof(tmpfs_dentry_t));
if (!root) {
if (!root)
return false;
}
tmpfs_dentry_initialize(root);
root->index = tmpfs_next_index++;
root->name = "";
root->type = TMPFS_DIRECTORY;
hash_table_insert(&dentries, &root->index, &root->dh_link);
 
/*
* This is only for debugging. Once we can create files and directories
96,6 → 137,7
d->parent = root;
d->type = TMPFS_DIRECTORY;
d->name = "dir1";
hash_table_insert(&dentries, &d->index, &d->dh_link);
 
d = (tmpfs_dentry_t *) malloc(sizeof(tmpfs_dentry_t));
if (!d) {
110,6 → 152,7
d->parent = root;
d->type = TMPFS_DIRECTORY;
d->name = "dir2";
hash_table_insert(&dentries, &d->index, &d->dh_link);
d = (tmpfs_dentry_t *) malloc(sizeof(tmpfs_dentry_t));
if (!d) {
127,6 → 170,7
d->name = "file1";
d->data = "This is the contents of /dir1/file1.\n";
d->size = strlen(d->data);
hash_table_insert(&dentries, &d->index, &d->dh_link);
 
d = (tmpfs_dentry_t *) malloc(sizeof(tmpfs_dentry_t));
if (!d) {
145,6 → 189,7
d->name = "file2";
d->data = "This is the contents of /dir2/file2.\n";
d->size = strlen(d->data);
hash_table_insert(&dentries, &d->index, &d->dh_link);
 
return true;
}
232,6 → 277,60
ipc_answer_3(rid, EOK, tmpfs_reg.fs_handle, dev_handle, dcur->index);
}
 
void tmpfs_read(ipc_callid_t rid, ipc_call_t *request)
{
int dev_handle = IPC_GET_ARG1(*request);
unsigned long index = IPC_GET_ARG2(*request);
off_t pos = IPC_GET_ARG3(*request);
size_t size = IPC_GET_ARG4(*request);
 
/*
* Lookup the respective dentry.
*/
link_t *hlp;
hlp = hash_table_find(&dentries, &index);
if (!hlp) {
ipc_answer_0(rid, ENOENT);
return;
}
tmpfs_dentry_t *dentry = hash_table_get_instance(hlp, tmpfs_dentry_t,
dh_link);
 
/*
* Receive the communication area.
*/
ipc_callid_t callid;
ipc_call_t call;
callid = async_get_call(&call);
if (IPC_GET_METHOD(call) != IPC_M_AS_AREA_SEND) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
 
int flags = IPC_GET_ARG3(call);
if (!(flags & AS_AREA_WRITE)) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
size_t sz = IPC_GET_ARG2(call);
uint8_t *buf = as_get_mappable_page(sz);
if (!buf) {
ipc_answer_0(callid, ENOMEM);
ipc_answer_0(rid, ENOMEM);
return;
}
ipc_answer_1(callid, EOK, buf); /* commit to share the area */
 
size_t bytes = max(0, min(dentry->size - pos, size));
memcpy(buf, dentry->data + pos, bytes);
 
(void) as_area_destroy(buf);
 
ipc_answer_1(rid, EOK, bytes);
}
 
/**
* @}
*/