aboutsummaryrefslogblamecommitdiff
path: root/src/kernel/user/vfs.c
blob: 32fcb03e5cb3888929e49724b53d5f1da306900f (plain) (tree)











































                                                                                                    
                             

















































                                                                               
                            

                           










                                  
                                    

                              
                                   





                                                                        

                                            

                                                       


                                                                               

                                             

                                                        






                                   
#include <debug.h>
#include <vfs.h>
#include <string.h>

// ============================= //
// FILESYSTEM DRIVER REGISTERING //
// ============================= //

typedef struct fs_driver {
	const char* name;
	fs_driver_ops_t *ops;
	struct fs_driver *next;
} fs_driver_t;

fs_driver_t *drivers = 0;

void register_fs_driver(const char* name, fs_driver_ops_t *ops) {
	fs_driver_t *d = (fs_driver_t*)malloc(sizeof(fs_driver_t));
	ASSERT(d != 0); // should we fail in a more graceful manner ?

	d->name = name;
	d->ops = ops;
	d->next = drivers;
	drivers = d;
}

// ================================== //
// CREATING AND DELETINF FILE SYSTEMS //
// ================================== //

fs_t *make_fs(const char* drv_name, fs_handle_t *source, char* opts) {
	// Look for driver
	fs_driver_t *d = 0;
	for(fs_driver_t *i = drivers; i != 0; i = i->next) {
		if (drv_name != 0 && strcmp(i->name, drv_name) == 0) d = i;
		if (drv_name == 0 && source != 0 && i->ops->detect && i->ops->detect(source)) d = i;
		if (d != 0) break;
	}

	// Open file system
	fs_t *fs = (fs_t*)malloc(sizeof(fs_t));
	if (fs == 0) return 0;

	if (d->ops->make(source, opts, fs)) {
		fs->refs = 1;
		return fs;
	} else {
		free(fs);
		return 0;
	}
}

bool fs_add_source(fs_t *fs, fs_handle_t *source) {
	return fs->ops->add_source && fs->ops->add_source(fs->data, source);
}

void ref_fs(fs_t *fs) {
	fs->refs++;
}

void unref_fs(fs_t *fs) {
	fs->refs--;
	if (fs->refs == 0) {
		fs->ops->shutdown(fs->data);
		free(fs);
	}
}

// DOING THINGS IN FLESYSTEMS //

bool fs_delete(fs_t *fs, const char* file) {
	return fs->ops->delete && fs->ops->delete(fs->data, file);
}

bool fs_rename(fs_t *fs, const char* from, const char* to) {
	return fs->ops->rename && fs->ops->rename(fs->data, from, to);
}

bool fs_stat(fs_t *fs, const char* name, stat_t *st) {
	return fs->ops->stat && fs->ops->stat(fs->data, name, st);
}

int fs_ioctl(fs_t *fs, const char* file, int command, void* data) {
	return fs->ops->ioctl && fs->ops->ioctl(fs->data, file, command, data);
}

// =================== //
// OPERATIONS ON FILES //
// =================== //

fs_handle_t* fs_open(fs_t *fs, const char* file, int mode) {
	fs_handle_t *h = (fs_handle_t*)malloc(sizeof(fs_handle_t));
	if (h == 0) return 0;

	if (fs->ops->open(fs->data, file, mode, h)) {
		h->refs = 1;
		h->fs = fs;
		ref_fs(fs);
		return h;
	} else {
		free(h);
		return 0;
	}
}

void ref_file(fs_handle_t *file) {
	file->refs++;
}

void unref_file(fs_handle_t *file) {
	file->refs--;
	if (file->refs == 0) {
		unref_fs(file->fs);
		file->ops->close(file->data);
		free(file);
	}
}

size_t file_read(fs_handle_t *f, size_t offset, size_t len, char* buf) {
	if (!(f->mode && FM_READ)) return 0;

	if (f->ops->read == 0) return 0;
	return f->ops->read(f->data, offset, len, buf);
}

size_t file_write(fs_handle_t *f, size_t offset, size_t len, const char* buf) {
	if (!(f->mode && FM_WRITE)) return 0;

	if (f->ops->write == 0) return 0;
	return f->ops->write(f->data, offset, len, buf);
}

int file_get_mode(fs_handle_t *f) {
	return f->mode;
}

/* vim: set ts=4 sw=4 tw=0 noet :*/