diff options
Diffstat (limited to 'inode.c')
-rw-r--r-- | inode.c | 204 |
1 files changed, 204 insertions, 0 deletions
@@ -0,0 +1,204 @@ +#include "inode.h" + +#include <assert.h> +#include <sys/mman.h> +#include <string.h> +#include <stdbool.h> +#include <stdlib.h> +#include <libgen.h> + +#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(i<path_len){ + /*el while empieza desde i=1, se come el primer slash, necesario + * para usar basename*/ + if(path_mod[i] == '/'){ + /*NULL-terminamos el string para conseguir solo ese dir/file*/ + path_mod[i]='\0'; + break; + } + i++; + } + + result=inode_search(disk_mem, current, path_mod); + free(path_mod); + + if(i < path_len){ + /* *si no se llego al final, se busca el dir actual, y se continua + * la busqueda*/ + /*RECURSION FTW!*/ + return get_inode_from_path(disk_mem, path + i, result); + } + + /*si se llego al final, devolvemos el inodo correspondiente a la + * iteracion*/ + + + return result; +} + +int inode_getattr(inode *f, ino_t inum, struct stat *stbuf) +{ + assert (f != NULL); + + stbuf->st_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; +} |