Directory support in tmpfs

This commit is contained in:
Kevin Lange 2013-04-23 23:21:16 -07:00
parent 716ce11c83
commit 8c16a86206

View File

@ -7,37 +7,63 @@
/* 1KB */
#define BLOCKSIZE 1024
#define TMPFS_TYPE_FILE 1
#define TMPFS_TYPE_DIR 2
static uint8_t volatile lock = 0;
struct tmpfs_file {
char * name;
size_t length;
size_t block_count;
size_t pointers;
uint32_t flags;
char ** blocks;
int type;
int mask;
int uid;
int gid;
unsigned int atime;
unsigned int mtime;
unsigned int ctime;
size_t length;
size_t block_count;
size_t pointers;
char ** blocks;
};
list_t * tmpfs_files = NULL;
struct tmpfs_dir;
struct tmpfs_dir {
char * name;
int type;
int mask;
int uid;
int gid;
unsigned int atime;
unsigned int mtime;
unsigned int ctime;
list_t * files;
struct tmpfs_dir * parent;
};
char empty_block[BLOCKSIZE] = {0};
struct tmpfs_dir * tmpfs_root = NULL;
fs_node_t * tmpfs_from_dir(struct tmpfs_dir * d);
static struct tmpfs_file * tmpfs_file_new(char * name) {
spin_lock(&lock);
struct tmpfs_file * t = malloc(sizeof(struct tmpfs_file));
t->name = strdup(name);
t->type = TMPFS_TYPE_FILE;
t->length = 0;
t->pointers = 2;
t->block_count = 0;
t->flags = 0;
t->mask = 0;
t->uid = 0;
t->gid = 0;
t->atime = now();
t->mtime = t->atime;
t->ctime = t->ctime;
t->blocks = malloc(t->pointers * sizeof(char *));
for (size_t i = 0; i < t->pointers; ++i) {
t->blocks[i] = NULL;
@ -47,6 +73,24 @@ static struct tmpfs_file * tmpfs_file_new(char * name) {
return t;
}
static struct tmpfs_dir * tmpfs_dir_new(char * name, struct tmpfs_dir * parent) {
spin_lock(&lock);
struct tmpfs_dir * d = malloc(sizeof(struct tmpfs_dir));
d->name = strdup(name);
d->type = TMPFS_TYPE_DIR;
d->mask = 0;
d->uid = 0;
d->gid = 0;
d->atime = now();
d->mtime = d->atime;
d->ctime = d->ctime;
d->files = list_create();
spin_unlock(&lock);
return d;
}
static void tmpfs_file_free(struct tmpfs_file * t) {
for (size_t i = 0; i < t->block_count; ++i) {
free(t->blocks[i]);
@ -85,6 +129,9 @@ static char * tmpfs_file_getset_block(struct tmpfs_file * t, size_t blockid, int
static uint32_t read_tmpfs(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) {
struct tmpfs_file * t = (struct tmpfs_file *)(node->device);
t->atime = now();
uint32_t end;
if (offset + size > t->length) {
end = t->length;
@ -124,6 +171,10 @@ static uint32_t read_tmpfs(fs_node_t *node, uint32_t offset, uint32_t size, uint
static uint32_t write_tmpfs(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) {
struct tmpfs_file * t = (struct tmpfs_file *)(node->device);
t->atime = now();
t->mtime = t->atime;
uint32_t end;
if (offset + size > t->length) {
t->length = offset + size;
@ -176,6 +227,9 @@ static fs_node_t * tmpfs_from_file(struct tmpfs_file * t) {
fnode->mask = t->mask;
fnode->uid = t->uid;
fnode->gid = t->gid;
fnode->atime = t->atime;
fnode->ctime = t->ctime;
fnode->mtime = t->mtime;
fnode->flags = FS_FILE;
fnode->read = read_tmpfs;
fnode->write = write_tmpfs;
@ -189,13 +243,14 @@ static fs_node_t * tmpfs_from_file(struct tmpfs_file * t) {
}
static struct dirent * readdir_tmpfs(fs_node_t *node, uint32_t index) {
struct tmpfs_dir * d = (struct tmpfs_dir *)node->device;
uint32_t i = 0;
debug_print(NOTICE, "tmpfs - readdir id=%d", index);
if (index >= tmpfs_files->length) return NULL;
if (index >= d->files->length) return NULL;
foreach(f, tmpfs_files) {
foreach(f, d->files) {
if (i == index) {
struct tmpfs_file * t = (struct tmpfs_file *)f->value;
struct dirent * out = malloc(sizeof(struct dirent));
@ -213,13 +268,20 @@ static struct dirent * readdir_tmpfs(fs_node_t *node, uint32_t index) {
static fs_node_t * finddir_tmpfs(fs_node_t * node, char * name) {
if (!name) return NULL;
struct tmpfs_dir * d = (struct tmpfs_dir *)node->device;
spin_lock(&lock);
foreach(f, tmpfs_files) {
foreach(f, d->files) {
struct tmpfs_file * t = (struct tmpfs_file *)f->value;
if (!strcmp(name, t->name)) {
spin_unlock(&lock);
return tmpfs_from_file(t);
switch (t->type) {
case TMPFS_TYPE_FILE:
return tmpfs_from_file(t);
case TMPFS_TYPE_DIR:
return tmpfs_from_dir((struct tmpfs_dir *)t);
}
}
}
@ -229,10 +291,11 @@ static fs_node_t * finddir_tmpfs(fs_node_t * node, char * name) {
}
static void unlink_tmpfs(fs_node_t * node, char * name) {
struct tmpfs_dir * d = (struct tmpfs_dir *)node->device;
int i = -1, j = 0;
spin_lock(&lock);
foreach(f, tmpfs_files) {
foreach(f, d->files) {
struct tmpfs_file * t = (struct tmpfs_file *)f->value;
if (!strcmp(name, t->name)) {
tmpfs_file_free(t);
@ -244,7 +307,7 @@ static void unlink_tmpfs(fs_node_t * node, char * name) {
}
if (i >= 0) {
list_remove(tmpfs_files, i);
list_remove(d->files, i);
}
spin_unlock(&lock);
@ -254,10 +317,11 @@ static void unlink_tmpfs(fs_node_t * node, char * name) {
void create_tmpfs(fs_node_t *parent, char *name, uint16_t permission) {
if (!name) return;
debug_print(CRITICAL, "Creating TMPFS file %s", name);
struct tmpfs_dir * d = (struct tmpfs_dir *)parent->device;
debug_print(CRITICAL, "Creating TMPFS file %s in %s", name, d->name);
spin_lock(&lock);
foreach(f, tmpfs_files) {
foreach(f, d->files) {
struct tmpfs_file * t = (struct tmpfs_file *)f->value;
if (!strcmp(name, t->name)) {
spin_unlock(&lock);
@ -273,17 +337,47 @@ void create_tmpfs(fs_node_t *parent, char *name, uint16_t permission) {
t->uid = current_process->user;
t->gid = current_process->user;
list_insert(tmpfs_files, t);
list_insert(d->files, t);
}
fs_node_t * tmpfs_create() {
void mkdir_tmpfs(fs_node_t * parent, char * name, uint16_t permission) {
if (!name) return;
struct tmpfs_dir * d = (struct tmpfs_dir *)parent->device;
debug_print(CRITICAL, "Creating TMPFS directory %s (in %s)", name, d->name);
spin_lock(&lock);
foreach(f, d->files) {
struct tmpfs_file * t = (struct tmpfs_file *)f->value;
if (!strcmp(name, t->name)) {
spin_unlock(&lock);
debug_print(WARNING, "... already exists.");
return; /* Already exists */
}
}
spin_unlock(&lock);
debug_print(NOTICE, "... creating a new directory.");
struct tmpfs_dir * out = tmpfs_dir_new(name, d);
out->mask = permission;
out->uid = current_process->user;
out->gid = current_process->user;
list_insert(d->files, out);
}
fs_node_t * tmpfs_from_dir(struct tmpfs_dir * d) {
fs_node_t * fnode = malloc(sizeof(fs_node_t));
memset(fnode, 0x00, sizeof(fs_node_t));
fnode->inode = 0;
strcpy(fnode->name, "tmp");
fnode->mask = 0777;
fnode->uid = 0;
fnode->gid = 0;
fnode->mask = d->mask;
fnode->uid = d->uid;
fnode->gid = d->gid;
fnode->device = d;
fnode->atime = d->atime;
fnode->mtime = d->mtime;
fnode->ctime = d->ctime;
fnode->flags = FS_DIRECTORY;
fnode->read = NULL;
fnode->write = NULL;
@ -293,7 +387,16 @@ fs_node_t * tmpfs_create() {
fnode->finddir = finddir_tmpfs;
fnode->create = create_tmpfs;
fnode->unlink = unlink_tmpfs;
fnode->mkdir = mkdir_tmpfs;
tmpfs_files = list_create();
return fnode;
}
fs_node_t * tmpfs_create() {
tmpfs_root = tmpfs_dir_new("tmp", NULL);
tmpfs_root->mask = 0777;
tmpfs_root->uid = 0;
tmpfs_root->gid = 0;
return tmpfs_from_dir(tmpfs_root);
}