aboutsummaryrefslogtreecommitdiff
path: root/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'inode.c')
-rw-r--r--inode.c204
1 files changed, 204 insertions, 0 deletions
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 <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;
+}