diff --git a/include/direntry.h b/include/direntry.h new file mode 100644 index 0000000..6b1c945 --- /dev/null +++ b/include/direntry.h @@ -0,0 +1,41 @@ +typedef struct fileNode { + char *name = NULL; + int inode_number; + int permissions; + char *Symbolink; + struct treeNode *subdirectory; + struct fileNode *next; + void serialize(char* buffer) { + u_int64_t t = inode_number; + for (int j = 0; j < 8; j++){ + buffer[j] = t & (((u_int64_t)1<<(8))-1); + t >>= 8; + } + strcpy(buffer+8, file_name); + } + void deserialize(char* buffer) { + inode_number = 0; + for (int j = 0; j < 8; j++) + inode_number = inode_number | (((u_int64_t)(unsigned char)buffer[j])<<(8*j)); + strcpy(file_name, buffer+8); + } +} FileNode; + +typedef struct { + int size; + FileNode **table; +} HashTable; + +typedef struct treeNode { + char *dirName; + HashTable *contents; + struct treeNode *parent; + FileNode *self_info; //self fileNode infromation +} TreeNode; + +/*root directory have its own initialization, so parent wont be NULL*/ +int fischl_add_entry(TreeNode *parent, int new_inode_number, const char *fileName, INode *new_inode); +/*if want to use dir mode use the subdirectory treeNode pointer */ +//e.g. FileNode *Dirnode = fischl_find_entry(); can see file inside with Dirnode->subdirectory +//e.g. go to the current Dirnode parent directory, use TreeNode *get_Dir_parent = Dirnode->subdirectory->parent; +FileNode *fischl_find_entry(TreeNode *root, const char *path); diff --git a/lib/direntry.cpp b/lib/direntry.cpp new file mode 100644 index 0000000..85f0a69 --- /dev/null +++ b/lib/direntry.cpp @@ -0,0 +1,133 @@ +/*********************************Hash operation******************************************** + +********************************************************************************************/ +// Hash operation +unsigned int hash(HashTable *h, char *key) { + unsigned int hashval = 0; + for (; *key != '\0'; key++) hashval = *key + (hashval << 5) - hashval; + return hashval % h->size; +} + +HashTable *createHashTable(int size) { + HashTable *newTable = (HashTable *)malloc(sizeof(HashTable)); + newTable->size = size; + newTable->table = (FileNode **)malloc(sizeof(FileNode *) * size); + for (int i = 0; i < size; i++) newTable->table[i] = NULL; + return newTable; +} + +FileNode *insertHash(HashTable *h, char *key, TreeNode *subdirectory) { + unsigned int hashval = hash(h, key); + FileNode *newNode = (FileNode *)malloc(sizeof(FileNode)); + newNode->name = strdup(key); + newNode->subdirectory = subdirectory; + newNode->next = h->table[hashval]; + h->table[hashval] = newNode; + return newNode; +} + +FileNode *lookupHash(HashTable *h, char *key) { + unsigned int hashval = hash(h, key); + FileNode *node = h->table[hashval]; + while (node != NULL) { + if (strcmp(node->name, key) == 0) return node; + node = node->next; + } + return NULL; // Not found +} + +void freeHashTable(HashTable *table) { + if (table == NULL) return; + + for (int i = 0; i < table->size; ++i) { + FileNode *current = table->table[i]; + while (current != NULL) { + FileNode *temp = current; + current = current->next; + // free(temp->name); + // free(temp); + } + } + free(table->table); + free(table); +} + +void freeTree(TreeNode *node) { + //printf("***********************FREE TREE %s**************************\n",node->dirName); + //printf("***********************FREE TREE **************************\n"); + if (node == NULL) return; + + if (node->contents != NULL) { + for (int i = 0; i < node->contents->size; ++i) { + FileNode *current = node->contents->table[i]; + while (current != NULL) { + FileNode *temp = current; + current = current->next; + + if (temp->subdirectory != NULL) { + freeTree(temp->subdirectory); + } + // Free the FileNode if it's not a directory + printf("free who %s\n",temp->name); + free(temp->name); + free(temp); + } + } + //printf("free %s's hash table\n",node->dirName); + freeHashTable(node->contents); + //node->contents = NULL; + } + //printf("free directory %s\n",node->dirName); + free(node->dirName); + node->dirName = NULL; + free(node); + node = NULL; + //printf("***********************END**************************\n"); +} + +/*********************************Direntry operation****************************************** + +********************************************************************************************/ +int fischl_add_entry(TreeNode *parent, int new_inode_number, const char *fileName, INode *new_inode){ + char *Name = strdup(fileName); + TreeNode *newDir = NULL; + /*If directory, malloc TreeNode, and then create filenode that belongs to Parent hash table content*/ + if ((new_inode->permissions & S_IFMT) == S_IFDIR) { + newDir = (TreeNode *)malloc(sizeof(TreeNode)); + newDir->dirName = Name; + newDir->contents = createHashTable(20);//hasSize define 20 + newDir->parent = parent; + } + FileNode *newFile = insertHash(parent->contents, Name, newDir); //newDir == NULL indicates it's a file + //assign INode *new_inode metadata to data member in FileNode structure + newFile->permissions = new_inode->permissions; + newFile->inode_number = new_inode_number; + //Diretory have its own file information, that is . here + if(newDir != NULL) + newDir->self_info = newFile; + //free(Name); cannot free name + return 0; +} + +FileNode *fischl_find_entry(TreeNode *root, const char *path){ + //support . and .. function + char *pathCopy = strdup(path); + char *segment = strtok(pathCopy, "/"); + TreeNode *current = root; + FileNode *file = NULL; + + while (segment != NULL && current != NULL) { + file = lookupHash(current->contents, segment); + if (file != NULL && file->subdirectory == NULL) { + free(pathCopy); + return file; //File found + //return current; return filenode + } + current = file ? file->subdirectory : NULL; + segment = strtok(NULL, "/"); + } + + free(pathCopy); + return file; // NULL if not found + //return current; return filenode +} \ No newline at end of file diff --git a/lib/files.cpp b/lib/files.cpp index f1f0087..9304fcb 100644 --- a/lib/files.cpp +++ b/lib/files.cpp @@ -2,45 +2,8 @@ #include "files.h" #include #include +#include "direntry.h" -/********************************************************************* - Directory Entry definition and function - - -*********************************************************************/ -struct DirectoryEntry { - u_int64_t inode_number; - char file_name[56]; - void serialize(char* buffer) { - u_int64_t t = inode_number; - for (int j = 0; j < 8; j++){ - buffer[j] = t & (((u_int64_t)1<<(8))-1); - t >>= 8; - } - strcpy(buffer+8, file_name); - } - void deserialize(char* buffer) { - inode_number = 0; - for (int j = 0; j < 8; j++) - inode_number = inode_number | (((u_int64_t)(unsigned char)buffer[j])<<(8*j)); - strcpy(file_name, buffer+8); - } -}; -//Directory collection -typedef struct { - //DirectoryEntry entries[MAX_ENTRIES]; with tree structure - unsigned int num_entries; -} Directory; -/* - * fishcl_add_entry() - * - * adds a file entry to the specified directory, using the same - * semantics as fishcl_find_entry(). It returns NULL if it failed. - * - */ -static int fishcl_add_entry(Directory *dir, unsigned int inode_number, const char *name){ - -} FilesOperation::FilesOperation(RawDisk& disk_): disk(disk_) { inop.initialize(disk);