From 2dd5cf430edaae01594d566c9f27d780c3ffb4ef Mon Sep 17 00:00:00 2001 From: Matias Linares Date: Sun, 26 Apr 2015 21:43:42 -0300 Subject: Initial commit --- Makefile | 28 ++ README | 0 block_walker.c | 368 +++++++++++++++++++++ block_walker.h | 25 ++ defs.h | 54 ++++ dir.c | 265 ++++++++++++++++ dir.h | 41 +++ disk.mdfs | Bin 0 -> 33554432 bytes file.c | 178 +++++++++++ file.h | 32 ++ fusewrapper.c | 412 ++++++++++++++++++++++++ inode.c | 204 ++++++++++++ inode.h | 76 +++++ log.c | 50 +++ log.h | 16 + medianin.c | 667 +++++++++++++++++++++++++++++++++++++++ medianin.h | 44 +++ mkfs.md/Makefile | 14 + mkfs.md/disk.mdfs | Bin 0 -> 33554432 bytes mkfs.md/mkfs.c | 90 ++++++ mkfs.md/mkfs.md | Bin 0 -> 10016 bytes mkfs.md/out | 2 + run.sh | 21 ++ test.sh | 10 + tests/read_diferentes_offsets.py | 20 ++ 25 files changed, 2617 insertions(+) create mode 100644 Makefile create mode 100644 README create mode 100644 block_walker.c create mode 100644 block_walker.h create mode 100644 defs.h create mode 100644 dir.c create mode 100644 dir.h create mode 100644 disk.mdfs create mode 100644 file.c create mode 100644 file.h create mode 100644 fusewrapper.c create mode 100644 inode.c create mode 100644 inode.h create mode 100644 log.c create mode 100644 log.h create mode 100644 medianin.c create mode 100644 medianin.h create mode 100644 mkfs.md/Makefile create mode 100644 mkfs.md/disk.mdfs create mode 100644 mkfs.md/mkfs.c create mode 100644 mkfs.md/mkfs.md create mode 100644 mkfs.md/out create mode 100644 run.sh create mode 100644 test.sh create mode 100644 tests/read_diferentes_offsets.py diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..ed14cc9 --- /dev/null +++ b/Makefile @@ -0,0 +1,28 @@ +TARGET=fusewrapper +CC=clang + +# Agregado glib para el block walker +CFLAGS+= -O0 -ansi -Werror -Wall -Wdeclaration-after-statement \ + -Wbad-function-cast -Wstrict-prototypes -Wmissing-declarations \ + -Wmissing-prototypes -Wno-unused-parameter \ + -Wunused-variable -g \ + `pkg-config --cflags fuse glib-2.0` +LDFLAGS=`pkg-config --libs fuse glib-2.0` + +SOURCES=$(shell echo *.c) +OBJECTS=$(SOURCES:.c=.o) + +all: $(TARGET) + +$(TARGET): $(OBJECTS) + $(CC) $^ -o $@ $(LDFLAGS) + +clean: + rm -f $(TARGET) $(OBJECTS) .depend *~ + +.depend: *.[ch] + $(CC) -MM `pkg-config --cflags fuse glib-2.0` $(SOURCES) >.depend + +-include .depend + +.PHONY: clean all diff --git a/README b/README new file mode 100644 index 0000000..e69de29 diff --git a/block_walker.c b/block_walker.c new file mode 100644 index 0000000..b4c2682 --- /dev/null +++ b/block_walker.c @@ -0,0 +1,368 @@ +#include +#include +#include +#include +#include +#include + +#include "block_walker.h" +#include "defs.h" + +struct _block_walker { + const char *fib; + const char *fbb; + const char *ipool; + const char *bpool; + + uint16_t *indblock_mem; + + GList *block_list; + GList *indirect_list; +}PACKED; + +uint16_t allocate_block(bwalker *bw); +int free_block(bwalker *bw, uint16_t block); + +/* Auxiliares */ +uint16_t allocate_block(bwalker *bw) +{ + uint16_t result = 0; + uint16_t i = 0; + + assert (bw != NULL); + /* Solo queremos desde el segundo inodo para + * que tengamos como error el 0 */ + for(i = 1; i < BLOCKPOOL_BLOCKS; i++) + if(GET_BIT(bw->fbb, i) == 0) + { + /* cambiamos el bitmap */ + SET_BIT_1((char*)bw->fbb, i); + result = i; + break; + } + /* Tiene que estar seteado a 1 */ + assert(GET_BIT(bw->fbb, i) == 1); + + return (result); +} + +int free_block(bwalker *bw, uint16_t block) +{ + char *block_mem = NULL; + assert (bw != NULL); + + block_mem = (char *) bw->bpool + (block * BLOCK_SIZE); + + /* Chequeamos error */ + if (GET_BIT(bw->fbb, block) == 0) + return -1; + + SET_BIT_0((char *)bw->fbb, block); + + return (0); +} + + +/* Creacion y destruccion */ + +bwalker *bwalker_create(const char *base_mem, size_t size, uint16_t *indirect_mem) +{ + bwalker *bw = NULL; + unsigned int i = 0; + uint16_t *indirect_ptr; + uint16_t indirect_num = 0; + + bw = calloc(1, sizeof(struct _block_walker)); + + assert (bw != NULL); + bw->fbb = (char *)base_mem + FBB_OFFSET; + bw->fib = (char *)base_mem + FIB_OFFSET; + bw->ipool = (char *)base_mem + INODEPOOL_OFFSET; + bw->bpool = (char *)base_mem + BLOCKPOOL_OFFSET; + + bw->indblock_mem = indirect_mem; + bw->block_list = NULL; + bw->indirect_list = NULL; + + if (size == 0) + { + /* No hay bloques, no hay nada, + * retornamos aqui */ + return (bw); + } + /* Deberia tener al menos un bloque indirecto. */ + assert ((*indirect_mem) != 0); + + indirect_num = *indirect_mem; + bw->indirect_list = g_list_append (bw->indirect_list, + GUINT_TO_POINTER(indirect_num)); + assert(indirect_num == GPOINTER_TO_UINT(bw->indirect_list->data)); + + indirect_ptr = (uint16_t *) bw->bpool + (BLOCK_SIZE*indirect_num); + + + while (size > 0) + { + /* Empezamos a meterles bloques */ + for(i = 0; i < 255 && size>0; i++) + { + if (indirect_ptr[i] != 0){ + bw->block_list = g_list_append (bw->block_list, + GUINT_TO_POINTER(indirect_ptr[i])); + } + if(indirect_ptr[i]==0){ + break; + } + + if(size > BLOCK_SIZE){ + size -= BLOCK_SIZE; + }else{ + size = 0; + } + } + + if(size != 0 && size>0) + + if(indirect_ptr[255] != 0) + + { + bw->indirect_list = g_list_append (bw->indirect_list, + GUINT_TO_POINTER(indirect_ptr[255])); + indirect_ptr = (uint16_t *) bw->bpool + (BLOCK_SIZE*indirect_ptr[255]); + } + } + + + /*assert (g_list_length(bw->indirect_list) > 0);*/ + + /*assert (*indirect_mem == GPOINTER_TO_UINT(g_list_first(bw->indirect_list)->data));*/ + /*assert (g_list_length(bw->indirect_list) > 0); + assert (g_list_length(bw->block_list) > 0);*/ + + return (bw); +} + +void bwalker_destroy (bwalker *bw) +{ + assert (bw != NULL); + + if(bw->block_list != NULL) + g_list_free(g_list_first(bw->block_list)); + if(bw->indirect_list != NULL) + g_list_free(g_list_first(bw->indirect_list)); + + free(bw); + bw = NULL; +} + +uint16_t bwalker_direct_length(bwalker *bw) +{ + assert(bw != NULL); + return ((uint16_t) g_list_length(bw->block_list)); +} + +uint16_t bwalker_indirect_length(bwalker *bw) +{ + assert(bw != NULL); + return ((uint16_t) g_list_length(bw->indirect_list)); +} + +uint16_t bwalker_allocate_block(bwalker *bw) +{ + uint16_t block = 0; + uint16_t indirect_block = 0; + uint16_t *buf; + uint16_t i =0 ; + bool no_first_indblock = false; + bool indblk_alloc = false; + assert (bw != NULL); + + no_first_indblock = (g_list_length(bw->indirect_list) == 0); + + if(no_first_indblock) + goto ALLOCATE_INDBLK; + + indirect_block = bwalker_last_indirect(bw); + /* Esto tiene que ser distinto de 0 si o si */ + buf = (uint16_t *) bw->bpool + (indirect_block * BLOCK_SIZE); + for(i = 0; i < 255; i++){ + if(buf[i] == 0) + goto ALLOCATE_BLOCK; + } + /* Si llegamos aca, aloca un indirecto y encima _no_ es el primero :B */ + +ALLOCATE_INDBLK: + indirect_block = allocate_block (bw); + assert(indirect_block != 0); + + if(!indirect_block) + goto ENOBLK; + if(no_first_indblock) + *(bw->indblock_mem) = indirect_block; + else + { + assert(buf != NULL); + assert(&(buf[255]) == &(buf[i])); + assert(i == 255); + buf[i] = indirect_block; + } + bw->indirect_list = g_list_append(bw->indirect_list, GUINT_TO_POINTER(indirect_block)); + i = 0; + indblk_alloc = true; + +ALLOCATE_BLOCK: + buf = (uint16_t *) bw->bpool + (indirect_block * BLOCK_SIZE); + block = allocate_block (bw); + if(!block) + { + if(indblk_alloc) + { + free_block(bw,indirect_block); + bw->indirect_list = g_list_remove(bw->indirect_list, GUINT_TO_POINTER(indirect_block)); + if(no_first_indblock) + *bw->indblock_mem = 0; + } + goto ENOBLK; + } + buf[i] = block; + + bw->block_list = g_list_append(bw->block_list, GUINT_TO_POINTER(block)); + + assert(block != 0); + return block; + +ENOBLK: + return 0; +} + +void bwalker_free_block(bwalker *bw) +{ + uint16_t list_length_b, list_length_i; + uint16_t *buf = NULL; + uint16_t block = 0; + uint16_t i = 0; + GList *auxlist = NULL; + assert(bw != NULL); + + if(g_list_length(bw->block_list) == 0) + return; + + list_length_b=g_list_length(bw->block_list); + list_length_i=g_list_length(bw->indirect_list); + /* Aca tenemos que ver si necesitamos deallocar un + * bloque indirecto. */ + auxlist = g_list_last(bw->indirect_list); + block = (uint16_t) auxlist->data; + buf = (uint16_t *) bw->bpool + (block*BLOCK_SIZE); + if(!buf[1]) + { + /* Dealocamos solamente un bloque. */ + for(i=1; buf[i]; i++) + ; + block = buf[i-1]; + free_block(bw, block); + /*no se actualiza la lista. mirenlo a ver que onda, + * me parecio que era asi, pero no me hace caso*/ + bw->block_list=g_list_remove(bw->block_list, g_list_last(bw->block_list)->data); + + buf[i-1] = 0; + + } + else + { + free_block(bw, buf[0]); + bw->block_list=g_list_remove(bw->block_list, g_list_last(bw->block_list)->data); + + buf[0] = 0; + + + if((auxlist = g_list_previous(auxlist))) + { + block = (uint16_t) auxlist->data; + buf = (uint16_t *) bw->bpool + + (block*BLOCK_SIZE); + free_block(bw, buf[255]); + /*el indirecto == buf[255]???*/ + bw->indirect_list=g_list_remove(bw->indirect_list, g_list_last(bw->indirect_list)->data); + + buf[255] = 0; + } + else + { + free_block(bw, *bw->indblock_mem); + bw->indirect_list=g_list_remove(bw->indirect_list, bw->indblock_mem); + + *bw->indblock_mem = 0; + } + + } + +} + +uint16_t bwalker_next(bwalker *bw) +{ + uint16_t result = 0; + + assert (bw != NULL); + if(g_list_length(bw->block_list) == 0) + return 0; + + + if(g_list_length(bw->block_list) == 1){ + return (uint16_t)GPOINTER_TO_UINT(bw->block_list->data); + } + if(bw->block_list!=g_list_last(bw->block_list)){ + assert(*(bw->indblock_mem)!=GPOINTER_TO_UINT(bw->block_list->data)); + result = (uint16_t)GPOINTER_TO_UINT(bw->block_list->data); + bw->block_list = g_list_next(bw->block_list); + } + return (result); +} + +uint16_t bwalker_prev(bwalker *bw) +{ + uint16_t result = 0; + + assert (bw != NULL); + + if (bw->block_list != g_list_first(bw->block_list)) + { + result = GPOINTER_TO_UINT(bw->block_list->data); + bw->block_list = g_list_previous(bw->block_list); + } + + return (result); +} + +uint16_t bwalker_last_indirect (bwalker *bw) +{ + uint16_t result = 0; + assert(bw != NULL); + assert(g_list_length(bw->indirect_list) > 0); + if(g_list_last(bw->indirect_list)) + { + result = (uint16_t) + GPOINTER_TO_UINT(g_list_last(bw->indirect_list)->data); + } + + return result; +} + +uint16_t bwalker_last_block (bwalker *bw) +{ + uint16_t result = 0; + assert (bw != NULL); + if(g_list_last(bw->block_list)) + result = GPOINTER_TO_UINT(g_list_last(bw->block_list)->data); + return result; +} + +uint16_t bwalker_block_is_last(bwalker *bw) +{ + assert(bw != NULL); + return (bw->block_list == g_list_last(bw->block_list)); +} +void bwalker_set_first(bwalker *bw) +{ + bw->block_list=g_list_first(bw->block_list); +} diff --git a/block_walker.h b/block_walker.h new file mode 100644 index 0000000..00efc09 --- /dev/null +++ b/block_walker.h @@ -0,0 +1,25 @@ +#ifndef _BLOCK_WALKER_H +#define _BLOCK_WALKER_H +#include + +typedef struct _block_walker bwalker; + +/* Creacion y destruccion */ +bwalker *bwalker_create(const char *base_mem,size_t size, uint16_t *indirect_mem); +void bwalker_destroy (bwalker *bw); + +/* Consigue un bloque libre. En caso de fallar, retorna 0 */ +uint16_t bwalker_direct_length(bwalker *bw); +uint16_t bwalker_indirect_length(bwalker *bw); + +uint16_t bwalker_allocate_block(bwalker *bw); +void bwalker_free_block(bwalker *bw); + +uint16_t bwalker_next(bwalker *bw); +uint16_t bwalker_prev(bwalker *bw); +uint16_t bwalker_last_indirect (bwalker *bw); +uint16_t bwalker_last_block (bwalker *bw); +uint16_t bwalker_block_is_last(bwalker *bw); + +void bwalker_set_first(bwalker *bw); +#endif diff --git a/defs.h b/defs.h new file mode 100644 index 0000000..d74abd5 --- /dev/null +++ b/defs.h @@ -0,0 +1,54 @@ +#ifndef _DEFS_H +#define _DEFS_H + +/* Gatos */ +/* Parámetros del disco */ +#define BLOCKS 65536 +#define BLOCK_SIZE 512 +#define MDFS_FILENAME "disk.mdfs" +#define BLOCKPOOL_BLOCKS 64491 +#define INODEPOOL_BLOCKS 1024 +/* Parámetros de la organización lógica del disco */ +/* superblock */ +#define MDFS_SUPER_MAGIC (0x14F5) +#define SUPERBLOCK_SIZE (1*BLOCK_SIZE) +/* inode bitmap */ +#define FIB_BLOCKS 4 +#define FIB_SIZE (FIB_BLOCKS*BLOCK_SIZE) +/* free block bitmap */ +#define FBB_SIZE (16*BLOCK_SIZE) +/* inode info */ +#define INODE_ENTRIES 16384 +#define INODE_SIZE 32 +#define NAME_LENGTH 26 +#define INODEPOOL_SIZE (1024*BLOCK_SIZE) +/* Posiciones absolutas de cada una de las secciones del disco */ +#define SUPERBLOCK_OFFSET 0 +#define FIB_OFFSET (SUPERBLOCK_OFFSET+SUPERBLOCK_SIZE) +#define FBB_OFFSET (FIB_OFFSET+FIB_SIZE) +#define INODEPOOL_OFFSET (FBB_OFFSET+FBB_SIZE) +#define BLOCKPOOL_OFFSET (INODEPOOL_OFFSET+INODEPOOL_SIZE) + +/* Operaciones FBB */ +#define SET_BIT_0(buf, i) ((buf)[(i)/8]&=~(1u<<(i)%8)) +#define SET_BIT_1(buf, i) ((buf)[(i)/8]|=1<<(i)%8) +#define GET_BIT(buf, i) ((buf)[(i)/8]>>(i)%8&1) + +/* Operaciones varias */ +#ifndef MAX +#define MAX(a,b) (((a)>(b))?(a):(b)) +#endif + +#ifndef MIN +#define MIN(a,b) (((a)<(b))?(a):(b)) +#endif + +#define DIV_CEIL(a,b) (((a)+(b)-1)/(b)) + +/* No quiero huecos al medio */ +#define PACKED __attribute__((packed)) + +/* Nos hartamos de poner lo mismo */ +#define NEW_TIME (uint32_t) time(NULL) + +#endif diff --git a/dir.c b/dir.c new file mode 100644 index 0000000..4b692bb --- /dev/null +++ b/dir.c @@ -0,0 +1,265 @@ +#include "dir.h" + +#include +#include +#include +#include +#include +#include + +#include "defs.h" +#include "block_walker.h" + +uint16_t dir_create(const char *disk_mem, mode_t mode) +{ + uint16_t ipos = 0; + dir *d = NULL; + time_t new_time = NEW_TIME; + + assert (disk_mem != NULL); + + ipos = inode_allocate_block(disk_mem); + if(ipos == 0) + return 0; + + d = (dir *) disk_mem + INODEPOOL_OFFSET + (ipos * INODE_SIZE); + d->uid = getuid(); + d->gid = getgid(); + d->mode = mode; + d->size = 0; + d->type = I_DIR; + d->nlinks = 1; + d->ctime = new_time; + d->mtime = new_time; + d->atime = new_time; + + return (ipos); +} + +uint16_t dir_add_direntry(const char *disk_mem, dir *d, const char *name, + uint16_t inumber, uint16_t sym) +{ + bwalker *walker = NULL; + uint16_t block = 0; + direntry *dentry = NULL; + uint16_t i = 0; + int result = 0; + + assert (disk_mem != NULL); + assert (d != NULL); + assert (name != NULL); + assert (strlen(name) < NAME_LENGTH); + + walker = bwalker_create(disk_mem, d->size, &(d->indirect)); + + if(bwalker_direct_length(walker)*BLOCK_SIZEsize+32){ + block = bwalker_allocate_block(walker); + }else{ + block = bwalker_last_block(walker); + + if(!block) + goto CLEAN; + } + + dentry = (direntry *) disk_mem + BLOCKPOOL_OFFSET + (block * BLOCK_SIZE); + + for(i = 0; i < 16; i++){ + if(strcmp(dentry[i].name, "\0") == 0){ + d->size += sizeof(direntry); /* Deberia ser 32*/ + dentry = &(dentry[i]); + strcpy(dentry->name, name); + dentry->inum = inumber; + dentry->symlink = sym; + result = 1; + goto CLEAN; + } + } + +CLEAN: + bwalker_destroy(walker); + + return result; +} + +uint16_t dir_remove_direntry(const char *disk_mem, dir *d, const char *name) +{ + bwalker *walker = NULL; + uint16_t result = 0; + uint16_t block = 0; + direntry *rm_dentry = NULL; + direntry *last_dentry = NULL; + uint16_t i; + + assert(disk_mem != NULL); + assert(d != NULL); + assert(name != NULL); + assert(strlen(name) < NAME_LENGTH); + + walker = bwalker_create(disk_mem, d->size, &(d->indirect)); + + /* Conseguimos el ultimo direntry */ + block = bwalker_last_block(walker); + assert(block != 0); + last_dentry = (direntry *) disk_mem + BLOCKPOOL_OFFSET + + (block * BLOCK_SIZE); + assert(last_dentry[0].inum != 0); + for(i = 0; i < 16; i++){ + if(last_dentry[i].inum == 0) + break; + } + assert(i > 0); + last_dentry = &(last_dentry[i-1]); + + while((block = bwalker_next(walker))) + { + rm_dentry = (direntry *) disk_mem + BLOCKPOOL_OFFSET + + (block * BLOCK_SIZE); + for(i = 0; i < 16; i++) + if(strcmp(name, rm_dentry[i].name) == 0) + { + /* Retornamos esto para eliminarlo fuera. */ + result = rm_dentry[i].inum; + /* Copiamos a la nueva posicion para ahorrarnos la + * fragmentacion externa. */ + strcpy(rm_dentry[i].name, last_dentry->name); + rm_dentry[i].inum = last_dentry->inum; + rm_dentry[i].symlink = last_dentry->symlink; + + /* Borramos los contenidos del ultimo. */ + last_dentry->name[0] = '\0'; + last_dentry->inum = 0; + last_dentry->symlink = 0; + + goto END; + } + + if(bwalker_block_is_last(walker)) + break; + } +END: + bwalker_destroy(walker); + return result; +} + + +dir *dir_get_from_path(const char *disk_mem, const char *path) +{ + uint16_t inum = 0; + char *dir_name = NULL; + + assert (disk_mem != NULL); + assert (path != NULL); + dir_name = calloc(strlen(path) + 1, sizeof(char)); + strcpy(dir_name, path); + inum = get_inode_from_path(disk_mem, dirname(dir_name), 1); + free(dir_name); + if(inum==0){ + return NULL; + } + return ((dir *)disk_mem+INODEPOOL_OFFSET+INODE_SIZE*inum); + +} + +uint16_t dir_search(const char *disk_mem, dir *idir,const char *name) +{ + bwalker *bw = NULL; + direntry *dentry; + uint16_t bnum, i; + + + assert(disk_mem != NULL); + assert(idir != NULL); + assert(name != NULL); + assert(strcmp(name, "")); + + + /* Salimos si esto esta vacio obviamente. */ + if(idir->size == 0){ + return 0; + } + + bw = bwalker_create(disk_mem, idir->size, &(idir->indirect)); + while ((bnum = bwalker_next(bw))) + { + dentry=(direntry *) disk_mem + BLOCKPOOL_OFFSET + (bnum*BLOCK_SIZE); + for(i=0; i<16; i++){ + if(strcmp(name, dentry[i].name) == 0){ + bwalker_destroy(bw); + return dentry[i].inum; + } + } + + if(bwalker_block_is_last(bw)) + break; + } + bwalker_destroy(bw); + return 0; +} + +int dir_rename_inode(const char *disk_mem, dir *d, + const char *old_name, const char *new_name) +{ + bwalker *bw = NULL; + direntry *dentry; + uint16_t i; + uint16_t bnum; + + assert(disk_mem != NULL); + assert(d != NULL); + assert(strcmp(old_name, "")); + assert(new_name != NULL); + assert(old_name != NULL); + assert(strlen(new_name) < NAME_LENGTH); + + /* Salimos si esto esta vacio obviamente. */ + if(d->size == 0){ + return 0; + } + + bw = bwalker_create(disk_mem, d->size, &(d->indirect)); + while ((bnum = bwalker_next(bw))) + { + dentry=(direntry *) disk_mem + BLOCKPOOL_OFFSET + (bnum*BLOCK_SIZE); + for(i=0; i<16; i++){ + if(strcmp(old_name, dentry[i].name) == 0){ + bwalker_destroy(bw); + strcpy(dentry[i].name,new_name); + return 1; + } + } + + if(bwalker_block_is_last(bw)) + break; + } + bwalker_destroy(bw); + return 0; +} + +uint16_t dir_readdir(const char *disk_mem, dir *d, void *buf, fuse_fill_dir_t filler) +{ + + bwalker *bw = NULL; + direntry *dentry; + uint16_t bnum, i; + + + assert(disk_mem != NULL); + assert(d != NULL); + + /* Salimos si esto esta vacio obviamente. */ + if(d->size == 0) + return 0; + + bw = bwalker_create(disk_mem, d->size, &(d->indirect)); + while ((bnum = bwalker_next(bw))){ + dentry=(direntry *) disk_mem + BLOCKPOOL_OFFSET + (bnum*BLOCK_SIZE); + for(i=0; i<16 && dentry[i].name[0] != '\0' ; i++){ + filler(buf, (const char *)&(dentry[i].name), NULL, 0); + } + + if(bwalker_block_is_last(bw)) + break; + } + bwalker_destroy(bw); + return 0; +} diff --git a/dir.h b/dir.h new file mode 100644 index 0000000..8c04b05 --- /dev/null +++ b/dir.h @@ -0,0 +1,41 @@ +#ifndef _DIR_H +#define _DIR_H + +#define _GNU_SOURCE +#include "inode.h" +#include +#include +#include + + +typedef inode dir; + +/* Crea un directorio con el modo pasado por parametro. + * Retorna el numero de inodo alocado. 0 en caso de error. */ +uint16_t dir_create(const char *disk_mem, mode_t mode); + +/* Agrega un direntry al directorio @d@ pasado por parametro. + * En caso de error retorna 0. */ +uint16_t dir_add_direntry(const char *disk_mem, dir *d, const char *name, + uint16_t inumber, uint16_t sym); +/* Quita un direntry del directorio y devuelve el numero de inodo a liberar + * a posteriori */ +uint16_t dir_remove_direntry(const char *disk_mem, dir *d, const char *name); + +/* Busca un nombre por las direntry del dir. Retorna el inodo del nombre + * buscado o 0 si no lo encuentra. */ +uint16_t dir_search(const char *disk_mem, dir *d,const char *name); + +/* Renombra un inodo pisando el nombre antiguo*/ +int dir_rename_inode(const char *disk_mem, dir *d, + const char *old_name, const char *new_name); + +/* Abstraccion del readdir */ +uint16_t dir_readdir(const char *disk_mem, dir *d, + void *buf, fuse_fill_dir_t filler); + +/* Retorna el ultimo directorio del path dado. + * Ex: path=/usr/share/icons/archlinux.png, retorna el directorio de incons*/ +dir *dir_get_from_path(const char *disk_mem, const char *path); + +#endif diff --git a/disk.mdfs b/disk.mdfs new file mode 100644 index 0000000..3318d0b Binary files /dev/null and b/disk.mdfs differ diff --git a/file.c b/file.c new file mode 100644 index 0000000..71f84ac --- /dev/null +++ b/file.c @@ -0,0 +1,178 @@ +#include "file.h" +#include "block_walker.h" + +#include +#include +#include +#include + +#include "defs.h" + +uint16_t file_create(const char *disk_mem, mode_t mode) +{ + uint16_t ipos = 0; + file *f = NULL; + bwalker *bw = NULL; + + assert (disk_mem != NULL); + + bw = bwalker_create (disk_mem, 0, 0); + ipos = inode_allocate_block(disk_mem); + + f = (file *) disk_mem + INODEPOOL_OFFSET + (ipos * INODE_SIZE); + f->uid = getuid(); + f->gid = getgid(); + f->mode = mode; + f->size = 0; + f->type = I_FILE; + f->nlinks = 1; + f->ctime = NEW_TIME; + f->mtime = NEW_TIME; + f->atime = NEW_TIME; + + bwalker_destroy (bw); + + return (ipos); +} + +size_t file_read (const char *disk_mem, file *f, char *buf, + size_t size, off_t offset) +{ + size_t result = 0; + size_t len = 0; + bwalker *bw = NULL; + uint16_t *block; + uint16_t bnum; + + assert (f != NULL); + assert (buf != NULL); + + bw = bwalker_create (disk_mem, f->size, &(f->indirect)); + + while (size > 0 && (bnum = bwalker_next(bw))) + { + block = (uint16_t *) disk_mem + BLOCKPOOL_OFFSET + (bnum*BLOCK_SIZE); + if (offset >= BLOCK_SIZE){ + /* Nos movemos (no escribimos) */ + offset -= BLOCK_SIZE; + continue; + } + assert(offset < BLOCK_SIZE); + + block += offset; + + len = MIN(size,(BLOCK_SIZE - offset)); + + memcpy(buf, block, len); + result += len; + buf += len; + size -= len; + offset = 0; + if(bwalker_block_is_last(bw)){ + break; + } + + } + + bwalker_destroy (bw); + return (result); +} + +int file_truncate (const char *disk_mem, file *f, off_t size) +{ + bwalker *walker; + uint16_t offset, i, fb_size, block=0; + assert(disk_mem != NULL); + assert(f != NULL); + + + walker=bwalker_create(disk_mem, f->size, &(f->indirect)); + /*el tamaño en bytes de la cantidad de bloques que ocupa el file + * siempre es >= file_size*/ + fb_size=(bwalker_direct_length(walker)*BLOCK_SIZE); + + if(f->size < size){ + /*si el pedacito que jode...*/ + offset=size-f->size; + /*es menor que 512, y ademas el nuevo tamaño no pasa al fb_size + * no es neceasrio alocar bloques, solo se cambia el tamaño*/ + if(offsetsize=size; + bwalker_destroy(walker); + return 0; + } + for(i=0; i<(DIV_CEIL(offset, BLOCK_SIZE)); i++){ + /*aloca lo que necesita*/ + block=bwalker_allocate_block(walker); + } + /*change size*/ + f->size=size; + }else{ + /*idem, pero al verez*/ + offset=f->size-size; + f->size=size; + if(offset=fb_size){ + f->size=size; + bwalker_destroy(walker); + return 0; + } + for(i=0; i<(DIV_CEIL(offset, BLOCK_SIZE)); i++){ + bwalker_free_block(walker); + } + f->size=size; + } + bwalker_destroy(walker); + return 0; +} + +size_t file_write (const char *disk_mem, file *f, char *buf, + size_t size, off_t offset) +{ + size_t result = 0; + size_t len = BLOCK_SIZE; + bwalker *bw = NULL; + uint16_t *block = NULL; + uint16_t bnum = 0; + time_t new_time = NEW_TIME; + + assert (disk_mem != NULL); + assert (f != NULL); + + + bw = bwalker_create (disk_mem, f->size, &(f->indirect)); + + while (size > 0 && (bnum = bwalker_next(bw))) + { + assert(bnum != f->indirect); + if (offset >= BLOCK_SIZE){ + /* Nos movemos (no escribimos) */ + offset -= BLOCK_SIZE; + continue; + } + block = (uint16_t *) disk_mem + BLOCKPOOL_OFFSET + (bnum*BLOCK_SIZE); + + assert(offset < BLOCK_SIZE); + block += offset; + + len = MIN(size,(BLOCK_SIZE - offset)); + + memcpy(block, buf, len); + + result += len; + buf += len; + size -= len; + offset = 0; + + if(bwalker_direct_length(bw)<=1){ + break; + } + + } + + f->atime = new_time; + f->mtime = new_time; + + bwalker_destroy (bw); + + return (result); +} diff --git a/file.h b/file.h new file mode 100644 index 0000000..0c0ac5e --- /dev/null +++ b/file.h @@ -0,0 +1,32 @@ +#ifndef _FILE_H +#define _FILE_H + +#define _GNU_SOURCE + +#include "inode.h" +#include "block_walker.h" + +#include +#include +#include +#include +#include + +typedef inode file; + +/* Crea un archivo vacio con el nombre y modo pasados por parametro. + * Devuelve el numero de inodo asociado o 0 en caso de error. */ +uint16_t file_create(const char *disk_mem, mode_t mode); + +/* Abstraccion de lectura de un archivo */ +size_t file_read (const char *disk_mem, file *f, char *buf, + size_t size, off_t offset); + +/* Abstraccion de truncar un archivo */ +int file_truncate (const char *disk_mem, file *f, off_t offset); + +/* Abstraccion de escribir un archivo */ +size_t file_write (const char *disk_mem, file *f, char *buf, + size_t size, off_t offset); + +#endif diff --git a/fusewrapper.c b/fusewrapper.c new file mode 100644 index 0000000..604f4a2 --- /dev/null +++ b/fusewrapper.c @@ -0,0 +1,412 @@ +/* $Date: 2010-09-30 15:40:39 -0300 (Thu, 30 Sep 2010) $ */ +/* $Revision: 1364 $ */ + +#define _GNU_SOURCE +#define FUSE_USE_VERSION 26 + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include "medianin.h" +#include "log.h" + +/* Variable global que contiene el SimpleFS */ +medianin *fs = NULL; + +/* + * Operaciones Básicas + */ + +static int fs_getattr(const char *path, struct stat *stbuf) +{ + int rta = 0; + debug3("[%li] ", time(NULL)); + debug1("getattr:%s", path); + rta = medianin_getattr(fs, path, stbuf); + debug2(" -> mode:%o size:%li", stbuf->st_mode, (long)stbuf->st_size); + debug3(" returns:%i", rta); + debug1("\n"); + return rta; +} + +static int fs_readlink(const char *path, char *buf, size_t size) +{ + int rta = 0; + debug3("[%li] ", time(NULL)); + debug1("readlink:%s size:%li", path, (long)size); + rta = medianin_readlink(fs, path, buf, size); + debug2(" -> returns:%i", rta); + debug1("\n"); + return rta; +} + +static int fs_mknod(const char *path, mode_t mode, dev_t rdev) +{ + int rta = 0; + debug3("[%li] ", time(NULL)); + debug1("mknod:%s mode:%o", path, mode); + rta = medianin_mknod(fs, path, mode); + debug3(" -> returns:%i", rta); + debug1("\n"); + return rta; +} + +static int fs_unlink(const char *path) +{ + int rta = 0; + debug3("[%li] ", time(NULL)); + debug1("unlink_file:%s", path); + rta = medianin_unlink(fs, path); + debug3(" -> returns:%i", rta); + debug1("\n"); + return rta; +} + +static int fs_symlink(const char *from, const char *to) +{ + int rta = 0; + debug3("[%li] ", time(NULL)); + debug1("symlink from:%s to:%s", from, to); + rta = medianin_symlink(fs, from, to); + debug3(" -> returns:%i", rta); + debug1("\n"); + return rta; +} + +static int fs_rename(const char *from, const char *to) +{ + int rta = 0; + debug3("[%li] ", time(NULL)); + debug1("rename from:%s to:%s", from, to); + rta = medianin_rename(fs, from, to); + debug3(" -> returns:%i", rta); + debug1("\n"); + return rta; +} + +static int fs_link(const char *from, const char *to) +{ + int rta = 0; + debug3("[%li] ", time(NULL)); + debug1("link from:%s to:%s", from, to); + rta = medianin_link(fs, from, to); + debug3(" -> returns:%i", rta); + debug1("\n"); + return rta; +} + +static int fs_chmod(const char *path, mode_t mode) +{ + int rta = 0; + debug3("[%li] ", time(NULL)); + debug1("chmod:%s modo:%o", path, mode); + rta = medianin_chmod(fs, path, mode); + debug3(" -> returns:%i", rta); + debug1("\n"); + return rta; +} + +static int fs_chown(const char *path, uid_t uid, gid_t gid) +{ + int rta = 0; + debug3("[%li] ", time(NULL)); + debug1("chown:%s uid:%i gid:%i", path, uid, gid); + rta = medianin_chown(fs, path, uid, gid); + debug3(" -> returns:%i", rta); + debug1("\n"); + return rta; +} + +static int fs_truncate(const char *path, off_t size) +{ + int rta = 0; + debug3("[%li] ", time(NULL)); + debug1("truncate:%s size:%li", path, (long)size); + rta = medianin_truncate(fs, path, size); + debug1("\n"); + return rta; +} + +static int fs_utime(const char *path, struct utimbuf *utb) +{ + int rta = 0; + struct timespec tv[2]; + tv[0].tv_sec = utb->actime; + tv[0].tv_nsec = 0; + tv[1].tv_sec = utb->modtime; + tv[1].tv_nsec = 0; + debug3("[%li] ", time(NULL)); + debug1("utime:%s atime:%li mtime:%li", + path, (long)utb->actime, (long)utb->modtime); + rta = medianin_utimens(fs, path, tv); + debug3(" -> returns:%i", rta); + debug1("\n"); + return rta; +} + +static int fs_open(const char *path, struct fuse_file_info *fi) +{ + int rta = 0; + debug3("[%li] ", time(NULL)); + debug1("*open:%s flags:%i", path, fi->flags); + debug1("\n"); + return rta; +} + +static int fs_read(const char *path, char *buf, size_t size, off_t offset, + struct fuse_file_info *fi) +{ + int rta = 0; + (void) fi; + debug3("[%li] ", time(NULL)); + debug1("read:%s size:%li offset:%li", path, (long)size, (long)offset); + rta = medianin_read(fs, path, buf, size, offset); + debug2(" -> returns:%i", rta); + debug1("\n"); + return rta; +} + +static int fs_write(const char *path, const char *buf, size_t size,off_t offset, + struct fuse_file_info *fi) +{ + int rta = 0; + (void) fi; + debug3("[%li] ", time(NULL)); + debug1("write:%s size:%li offset:%li", path, (long)size, (long)offset); + rta = medianin_write(fs, path, buf, size, offset); + debug2(" -> returns:%i", rta); + debug1("\n"); + return rta; +} + +static int fs_statfs(const char *path, struct statvfs *stbuf) +{ + int rta = 0; + debug3("[%li] ", time(NULL)); + debug1("statfs:%s", path); + rta = medianin_statfs(fs, path, stbuf); + debug2(" -> returns:%i", rta); + debug1("\n"); + return rta; +} + + +static int fs_release(const char *path, struct fuse_file_info *fi) +{ + int rta = 0; + debug3("[%li] ", time(NULL)); + debug1("*release:%s flags:%i", path, fi->flags); + debug1("\n"); + return rta; +} + +static int fs_utimens(const char *path, const struct timespec tv[2]) +{ + int rta = 0; + debug3("[%li] ", time(NULL)); + debug1("utimens:%s atime:%li mtime:%li", + path, (long)tv[0].tv_sec, (long)tv[1].tv_sec); + rta = medianin_utimens(fs, path, tv); + debug3(" -> returns:%i", rta); + debug1("\n"); + return rta; +} + +/* + * Operaciones sobre Directorios + */ + +static int fs_mkdir(const char *path, mode_t mode) +{ + int rta = 0; + debug3("[%li] ", time(NULL)); + debug1("mkdir:%s mode:%o", path, mode); + rta = medianin_mkdir(fs, path, mode); + debug3(" -> returns:%i", rta); + debug1("\n"); + return rta; +} + +static int fs_rmdir(const char *path) +{ + int rta = 0; + debug3("[%li] ", time(NULL)); + debug1("rmdir:%s", path); + rta = medianin_rmdir(fs, path); + debug3(" -> returns:%i", rta); + debug1("\n"); + return rta; +} + +static int fs_readdir(const char *path, void *buf, + fuse_fill_dir_t filler, off_t offset, + struct fuse_file_info *fi) +{ + int rta = 0; + (void) fi; /* Para que no diga que la variable está sin usar */ + debug3("[%li] ", time(NULL)); + debug1("readdir:%s", path); + rta = medianin_readdir(fs, path, buf, filler); + debug3(" -> returns:%i", rta); + debug1("\n"); + return rta; +} + + +static struct fuse_operations fs_oper = +{ + /* Operaciones sobre archivos, NI = no implementada */ + .getattr = fs_getattr, /* Done */ + .readlink = fs_readlink, + .mknod = fs_mknod, /* Done */ + .unlink = fs_unlink, + .symlink = fs_symlink, + .rename = fs_rename, + .link = fs_link, + .chmod = fs_chmod, /* Almost done */ + .chown = fs_chown, /* Almost done */ + .truncate = fs_truncate, + .utime = fs_utime, /* Almost done */ + .open = fs_open, /* NI */ + .read = fs_read, + .write = fs_write, + .statfs = fs_statfs, /* Done */ + .release = fs_release, /* NI */ + .utimens = fs_utimens, /* Almost done */ + /* Operaciones sobre directorios */ + .mkdir = fs_mkdir, + .rmdir = fs_rmdir, + .readdir = fs_readdir, +}; + +/* !! end Rafa !! */ + +int main(int argc, char *argv[]) +{ + /* Cheat es una variable al estilo de argv pero solo con argumentos + * parseados como validos. La uso para trabajar menos + */ + char *cheat[10]; /* 10 es un indice que nunca se alcanza */ + int i = 1; + int argi = 1; + char *logfilename = NULL; + char *mountpoint = NULL; + char *tailptr = NULL; /* Variable temporal usada pora strtol */ + int loglevel = 3; /* default loglevel */ + fs_oper.utimens = 0; + cheat[0] = argv[0]; + + /* i==1 && argi == 1 i se usa con cheat y argi con argv */ + /* cuando consumo un argumento aumento argi */ + /* cuando agrego uno para fusemain aumento i */ + while (argi < argc) + { + if (strcmp(argv[argi], "-h") == 0) + { + printf("uso: %s [opciones] mountpoint\n" + "opciones:\n" + "\t-h\t\tImprime esta ayuda.\n\n" + "\t-logfile file\n" + "\t-l file\t\tGuarda los logs en el archivo" + " especificado.\n\n" + "\t-loglevel num\n" + "\t-n num\t\tEspecifica el nivel de log. " + "Por defecto es 3.\n\n" + , argv[0]); + return 1; + } + else if (strcmp(argv[argi], "-logfile") == 0 + || strcmp(argv[argi], "-l") == 0) + { + argi++; + if(argi < argc) logfilename = argv[argi]; + else + { + fprintf(stderr, "Se debe especificar un nombre" + " de archivo\n"); + return 1; + } + loglevel=1; /* Para evitar malos usos */ + } + else if (strcmp(argv[argi], "-loglevel") == 0 + || strcmp(argv[argi], "-n") == 0) + { + argi++; + if (argi < argc) + { + loglevel = (int)strtol(argv[argi], &tailptr, 10); + if (tailptr == argv[argi]) + { + fprintf(stderr, + "El nivel de log debe" + "ser ún numero\n"); + return 1; + } + if (loglevel < 0) + { + fprintf(stderr, + "El nivel de log debe" + "ser un número natural\n"); + return 1; + } + } + else + { + fprintf(stderr, "Se debe especificar un nivel" + " de log\n"); + return 1; + } + } + else if (argv[argi][0] == '-') + { + fprintf(stderr, "Opción no reconocida:" + "%s\n",argv[argi]); + return 1; + } + else if (mountpoint == NULL) + { + mountpoint = argv[argi]; + } + argi++; + } + if(mountpoint == NULL) + { + fprintf(stderr, "Argumentos insuficientes: " + "hace falta un mountpoint\n"); + return 1; + } + cheat[i++] = mountpoint; + if (loglevel != 0) + { + cheat[i++] = "-f"; + } + cheat[i] = NULL; + + if (log_open(logfilename, loglevel)!=0) + { + fprintf(stderr, "Advertencia! no se pudo inicializar el log\n"); + } + + debug3("Los numeros a la izquierda indican el momento en que la " + "llamada a la\nfunción se efectuó según time(NULL).\n"); + + fs = medianin_create(); + if (fs == NULL) + { + return ENOMEM; + } + + fuse_main(i, cheat, &fs_oper, NULL); /* El corazón del programa */ + + medianin_destroy(fs); + log_close(); + + return 0; +} diff --git a/inode.c b/inode.c new file mode 100644 index 0000000..556aad3 --- /dev/null +++ b/inode.c @@ -0,0 +1,204 @@ +#include "inode.h" + +#include +#include +#include +#include +#include +#include + +#include "defs.h" +#include "block_walker.h" + + +/* Auxiliares */ +uint16_t get_path_length(const char *path); +char *get_next_dir(const char *path, uint16_t position); +int16_t name_check(char *path, direntry *entry_block); +int16_t inode_search(const char *disk_mem, inode *current, char *path); + +/*Parser*/ + +int16_t name_check(char *path, direntry *entry_block) +{ + int16_t result=-1; + int i = 0; + + assert(path != NULL); + assert(entry_block != NULL); + + for(i=0; i<16 && entry_block[i].inum != 0; i++){ + if(strcmp(entry_block[i].name, path)){ + result=entry_block[i].inum; + break; + } + } + return result; +} + +int16_t inode_search(const char *disk_mem, inode *current, char *path) +{ + + bwalker *bw = NULL; + direntry *dentry = NULL; + int16_t result = -1; + uint16_t block; + + assert (disk_mem != NULL); + assert (current != NULL); + assert (path != NULL); + + bw=bwalker_create(disk_mem, current->size, &(current->indirect)); + + while(result==-1 && (block=bwalker_next(bw))!=0){ + dentry=(direntry *)disk_mem+BLOCKPOOL_OFFSET+(block*BLOCK_SIZE); + result=name_check(path, dentry); + } + bwalker_destroy (bw); + + return result; +} + +/* Publico. */ + +/*Parse*/ +int16_t get_inode_from_path(const char *disk_mem, char *path, int16_t current_inum) +{ + int16_t i=1, path_len=strlen(path), result=0; + char *path_mod = NULL; + inode *current=(inode *)disk_mem+INODEPOOL_OFFSET+current_inum*INODE_SIZE; + + assert (disk_mem != NULL); + assert (path != NULL); + + /* Chequeamos si es root al principio :) */ + if (strcmp(path, "/") == 0) + return 1; + + /* Vamos a ponerle 2 mas por las moscas :) */ + path_mod = calloc(path_len + 2, sizeof(char)); + strcpy(path_mod, path); + + while(ist_ino = inum; + stbuf->st_mode = f->mode; + stbuf->st_nlink = f->nlinks; + stbuf->st_uid = f->uid; + stbuf->st_gid = f->gid; + stbuf->st_size = f->size; + stbuf->st_blksize = BLOCK_SIZE; + stbuf->st_blocks = (f->size / BLOCK_SIZE); + stbuf->st_atime = f->atime; + stbuf->st_ctime = f->ctime; + stbuf->st_mtime = f->mtime; + + return (0); +} +uint16_t inode_allocate_block(const char *disk_mem) +{ + uint16_t result = 0; + uint16_t i = 0; + + assert (disk_mem != NULL); + /* Solo queremos desde el segundo inodo para + * que tengamos como error el 0 */ + for(i = 1; i < FIB_SIZE; i++) + if(GET_BIT(disk_mem + FIB_OFFSET, i) == 0) + { + /* cambiamos el bitmap */ + SET_BIT_1((char*)disk_mem + FIB_OFFSET, i); + result = i; + break; + } + assert(GET_BIT(disk_mem + FIB_OFFSET, i) == 1); + + return (result); +} + +void inode_free_block(const char *disk_mem, uint16_t pos) +{ + assert (disk_mem != NULL); + assert (pos <= FIB_SIZE); + SET_BIT_0((char *)disk_mem + FIB_OFFSET, pos); +} + +int inode_chmod (inode *f, mode_t mode) +{ + assert (f != NULL); + + f->mode = mode; + f->ctime = NEW_TIME; + return (0); +} + +int inode_chown(inode *f, uid_t uid, gid_t gid) +{ + assert (f != NULL); + if (gid != -1) + f->gid = gid; + if (uid != -1) + f->uid = uid; + + f->ctime = NEW_TIME; + + return 0; +} + +int inode_utime(inode *f, const struct timespec tv[2]) +{ + assert (f != NULL); + + f->atime = (uint32_t) tv[1].tv_nsec; + f->ctime = (uint32_t) tv[1].tv_nsec; + f->mtime = (uint32_t) tv[1].tv_nsec; + + return (0); +} + +mode_t inode_get_mode(inode *i) +{ + assert (i != NULL); + return i->mode; +} + + +/* Direntry */ + +void direntry_clean(direntry *dentry) +{ + assert (dentry != NULL); + dentry->inum = 0; + dentry->name[0] = '\0'; + dentry->symlink = 0; +} diff --git a/inode.h b/inode.h new file mode 100644 index 0000000..7eee890 --- /dev/null +++ b/inode.h @@ -0,0 +1,76 @@ +#ifndef _INODE_H +#define _INODE_H + +#define _GNU_SOURCE +#include +#include +#include +#include + +#include + +/* Define los tipos que pueden ser los inodos. */ +enum { + I_FILE = 0, + I_DIR = 1, +}; + +/* + * {4} size + * {4} tipo (necesario para llegar a 32) + * {2} mode + * {2} uid + * {2} gid + * {12} atime,ctime, mtime + * {2} indirect + * {4} nlinks + * + * total 32 bytes + */ +struct _inode_t { + uint32_t size; /* Tamaño del inodo */ + uint32_t type; /* tipo */ + + uint16_t mode; /* acceso */ + uint16_t uid; + uint16_t gid; + + uint32_t atime; + uint32_t ctime; + uint32_t mtime; + + uint16_t indirect; + + uint32_t nlinks; +} __attribute__((packed)); + +/* Sinonimo ? */ +typedef struct _inode_t inode; + +/* Asociacion de nombre y numero de inodo + * 32 bytes tambien */ +struct _direntry_t { + uint32_t inum; + char name[26]; + uint16_t symlink; +} __attribute__((packed)); + +typedef struct _direntry_t direntry; + +/* Consigue un numero de inodo a partir de un path */ +int16_t get_inode_from_path(const char *disk_mem, char *path, int16_t current); + +/* Funciones del filesystem */ +int inode_getattr(inode *i, ino_t inum, struct stat *stbuf); +int inode_chown(inode *i, uid_t uid, gid_t gid); +int inode_chmod (inode *i, mode_t mode); +int inode_utime(inode *i, const struct timespec tv[2]); +mode_t inode_get_mode (inode *i); + +/* Consigue un nuevo inodo, devolviendo su numero y alocandolo */ +uint16_t inode_allocate_block(const char *disk_mem); +/* Libera un bloque pasado por parametro */ +void inode_free_block(const char *disk_mem, uint16_t pos); + +void direntry_clean(direntry *dentry); +#endif diff --git a/log.c b/log.c new file mode 100644 index 0000000..cfa1cf6 --- /dev/null +++ b/log.c @@ -0,0 +1,50 @@ +/* $Date: 2010-09-30 15:40:39 -0300 (Thu, 30 Sep 2010) $ */ +/* $Revision: 1364 $ */ + +#include "log.h" +#include + +static int loglevel=0; +static FILE *logfile=NULL; + +int log_open(const char *filename, const int ll) +{ + loglevel = 0; + if (filename == NULL) logfile = stdout; + else logfile = fopen(filename, "w"); + if (logfile == NULL) return 1; + loglevel = ll; + return 0; +} + +void log_close(void) +{ + fclose(logfile); +} + +void debug1(const char * format, ...) +{ + va_list args; + if (loglevel < 1 || logfile == NULL) return; + va_start(args, format); + vfprintf(logfile,format,args); + va_end(args); +} + +void debug2(const char *format, ...) +{ + va_list args; + if (loglevel < 2 || logfile == NULL) return; + va_start(args, format); + vfprintf(logfile,format,args); + va_end(args); +} + +void debug3(const char *format, ...) +{ + va_list args; + if (loglevel < 3 || logfile == NULL) return; + va_start(args, format); + vfprintf(logfile,format,args); + va_end(args); +} diff --git a/log.h b/log.h new file mode 100644 index 0000000..384f0e6 --- /dev/null +++ b/log.h @@ -0,0 +1,16 @@ +/* $Date: 2010-09-30 15:40:39 -0300 (Thu, 30 Sep 2010) $ */ +/* $Revision: 1364 $ */ + +#ifndef __LOG_H +#define __LOG_H + +#include + +int log_open(const char *filename, const int level); +void log_close(void); + +void debug1(const char *format, ...) __attribute__((format(printf, 1, 2))); +void debug2(const char *format, ...) __attribute__((format(printf, 1, 2))); +void debug3(const char *format, ...) __attribute__((format(printf, 1, 2))); + +#endif /* __LOG_H */ diff --git a/medianin.c b/medianin.c new file mode 100644 index 0000000..36781a6 --- /dev/null +++ b/medianin.c @@ -0,0 +1,667 @@ +#include "medianin.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#include "defs.h" +#include "dir.h" +#include "file.h" +#include "inode.h" +#include "block_walker.h" + +/* Invariante de representación */ +#define INVREP(self) ((self)!=NULL && (self)->disk_mem!=NULL && 0<(self)->disk_fd) + +/* El FS medianin es el archivo con el disco mapeado en memoria y su fd */ +struct PACKED medianin_s +{ + char *disk_mem; /* puntero al inicio del disco mapeado en memoria */ + int disk_fd; /* fd del openfile con el disco */ + time_t mount_time; /* tiempo de montaje: a,m,ctime del rootdir */ +}; + +char *media_block=NULL; +/* Auxiliares */ + +uint16_t free_blocks_count(const char *disk_mem); +uint16_t free_inodes_count(const char *disk_mem); + +uint16_t free_blocks_count(const char *disk_mem) +{ + uint16_t i, s=0; + char *buf=(char *)disk_mem+FBB_OFFSET; + /*Conseguir los bloques vacios*/ + for(i=0; idisk_mem = NULL; + result->disk_fd = open(MDFS_FILENAME, O_RDWR); + map=mmap(NULL, BLOCKS*BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, result->disk_fd, 0); + /*Nos aseguramos que el mapeo se realize correctamente*/ + if(map==MAP_FAILED) + perror("mmap"); + + result->disk_mem = map; + + result->mount_time = time(NULL); + + assert(result != NULL); + assert(INVREP(result)); + + return result; +} + +void medianin_destroy(medianin *self) +{ + assert(INVREP(self)); + + close (self->disk_fd); + /*Cerramos el fd, y guardamos los cambios*/ + if(msync(self->disk_mem, BLOCKS*BLOCK_SIZE, MS_SYNC) == -1) + perror("msync"); + if(munmap(self->disk_mem, BLOCKS*BLOCK_SIZE) == -1) + perror("munmap"); + + free(self); self = NULL; +} + +/* + * Operaciones Básicas + */ + +int medianin_getattr(medianin *self, const char *path, struct stat *stbuf) +{ + dir *pdir = NULL; + char *name, *path_c; + uint16_t block = 0; + inode *ind = NULL; + + assert(INVREP(self)); + assert(path != NULL); + assert(stbuf != NULL); + + if(strcmp(path,"/") == 0) + { + ind = (inode *) self->disk_mem + INODEPOOL_OFFSET + (1 * INODE_SIZE); + return inode_getattr(ind, 1, stbuf); + } + + pdir = dir_get_from_path(self->disk_mem, path); + + if (!pdir) + return -ENOENT; + + path_c=calloc(NAME_LENGTH, sizeof(char)); + strcpy(path_c, path); + + + name=calloc(NAME_LENGTH, sizeof(char)); + strcpy (name, basename(path_c)); + + block = dir_search(self->disk_mem, pdir, name); + free(path_c); + free(name); + + if (!block){ + return -ENOENT; + } + + ind = (inode *) self->disk_mem + INODEPOOL_OFFSET + (block * INODE_SIZE); + + return inode_getattr(ind, block, stbuf); +} + +int medianin_readlink(medianin *self, const char *path, char *buf, size_t size) +{ + uint16_t inode_block = 0; + dir *parent_dir = NULL; + file *f = NULL; + char name[26]; + + assert(INVREP(self)); + assert(path!=NULL); + assert(buf!=NULL); + + parent_dir = dir_get_from_path(self->disk_mem, path); + + if(!parent_dir) + return -ENOENT; + + strncpy(&(name[0]), basename((char *)path), 26); + + inode_block = dir_search(self->disk_mem, parent_dir, name); + + if(!inode_block) + return -ENOENT; + f = (file *) self->disk_mem + INODEPOOL_OFFSET + (inode_block*INODE_SIZE); + + if(S_ISDIR(inode_get_mode((inode *) f))) + return -EISDIR; + + return file_read(self->disk_mem, f, buf, size, 0); +} + +int medianin_mknod(medianin *self, const char *path, mode_t mode) +{ + dir *idir = NULL; + uint16_t ifile = 0; + char bname[26]; + + assert(INVREP(self)); + assert(path!=NULL); + + strncpy(&(bname[0]),basename((char *) path), 26); + + if(strlen(bname)>25){ + return -ENAMETOOLONG; + } + + idir=dir_get_from_path(self->disk_mem, path); + + if(dir_search(self->disk_mem ,idir, bname)){ + return -EEXIST; + } + + if((ifile=file_create(self->disk_mem, mode))==0){ + return -ENOSPC; + } + + if((dir_add_direntry(self->disk_mem, idir, bname, ifile, 0))==0){ + inode_free_block(self->disk_mem, ifile); + return -ENOSPC; + } + + return 0; +} + +int medianin_unlink(medianin *self, const char *path) +{ + int result = 0; + assert(INVREP(self)); + assert(path!=NULL); + + result = 0; + return result; +} + +int medianin_symlink(medianin *self, const char *from, const char *to) +{ + int result = 0; + assert(INVREP(self)); + assert(from!=NULL && to!=NULL); + + result = 0; + return result; +} + +int medianin_rename(medianin *self, const char *from, const char *to) +{ + int result = 0; + + assert(INVREP(self)); + assert(from!=NULL && to!=NULL); + + result = 0; + return result; +} + +int medianin_link(medianin *self, const char *from, const char *to) +{ + int result = 0; + char *to_c = NULL; + char *from_c = NULL; + uint16_t inum_from; + dir *from_dir, *to_dir; + file *f; + time_t itime; + + assert(INVREP(self)); + assert(from!=NULL && to!=NULL); + + + if(strlen(basename((char *)to))>25){ + return -ENAMETOOLONG; + } + + to_c = calloc(NAME_LENGTH, sizeof(char)); + from_c = calloc(NAME_LENGTH, sizeof(char)); + + strcpy(to_c, to); + strcpy(from_c, from); + + from_dir=dir_get_from_path(self->disk_mem, to); + + if((inum_from=dir_search(self->disk_mem, from_dir, basename((char *)from)))==0){ + result = -ENOENT; + goto CLEAN; + } + + f=(file *)self->disk_mem+INODEPOOL_OFFSET+inum_from*INODE_SIZE; + + if(S_ISDIR(f->mode)==1){ + result = -EPERM; + goto CLEAN; + } + + if((to_dir=dir_get_from_path(self->disk_mem, to))==NULL){ + result = -ENOENT; + goto CLEAN; + } + + if(!dir_add_direntry(self->disk_mem, to_dir, basename((char *)to), inum_from, 0)){ + result = -ENOSPC; + goto CLEAN; + } + + itime=NEW_TIME; + + f->nlinks+=1; + f->atime=itime; + f->mtime=itime; + +CLEAN: + free(to_c); + free(from_c); + return result; +} + +int medianin_chmod(medianin *self, const char *path, mode_t mode) +{ + dir *pdir = NULL; + char *name; + uint16_t block = 0; + inode *ind = NULL; + + assert(INVREP(self)); + assert(path != NULL); + + if(strcmp(path,"/") == 0) + { + ind = (inode *) self->disk_mem + INODEPOOL_OFFSET + (1 * INODE_SIZE); + return inode_chmod(ind, mode); + } + + pdir = dir_get_from_path(self->disk_mem, path); + + if (!pdir) + return -ENOENT; + + name = calloc(NAME_LENGTH, sizeof(char)); + strncpy (name, basename((char *) path), NAME_LENGTH); + + block = dir_search(self->disk_mem, pdir, name); + free(name); + + if (!block) + return -ENOENT; + + ind = (inode *) self->disk_mem + INODEPOOL_OFFSET + (block * INODE_SIZE); + return inode_chmod(ind, mode); +} + +int medianin_chown(medianin *self,const char *path, uid_t uid, gid_t gid) +{ + dir *pdir = NULL; + char *name = NULL; + uint16_t block = 0; + inode *ind = NULL; + + assert(INVREP(self)); + assert(path != NULL); + + if(strcmp(path,"/") == 0) + { + ind = (inode *) self->disk_mem + INODEPOOL_OFFSET + (1 * INODE_SIZE); + return inode_chown(ind, uid,gid); + } + + pdir = dir_get_from_path(self->disk_mem, path); + + if (!pdir) + return -ENOENT; + + name = calloc(NAME_LENGTH, sizeof(char)); + strncpy (name, basename((char *) path), 24); + + block = dir_search(self->disk_mem, pdir, name); + free(name); + + if (!block) + return -ENOENT; + + ind = (inode *) self->disk_mem + INODEPOOL_OFFSET + (block * INODE_SIZE); + + return inode_chown(ind, uid, gid); +} + +int medianin_truncate(medianin *self, const char *path, off_t size) +{ + dir *parent_dir = NULL; + file *f = NULL; + char *name = NULL; + uint16_t file_pos = 0; + + assert(INVREP(self)); + assert(path!=NULL); + + if(strcmp(path,"/") == 0) + return -EISDIR; + /* Conseguimos el directorio padre. */ + parent_dir = dir_get_from_path(self->disk_mem, path); + if(!parent_dir) + return -ENOENT; + + name = calloc(NAME_LENGTH, sizeof(char)); + strncpy (name, basename((char *) path), 26); + + + file_pos = dir_search(self->disk_mem, parent_dir, name); + free(name); + + if(!file_pos) + return -ENOENT; + + f = (file *) self->disk_mem + INODEPOOL_OFFSET + (file_pos*INODE_SIZE); + file_truncate(self->disk_mem, f, size); + return 0; + + +} + +int medianin_read(medianin *self, const char *path, + char *buffer, size_t size, off_t offset) +{ + uint16_t inode_block = 0; + dir *parent_dir = NULL; + file *f = NULL; + char *name = NULL; + + assert(INVREP(self)); + assert(path!=NULL); + assert(buffer!=NULL); + + parent_dir = dir_get_from_path(self->disk_mem, path); + + if(!parent_dir) + return -ENOENT; + + name = calloc(NAME_LENGTH, sizeof(char)); + strncpy(name, basename((char *)path), NAME_LENGTH); + + inode_block = dir_search(self->disk_mem, parent_dir, name); + free(name); + + if(!inode_block) + return -ENOENT; + f = (file *) self->disk_mem + INODEPOOL_OFFSET + (inode_block*INODE_SIZE); + + if(S_ISDIR(inode_get_mode((inode *) f))) + return -EISDIR; + + return file_read(self->disk_mem, f, buffer, size, offset); +} + +int medianin_write(medianin *self, const char *path, + const char *buffer, size_t size, off_t offset) +{ + uint16_t inode_block = 0, result = 0; + dir *parent_dir = NULL; + file *f = NULL; + char *name = NULL; + + assert(INVREP(self)); + assert(path!=NULL); + assert(buffer!=NULL); + + parent_dir = dir_get_from_path(self->disk_mem, path); + + if(parent_dir==NULL) + return -ENOENT; + + name = calloc(NAME_LENGTH, sizeof(char)); + strncpy (name, basename((char *) path), NAME_LENGTH); + + + inode_block = dir_search(self->disk_mem, parent_dir, name); + free(name); + + if(inode_block == 0) + return -ENOENT; + f = (file *) self->disk_mem + INODEPOOL_OFFSET + (inode_block*INODE_SIZE); + + if(S_ISDIR(inode_get_mode((inode *)f))) + return -EISDIR; + + + if(file_truncate(self->disk_mem, f, f->size+size)!=0){ + return -ENOSPC; + } + + result=file_write(self->disk_mem, f, (char *)buffer, size, offset); + + return result; +} + +int medianin_statfs(medianin *self, const char *path, struct statvfs *stbuf) { + int result = 0; + uint16_t free_blocks=free_blocks_count(self->disk_mem), free_inodes=free_inodes_count(self->disk_mem); + + assert(INVREP(self)); + assert(path!=NULL); + assert(stbuf!=NULL); + + + /* man statvfs */ + stbuf->f_bsize=BLOCK_SIZE; + stbuf->f_frsize=BLOCK_SIZE; + stbuf->f_blocks=(fsblkcnt_t)BLOCKS; + stbuf->f_bfree=(fsblkcnt_t)free_blocks; + stbuf->f_bavail=(fsblkcnt_t)free_blocks; + stbuf->f_files=(fsblkcnt_t)INODE_ENTRIES; + stbuf->f_ffree=(fsblkcnt_t)free_inodes; + stbuf->f_ffree=(fsblkcnt_t)free_inodes; + stbuf->f_flag=S_IRUSR | S_IWUSR | S_IXUSR | S_IXGRP | S_IRGRP | S_IROTH | S_IXOTH | S_IFDIR; + stbuf->f_namemax=26; + + result = 0; + return result; +} + +int medianin_utimens(medianin *self, const char *path, const struct timespec tv[2]) +{ + char *name = NULL; + dir *parent_dir = NULL; + inode *in = NULL; + uint16_t inode_block = 0; + + assert(INVREP(self)); + assert(path!=NULL); + + if(strcmp(path, "/")) + { + in = (inode *) self->disk_mem + INODEPOOL_OFFSET + INODE_SIZE; + return inode_utime(in, tv); + } + + parent_dir = dir_get_from_path(self->disk_mem, path); + + if(!parent_dir) + return -ENOENT; + + name = calloc(NAME_LENGTH, sizeof(char)); + strncpy (name, basename((char *) path), NAME_LENGTH); + + inode_block = dir_search(self->disk_mem, parent_dir, name); + free(name); + + if (!inode_block) + return -ENOENT; + + in = (inode *) self->disk_mem + INODEPOOL_OFFSET + + (inode_block*INODE_SIZE); + return inode_utime(in, tv); +} + +/* + * Operaciones sobre Directorios + */ + +int medianin_mkdir(medianin *self, const char *path, mode_t mode) +{ + int result = 0; + dir *idir = NULL; + uint16_t inode_dir = 0; + char *name = NULL; + + assert(INVREP(self)); + assert(path!=NULL); + + if(S_ISDIR(mode) == 0) + mode = mode | S_IFDIR; + name = calloc(NAME_LENGTH, sizeof(char)); + strncpy (name, basename((char *) path), NAME_LENGTH); + + if(strlen(name) > 25){ + result = -ENAMETOOLONG; + goto CLEAN; + } + + idir=dir_get_from_path(self->disk_mem, path); + + if(dir_search(self->disk_mem ,idir, name)){ + result = -EEXIST; + goto CLEAN; + } + + if((inode_dir=dir_create(self->disk_mem, mode))==0){ + result = -ENOSPC; + goto CLEAN; + } + + if((dir_add_direntry(self->disk_mem, idir, name, inode_dir, 0))==0){ + inode_free_block(self->disk_mem, inode_dir); + result = -ENOSPC; + goto CLEAN; + } + + assert(GET_BIT(self->disk_mem + FIB_OFFSET, inode_dir) == 1); + +CLEAN: + free(name); + return result; +} + +int medianin_rmdir(medianin *self, const char *path) +{ + int result = 0; + dir *parent_dir = NULL; + char *name; + uint16_t inum; + uint16_t search_num; + inode *i; + + assert(INVREP(self)); + assert(path!=NULL); + + + parent_dir = dir_get_from_path(self->disk_mem, path); + if(!parent_dir) + return -ENOENT; + + name = calloc(NAME_LENGTH, sizeof(char)); + strncpy (name, basename((char *) path), NAME_LENGTH); + + search_num = dir_search(self->disk_mem, parent_dir, name); + + if(!search_num) + return -ENOENT; + + i = (inode *) self->disk_mem + INODEPOOL_OFFSET + (search_num * INODE_SIZE); + + + if(!S_ISDIR(inode_get_mode(i))) + return -ENOTDIR; + if((inode_get_mode(i) & S_IWUSR) == 0) + return -EPERM; + + /* Chequeos de permisos. */ + inum = dir_remove_direntry(self->disk_mem, parent_dir, name); + free(name); + + inode_free_block(self->disk_mem, inum); + + assert(inum == search_num); + return result; +} + +int medianin_readdir(medianin *self, const char *path, void *buf, + fuse_fill_dir_t filler) +{ + int result = 0; + dir *parent_dir = NULL; + dir *my_dir = NULL; + uint16_t dir_inumber = 0; + char *name = NULL; + + assert(INVREP(self)); + assert(path!=NULL && buf!=NULL); + + if(strcmp(path, "/") == 0) + { + /* Root dir */ + my_dir = (dir *) self->disk_mem + INODEPOOL_OFFSET + (1 * INODE_SIZE); + goto FILL; + } + parent_dir = dir_get_from_path(self->disk_mem, path); + + if (parent_dir == NULL) + return -ENOENT; + + name = calloc(NAME_LENGTH, sizeof(char)); + strncpy(name, basename((char *) path), NAME_LENGTH); + + dir_inumber = dir_search(self->disk_mem, parent_dir, name); + free(name); + + if(!dir_inumber) + return -ENOENT; + my_dir = (dir *) self->disk_mem + INODEPOOL_OFFSET + (dir_inumber * INODE_SIZE); + +FILL: + filler(buf, ".", NULL, 0); + filler(buf, "..", NULL, 0); + + dir_readdir(self->disk_mem, my_dir, buf, filler); + + return result; +} diff --git a/medianin.h b/medianin.h new file mode 100644 index 0000000..e0b070b --- /dev/null +++ b/medianin.h @@ -0,0 +1,44 @@ +#ifndef __MEDIANIN_H +#define __MEDIANIN_H + +#define _GNU_SOURCE +#define FUSE_USE_VERSION 26 + +#include +#include +#include +#include +#include + +#include "defs.h" +typedef struct medianin_s medianin; + +/* Constructores y Destructores */ +medianin *medianin_create(void); +void medianin_destroy(medianin *self); + +/* Operaciones Básicas */ +int medianin_getattr(medianin *self, const char *path, struct stat *stbuf); +int medianin_readlink(medianin *self, const char *path, char *buf, size_t size); +int medianin_mknod(medianin *self, const char *path, mode_t mode); +int medianin_unlink(medianin *self, const char *path); +int medianin_symlink(medianin *self, const char *from, const char *to); +int medianin_rename(medianin *self, const char *from, const char *to); +int medianin_link(medianin *self, const char *from, const char *to); +int medianin_chmod(medianin *self, const char *path, mode_t mode); +int medianin_chown(medianin *self, const char *path, uid_t uid, gid_t gid); +int medianin_truncate(medianin *self, const char *path, off_t size); +int medianin_read(medianin *self, const char *path, + char *buffer, size_t size, off_t offset); +int medianin_write(medianin *self, const char *path, + const char *buffer, size_t size, off_t offset); +int medianin_statfs(medianin *self, const char *path, struct statvfs *stbuf); +int medianin_utimens(medianin *self, const char *path, const struct timespec tv[2]); + +/* Operaciones sobre Directorios */ +int medianin_mkdir(medianin *self, const char *path, mode_t mode); +int medianin_rmdir(medianin *self, const char *path); +int medianin_readdir(medianin *self, const char *path, void *buf, + fuse_fill_dir_t filler); + +#endif /* __MEDIANIN_H */ diff --git a/mkfs.md/Makefile b/mkfs.md/Makefile new file mode 100644 index 0000000..e91a5e5 --- /dev/null +++ b/mkfs.md/Makefile @@ -0,0 +1,14 @@ +FILES=mkfs.c +TARGET=mkfs.md +CFLAGS=-Wall -Werror -Wextra -g + +all: $(FILES) + clang $(CFLAGS) -o $(TARGET) $(FILES) + +with-inode: $(FILES) + clang $(CFLAGS) -D_HAS_TRACKED_INODE -o $(TARGET) $(FILES) + +clean: + rm -f $(TARGET) *.o + +.PHONY: clean diff --git a/mkfs.md/disk.mdfs b/mkfs.md/disk.mdfs new file mode 100644 index 0000000..0dae906 Binary files /dev/null and b/mkfs.md/disk.mdfs differ diff --git a/mkfs.md/mkfs.c b/mkfs.md/mkfs.c new file mode 100644 index 0000000..37c6e6e --- /dev/null +++ b/mkfs.md/mkfs.c @@ -0,0 +1,90 @@ +#include "../defs.h" +#include "../inode.h" + +#include + +#include +#include +#include +#include +#include + +#include +#include + +struct PACKED superblock { + uint16_t magic; + uint32_t free_size; + uint32_t max_size; +}; + +int main(int argc, char *argv[]) +{ + char *fs = NULL; + int fd = 0; + struct superblock *sb= NULL; + inode *rootdir = NULL; +#ifdef _HAS_TRACKED_INODE + direntry *dentry = NULL; +#endif + + if (argc != 2){ + printf("Uso: %s [file]\n" + "Necesita proveer un nombre para el filesystem", + argv[0]); + return -2; + } + + fd = open(argv[1], O_WRONLY | O_CREAT, 0777); + + fs = calloc (BLOCKS*BLOCK_SIZE, sizeof(char)); + if (!fs){ + fprintf(stderr, "No hay suficiente memoria para alocar el filesystem\n"); + return (1); + } + sb = (struct superblock *) fs; + + sb->magic = 0xF514; /* No hay ganas de hacer aritmetica con lo que esta en el defs.h */ + sb->max_size = BLOCK_SIZE * BLOCKPOOL_BLOCKS; + sb->free_size = BLOCK_SIZE * BLOCKPOOL_BLOCKS; + SET_BIT_1((char *)sb + FBB_OFFSET, 0); + /* El primer elemento del inodepool es el rootdir */ + SET_BIT_1((char*) sb + FIB_OFFSET, 1); + + + rootdir = (inode *) sb + INODEPOOL_OFFSET + sizeof(inode); + + rootdir->type = I_DIR; + rootdir->mode = S_IRUSR | S_IWUSR | S_IXUSR | S_IXGRP | S_IRGRP | S_IROTH | S_IXOTH | S_IFDIR; + rootdir->uid = getuid(); + rootdir->gid = getgid(); + rootdir->indirect=2; + rootdir->atime = (uint32_t) time(NULL); + rootdir->ctime = (uint32_t) time(NULL); + rootdir->mtime = (uint32_t) time(NULL); + + rootdir->nlinks = 1; + +#ifndef _HAS_TRACKED_INODE + rootdir->size = 0; +#else + rootdir->size = sizeof(direntry); + /* Primer bloque */ + /*SET_BIT_1((char *)sb + FBB_OFFSET, 0); */ + dentry = (direntry *) sb + BLOCKPOOL_OFFSET; + dentry->inode = 0; + dentry->name[0] = '/'; + dentry->name[1] = '\0'; + dentry->symlink = 0; +#endif + + if ((write(fd, (void *) fs, BLOCKS*BLOCK_SIZE)) == -1){ + perror("write"); + close(fd); + return -1; + } + close(fd); + free(fs); + + return (0); +} diff --git a/mkfs.md/mkfs.md b/mkfs.md/mkfs.md new file mode 100644 index 0000000..90a9507 Binary files /dev/null and b/mkfs.md/mkfs.md differ diff --git a/mkfs.md/out b/mkfs.md/out new file mode 100644 index 0000000..ad97aa8 --- /dev/null +++ b/mkfs.md/out @@ -0,0 +1,2 @@ +clang -Wall -Werror -Wextra -g -std=c99 -o mkfs.md mkfs.c +Makefile:6: recipe for target 'all' failed diff --git a/run.sh b/run.sh new file mode 100644 index 0000000..0beb5eb --- /dev/null +++ b/run.sh @@ -0,0 +1,21 @@ +NEW_DISK="mkfs.md/disk.mdfs" + +echo "Compilando..." +make > /dev/null +if [ $? -ne 0 ]; then + echo "Error de compilacion" + exit 1 +fi + +fusermount -u ./mnt 2> /dev/null && echo "Desmontando" + +echo "Copiando $NEW_DISK" +cp ./$NEW_DISK . + +if [ "$1" == "valgrind" ]; then + valgrind --show-reachable=yes --leak-check=full ./fusewrapper mnt +else + ./fusewrapper mnt +fi + +exit 0 diff --git a/test.sh b/test.sh new file mode 100644 index 0000000..b86ee89 --- /dev/null +++ b/test.sh @@ -0,0 +1,10 @@ +touch mnt/{a,b,c,d,e,f} +mkdir mnt/{1,2,3,4,5,6,7} +mkdir -p mnt/z/z/z/z/z/z/z +echo "Hola mundo" > mnt/a +link mnt/a mnt/linked +stat mnt/a +stat mnt/linked +rmdir mnt/1 +cat -v mnt/a +cat -v mnt/linked diff --git a/tests/read_diferentes_offsets.py b/tests/read_diferentes_offsets.py new file mode 100644 index 0000000..008ef05 --- /dev/null +++ b/tests/read_diferentes_offsets.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- + +import sys +import random +random.seed("Yeah babe") + +text = open(sys.argv[1]).read() + +fin = open(sys.argv[1]) +for _ in xrange(1000): + offset = random.randint(0, len(text)) + size = random.randint(0, min(len(text) - offset - 1, 10 * 1024)) + fin.seek(offset) + chunk = fin.read(size) + assert len(chunk) <= size + assert len(chunk) != 0 + if text[offset:offset + len(chunk)] != chunk: + s = "Read fails for file {} with offset {} and size {}" + raise IOError(s.format(sys.argv[1], offset, size)) +print "Success!" -- cgit v1.2.3-54-g00ecf