diff options
Diffstat (limited to 'dir.c')
-rw-r--r-- | dir.c | 265 |
1 files changed, 265 insertions, 0 deletions
@@ -0,0 +1,265 @@ +#include "dir.h" + +#include <assert.h> +#include <unistd.h> +#include <libgen.h> +#include <string.h> +#include <stdbool.h> +#include <sys/mman.h> + +#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_SIZE<d->size+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; +} |