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