diff --git a/#Makefile# b/#Makefile# new file mode 100755 index 0000000..6fd7ef7 --- /dev/null +++ b/#Makefile# @@ -0,0 +1,90 @@ +# +# Sample Makefile for COMP 421 YFS and user programs. +# +# The YFS server built will be named "yfs". *ALL* Makefiles +# for this lab must have a "yfs" rule in them, and must +# produce a YFS server executable named "yfs" -- we will run +# your Makefile and will grade the resulting executable +# named "yfs". Likewise, *ALL* Makefiles must have a rule +# named "iolib.a" to make your YFS library. +# +# Define the list of everything to be made by this Makefile. +# The list should include "yfs" (the name of your server) and +# "iolib.a" (the name of your library), plus the list of user +# test programs you also want to be made by this Makefile. +# For example, the definition below specifies to make Yalnix +# test user programs test1, test2, and test3, all of which will +# be linked with your library to enable them to use your +# server. You should modify this list to the list of your +# own test programs. +# +# For each user test program, the Makefile will make the +# program out of a single correspondingly named source file. +# In addition to this single source file for each test +# program, each program will also be linked with your library. +# For example, the Makefile will make test1 out of test1.c, +# if you have a file named test1.c in this directory. +# + +ALL = yfs iolib.a init + +# +# You must modify the YFS_OBJS and YFS_SRCS definitions below. +# YFS_OBJS should be a list of the .o files that make up your +# YFS server, and YFS_SRCS should be a list of the corresponding +# source files that make up your serever. +# +YFS_OBJS = yfs.o +YFS_SRCS = yfs.c + +# +# You must also modify the IOLIB_OBJS and IOLIB_SRCS definitions +# below. IOLIB_OBJS should be a list of the .o files that make up +# your YFS library, and IOLIB_SRCS should be a list of the +# corresponding source files that make up your library. +# +IOLIB_OBJS = iolib.o +IOLIB_SRCS = iolib.c + +# +# You should not have to modify anything else in this Makefile +# below here. If you want to, however, you may modify things +# such as the definition of CFLAGS, for example. +# + +LANG = gcc + +PUBLIC_DIR = /clear/courses/comp421/pub + +CPPFLAGS = -I$(PUBLIC_DIR)/include +CFLAGS = -g -Wall + +%: %.o + $(LINK.o) -o $@ $^ iolib.a $(LOADLIBES) $(LDLIBS) + +LINK.o = $(PUBLIC_DIR)/bin/link-user-$(LANG) $(LDFLAGS) $(TARGET_ARCH) + +%: %.c +%: %.cc +%: %.cpp + +all: $(ALL) + +yfs: $(YFS_OBJS) + $(LINK.o) -o $@ $^ $(PUBLIC_DIR)/lib/print-yfs.o $(LOADLIBES) $(LDLIBS) + +iolib.a: $(IOLIB_OBJS) + rm -f $@ + ar rv $@ $(IOLIB_OBJS) + ranlib $@ + +mkyfs: mkyfs.c + $(CC) $(CPPFLAGS) -o mkyfs mkyfs.c + +clean: + rm -f $(YFS_OBJS) $(IOLIB_OBJS) $(ALL) + +depend: + $(CC) $(CPPFLAGS) -M $(YFS_SRCS) $(IOLIB_SRCS) > .depend + +#include .depend diff --git a/#iolib.c# b/#iolib.c# new file mode 100755 index 0000000..2f44275 --- /dev/null +++ b/#iolib.c# @@ -0,0 +1,438 @@ +#include "yfs.h" + +// TODO: clean pathnames before passing to YFS +// take care of "//" +// make sure less than MAXPATHNAMELEN + +// TODO: enable relative path names by tracking current directory and sending inode to YFS + +struct Open_File { + short inode; + int position; +}; +y +struct Open_File files[MAX_OPEN_FILES]; + +int num_open_files = 0; +int files_initialized = 0; +short current_dir = ROOTINODE; + +void Initialize_Files(){ + int i; + for(i = 0; i < MAX_OPEN_FILES; i++){ + files[i].inode = -1; + files[i].position = 0; + } + files_initialized = 1; +} + +// condenses consecutive '/'s and replaces trailing '/' with '.' +// returns the length of the new pathname which is no more than strlen(pathname) + 1 +int format_pathname(char* oldname, char* newname){ + + int len = strlen(oldname); + int i = 0; int j = 0; + for(i = 0; i < len; i++){ + if(oldname[i] == '/' && oldname[i+1] == '/'){ + continue; + } + newname[j] = oldname[i]; + j++; + } + int newlen = j; + + if(newname[newlen-1] == '/'){ + newname[newlen] = '.'; + newname[newlen+1] = '\0'; + return newlen+1; + } + else{ + newname[newlen] = '\0'; + return newlen; + } +} + +int CallYFS(uint8_t code, void** args, int* arg_sizes, int num_args){ + char msg[MESSAGE_SIZE]; + msg[0] = (char)code; + + int i; + int offset = 1; + + + for(i = 0; i < num_args; i++){ + // no longs are passed so sizeof(void*) applies exclusively to pointers + if(arg_sizes[i] == sizeof(void*) && *(void**)args[i] == NULL){ + fprintf(stderr, "ERROR: null pointer argument provided\n"); + return ERROR; + } + memcpy(msg + offset, (char**)(args[i]), arg_sizes[i]); + offset += arg_sizes[i]; + } + + int success = Send(msg, -FILE_SYSTEM); + + //---------------------------------------------------------------------------------------- + // pass control to YFS; upon return, msg should be overwritten with single int reply value + //---------------------------------------------------------------------------------------- + + int result = *(int*)msg; + if(success == -1 || result == -1){ + switch(code){ + case CODE_OPEN: + fprintf(stderr, "ERROR: YFS failed to open file\n"); break; + case CODE_CLOSE: + fprintf(stderr, "ERROR: YFS failed to close file\n"); break; + case CODE_CREATE: + fprintf(stderr, "ERROR: YFS failed to create file\n"); break; + case CODE_READ: + fprintf(stderr, "ERROR: YFS failed to read file\n"); break; + case CODE_WRITE: + fprintf(stderr, "ERROR: YFS failed to write to file\n"); break; + case CODE_SEEK: + fprintf(stderr, "ERROR: YFS failed to seek file\n"); break; + case CODE_LINK: + fprintf(stderr, "ERROR: YFS failed to create link\n"); break; + case CODE_UNLINK: + fprintf(stderr, "ERROR: YFS failed to unlink path\n"); break; + case CODE_SYMLINK: + fprintf(stderr, "ERROR: YFS failed to create symbolic link\n"); break; + case CODE_READLINK: + fprintf(stderr, "ERROR: YFS failed to read symbolic link\n"); break; + case CODE_MKDIR: + fprintf(stderr, "ERROR: YFS failed to make directory\n"); break; + case CODE_RMDIR: + fprintf(stderr, "ERROR: YFS failed to remove directory\n"); break; + case CODE_CHDIR: + fprintf(stderr, "ERROR: YFS failed to change directory\n"); break; + case CODE_STAT: + fprintf(stderr, "ERROR: YFS failed to retrieve stats\n"); break; + case CODE_SYNC: + fprintf(stderr, "ERROR: YFS failed to sync storage\n"); break; + case CODE_SHUTDOWN: + fprintf(stderr, "ERROR: YFS failed to shutdown\n"); break; + } + } + return result; +} + +int Open(char* pathname){ + if(!files_initialized) + Initialize_Files(); + + if(num_open_files >= MAX_OPEN_FILES){ + fprintf(stderr, "ERROR: maximum number of files already open\n"); + return 0; + } + + char* tmp = pathname; + pathname = (char*)malloc(strlen(pathname) + 2); + int pathname_size = format_pathname(tmp, pathname); + void* args[3] = {(void*)&pathname, (void*)&pathname_size, (void*)¤t_dir}; + int arg_sizes[3] = {sizeof(pathname), sizeof(pathname_size), sizeof(current_dir)}; + int inode = CallYFS(CODE_OPEN, args, arg_sizes, 3); + + int i; + for(i = 0; i < MAX_OPEN_FILES; i++){ + if(files[i].inode == -1){ + files[i].inode = inode; + num_open_files++; + return i; + } + } + + // no reason this should ever occur since we already check max open files + return ERROR; +} + +int Close(int fd){ + if(!files_initialized) + Initialize_Files(); + + if(fd < 0 || fd >= MAX_OPEN_FILES || files[fd].inode == -1){ + fprintf(stderr, "ERROR: file descriptor is invalid\n"); + return ERROR; + } + + files[fd].inode = -1; + files[fd].position = 0; + num_open_files--; + return 0; +} + +int Create(char *pathname){ + if(!files_initialized) + Initialize_Files(); + + if(num_open_files >= MAX_OPEN_FILES){ + fprintf(stderr, "ERROR: maximum number of files already open\n"); + return 0; + } + + + char* tmp = pathname; + pathname = (char*)malloc(strlen(pathname) + 2); + int pathname_size = format_pathname(tmp, pathname); + void* args[3] = {(void*)&pathname, (void*)&pathname_size, (void*)¤t_dir}; + int arg_sizes[3] = {sizeof(pathname), sizeof(pathname_size), sizeof(current_dir)}; + int inode = CallYFS(CODE_CREATE, args, arg_sizes, 3); + + int i; + for(i = 0; i < MAX_OPEN_FILES; i++){ + if(files[i].inode == -1){ + files[i].inode = inode; + num_open_files++; + return i; + } + } + + // no reason this should ever occur since we already check max open files + return ERROR; + +} + +int Read(int fd, void *buf, int size){ + if(!files_initialized) + Initialize_Files(); + + if(fd < 0 || fd >= MAX_OPEN_FILES || files[fd].inode == -1){ + fprintf(stderr, "ERROR: file descriptor is invalid\n"); + return ERROR; + } + + short inode = files[fd].inode; + int position = files[fd].position; + + void* args[4] = {(void*)&buf, (void*)&size, (void*)&inode, (void*)&position}; + int arg_sizes[4] = {sizeof(buf), sizeof(size), sizeof(inode), sizeof(position)}; + int result = CallYFS(CODE_READ, args, arg_sizes, 4); + + if(result == -1) + return ERROR; + + files[fd].position += result; + return result; +} + +int Write(int fd, void *buf, int size){ + if(!files_initialized) + Initialize_Files(); + + if(fd < 0 || fd >= MAX_OPEN_FILES || files[fd].inode == -1){ + fprintf(stderr, "ERROR: file descriptor is invalid\n"); + return ERROR; + } + + short inode = files[fd].inode; + int position = files[fd].position; + + void* args[4] = {(void*)&buf, (void*)&size, (void*)&inode, (void*)&position}; + int arg_sizes[4] = {sizeof(buf), sizeof(size), sizeof(inode), sizeof(position)}; + int result = CallYFS(CODE_WRITE, args, arg_sizes, 4); + + if(result == -1) + return ERROR; + + files[fd].position += result; + return result; +} + +int Seek(int fd, int offset, int whence){ + if(!files_initialized) + Initialize_Files(); + + if(fd < 0 || fd >= MAX_OPEN_FILES || files[fd].inode == -1){ + fprintf(stderr, "ERROR: file descriptor is invalid\n"); + return ERROR; + } + + int new_position; + + switch(whence){ + case SEEK_SET: + new_position = offset; + break; + case SEEK_CUR: + new_position = files[fd].position + offset; + break; + case SEEK_END: + ; // fix a dumb "declaration after statement" C quirk + void* args[1] = {(void*)&files[fd].inode}; + int arg_sizes[1] = {sizeof(files[fd].inode)}; + new_position = CallYFS(CODE_SEEK, args, arg_sizes, 1) - offset; + break; + default: + fprintf(stderr, "ERROR: whence value invalid\n"); + } + + if(new_position < 0){ + fprintf(stderr, "ERROR: new file position would be negative\n"); + return ERROR; + } + + files[fd].position = new_position; + return 0; +} + +int Link(char *oldname, char *newname){ + + char* tmp1 = oldname; + oldname = (char*)malloc(strlen(oldname) + 2); + int oldname_size = format_pathname(tmp1, oldname); + char* tmp2 = newname; + newname = (char*)malloc(strlen(newname) + 2); + int newname_size = format_pathname(tmp2, newname); + + void* args[5] = {(void*)&oldname, (void*)&oldname_size, (void*)&newname, + (void*)&newname_size, (void*)¤t_dir}; + int arg_sizes[5] = {sizeof(oldname), sizeof(oldname_size), sizeof(newname), + sizeof(newname_size), sizeof(current_dir)}; + return CallYFS(CODE_LINK, args, arg_sizes, 5); +} + +int Unlink(char *pathname){ + char* tmp = pathname; + pathname = (char*)malloc(strlen(pathname) + 2); + int pathname_size = format_pathname(tmp, pathname); + void* args[3] = {(void*)&pathname, (void*)&pathname_size, (void*)¤t_dir}; + int arg_sizes[3] = {sizeof(pathname), sizeof(pathname_size), sizeof(current_dir)}; + return CallYFS(CODE_UNLINK, args, arg_sizes, 3); +} + +int SymLink(char *oldname, char *newname){ + char* tmp1 = oldname; + oldname = (char*)malloc(strlen(oldname) + 2); + int oldname_size = format_pathname(tmp1, oldname); + char* tmp2 = newname; + newname = (char*)malloc(strlen(newname) + 2); + int newname_size = format_pathname(tmp2, newname); + void* args[5] = {(void*)&oldname, (void*)&oldname_size, (void*)&newname, + (void*)&newname_size, (void*)¤t_dir}; + int arg_sizes[5] = {sizeof(oldname), sizeof(oldname_size), sizeof(newname), + sizeof(newname_size), sizeof(current_dir)}; + return CallYFS(CODE_SYMLINK, args, arg_sizes, 5); +} + +int ReadLink(char *pathname, char *buf, int len){ + char* tmp = pathname; + pathname = (char*)malloc(strlen(pathname) + 2); + int pathname_size = format_pathname(tmp, pathname); + void* args[5] = {(void*)&pathname, (void*)&pathname_size, (void*)&buf, (void*)&len, + (void*)¤t_dir}; + int arg_sizes[5] = {sizeof(pathname), sizeof(pathname_size), sizeof(buf), sizeof(len), + sizeof(current_dir)}; + return CallYFS(CODE_READLINK, args, arg_sizes, 5); +} + +int MkDir(char *pathname){ + char* tmp = pathname; + pathname = (char*)malloc(strlen(pathname) + 2); + int pathname_size = format_pathname(tmp, pathname); + void* args[3] = {(void*)&pathname, (void*)&pathname_size, (void*)¤t_dir}; + int arg_sizes[3] = {sizeof(pathname), sizeof(pathname_size), sizeof(current_dir)}; + return CallYFS(CODE_MKDIR, args, arg_sizes, 3); +} + +int RmDir(char *pathname){ + char* tmp = pathname; + pathname = (char*)malloc(strlen(pathname) + 2); + int pathname_size = format_pathname(tmp, pathname); + void* args[2] = {(void*)&pathname, (void*)&pathname_size}; + int arg_sizes[2] = {sizeof(pathname), sizeof(pathname_size)}; + return CallYFS(CODE_RMDIR, args, arg_sizes, 2); +} + +int ChDir(char *pathname){ + char* tmp = pathname; + pathname = (char*)malloc(strlen(pathname) + 2); + int pathname_size = format_pathname(tmp, pathname); + void* args[3] = {(void*)&pathname, (void*)&pathname_size, (void*)¤t_dir}; + int arg_sizes[3] = {sizeof(pathname), sizeof(pathname_size), sizeof(current_dir)}; + short new_inum = CallYFS(CODE_CHDIR, args, arg_sizes, 3); + + if(new_inum == ERROR){ + return ERROR; + } + current_dir = new_inum; + return 0; +} + +int Stat(char *pathname, struct Stat* statbuf){ + char* tmp = pathname; + pathname = (char*)malloc(strlen(pathname) + 2); + int pathname_size = format_pathname(tmp, pathname); + void* args[4] = {(void*)&pathname, (void*)&pathname_size, (void*)&statbuf, + (void*)¤t_dir}; + int arg_sizes[4] = {sizeof(pathname), sizeof(pathname_size), sizeof(statbuf), + sizeof(current_dir)}; + return CallYFS(CODE_STAT, args, arg_sizes, 4); +} + +int Sync(void){ + return CallYFS(CODE_SYNC, NULL, NULL, 0); +} + +int Shutdown(void){ + return CallYFS(CODE_SHUTDOWN, NULL, NULL, 0); +} + +/* + char* test1 = "/standard/directory/path/name"; + char* test2 = "/this/is/a/path/to/dir/"; + char* test3 = "/"; + char* test4 = NULL; + char* test5 = "////this/has///a/bunch//////of//slashes////"; + char* test6 = "noslashes"; + char* test7 = "finally, this is a dot ending/"; + + char* result1 = (char*)malloc(50); + char* result2 = (char*)malloc(50); + char* result3 = (char*)malloc(50); + char* result4 = (char*)malloc(50); + char* result5 = (char*)malloc(50); + char* result6 = (char*)malloc(50); + char* result7 = (char*)malloc(50); + + format_pathname(test1, result1); + format_pathname(test2, result2); + format_pathname(test3, result3); + //format_pathname(test4, result4); + format_pathname(test5, result5); + format_pathname(test6, result6); + format_pathname(test7, result7); + + printf("%s\n", result1); + printf("%s\n", result2); + printf("%s\n", result3); + //printf("%s\n", result4); + printf("%s\n", result5); + printf("%s\n", result6); + printf("%s\n", result7); + */ + +/* +void print_bits_short(uint8_t n){ + int i; + for(i = 0; i < 8; i++){ + if(n & 128) + printf("1"); + else + printf("0"); + n <<=1; + } +} + + +void print_bits_long(uint64_t n){ + int i; + for(i = 0; i < 64; i++){ + if(n & 9223372036854775808) + printf("1"); + else + printf("0"); + n <<=1; + if(i % 8 == 7) + printf(" "); + } +} +*/ diff --git a/#lru_cache.c# b/#lru_cache.c# new file mode 100755 index 0000000..f33571a --- /dev/null +++ b/#lru_cache.c# @@ -0,0 +1,349 @@ +#include +#include +#include +#include + +#define SIZE 100 +#define BLOCKSIZE 32 +#define BLOCK_CACHESIZE 2 // Needs to be modified to another number. +int current_blockcache_number; + + +//Dirty = 1 means it is dirty +//Dirty = 0 means it is not dirty + +struct block_info { + int dirty; + int block_number; + struct block_info *next; + struct block_info *prev; + char data[BLOCKSIZE]; +}; + +struct block_wrap { + int key; + struct block_info* block_data; +}; +struct block_info* block_front; +struct block_info* block_rear; + +struct block_wrap* block_hashtable[SIZE]; +struct block_wrap* default_block_wrap; +struct block_info* default_block_info; +// struct block_wrap* item; + +int generate_hash_code(int key) { + //Hash code generator. + return key % SIZE; +} + +struct block_wrap *get_block(int key) { + //Obtains the hash code. + int hash_index = generate_hash_code(key); + + while(block_hashtable[hash_index] != NULL) { + + if(block_hashtable[hash_index]->key == key){ + return block_hashtable[hash_index]; + } + + ++hash_index; + + hash_index %= SIZE; + } + + return NULL; +} + +void put_block_to_hashtable(int key, struct block_info* data_input) { + + struct block_wrap *item = (struct block_wrap*) malloc(sizeof(struct block_wrap)); + item->block_data = data_input; + item->key = key; + + int hash_index = generate_hash_code(key); + + while(block_hashtable[hash_index] != NULL && block_hashtable[hash_index]->key != -1) { + ++hash_index; + + hash_index %= SIZE; + } + + block_hashtable[hash_index] = item; +} + +struct block_wrap* remove_block_from_hashtable(int block_num) { + + int hash_index = generate_hash_code(block_num); + + while(block_hashtable[hash_index] != NULL) { + + if(block_hashtable[hash_index]->key == block_num) { + struct block_wrap* temp = block_hashtable[hash_index]; + + block_hashtable[hash_index] = default_block_wrap; + + return temp; + } + + ++hash_index; + + hash_index %= SIZE; + } + + return NULL; +} + +void print_cache() { + int i = 0; + + for(i = 0; ikey,block_hashtable[i]->key); + else + printf(" ~~ "); + } + + printf("\n"); +} + + +void enqueue_block(struct block_info * x) { + //Puts to end. + if(block_front == NULL && block_rear == NULL){ + block_front = block_rear = x; + block_front->prev = NULL; + block_rear->next = NULL; + return; + } + block_rear->next = x; + x->prev = block_rear; + block_rear = x; + block_rear->next = NULL; +} + + +void dequeue_block() { + //Eliminate the block_front; + if(block_front == NULL) { + printf("Queue is Empty\n"); + return; + } + if(block_front == block_rear) { + block_front = block_rear = NULL; + }else { + block_front->next->prev = NULL; + block_front = block_front->next; + block_front->prev = NULL; + } + +} + +void remove_queue_block(struct block_info * x) { + if(x->prev != NULL && x->next != NULL){ + x->prev->next = x->next; + x->next->prev = x->prev; + }else if(x->prev != NULL && x->next == NULL) { + block_rear = block_rear->prev; + block_rear->next = NULL; + }else if(x->prev == NULL && x->next != NULL) { + dequeue_block(); + } +} + +void Print() { + struct block_info* temp = block_front; + while(temp != NULL) { + printf("%d\n",temp->block_number); + temp = temp->next; + } + free(temp); +} + + +void init() { + current_blockcache_number = 0; + block_front = NULL; + block_rear = NULL; + default_block_wrap = (struct block_wrap*) malloc(sizeof(struct block_wrap)); + default_block_wrap->key = -1; + + default_block_info = (struct block_info*) malloc(sizeof(struct block_info)); + default_block_info->block_number = -1; +} + +struct block_info* get_lru_block(int block_num) { + struct block_wrap* result = get_block(block_num); + if(result == NULL) { + return default_block_info; + }else{ + //Recently used. + remove_queue_block(result->block_data); + enqueue_block(result->block_data); + // put_to_block_front(result); + + return result->block_data; + } +} + +void evict_block(){ + //Test whether there is a key to be evict_blocked. + if(current_blockcache_number == BLOCK_CACHESIZE) { + int to_be_removed_key = block_front->block_number; + //Here should be another method sync to write inode back to the disk. + + + + + + // if(block_front->dirty == 1) { + // WriteSector(block_front->block_number, (void*)(block_front->data)); + // } + dequeue_block(); + remove_block_from_hashtable(to_be_removed_key); + //Decrement the current block cache number by 1. + current_blockcache_number--; + } +} + +void set_lru_block(int block_num, struct block_info* input_block) { + if(get_block(block_num) == NULL) { + // printf("Key not found\n"); + //Determines whether a key needs to be removed. + evict_block(); + enqueue_block(input_block); + put_block_to_hashtable(block_num, input_block); + current_blockcache_number++; + return; + }else{ + + remove_queue_block(get_block(block_num)->block_data); + enqueue_block(input_block); + put_block_to_hashtable(block_num, input_block); + + return; + } + +} + +void clear_lru_block() { + int i; + for (i = 0;i block_number = 1; + x1->dirty = 0; + + struct block_info *x2 = (struct block_info*) malloc(sizeof(struct block_info)); + x2->block_number = 2; + x2->dirty = 1; + struct block_info *x3 = (struct block_info*) malloc(sizeof(struct block_info)); + x3->block_number = 3; + x3->dirty = 1; + struct block_info *x4 = (struct block_info*) malloc(sizeof(struct block_info)); + x4->block_number = 4; + x4->dirty = 1; + struct block_info *x5 = (struct block_info*) malloc(sizeof(struct block_info)); + x5->block_number = 5; + + set_lru_block(1, x1); + set_lru_block(2, x2); + // set_lru_block(3, x3); + // set_lru_block(4, x4); + // set_lru_block(5, x5); + + // printf("%d\n", current_blockcache_number); + // print_cache(); + //Test case 0: + printf("----test case 0----\n"); + printf("%d\n", get_lru_block(1)->block_number); + set_lru_block(3, x3); + printf("%d\n", get_lru_block(2)->block_number); + set_lru_block(4, x4); + printf("%d\n", get_lru_block(1)->block_number); + printf("%d\n", get_lru_block(3)->block_number); + printf("%d\n", get_lru_block(4)->block_number); + // Print(); + + + //Test case 1: + printf("----test case 1----\n"); + enqueue_block(x1); + enqueue_block(x2); + enqueue_block(x3); + enqueue_block(x4); + enqueue_block(x5); + if(block_front->prev == NULL && block_rear->next == NULL) { + printf("There is nothing in block_front of the linked list and after the linked list.\n"); + } + //Prints the list. + Print(); + printf("----test case 2----\n"); + //Result should be 1, 2, 3, 4, 5 + + //Test case 2: + dequeue_block(); + if(block_front->prev == NULL && block_rear->next == NULL) { + printf("There is nothing in block_front of the linked list and after the linked list.\n"); + } + + Print(); + //Result should be 2, 3 + //Test case 3; + printf("----test case 3----\n"); + remove_queue_block(block_front); + if(block_front->prev == NULL && block_rear->next == NULL) { + printf("There is nothing in block_front of the linked list and after the linked list.\n"); + } + Print(); + //Result should be 3, 4, 5 + printf("----test case 4----\n"); + remove_queue_block(block_front); + if(block_front->prev == NULL && block_rear->next == NULL) { + printf("There is nothing in block_front of the linked list and after the linked list.\n"); + } + Print(); + + + printf("----test case 5----\n"); + remove_queue_block(block_rear); + if(block_front->prev == NULL && block_rear->next == NULL) { + printf("There is nothing in block_front of the linked list and after the linked list.\n"); + } + Print(); + + printf("----test case 6----\n"); + enqueue_block(x1); + enqueue_block(x2); + enqueue_block(x3); + remove_queue_block(block_front->next->next); + if(block_front->prev == NULL && block_rear->next == NULL) { + printf("There is nothing in block_front of the linked list and after the linked list.\n"); + } + Print(); + + clear_lru_block(); + printf("----test case 7----\n"); + set_lru_block(1, x1); + set_lru_block(2, x2); + printf("goodm\n"); + struct block_info* tmp = get_lru_block(1); + printf("%d\n", tmp->block_number); + printf("%d\n", tmp->dirty); + printf("-------------------\n"); + set_lru_block(1, x3); + Print(); + +} diff --git a/#yfs.c# b/#yfs.c# new file mode 100755 index 0000000..3695f28 --- /dev/null +++ b/#yfs.c# @@ -0,0 +1,1063 @@ +#include "yfs.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#define SIZE 100 +// #define BLOCKSIZE 32 +#define CACHESIZE 32 // Needs to be modified to another number. + +//Dirty = 1 means it is dirty +//Dirty = 0 means it is not dirty + +//Block variables: +int current_blockcache_number; +struct block_info { + int dirty; + int block_number; + struct block_info *next; + struct block_info *prev; + char data[BLOCKSIZE]; +}; + +struct block_wrap { + int key; + struct block_info* block_data; +}; + +struct block_info* block_front; +struct block_info* block_rear; + +struct block_wrap* block_hashtable[SIZE]; +struct block_wrap* default_block_wrap; +struct block_info* default_block_info; + +//Inode variable +int current_inodecache_number; + +struct inode_info { + int dirty; + int inode_number; + struct inode_info *next; + struct inode_info *prev; + struct inode *inode_val; //From the filesystem.h +}; + +struct inode_wrap { + int key; + struct inode_info* inode_data; +}; +struct inode_info* inode_front; +struct inode_info* inode_rear; + +struct inode_wrap* inode_hashtable[SIZE]; +struct inode_wrap* default_inode_wrap; +struct inode_info* default_inode_info; +//Declare +int calculate_inode_to_block_number(int inode_number) ; +struct block_info* read_block_from_disk(int block_num); +int sync(); + + +void init() { + current_blockcache_number = 0; + block_front = NULL; + block_rear = NULL; + default_block_wrap = (struct block_wrap*) malloc(sizeof(struct block_wrap)); + default_block_wrap->key = -1; + + default_block_info = (struct block_info*) malloc(sizeof(struct block_info)); + default_block_info->block_number = -1; + + + current_inodecache_number = 0; + inode_front = NULL; + inode_rear = NULL; + default_inode_wrap = (struct inode_wrap*) malloc(sizeof(struct inode_wrap)); + default_inode_wrap->key = -1; + + default_inode_info = (struct inode_info*) malloc(sizeof(struct inode_info)); + default_inode_info->inode_number = -1; +} + +int calculate_inode_to_block_number(int inode_number) { + return 1 + (inode_number / (BLOCKSIZE / INODESIZE)); +} + +int generate_hash_code(int key) { + //Hash code generator. + return key % SIZE; +} + +struct block_wrap *get_block(int key) { + //Obtains the hash code. + int hash_index = generate_hash_code(key); + + while(block_hashtable[hash_index] != NULL) { + + if(block_hashtable[hash_index]->key == key){ + return block_hashtable[hash_index]; + } + + ++hash_index; + + hash_index %= SIZE; + } + + return NULL; +} + +void put_block_to_hashtable(int key, struct block_info* data_input) { + + struct block_wrap *item = (struct block_wrap*) malloc(sizeof(struct block_wrap)); + item->block_data = data_input; + item->key = key; + + int hash_index = generate_hash_code(key); + + while(block_hashtable[hash_index] != NULL && block_hashtable[hash_index]->key != -1) { + ++hash_index; + + hash_index %= SIZE; + } + + block_hashtable[hash_index] = item; +} + +struct block_wrap* remove_block_from_hashtable(int block_num) { + + int hash_index = generate_hash_code(block_num); + + while(block_hashtable[hash_index] != NULL) { + + if(block_hashtable[hash_index]->key == block_num) { + struct block_wrap* temp = block_hashtable[hash_index]; + + block_hashtable[hash_index] = default_block_wrap; + + return temp; + } + + ++hash_index; + + hash_index %= SIZE; + } + + return NULL; +} + +void enqueue_block(struct block_info * x) { + //Puts to end. + if(block_front == NULL && block_rear == NULL){ + block_front = block_rear = x; + block_front->prev = NULL; + block_rear->next = NULL; + return; + } + block_rear->next = x; + x->prev = block_rear; + block_rear = x; + block_rear->next = NULL; +} + +void dequeue_block() { + //Eliminate the block_front; + if(block_front == NULL) { + printf("Queue is Empty\n"); + return; + } + if(block_front == block_rear) { + block_front = block_rear = NULL; + }else { + block_front->next->prev = NULL; + block_front = block_front->next; + block_front->prev = NULL; + } + +} + +void remove_queue_block(struct block_info * x) { + if(x->prev != NULL && x->next != NULL){ + x->prev->next = x->next; + x->next->prev = x->prev; + }else if(x->prev != NULL && x->next == NULL) { + block_rear = block_rear->prev; + block_rear->next = NULL; + }else if(x->prev == NULL && x->next != NULL) { + dequeue_block(); + } +} + +struct block_info* get_lru_block(int block_num) { + struct block_wrap* result = get_block(block_num); + if(result == NULL) { + return default_block_info; + }else{ + //Recently used. + remove_queue_block(result->block_data); + enqueue_block(result->block_data); + // put_to_block_front(result); + + return result->block_data; + } +} +int sync() { + //Write everything back to the disk. Syncs everything. + struct inode_info* tmp_inode = inode_front; + struct block_info* tmp_block = block_front; + + while(tmp_inode != NULL) { + int inode_number = tmp_inode->inode_number; + if(tmp_inode->dirty == 1) { + //The value is dirty. + int block_num_to_write = calculate_inode_to_block_number(inode_number); + struct block_info *tmp = read_block_from_disk(block_num_to_write); + memcpy((void*)(tmp->data + (inode_number - (BLOCKSIZE/INODESIZE) * (block_num_to_write - 1)) * INODESIZE), (void*)(&inode_front->inode_val), INODESIZE); + tmp->dirty = 1; + tmp_inode->dirty = 0; + } + tmp_inode = tmp_inode->next; + } + + while(tmp_block != NULL) { + if(tmp_block->dirty == 1) { + //The block is dirty, so write it back. + int sig = WriteSector(tmp_block->block_number, (void*)(tmp_block->data)); + if(sig == 0) { + tmp_block->dirty = 0; + + }else{ + printf("An error is generated when doing WriteSector.\n"); + return -1; + } + //Marks the current block to not dirty. + tmp_block->dirty = 0; + } + tmp_block = tmp_block->next; + } + return 0; +} + + +void evict_block(){ + //Test whether there is a key to be evict_blocked. + if(current_blockcache_number >= BLOCK_CACHESIZE) { + int to_be_removed_key = block_front->block_number; + //Here should be another method sync to write inode back to the disk. + sync(); + if(block_front->dirty == 1) { + int sig = WriteSector(block_front->block_number, (void*)(block_front->data)); + if(sig == 0) { + printf("An error is generated when doing WriteSector.\n"); + } + } + dequeue_block(); + remove_block_from_hashtable(to_be_removed_key); + //Decrement the current block cache number by 1. + current_blockcache_number--; + } +} + +void set_lru_block(int block_num, struct block_info* input_block) { + if(get_block(block_num) == NULL) { + // printf("Key not found\n"); + //Determines whether a key needs to be removed. + evict_block(); + enqueue_block(input_block); + put_block_to_hashtable(block_num, input_block); + current_blockcache_number++; + return; + }else{ + + remove_queue_block(get_block(block_num)->block_data); + enqueue_block(input_block); + put_block_to_hashtable(block_num, input_block); + + return; + } + +} + + +//Inode functions + +struct inode_wrap *get_inode(int key) { + //Obtains the hash code. + int hash_index = generate_hash_code(key); + + while(inode_hashtable[hash_index] != NULL) { + + if(inode_hashtable[hash_index]->key == key){ + return inode_hashtable[hash_index]; + } + + ++hash_index; + + hash_index %= SIZE; + } + + return NULL; +} + +void put_inode_to_hashtable(int key, struct inode_info* data_input) { + + struct inode_wrap *item = (struct inode_wrap*) malloc(sizeof(struct inode_wrap)); + item->inode_data = data_input; + item->key = key; + + int hash_index = generate_hash_code(key); + + while(inode_hashtable[hash_index] != NULL && inode_hashtable[hash_index]->key != -1) { + ++hash_index; + + hash_index %= SIZE; + } + + inode_hashtable[hash_index] = item; +} + +struct inode_wrap* remove_inode_from_hashtable(int inode_num) { + + int hash_index = generate_hash_code(inode_num); + + while(inode_hashtable[hash_index] != NULL) { + + if(inode_hashtable[hash_index]->key == inode_num) { + struct inode_wrap* temp = inode_hashtable[hash_index]; + + inode_hashtable[hash_index] = default_inode_wrap; + + return temp; + } + + ++hash_index; + + hash_index %= SIZE; + } + + return NULL; +} + +void enqueue_inode(struct inode_info * x) { + //Puts to end. + if(inode_front == NULL && inode_rear == NULL){ + inode_front = inode_rear = x; + inode_front->prev = NULL; + inode_rear->next = NULL; + return; + } + inode_rear->next = x; + x->prev = inode_rear; + inode_rear = x; + inode_rear->next = NULL; +} + + +void dequeue_inode() { + //Eliminate the inode_front; + if(inode_front == NULL) { + printf("Queue is Empty\n"); + return; + } + if(inode_front == inode_rear) { + inode_front = inode_rear = NULL; + }else { + inode_front->next->prev = NULL; + inode_front = inode_front->next; + inode_front->prev = NULL; + } + +} + +void remove_queue_inode(struct inode_info * x) { + if(x->prev != NULL && x->next != NULL){ + x->prev->next = x->next; + x->next->prev = x->prev; + }else if(x->prev != NULL && x->next == NULL) { + inode_rear = inode_rear->prev; + inode_rear->next = NULL; + }else if(x->prev == NULL && x->next != NULL) { + dequeue_inode(); + } +} + + +struct inode_info* get_lru_inode(int inode_num) { + struct inode_wrap* result = get_inode(inode_num); + if(result->key == -1) { + return default_inode_info; + }else{ + //Recently used. + remove_queue_inode(result->inode_data); + enqueue_inode(result->inode_data); + // put_to_inode_front(result); + + return result->inode_data; + } +} + +struct block_info* read_block_from_disk(int block_num) { + struct block_info* result = get_lru_block(block_num); + if(result->block_number == -1) { + //Reads from the disk. + result = (struct block_info*)malloc(sizeof(struct block_info)); + ReadSector(block_num, (void*)(result->data)); + //Sets the dirty to not dirty + result->dirty = 0; + set_lru_block(block_num, result); + //To obtain the block_info. + return get_lru_block(block_num); + + }else{ + return result; + } +} + +struct inode_info* read_inode_from_disk(int inode_num) { + struct inode_info* result = get_lru_inode(inode_num); + if(result->inode_number == -1) { + int block_num = calculate_inode_to_block_number(inode_num); + struct block_info* tmp = get_lru_block(block_num); + if(tmp->block_number == -1) { + tmp = read_block_from_disk(block_num); + + }else{ + //The block is in the cache. + + } + }else{ + return result; + } +} + + +void set_lru_inode(int inode_num, struct inode_info* input_inode) { + if(get_inode(inode_num) == NULL) { + //Determines whether a key needs to be removed. + + //evicts. + //Test whether there is a key to be evict_inodeed. + if(current_inodecache_number >= INODE_CACHESIZE) { + int to_be_removed_key = inode_front->inode_number; + //Here should be another method sync to write inode back to the disk. + + //Remove the key from the hashtable + remove_inode_from_hashtable(to_be_removed_key); + //Should call sync. + sync(); + + if(inode_front->dirty == 1) { + int block_num_to_write = calculate_inode_to_block_number(to_be_removed_key); + struct block_info *tmp = read_block_from_disk(block_num_to_write); + int index = inode_num - (BLOCKSIZE/INODESIZE) * (block_num_to_write - 1); + memcpy((void*)(tmp->data + index * INODESIZE), (void*)(&inode_front->inode_val), INODESIZE); + tmp->dirty = 1; + } + + dequeue_inode(); + remove_inode_from_hashtable(to_be_removed_key); + + + + //Decrement the current block cache number by 1. + current_inodecache_number--; + } + enqueue_inode(input_inode); + put_inode_to_hashtable(inode_num, input_inode); + current_inodecache_number++; + return; + }else{ + + + remove_queue_inode(get_inode(inode_num)->inode_data); + enqueue_inode(input_inode); + put_inode_to_hashtable(inode_num, input_inode); + return; + } +} + + +int convert_pathname_to_inode_number(char *pathname, int len_path, int proc_inum) { + if(pathname == NULL ) { + return 0; + } + int cur_inode = proc_inum; + if(len_path == 0) { + return cur_inode; + } + char node_name[DIRNAMELEN]; + memset(node_name,'\0',DIRNAMELEN); +} + +// allocate space for the file_inode to hold up to "newsize" data +int grow_file(struct inode* file_inode, int newsize){ + if(newsize < file_inode->size){ + // do we need to handle shrinking file as well?? + return 0; + } + + int current = file_inode->size; + + // fill up direct blocks first + if(current < BLOCKSIZE * NUM_DIRECT){ + while(current < BLOCKSIZE * NUM_DIRECT && current < newsize){ + // assign a new block in direct + } + } + + // if direct blocks not enough, then access indirect blocks + if(current < newsize){ + + } + + return 0; +} + +// returns a pointer to the data starting at "position" in the file described by "file_inode" +char* get_data_at_position(struct inode* file_inode, int position){ + return NULL; +} + +int add_directory_entry(short dir_inum, struct dir_entry new_entry){ + // parse directory for free entry slots + + struct inode_info* dir_info = read_inode_from_disk(dir_inum); + if(dir_info->inode_number == -1 || dir_info->inode_val->type != INODE_DIRECTORY){ + fprintf(stderr, "ERROR: not a valid directory inode number\n"); + } + int dir_size = dir_info->inode_val->size; + int position = 0; + struct dir_entry old_entry; + + // look for a blank entry in the middle of the directory first and overwrite with new entry + while(position < dir_size){ + FSRead(&old_entry, sizeof(old_entry), dir_inum, position); + if(old_entry.inum == 0){ + return FSWrite(&new_entry, sizeof(new_entry), dir_inum, position); + } + position += sizeof(old_entry); + } + + // if none available, write new entry at the end of the file + return FSWrite(&new_entry, sizeof(new_entry), dir_inum, position); +} + +int get_parent_inum(char* pathname){ + // parse backwards and look for last '/' + int i; + for(i = strlen(pathname) - 1; i >= 0; i--){ + if(pathname[i] == '/') + break; + } + if(i < 0) + return ERROR; + + // attempt to get inode of parent directory + int parent_path_len = i + 1; + char* parent_path = (char*)malloc(parent_path_len + 1); + memcpy(parent_path, pathname, parent_path_len); + parent_path[parent_path_len] = '\0'; + short parent_inum = convert_pathname_to_inode_number(parent_path, strlen(parent_path), 0); + free(parent_path); + + if(parent_inum == ERROR){ + fprintf(stderr, "ERROR: failed to obtain path to parent directory\n"); + return ERROR; + } + return parent_inum; +} + +// takes a pathname and returns a pointer to the name of the last file in the path +// note that the pointer points to a section of the original parameter +char* get_filename(char* pathname){ + int i; + for(i = strlen(pathname) - 1; i >= 0; i--){ + if(pathname[i] == '/'){ + return pathname + i + 1; + } + } + return NULL; +} + +// creates a new file under the given parent directory +int create_file(char* filename, short parent_inum, int type){ + short file_inum; + + // allocate new inode for file + int i; + for(i = 0; i < NUM_INODES; i++){ + if(free_inodes[i] == FREE){ + file_inum = i; + break; + } + } + + if(file_inum == NUM_INODES){ + fprintf(stderr, "ERROR: no more inodes left for new file\n"); + return ERROR; + } + + struct inode* file_inode = read_inode_from_disk(file_inum)->inode_val; + file_inode->type = type; + file_inode->nlink = 1; + file_inode->reuse++; + file_inode->size = 0; + + //TODO: correct way to rewrite inode to disk? + + // create and populate new directory entry + struct dir_entry entry; + entry.inum = file_inum; + int filename_len = strlen(filename); + if(filename_len > DIRNAMELEN) + filename_len = DIRNAMELEN; + memcpy(entry.name, filename, filename_len); + + if(!add_directory_entry(parent_inum, entry)){ + // undo prior process to create inode for thefile + free_inodes[file_inum] = FREE; + file_inode->type = INODE_FREE; + file_inode->nlink = 0; + file_inode->reuse--; + + fprintf(stderr, "ERROR: failed to add file to directory\n"); + return ERROR; + } + + return file_inum; +} + +void init_free(){ + + // TODO: can read_inode_from_disk handle fs_header like this? + struct inode_info* i_info = read_inode_from_disk(0); + struct fs_header* header = (struct fs_header*)(i_info->inode_val); + + NUM_INODES = header->num_inodes; + NUM_BLOCKS = header->num_blocks; + + free_inodes = (short*)malloc(NUM_INODES * sizeof(short)); + free_blocks = (short*)malloc(NUM_BLOCKS * sizeof(short)); + + free_inodes[0] = TAKEN; // fs_header inode is also taken + free_blocks[0] = TAKEN; // boot block is taken + + int i; + // loop through all inodes + for(i = 1; i < NUM_INODES; i++){ + struct inode* current_inode = read_inode_from_disk(i)->inode_val; + if(current_inode->type == INODE_FREE){ + free_blocks[i] = TAKEN; + + int j = 0; + // loop through direct blocks + while(j < NUM_DIRECT && j * BLOCKSIZE < current_inode->size){ + free_blocks[current_inode->direct[j]] = TAKEN; + j++; + } + + // if file still has more blocks, explore indirect block as well + if(j * BLOCKSIZE < current_inode->size){ + int* indirect_block = (int*)(read_block_from_disk(current_inode->indirect)->data); + while(j * BLOCKSIZE < current_inode->size){ + free_blocks[indirect_block[j - NUM_DIRECT]] = TAKEN; + j++; + } + } + } + } +} + +int FSOpen(char *pathname, short current_dir){ + return convert_pathname_to_inode_number(pathname, strlen(pathname), 0); +} + +int FSCreate(char *pathname, short current_dir){ + short parent_inum = get_parent_inum(pathname); + char* filename = get_filename(pathname); + return create_file(filename, parent_inum, INODE_REGULAR); +} + +int FSRead(void *buf, int size, short inode, int position){ + struct inode_info* info = read_inode_from_disk(inode); + if(info->inode_number == -1){ + fprintf(stderr, "ERROR: not a valid inode number\n"); + return ERROR; + } + struct inode* file_inode = info->inode_val; + + int offset = 0; + // keep reading while buf is not full and we have not reached the end of the file + while(offset < size || position + offset < file_inode->size){ + char* data = get_data_at_position(file_inode, position + offset); + + // readable size is min of space left in current block and size left in buffer + int readable_size = BLOCKSIZE; + if((position + offset) % BLOCKSIZE != 0) + readable_size = (position + offset) % BLOCKSIZE; + if(size - offset < readable_size) + readable_size = size - offset; + if(file_inode->size - (position + offset) < readable_size) + readable_size = file_inode->size - (position + offset); + + memcpy(buf + offset, data, readable_size); + offset += readable_size; + } + + return 0; +} + +int FSWrite(void *buf, int size, short inode, int position){ + struct inode_info* info = read_inode_from_disk(inode); + if(info->inode_number == -1){ + fprintf(stderr, "ERROR: not a valid inode number\n"); + return ERROR; + } + struct inode* file_inode = info->inode_val; + + // if writing past the size of the current file then we need to expand it first + if(grow_file(file_inode, position + size) == ERROR){ + printf("ERROR: failed to grow file in write operation\n"); + return ERROR; + } + + int offset = 0; + // write over existing data first + while(offset < size || position + offset < file_inode->size){ + char* data = get_data_at_position(file_inode, position + offset); + + // writeable size is min of blocksize, space left in buf, and space left in file + int writeable_size = BLOCKSIZE; + if((position + offset) % BLOCKSIZE != 0) + writeable_size = (position + offset) % BLOCKSIZE; + if(size - offset < writeable_size) + writeable_size = size - offset; + + memcpy(data, buf + offset, writeable_size); + offset += writeable_size; + } + + return 0; +} + +// This just returns the size of a given file... it's only necessary for a particular case of +// seek in the iolib +int FSSeek(short inode){ + struct inode_info* info = read_inode_from_disk(inode); + if(info->inode_number == -1){ + fprintf(stderr, "ERROR: not a valid inode number\n"); + return ERROR; + } + return info->inode_val->size; +} + +int FSLink(char *oldname, char *newname, short current_dir){ + return 0; +} + +int FSUnlink(char *pathname, short current_dir){ + return 0; +} + +int FSSymLink(char *oldname, char *newname, short current_dir){ + short parent_inum = get_parent_inum(newname); + char* filename = get_filename(newname); + short inum = create_file(filename, parent_inum, INODE_SYMLINK); + if(inum == ERROR) + return ERROR; + + int result = FSWrite((void*)oldname, strlen(oldname), inum, 0); + return result; +} + +int FSReadLink(char *pathname, char *buf, int len, short current_dir){ + return 0; +} + +int FSMkDir(char *pathname, short current_dir){ + + short parent_inum = get_parent_inum(pathname); + char* filename = get_filename(pathname); + short inum = create_file(filename, parent_inum, INODE_REGULAR); + if(inum == ERROR) + return ERROR; + + struct dir_entry dot; + struct dir_entry dotdot; + + char* strdot = "."; + memcpy(dot.name, strdot, strlen(strdot)); + dot.name[strlen(strdot)] = '\0'; + dot.inum = inum; + + char* strdotdot = ".."; + memcpy(dotdot.name, strdotdot, strlen(strdotdot)); + dotdot.name[strlen(strdotdot)] = '\0'; + dotdot.inum = parent_inum; + + add_directory_entry(inum, dot); + add_directory_entry(inum, dotdot); + + return 0; +} + +int FSRmDir(char *pathname, short current_dir){ + return 0; +} + +int FSChDir(char *pathname, short current_dir){ + return 0; +} + +int FSStat(char *pathname, struct Stat* statbuf, short current_dir){ + return 0; +} + +int FSSync(void){ + return 0; +} + +int FSShutdown(void){ + return 0; +} + +int Redirect_Call(char* msg, int pid){ +#pragma GCC diagnostic push /*ignore unavoidable gcc warning caused by unconventional casting */ +#pragma GCC diagnostic ignored "-Wint-to-pointer-cast" + + char* current = msg; + uint8_t code = (uint8_t)(msg[0]); + int result; + + switch(code){ + case CODE_OPEN:{ + char* upathname; int upathname_size; short ucurrent_dir; + memcpy(&upathname, current += sizeof(code), sizeof(upathname)); + memcpy(&upathname_size, current += sizeof(upathname), sizeof(upathname_size)); + memcpy(&ucurrent_dir, current += sizeof(upathname_size), sizeof(ucurrent_dir)); + + char* pathname = (char*)malloc(upathname_size + 1); + CopyFrom(pid, pathname, upathname, upathname_size + 1); + result = FSOpen(pathname, ucurrent_dir); + free(pathname); + break; + } + case CODE_CREATE:{ + char* upathname; int upathname_size; short ucurrent_dir; + memcpy(&upathname, current += sizeof(code), sizeof(upathname)); + memcpy(&upathname_size, current += sizeof(upathname), sizeof(upathname_size)); + memcpy(&ucurrent_dir, current += sizeof(upathname_size), sizeof(ucurrent_dir)); + + char* pathname = (char*)malloc(upathname_size + 1); + CopyFrom(pid, pathname, upathname, upathname_size + 1); + result = FSCreate(pathname, ucurrent_dir); + free(pathname); + break; + } + case CODE_READ:{ + char* ubuf; int usize; short uinode; int uposition; + memcpy(&ubuf, current += sizeof(code), sizeof(ubuf)); + memcpy(&usize, current += sizeof(ubuf), sizeof(usize)); + memcpy(&uinode, current += sizeof(usize), sizeof(uinode)); + memcpy(&uposition, current += sizeof(uinode), sizeof(uposition)); + + char* buf = malloc(usize + 1); + result = FSRead(buf, usize, uinode, uposition); + CopyTo(pid, ubuf, buf, usize + 1); + free(buf); + break; + } + case CODE_WRITE:{ + char* ubuf; int usize; short uinode; int uposition; + memcpy(&ubuf, current += sizeof(code), sizeof(ubuf)); + memcpy(&usize, current += sizeof(ubuf), sizeof(usize)); + memcpy(&uinode, current += sizeof(usize), sizeof(uinode)); + memcpy(&uposition, current += sizeof(uinode), sizeof(uposition)); + + char* buf = malloc(usize + 1); + CopyFrom(pid, buf, ubuf, usize + 1); + result = FSWrite(buf, usize, uinode, uposition); + free(buf); + break; + } + case CODE_SEEK:{ + short inode; + memcpy(&inode, current += sizeof(code), sizeof(inode)); + result = FSSeek(inode); + break; + } + case CODE_LINK:{ + char* uoldname; int uoldname_size; char* unewname; int unewname_size; + short ucurrent_dir; + memcpy(&uoldname, current += sizeof(code), sizeof(uoldname)); + memcpy(&uoldname_size, current += sizeof(uoldname), sizeof(uoldname_size)); + memcpy(&unewname, current += sizeof(unewname_size), sizeof(unewname)); + memcpy(&unewname_size, current += sizeof(unewname), sizeof(unewname_size)); + memcpy(&ucurrent_dir, current += sizeof(unewname_size), sizeof(ucurrent_dir)); + + char* oldname = malloc(uoldname_size + 1); + char* newname = malloc(unewname_size + 1); + CopyFrom(pid, oldname, uoldname, uoldname_size + 1); + CopyFrom(pid, newname, unewname, unewname_size + 1); + result = FSLink(oldname, newname, ucurrent_dir); + break; + } + case CODE_UNLINK:{ + char* upathname; int upathname_size; short ucurrent_dir; + memcpy(&upathname, current += sizeof(code), sizeof(upathname)); + memcpy(&upathname_size, current += sizeof(upathname), sizeof(upathname_size)); + memcpy(&ucurrent_dir, current += sizeof(upathname_size), sizeof(ucurrent_dir)); + + char* pathname = (char*)malloc(upathname_size + 1); + CopyFrom(pid, pathname, upathname, upathname_size + 1); + result = FSUnlink(pathname, ucurrent_dir); + free(pathname); + break; + } + case CODE_SYMLINK:{ + char* uoldname; int uoldname_size; char* unewname; int unewname_size; + short ucurrent_dir; + memcpy(&uoldname, current += sizeof(code), sizeof(uoldname)); + memcpy(&uoldname_size, current += sizeof(uoldname), sizeof(uoldname_size)); + memcpy(&unewname, current += sizeof(unewname_size), sizeof(unewname)); + memcpy(&unewname_size, current += sizeof(unewname), sizeof(unewname_size)); + memcpy(&ucurrent_dir, current += sizeof(unewname_size), sizeof(ucurrent_dir)); + + char* oldname = malloc(uoldname_size + 1); + char* newname = malloc(unewname_size + 1); + CopyFrom(pid, oldname, uoldname, uoldname_size + 1); + CopyFrom(pid, newname, unewname, unewname_size + 1); + result = FSSymLink(oldname, newname, ucurrent_dir); + break; + } + case CODE_READLINK:{ + char* upathname; int upathname_size; char* ubuf; int ulen; short ucurrent_dir; + memcpy(&upathname, current += sizeof(code), sizeof(upathname)); + memcpy(&upathname_size, current += sizeof(upathname), sizeof(upathname_size)); + memcpy(&ubuf, current += sizeof(upathname_size), sizeof(ubuf)); + memcpy(&ulen, current += sizeof(ubuf), sizeof(ulen)); + memcpy(&ucurrent_dir, current += sizeof(ulen), sizeof(ucurrent_dir)); + + char* pathname = malloc(upathname_size + 1); + char* buf = malloc(ulen + 1); + CopyFrom(pid, pathname, upathname, upathname_size + 1); + result = FSReadLink(pathname, buf, ulen, ucurrent_dir); + CopyTo(pid, ubuf, buf, ulen + 1); + free(pathname); + free(buf); + break; + } + case CODE_MKDIR:{ + char* upathname; int upathname_size; short ucurrent_dir; + memcpy(&upathname, current += sizeof(code), sizeof(upathname)); + memcpy(&upathname_size, current += sizeof(upathname), sizeof(upathname_size)); + memcpy(&ucurrent_dir, current += sizeof(upathname_size), sizeof(ucurrent_dir)); + + char* pathname = (char*)malloc(upathname_size + 1); + CopyFrom(pid, pathname, upathname, upathname_size + 1); + result = FSMkDir(pathname, ucurrent_dir); + free(pathname); + break; + } + case CODE_RMDIR:{ + char* upathname; int upathname_size; short ucurrent_dir; + memcpy(&upathname, current += sizeof(code), sizeof(upathname)); + memcpy(&upathname_size, current += sizeof(upathname), sizeof(upathname_size)); + memcpy(&ucurrent_dir, current += sizeof(upathname_size), sizeof(ucurrent_dir)); + + char* pathname = (char*)malloc(upathname_size + 1); + CopyFrom(pid, pathname, upathname, upathname_size + 1); + result = FSRmDir(pathname, ucurrent_dir); + free(pathname); + break; + } + case CODE_CHDIR:{ + char* upathname; int upathname_size; short ucurrent_dir; + memcpy(&upathname, current += sizeof(code), sizeof(upathname)); + memcpy(&upathname_size, current += sizeof(upathname), sizeof(upathname_size)); + memcpy(&ucurrent_dir, current += sizeof(upathname_size), sizeof(ucurrent_dir)); + + char* pathname = (char*)malloc(upathname_size + 1); + CopyFrom(pid, pathname, upathname, upathname_size + 1); + result = FSChDir(pathname, ucurrent_dir); + free(pathname); + break; + } + case CODE_STAT:{ + char* upathname; int upathname_size; struct Stat* ustatbuf; short ucurrent_dir; + memcpy(&upathname, current += sizeof(code), sizeof(upathname)); + memcpy(&upathname_size, current += sizeof(upathname), sizeof(upathname_size)); + memcpy(&ustatbuf, current += sizeof(upathname_size), sizeof(ustatbuf)); + memcpy(&ucurrent_dir, current += sizeof(ustatbuf), sizeof(ucurrent_dir)); + + char* pathname = (char*)malloc(upathname_size + 1); + struct Stat* statbuf = (struct Stat*)malloc(sizeof(struct Stat)); + CopyFrom(pid, pathname, upathname, upathname_size + 1); + result = FSStat(pathname, statbuf, ucurrent_dir); + CopyTo(pid, ustatbuf, statbuf, sizeof(statbuf)); + free(pathname); + free(statbuf); + break; + } + case CODE_SYNC:{ + result = FSSync(); + break; + } + case CODE_SHUTDOWN:{ + result = FSShutdown(); + break; + } + default:{ + result = ERROR; + } + + } + return result; +#pragma GCC diagnostic pop /*pop -Wint-to-pointer-cast ignore warning*/ +} + +int main(int argc, char** argv){ + + int pid = Fork(); + if(pid == 0){ + Exec(argv[1], argv + 1); + } + + Register(FILE_SERVER); + init(); + init_free(); + + // stand by and simply route messages from here on out + while(1){ + char msg[MESSAGE_SIZE]; + int pid = Receive(msg); + if(pid == -1){ + fprintf(stderr, "Receive() returned error\n"); + continue; + } + if(pid == 0){ + fprintf(stderr, "Recieve() returned 0 to avoid deadlock\n"); + continue; + } + + int result = Redirect_Call(msg, pid); + + // clean msg + int i; + for(i = 0; i < MESSAGE_SIZE; i++){ + msg[i] = '\0'; + } + + // copy in result and reply + memcpy(msg, &result, sizeof(result)); + Reply(msg, pid); + } + + return 0; +} diff --git a/DISK b/DISK new file mode 100755 index 0000000..4a7a554 Binary files /dev/null and b/DISK differ diff --git a/Makefile b/Makefile new file mode 100755 index 0000000..82235bf --- /dev/null +++ b/Makefile @@ -0,0 +1,90 @@ +# +# Sample Makefile for COMP 421 YFS and user programs. +# +# The YFS server built will be named "yfs". *ALL* Makefiles +# for this lab must have a "yfs" rule in them, and must +# produce a YFS server executable named "yfs" -- we will run +# your Makefile and will grade the resulting executable +# named "yfs". Likewise, *ALL* Makefiles must have a rule +# named "iolib.a" to make your YFS library. +# +# Define the list of everything to be made by this Makefile. +# The list should include "yfs" (the name of your server) and +# "iolib.a" (the name of your library), plus the list of user +# test programs you also want to be made by this Makefile. +# For example, the definition below specifies to make Yalnix +# test user programs test1, test2, and test3, all of which will +# be linked with your library to enable them to use your +# server. You should modify this list to the list of your +# own test programs. +# +# For each user test program, the Makefile will make the +# program out of a single correspondingly named source file. +# In addition to this single source file for each test +# program, each program will also be linked with your library. +# For example, the Makefile will make test1 out of test1.c, +# if you have a file named test1.c in this directory. +# + +ALL = yfs iolib.a + +# +# You must modify the YFS_OBJS and YFS_SRCS definitions below. +# YFS_OBJS should be a list of the .o files that make up your +# YFS server, and YFS_SRCS should be a list of the corresponding +# source files that make up your serever. +# +YFS_OBJS = yfs.o cache.o +YFS_SRCS = yfs.c cache.c + +# +# You must also modify the IOLIB_OBJS and IOLIB_SRCS definitions +# below. IOLIB_OBJS should be a list of the .o files that make up +# your YFS library, and IOLIB_SRCS should be a list of the +# corresponding source files that make up your library. +# +IOLIB_OBJS = iolib.o +IOLIB_SRCS = iolib.c + +# +# You should not have to modify anything else in this Makefile +# below here. If you want to, however, you may modify things +# such as the definition of CFLAGS, for example. +# + +LANG = gcc + +PUBLIC_DIR = /clear/courses/comp421/pub + +CPPFLAGS = -I$(PUBLIC_DIR)/include +CFLAGS = -g -Wall + +%: %.o + $(LINK.o) -o $@ $^ iolib.a $(LOADLIBES) $(LDLIBS) + +LINK.o = $(PUBLIC_DIR)/bin/link-user-$(LANG) $(LDFLAGS) $(TARGET_ARCH) + +%: %.c +%: %.cc +%: %.cpp + +all: $(ALL) + +yfs: $(YFS_OBJS) + $(LINK.o) -o $@ $^ $(PUBLIC_DIR)/lib/print-yfs.o $(LOADLIBES) $(LDLIBS) + +iolib.a: $(IOLIB_OBJS) + rm -f $@ + ar rv $@ $(IOLIB_OBJS) + ranlib $@ + +mkyfs: mkyfs.c + $(CC) $(CPPFLAGS) -o mkyfs mkyfs.c + +clean: + rm -f $(YFS_OBJS) $(IOLIB_OBJS) $(ALL) + +depend: + $(CC) $(CPPFLAGS) -M $(YFS_SRCS) $(IOLIB_SRCS) > .depend + +#include .depend diff --git a/README b/README new file mode 100755 index 0000000..cd00adf --- /dev/null +++ b/README @@ -0,0 +1,15 @@ +td18 Thien-Nam Dinh +zh7 Ziqi Hong + +---------------------------------------------------------------------------- + +- All the test we used are the folder "tests" + - not linked to the make file +- We built our own cache rather than import one + - all related methods are in "cache.c" + - separate structures/methods for inode and block +- Free blocks/inodes are kept in an array of ints and booted at startup + +- Everything *should* be functional + +---------------------------------------------------------------------------- \ No newline at end of file diff --git a/README.md b/README.md new file mode 100755 index 0000000..5bb920b --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# yalnix_FS +Lab3: Yalnix File System diff --git a/README~ b/README~ new file mode 100755 index 0000000..9b07b70 --- /dev/null +++ b/README~ @@ -0,0 +1,9 @@ +td18 Thien-Nam Dinh +zh7 Ziqi Hong + +-------------------------------------------------------------------- + +- All the test we used are the folder "tests" + - not linked to the make file +- We built our own cache; all related methods are in "cache.c" +- Everything *should* be working \ No newline at end of file diff --git a/TRACE b/TRACE new file mode 100755 index 0000000..e69de29 diff --git a/TTYLOG b/TTYLOG new file mode 100755 index 0000000..e69de29 diff --git a/TTYLOG.0 b/TTYLOG.0 new file mode 100755 index 0000000..e69de29 diff --git a/TTYLOG.1 b/TTYLOG.1 new file mode 100755 index 0000000..e69de29 diff --git a/TTYLOG.2 b/TTYLOG.2 new file mode 100755 index 0000000..e69de29 diff --git a/TTYLOG.3 b/TTYLOG.3 new file mode 100755 index 0000000..e69de29 diff --git a/a.out b/a.out new file mode 100755 index 0000000..3e6d8c2 Binary files /dev/null and b/a.out differ diff --git a/cache.c b/cache.c new file mode 100755 index 0000000..38cfb3a --- /dev/null +++ b/cache.c @@ -0,0 +1,501 @@ +#include "yfs.h" + +void Print() { + + printf("\n---- Inode hashmap -----\n"); + int i = 0; + for(i = 0; i < INODE_CACHESIZE; i++){ + struct inode_wrap* elm = inode_hashtable[i]; + if(inode_hashtable[i] != NULL) + printf("Index %d - Key: %d, Pointer: %ld\n", i, elm->key, (long)elm->inode_data); + } + printf("\n---- Inode linked list -----\n"); + struct inode_info* temp1 = inode_front; + while(temp1 != NULL) { + printf("Inode Number: %d Pointer: %ld\n", temp1->inode_number, (long)temp1); + temp1 = temp1->next; + } + printf("\n"); + + + printf("\n---- Block hashmap -----\n"); + for(i = 0; i < BLOCK_CACHESIZE; i++){ + struct block_wrap* elm = block_hashtable[i]; + if(block_hashtable[i] != NULL) + printf("Index %d - Key: %d, Pointer: %ld Dirty? %d\n", i, elm->key, + (long)elm->block_data, elm->block_data->dirty); + } + printf("\n---- Block linked list -----\n"); + struct block_info* temp2 = block_front; + while(temp2 != NULL) { + printf("Block Number: %d Pointer: %ld Dirty? %d\n", temp2->block_number, (long)temp2, + temp2->dirty); + temp2 = temp2->next; + } + printf("\n"); +} + +void init() { + current_blockcache_number = 0; + block_front = NULL; + block_rear = NULL; + default_block_wrap = (struct block_wrap*) malloc(sizeof(struct block_wrap)); + default_block_wrap->key = -1; + + default_block_info = (struct block_info*) malloc(sizeof(struct block_info)); + default_block_info->block_number = -1; + + current_inodecache_number = 0; + inode_front = NULL; + inode_rear = NULL; + default_inode_wrap = (struct inode_wrap*) malloc(sizeof(struct inode_wrap)); + default_inode_wrap->key = -1; + + default_inode_info = (struct inode_info*) malloc(sizeof(struct inode_info)); + default_inode_info->inode_number = -1; + + default_inode_wrap->inode_data = default_inode_info; + + //adding for loop to initialize to null + int i; + for(i = 0; i < INODE_CACHESIZE; i++){ + inode_hashtable[i] = NULL; + } + for(i = 0; i < BLOCK_CACHESIZE; i++){ + block_hashtable[i] = NULL; + } +} + +int calculate_inode_to_block_number(int inode_number) { + return 1 + (inode_number / (BLOCKSIZE / INODESIZE)); +} + +int generate_hash_code_inode(int key) { + //Hash code generator. + return key % INODE_CACHESIZE; +} + +int generate_hash_code_block(int key) { + //Hash code generator. + return key % BLOCK_CACHESIZE; +} + +struct block_wrap *get_block(int key) { + //Obtains the hash code. + int hash_index = generate_hash_code_block(key); + int start = hash_index; + + while(block_hashtable[hash_index] != NULL) { + if(block_hashtable[hash_index]->key == key){ + return block_hashtable[hash_index]; + } + + ++hash_index; + + hash_index %= BLOCK_CACHESIZE; + + // made a full circle without finding an opening + if(hash_index == start) + return NULL; + } + + return NULL; +} + +void put_block_to_hashtable(int key, struct block_info* data_input) { + + struct block_wrap *item = (struct block_wrap*) malloc(sizeof(struct block_wrap)); + item->block_data = data_input; + item->key = key; + + int hash_index = generate_hash_code_block(key); + + while(block_hashtable[hash_index] != NULL && block_hashtable[hash_index]->key != -1) { + ++hash_index; + + hash_index %= BLOCK_CACHESIZE; + } + + block_hashtable[hash_index] = item; +} + +struct block_wrap* remove_block_from_hashtable(int block_num) { + + int hash_index = generate_hash_code_block(block_num); + int start = hash_index; + + while(block_hashtable[hash_index] != NULL) { + + if(block_hashtable[hash_index]->key == block_num) { + struct block_wrap* temp = block_hashtable[hash_index]; + + block_hashtable[hash_index] = default_block_wrap; + + return temp; + } + + ++hash_index; + + hash_index %= BLOCK_CACHESIZE; + + // made full circule without finding opening + if(hash_index == start) + return NULL; + } + + return NULL; +} + +void enqueue_block(struct block_info * x) { + //Puts to end. + if(block_front == NULL && block_rear == NULL){ + block_front = block_rear = x; + block_front->prev = NULL; + block_rear->next = NULL; + return; + } + block_rear->next = x; + x->prev = block_rear; + block_rear = x; + block_rear->next = NULL; + block_front->prev = NULL; +} + +void dequeue_block() { + //Eliminate the block_front; + if(block_front == NULL) { + printf("Queue is Empty\n"); + return; + } + if(block_front == block_rear) { + block_front = block_rear = NULL; + }else { + block_front->next->prev = NULL; + block_front = block_front->next; + block_front->prev = NULL; + } + +} + +void remove_queue_block(struct block_info * x) { + if(x->prev != NULL && x->next != NULL){ + x->prev->next = x->next; + x->next->prev = x->prev; + x->prev = NULL; + x->next = NULL; + }else if(x->prev != NULL && x->next == NULL) { + block_rear = block_rear->prev; + block_rear->next = NULL; + x->prev = NULL; + x->next = NULL; + }else if(x->prev == NULL && x->next != NULL) { + dequeue_block(); + x->prev = NULL; + x->next = NULL; + } +} + + +struct block_info* get_lru_block(int block_num) { + struct block_wrap* result = get_block(block_num); + if(result == NULL) { + return default_block_info; + }else{ + //Recently used. + remove_queue_block(result->block_data); + enqueue_block(result->block_data); + // put_to_block_front(result); + + return result->block_data; + } +} + +int sync() { + //Write everything back to the disk. Syncs everything. + struct inode_info* tmp_inode = inode_front; + struct block_info* tmp_block = block_front; + + while(tmp_inode != NULL) { + int inode_number = tmp_inode->inode_number; + if(tmp_inode->dirty == 1) { + //The value is dirty. + int block_num_to_write = calculate_inode_to_block_number(inode_number); + struct block_info *tmp = read_block_from_disk(block_num_to_write); + memcpy((void*)(tmp->data + (inode_number - (BLOCKSIZE/INODESIZE) * (block_num_to_write - 1)) * INODESIZE), (void*)(tmp_inode->inode_val), INODESIZE); + tmp->dirty = 1; + tmp_inode->dirty = 0; + } + tmp_inode = tmp_inode->next; + } + + while(tmp_block != NULL) { + if(tmp_block->dirty == 1) { + //The block is dirty, so write it back. + int sig = WriteSector(tmp_block->block_number, (void*)(tmp_block->data)); + if(sig == 0) { + tmp_block->dirty = 0; + + }else{ + printf("ERROR: WriteSector call failed.\n"); + return ERROR; + } + //Marks the current block to not dirty. + tmp_block->dirty = 0; + } + tmp_block = tmp_block->next; + } + return 0; +} + + +void evict_block(){ + //Test whether there is a key to be evict_blocked. + if(current_blockcache_number >= BLOCK_CACHESIZE) { + int to_be_removed_key = block_front->block_number; + //Here should be another method sync to write inode back to the disk. + sync(); + if(block_front->dirty == 1) { + int sig = WriteSector(block_front->block_number, (void*)(block_front->data)); + if(sig == 0) { + printf("An error is generated when doing WriteSector.\n"); + } + } + dequeue_block(); + remove_block_from_hashtable(to_be_removed_key); + //Decrement the current block cache number by 1. + current_blockcache_number--; + } +} + +void set_lru_block(int block_num, struct block_info* input_block) { + if(get_block(block_num) == NULL) { + // printf("Key not found\n"); + //Determines whether a key needs to be removed. + evict_block(); + enqueue_block(input_block); + put_block_to_hashtable(block_num, input_block); + current_blockcache_number++; + return; + }else{ + + remove_queue_block(get_block(block_num)->block_data); + enqueue_block(input_block); + put_block_to_hashtable(block_num, input_block); + + return; + } + +} + + +//Inode functions + +struct inode_wrap *get_inode(int key) { + //Obtains the hash code. + int hash_index = generate_hash_code_inode(key); + int start = hash_index; + while(inode_hashtable[hash_index] != NULL) { + if(inode_hashtable[hash_index]->key == key){ + return inode_hashtable[hash_index]; + } + + ++hash_index; + + hash_index %= INODE_CACHESIZE; + + //made a full circle but couldn't find an opening + if(hash_index == start) + return NULL; + } + + return NULL; +} + +void put_inode_to_hashtable(int key, struct inode_info* data_input) { + + struct inode_wrap *item = (struct inode_wrap*) malloc(sizeof(struct inode_wrap)); + item->inode_data = data_input; + item->key = key; + + int hash_index = generate_hash_code_inode(key); + + while(inode_hashtable[hash_index] != NULL && inode_hashtable[hash_index]->key != -1) { + ++hash_index; + + hash_index %= INODE_CACHESIZE; + } + + inode_hashtable[hash_index] = item; +} + +struct inode_wrap* remove_inode_from_hashtable(int inode_num) { + + int hash_index = generate_hash_code_inode(inode_num); + int start = hash_index; + + while(inode_hashtable[hash_index] != NULL) { + if(inode_hashtable[hash_index]->key == inode_num) { + struct inode_wrap* temp = inode_hashtable[hash_index]; + + inode_hashtable[hash_index] = default_inode_wrap; + + return temp; + } + + ++hash_index; + + hash_index %= INODE_CACHESIZE; + + // made full circle without finding an opening + if(hash_index == start) + return NULL; + } + + return NULL; +} + +void enqueue_inode(struct inode_info * x) { + //Puts to end. + if(inode_front == NULL && inode_rear == NULL){ + inode_front = inode_rear = x; + inode_front->prev = NULL; + inode_rear->next = NULL; + return; + } + inode_rear->next = x; + x->prev = inode_rear; + inode_rear = x; + inode_rear->next = NULL; +} + + +void dequeue_inode() { + //Eliminate the inode_front; + if(inode_front == NULL) { + printf("Queue is Empty\n"); + return; + } + if(inode_front == inode_rear) { + inode_front = inode_rear = NULL; + }else { + inode_front->next->prev = NULL; + inode_front = inode_front->next; + inode_front->prev = NULL; + } + +} + +void remove_queue_inode(struct inode_info * x) { + if(x->prev != NULL && x->next != NULL){ + x->prev->next = x->next; + x->next->prev = x->prev; + x->next = NULL; + x->prev = NULL; + }else if(x->prev != NULL && x->next == NULL) { + inode_rear = inode_rear->prev; + inode_rear->next = NULL; + x->next = NULL; + x->prev = NULL; + }else if(x->prev == NULL && x->next != NULL) { + dequeue_inode(); + x->next = NULL; + x->prev = NULL; + } +} + + +struct inode_info* get_lru_inode(int inode_num) { + struct inode_wrap* result = get_inode(inode_num); + if(result == NULL) { + return default_inode_info; + }else{ + //Recently used. + remove_queue_inode(result->inode_data); + enqueue_inode(result->inode_data); + // put_to_inode_front(result); + + return result->inode_data; + } +} + +struct block_info* read_block_from_disk(int block_num) { + struct block_info* result = get_lru_block(block_num); + if(result->block_number == -1) { + //Reads from the disk. + result = (struct block_info*)malloc(sizeof(struct block_info)); + ReadSector(block_num, (void*)(result->data)); + //Sets the dirty to not dirty + result->dirty = 0; + result->block_number = block_num; + set_lru_block(block_num, result); + //To obtain the block_info. + return get_lru_block(block_num); + + }else{ + return result; + } +} + +struct inode_info* read_inode_from_disk(int inode_num) { + struct inode_info* result = get_lru_inode(inode_num); + if(result->inode_number == -1) { + int block_num = calculate_inode_to_block_number(inode_num); + struct block_info* tmp = get_lru_block(block_num); + if(tmp->block_number == -1) { + tmp = read_block_from_disk(block_num); + } + result = (struct inode_info*) malloc(sizeof(struct inode_info)); + result->inode_number = inode_num; + result->dirty = 0; + result->inode_val = (struct inode*)malloc(sizeof(struct inode)); + + memcpy((result->inode_val), tmp->data+(inode_num-(block_num-1)*(BLOCKSIZE/INODESIZE)) * INODESIZE, INODESIZE); + set_lru_inode(inode_num, result); + } + return result; +} + + +void set_lru_inode(int inode_num, struct inode_info* input_inode) { + if(get_inode(inode_num) == NULL) { + //Determines whether a key needs to be removed. + + //evicts. + //Test whether there is a key to be evict_inodeed. + if(current_inodecache_number >= INODE_CACHESIZE) { + int to_be_removed_key = inode_front->inode_number; + //Here should be another method sync to write inode back to the disk. + + //Remove the key from the hashtable + remove_inode_from_hashtable(to_be_removed_key); + //Should call sync. + sync(); + + if(inode_front->dirty == 1) { + int block_num_to_write = calculate_inode_to_block_number(to_be_removed_key); + struct block_info *tmp = read_block_from_disk(block_num_to_write); + int index = inode_num - (BLOCKSIZE/INODESIZE) * (block_num_to_write - 1); + memcpy((void*)(tmp->data + index * INODESIZE), (void*)(inode_front->inode_val), INODESIZE); + tmp->dirty = 1; + } + + dequeue_inode(); + remove_inode_from_hashtable(to_be_removed_key); + + + + //Decrement the current block cache number by 1. + current_inodecache_number--; + } + enqueue_inode(input_inode); + put_inode_to_hashtable(inode_num, input_inode); + current_inodecache_number++; + return; + }else{ + + remove_queue_inode(get_inode(inode_num)->inode_data); + enqueue_inode(input_inode); + put_inode_to_hashtable(inode_num, input_inode); + return; + } +} diff --git a/cache.o b/cache.o new file mode 100755 index 0000000..bb6e1ad Binary files /dev/null and b/cache.o differ diff --git a/init b/init new file mode 100755 index 0000000..0de2b7b Binary files /dev/null and b/init differ diff --git a/init.c b/init.c new file mode 100755 index 0000000..67345e6 --- /dev/null +++ b/init.c @@ -0,0 +1,76 @@ +#include +#include +#include + +#include +#include +#include + +int main(int argc, char** argv){ + + int buflen = 100; + char buf[buflen]; + char* buf2 = "contents to be written"; + + char* pathname1 = "/home/thien-nam/Documents"; + char* pathname2 = "/usr/bin"; + int fd; + struct Stat stat; + + printf("\nopening file\n"); + fd = Open(pathname1); + printf("\nclosing file\n"); + Close(fd); + + printf("\ncreating file\n"); + fd = Create(pathname2); + + printf("\nreading file\n"); + printf("buffer pointer for reading %d\n", buf); + Read(fd, buf, buflen); + printf("read contents: %s\n", buf); + + printf("\nwriting file\n"); + Write(fd, buf2, strlen(buf2)); + + printf("\nseeking file\n"); + Seek(fd, 15, SEEK_END); + + printf("\nlinking paths\n"); + Link(pathname1, pathname2); + + printf("\nunlinking path\n"); + Unlink(pathname2); + + printf("\nsymlinking paths\n"); + SymLink(pathname1, pathname2); + + printf("\nreading link\n"); + ReadLink(pathname1, buf, buflen); + printf("link: %s\n", buf); + + printf("\nmaking dir\n"); + MkDir(pathname1); + + printf("\nremoving dir\n"); + RmDir(pathname1); + + printf("\nchanging dir\n"); + ChDir(pathname1); + + printf("\nreading stat\n"); + Stat(pathname1, &stat); + printf("stats: inum %d type %d size %d nlink %d\n", stat.inum, stat.type, stat.size, stat.nlink); + + printf("\nsynching\n"); + Sync(); + + printf("\nshutting down\n"); + Shutdown(); + + while(1){ + Pause(); + printf("idling\n"); + } + return 0; +} diff --git a/iolib.a b/iolib.a new file mode 100755 index 0000000..e6670d4 Binary files /dev/null and b/iolib.a differ diff --git a/iolib.c b/iolib.c new file mode 100755 index 0000000..8e82a34 --- /dev/null +++ b/iolib.c @@ -0,0 +1,453 @@ +#include "yfs.h" + +// TODO: make sure less than MAXPATHNAMELEN + +struct Open_File { + short inode; + int position; +}; + +struct Open_File files[MAX_OPEN_FILES]; + +int num_open_files = 0; +int files_initialized = 0; +short current_dir = ROOTINODE; + +void Initialize_Files(){ + int i; + for(i = 0; i < MAX_OPEN_FILES; i++){ + files[i].inode = -1; + files[i].position = 0; + } + files_initialized = 1; +} + +// condenses consecutive '/'s and replaces trailing '/' with '.' +// returns the length of the new pathname which is no more than strlen(pathname) + 1 +int format_pathname(char* oldname, char* newname){ + + int len = strlen(oldname); + int i = 0; int j = 0; + for(i = 0; i < len; i++){ + if(oldname[i] == '/' && oldname[i+1] == '/'){ + continue; + } + newname[j] = oldname[i]; + j++; + } + int newlen = j; + + if(newname[newlen-1] == '/'){ + newname[newlen] = '.'; + newname[newlen+1] = '\0'; + return newlen+1; + } + else{ + newname[newlen] = '\0'; + return newlen; + } +} + +int CallYFS(uint8_t code, void** args, int* arg_sizes, int num_args){ + char msg[MESSAGE_SIZE]; + msg[0] = (char)code; + + int i; + int offset = 1; + + + for(i = 0; i < num_args; i++){ + // no longs are passed so sizeof(void*) applies exclusively to pointers + if(arg_sizes[i] == sizeof(void*) && *(void**)args[i] == NULL){ + fprintf(stderr, "ERROR: null pointer argument provided\n"); + return ERROR; + } + memcpy(msg + offset, (char**)(args[i]), arg_sizes[i]); + offset += arg_sizes[i]; + } + + int success = Send(msg, -FILE_SYSTEM); + + //---------------------------------------------------------------------------------------- + // pass control to YFS; upon return, msg should be overwritten with single int reply value + //---------------------------------------------------------------------------------------- + + int result = *(int*)msg; + if(success == -1 || result == -1){ + switch(code){ + case CODE_OPEN: + fprintf(stderr, "ERROR: YFS failed to open file\n"); break; + case CODE_CLOSE: + fprintf(stderr, "ERROR: YFS failed to close file\n"); break; + case CODE_CREATE: + fprintf(stderr, "ERROR: YFS failed to create file\n"); break; + case CODE_READ: + fprintf(stderr, "ERROR: YFS failed to read file\n"); break; + case CODE_WRITE: + fprintf(stderr, "ERROR: YFS failed to write to file\n"); break; + case CODE_SEEK: + fprintf(stderr, "ERROR: YFS failed to seek file\n"); break; + case CODE_LINK: + fprintf(stderr, "ERROR: YFS failed to create link\n"); break; + case CODE_UNLINK: + fprintf(stderr, "ERROR: YFS failed to unlink path\n"); break; + case CODE_SYMLINK: + fprintf(stderr, "ERROR: YFS failed to create symbolic link\n"); break; + case CODE_READLINK: + fprintf(stderr, "ERROR: YFS failed to read symbolic link\n"); break; + case CODE_MKDIR: + fprintf(stderr, "ERROR: YFS failed to make directory\n"); break; + case CODE_RMDIR: + fprintf(stderr, "ERROR: YFS failed to remove directory\n"); break; + case CODE_CHDIR: + fprintf(stderr, "ERROR: YFS failed to change directory\n"); break; + case CODE_STAT: + fprintf(stderr, "ERROR: YFS failed to retrieve stats\n"); break; + case CODE_SYNC: + fprintf(stderr, "ERROR: YFS failed to sync storage\n"); break; + case CODE_SHUTDOWN: + fprintf(stderr, "ERROR: YFS failed to shutdown\n"); break; + } + } + return result; +} + +int Open(char* pathname){ + if(!files_initialized) + Initialize_Files(); + + if(num_open_files >= MAX_OPEN_FILES){ + fprintf(stderr, "ERROR: maximum number of files already open\n"); + return 0; + } + + char* tmp = pathname; + pathname = (char*)malloc(strlen(pathname) + 2); + int pathname_size = format_pathname(tmp, pathname); + void* args[3] = {(void*)&pathname, (void*)&pathname_size, (void*)¤t_dir}; + int arg_sizes[3] = {sizeof(pathname), sizeof(pathname_size), sizeof(current_dir)}; + int inode = CallYFS(CODE_OPEN, args, arg_sizes, 3); + free(pathname); + + int i; + for(i = 0; i < MAX_OPEN_FILES; i++){ + if(files[i].inode == -1){ + files[i].inode = inode; + num_open_files++; + return i; + } + } + + // no reason this should ever occur since we already check max open files + return ERROR; +} + +int Close(int fd){ + if(!files_initialized) + Initialize_Files(); + + if(fd < 0 || fd >= MAX_OPEN_FILES || files[fd].inode == -1){ + fprintf(stderr, "ERROR: file descriptor is invalid\n"); + return ERROR; + } + + files[fd].inode = -1; + files[fd].position = 0; + num_open_files--; + return 0; +} + +int Create(char *pathname){ + if(!files_initialized) + Initialize_Files(); + + if(num_open_files >= MAX_OPEN_FILES){ + fprintf(stderr, "ERROR: maximum number of files already open\n"); + return 0; + } + + + char* tmp = pathname; + pathname = (char*)malloc(strlen(pathname) + 2); + int pathname_size = format_pathname(tmp, pathname); + void* args[3] = {(void*)&pathname, (void*)&pathname_size, (void*)¤t_dir}; + int arg_sizes[3] = {sizeof(pathname), sizeof(pathname_size), sizeof(current_dir)}; + int inode = CallYFS(CODE_CREATE, args, arg_sizes, 3); + free(pathname); + + int i; + for(i = 0; i < MAX_OPEN_FILES; i++){ + if(files[i].inode == -1){ + files[i].inode = inode; + num_open_files++; + return i; + } + } + + // no reason this should ever occur since we already check max open files + return ERROR; + +} + +int Read(int fd, void *buf, int size){ + if(!files_initialized) + Initialize_Files(); + + if(fd < 0 || fd >= MAX_OPEN_FILES || files[fd].inode == -1){ + fprintf(stderr, "ERROR: file descriptor is invalid\n"); + return ERROR; + } + + short inode = files[fd].inode; + int position = files[fd].position; + void* args[4] = {(void*)&buf, (void*)&size, (void*)&inode, (void*)&position}; + int arg_sizes[4] = {sizeof(buf), sizeof(size), sizeof(inode), sizeof(position)}; + int result = CallYFS(CODE_READ, args, arg_sizes, 4); + if(result == -1) + return ERROR; + + files[fd].position += result; + + return result; +} + +int Write(int fd, void *buf, int size){ + if(!files_initialized) + Initialize_Files(); + + if(fd < 0 || fd >= MAX_OPEN_FILES || files[fd].inode == -1){ + fprintf(stderr, "ERROR: file descriptor is invalid\n"); + return ERROR; + } + + short inode = files[fd].inode; + int position = files[fd].position; + + void* args[4] = {(void*)&buf, (void*)&size, (void*)&inode, (void*)&position}; + int arg_sizes[4] = {sizeof(buf), sizeof(size), sizeof(inode), sizeof(position)}; + int result = CallYFS(CODE_WRITE, args, arg_sizes, 4); + + if(result == -1) + return ERROR; + + files[fd].position += result; + return result; +} + +int Seek(int fd, int offset, int whence){ + if(!files_initialized) + Initialize_Files(); + + if(fd < 0 || fd >= MAX_OPEN_FILES || files[fd].inode == -1){ + fprintf(stderr, "ERROR: file descriptor is invalid\n"); + return ERROR; + } + + int new_position; + + switch(whence){ + case SEEK_SET: + new_position = offset; + break; + case SEEK_CUR: + new_position = files[fd].position + offset; + break; + case SEEK_END: + ; // fix a dumb "declaration after statement" C quirk + void* args[1] = {(void*)&files[fd].inode}; + int arg_sizes[1] = {sizeof(files[fd].inode)}; + new_position = CallYFS(CODE_SEEK, args, arg_sizes, 1) - offset; + break; + default: + fprintf(stderr, "ERROR: whence value invalid\n"); + } + + if(new_position < 0){ + fprintf(stderr, "ERROR: new file position would be negative\n"); + return ERROR; + } + + files[fd].position = new_position; + return 0; +} + +int Link(char *oldname, char *newname){ + char* tmp1 = oldname; + oldname = (char*)malloc(strlen(oldname) + 2); + int oldname_size = format_pathname(tmp1, oldname); + char* tmp2 = newname; + newname = (char*)malloc(strlen(newname) + 2); + int newname_size = format_pathname(tmp2, newname); + + void* args[5] = {(void*)&oldname, (void*)&oldname_size, (void*)&newname, + (void*)&newname_size, (void*)¤t_dir}; + int arg_sizes[5] = {sizeof(oldname), sizeof(oldname_size), sizeof(newname), + sizeof(newname_size), sizeof(current_dir)}; + int result = CallYFS(CODE_LINK, args, arg_sizes, 5); + free(oldname); + free(newname); + return result; +} + +int Unlink(char *pathname){ + char* tmp = pathname; + pathname = (char*)malloc(strlen(pathname) + 2); + int pathname_size = format_pathname(tmp, pathname); + void* args[3] = {(void*)&pathname, (void*)&pathname_size, (void*)¤t_dir}; + int arg_sizes[3] = {sizeof(pathname), sizeof(pathname_size), sizeof(current_dir)}; + int result = CallYFS(CODE_UNLINK, args, arg_sizes, 3); + free(pathname); + return result; +} + +int SymLink(char *oldname, char *newname){ + char* tmp1 = oldname; + oldname = (char*)malloc(strlen(oldname) + 2); + int oldname_size = format_pathname(tmp1, oldname); + char* tmp2 = newname; + newname = (char*)malloc(strlen(newname) + 2); + int newname_size = format_pathname(tmp2, newname); + void* args[5] = {(void*)&oldname, (void*)&oldname_size, (void*)&newname, + (void*)&newname_size, (void*)¤t_dir}; + int arg_sizes[5] = {sizeof(oldname), sizeof(oldname_size), sizeof(newname), + sizeof(newname_size), sizeof(current_dir)}; + int result = CallYFS(CODE_SYMLINK, args, arg_sizes, 5); + free(oldname); + free(newname); + if(result == ERROR) + return ERROR; + return 0; +} + +int ReadLink(char *pathname, char *buf, int len){ + char* tmp = pathname; + pathname = (char*)malloc(strlen(pathname) + 2); + int pathname_size = format_pathname(tmp, pathname); + void* args[5] = {(void*)&pathname, (void*)&pathname_size, (void*)&buf, (void*)&len, + (void*)¤t_dir}; + int arg_sizes[5] = {sizeof(pathname), sizeof(pathname_size), sizeof(buf), sizeof(len), + sizeof(current_dir)}; + int result = CallYFS(CODE_READLINK, args, arg_sizes, 5); + free(pathname); + return result; +} + +int MkDir(char *pathname){ + char* tmp = pathname; + pathname = (char*)malloc(strlen(pathname) + 2); + int pathname_size = format_pathname(tmp, pathname); + void* args[3] = {(void*)&pathname, (void*)&pathname_size, (void*)¤t_dir}; + int arg_sizes[3] = {sizeof(pathname), sizeof(pathname_size), sizeof(current_dir)}; + int result = CallYFS(CODE_MKDIR, args, arg_sizes, 3); + free(pathname); + return result; +} + +int RmDir(char *pathname){ + char* tmp = pathname; + pathname = (char*)malloc(strlen(pathname) + 2); + int pathname_size = format_pathname(tmp, pathname); + void* args[2] = {(void*)&pathname, (void*)&pathname_size}; + int arg_sizes[2] = {sizeof(pathname), sizeof(pathname_size)}; + int result = CallYFS(CODE_RMDIR, args, arg_sizes, 2); + free(pathname); + return result; +} + +int ChDir(char *pathname){ + char* tmp = pathname; + pathname = (char*)malloc(strlen(pathname) + 2); + int pathname_size = format_pathname(tmp, pathname); + void* args[3] = {(void*)&pathname, (void*)&pathname_size, (void*)¤t_dir}; + int arg_sizes[3] = {sizeof(pathname), sizeof(pathname_size), sizeof(current_dir)}; + short new_inum = CallYFS(CODE_CHDIR, args, arg_sizes, 3); + free(pathname); + + if(new_inum == ERROR){ + return ERROR; + } + current_dir = new_inum; + return 0; +} + +int Stat(char *pathname, struct Stat* statbuf){ + char* tmp = pathname; + pathname = (char*)malloc(strlen(pathname) + 2); + int pathname_size = format_pathname(tmp, pathname); + void* args[4] = {(void*)&pathname, (void*)&pathname_size, (void*)&statbuf, + (void*)¤t_dir}; + int arg_sizes[4] = {sizeof(pathname), sizeof(pathname_size), sizeof(statbuf), + sizeof(current_dir)}; + int result = CallYFS(CODE_STAT, args, arg_sizes, 4); + free(pathname); + return result; +} + +int Sync(void){ + return CallYFS(CODE_SYNC, NULL, NULL, 0); +} + +int Shutdown(void){ + return CallYFS(CODE_SHUTDOWN, NULL, NULL, 0); +} + +/* + char* test1 = "/standard/directory/path/name"; + char* test2 = "/this/is/a/path/to/dir/"; + char* test3 = "/"; + char* test4 = NULL; + char* test5 = "////this/has///a/bunch//////of//slashes////"; + char* test6 = "noslashes"; + char* test7 = "finally, this is a dot ending/"; + + char* result1 = (char*)malloc(50); + char* result2 = (char*)malloc(50); + char* result3 = (char*)malloc(50); + char* result4 = (char*)malloc(50); + char* result5 = (char*)malloc(50); + char* result6 = (char*)malloc(50); + char* result7 = (char*)malloc(50); + + format_pathname(test1, result1); + format_pathname(test2, result2); + format_pathname(test3, result3); + //format_pathname(test4, result4); + format_pathname(test5, result5); + format_pathname(test6, result6); + format_pathname(test7, result7); + + printf("%s\n", result1); + printf("%s\n", result2); + printf("%s\n", result3); + //printf("%s\n", result4); + printf("%s\n", result5); + printf("%s\n", result6); + printf("%s\n", result7); + */ + +/* +void print_bits_short(uint8_t n){ + int i; + for(i = 0; i < 8; i++){ + if(n & 128) + printf("1"); + else + printf("0"); + n <<=1; + } +} + + +void print_bits_long(uint64_t n){ + int i; + for(i = 0; i < 64; i++){ + if(n & 9223372036854775808) + printf("1"); + else + printf("0"); + n <<=1; + if(i % 8 == 7) + printf(" "); + } +} +*/ diff --git a/iolib.o b/iolib.o new file mode 100755 index 0000000..324b6dc Binary files /dev/null and b/iolib.o differ diff --git a/lib_test b/lib_test new file mode 100755 index 0000000..37b8f12 Binary files /dev/null and b/lib_test differ diff --git a/lib_test.c b/lib_test.c new file mode 100755 index 0000000..8a01dc0 --- /dev/null +++ b/lib_test.c @@ -0,0 +1,73 @@ +#include +#include +#include + +#include +#include +#include + +int main(int argc, char** argv){ + + int buflen = 100; + char buf[buflen]; + char* buf2 = "contents to be written"; + + char* pathname1 = "/home/thien-nam/Documents"; + char* pathname2 = "/usr/bin"; + int fd; + struct Stat stat; + + printf("\nopening file\n"); + fd = Open(pathname1); + + printf("\nclosing file\n"); + Close(fd); + + printf("\ncreating file\n"); + fd = Create(pathname2); + + printf("\nreading file\n"); + Read(fd, buf, buflen); + + printf("\nwriting file\n"); + Write(fd, buf2, strlen(buf2)); + + printf("\nseeking file\n"); + Seek(fd, 15, SEEK_END); + + printf("\nlinking paths\n"); + Link(pathname1, pathname2); + + printf("\nunlinking path\n"); + Unlink(pathname2); + + printf("\nsymlinking paths\n"); + SymLink(pathname1, pathname2); + + printf("\nreading link\n"); + ReadLink(pathname1, buf, buflen); + + printf("\nmaking dir\n"); + MkDir(pathname1); + + printf("\nremoving dir\n"); + RmDir(pathname1); + + printf("\nchanging dir\n"); + ChDir(pathname1); + + printf("\nreading stat\n"); + Stat(pathname1, &stat); + + printf("\nsynching\n"); + Sync(); + + printf("\nshutting down\n"); + Shutdown(); + + while(1){ + Pause(); + printf("idling\n"); + } + return 0; +} diff --git a/lib_test.c~ b/lib_test.c~ new file mode 100755 index 0000000..67345e6 --- /dev/null +++ b/lib_test.c~ @@ -0,0 +1,76 @@ +#include +#include +#include + +#include +#include +#include + +int main(int argc, char** argv){ + + int buflen = 100; + char buf[buflen]; + char* buf2 = "contents to be written"; + + char* pathname1 = "/home/thien-nam/Documents"; + char* pathname2 = "/usr/bin"; + int fd; + struct Stat stat; + + printf("\nopening file\n"); + fd = Open(pathname1); + printf("\nclosing file\n"); + Close(fd); + + printf("\ncreating file\n"); + fd = Create(pathname2); + + printf("\nreading file\n"); + printf("buffer pointer for reading %d\n", buf); + Read(fd, buf, buflen); + printf("read contents: %s\n", buf); + + printf("\nwriting file\n"); + Write(fd, buf2, strlen(buf2)); + + printf("\nseeking file\n"); + Seek(fd, 15, SEEK_END); + + printf("\nlinking paths\n"); + Link(pathname1, pathname2); + + printf("\nunlinking path\n"); + Unlink(pathname2); + + printf("\nsymlinking paths\n"); + SymLink(pathname1, pathname2); + + printf("\nreading link\n"); + ReadLink(pathname1, buf, buflen); + printf("link: %s\n", buf); + + printf("\nmaking dir\n"); + MkDir(pathname1); + + printf("\nremoving dir\n"); + RmDir(pathname1); + + printf("\nchanging dir\n"); + ChDir(pathname1); + + printf("\nreading stat\n"); + Stat(pathname1, &stat); + printf("stats: inum %d type %d size %d nlink %d\n", stat.inum, stat.type, stat.size, stat.nlink); + + printf("\nsynching\n"); + Sync(); + + printf("\nshutting down\n"); + Shutdown(); + + while(1){ + Pause(); + printf("idling\n"); + } + return 0; +} diff --git a/lru_cache.c b/lru_cache.c new file mode 100755 index 0000000..9c40160 --- /dev/null +++ b/lru_cache.c @@ -0,0 +1,349 @@ +#include +#include +#include +#include + +#define SIZE 100 +#define BLOCKSIZE 32 +#define BLOCK_CACHESIZE 2 // Needs to be modified to another number. +int current_blockcache_number; + + +//Dirty = 1 means it is dirty +//Dirty = 0 means it is not dirty + +struct block_info { + int dirty; + int block_number; + struct block_info *next; + struct block_info *prev; + char data[BLOCKSIZE]; +}; + +struct block_wrap { + int key; + struct block_info* block_data; +}; +struct block_info* block_front; +struct block_info* block_rear; + +struct block_wrap* block_hashtable[SIZE]; +struct block_wrap* default_block_wrap; +struct block_info* default_block_info; +// struct block_wrap* item; + +int generate_hash_code(int key) { + //Hash code generator. + return key % SIZE; +} + +struct block_wrap *get_block(int key) { + //Obtains the hash code. + int hash_index = generate_hash_code(key); + + while(block_hashtable[hash_index] != NULL) { + + if(block_hashtable[hash_index]->key == key){ + return block_hashtable[hash_index]; + } + + ++hash_index; + + hash_index %= SIZE; + } + + return NULL; +} + +void put_block_to_hashtable(int key, struct block_info* data_input) { + + struct block_wrap *item = (struct block_wrap*) malloc(sizeof(struct block_wrap)); + item->block_data = data_input; + item->key = key; + + int hash_index = generate_hash_code(key); + + while(block_hashtable[hash_index] != NULL && block_hashtable[hash_index]->key != -1) { + ++hash_index; + + hash_index %= SIZE; + } + + block_hashtable[hash_index] = item; +} + +struct block_wrap* remove_block_from_hashtable(int block_num) { + + int hash_index = generate_hash_code(block_num); + + while(block_hashtable[hash_index] != NULL) { + + if(block_hashtable[hash_index]->key == block_num) { + struct block_wrap* temp = block_hashtable[hash_index]; + + block_hashtable[hash_index] = default_block_wrap; + + return temp; + } + + ++hash_index; + + hash_index %= SIZE; + } + + return NULL; +} + +void print_cache() { + int i = 0; + + for(i = 0; ikey,block_hashtable[i]->key); + else + printf(" ~~ "); + } + + printf("\n"); +} + + +void enqueue_block(struct block_info * x) { + //Puts to end. + if(block_front == NULL && block_rear == NULL){ + block_front = block_rear = x; + block_front->prev = NULL; + block_rear->next = NULL; + return; + } + block_rear->next = x; + x->prev = block_rear; + block_rear = x; + block_rear->next = NULL; +} + + +void dequeue_block() { + //Eliminate the block_front; + if(block_front == NULL) { + printf("Queue is Empty\n"); + return; + } + if(block_front == block_rear) { + block_front = block_rear = NULL; + }else { + block_front->next->prev = NULL; + block_front = block_front->next; + block_front->prev = NULL; + } + +} + +void remove_queue_block(struct block_info * x) { + if(x->prev != NULL && x->next != NULL){ + x->prev->next = x->next; + x->next->prev = x->prev; + }else if(x->prev != NULL && x->next == NULL) { + block_rear = block_rear->prev; + block_rear->next = NULL; + }else if(x->prev == NULL && x->next != NULL) { + dequeue_block(); + } +} + +void Print() { + struct block_info* temp = block_front; + while(temp != NULL) { + printf("%d\n",temp->block_number); + temp = temp->next; + } + free(temp); +} + + +void init() { + current_blockcache_number = 0; + block_front = NULL; + block_rear = NULL; + default_block_wrap = (struct block_wrap*) malloc(sizeof(struct block_wrap)); + default_block_wrap->key = -1; + + default_block_info = (struct block_info*) malloc(sizeof(struct block_info)); + default_block_info->block_number = -1; +} + +struct block_info* get_lru_block(int block_num) { + struct block_wrap* result = get_block(block_num); + if(result == NULL) { + return default_block_info; + }else{ + //Recently used. + remove_queue_block(result->block_data); + enqueue_block(result->block_data); + // put_to_block_front(result); + + return result->block_data; + } +} + +void evict_block(){ + //Test whether there is a key to be evict_blocked. + if(current_blockcache_number == BLOCK_CACHESIZE) { + int to_be_removed_key = block_front->block_number; + //Here should be another method sync to write inode back to the disk. + + + + + + // if(block_front->dirty == 1) { + // WriteSector(block_front->block_number, (void*)(block_front->data)); + // } + dequeue_block(); + remove_block_from_hashtable(to_be_removed_key); + //Decrement the current block cache number by 1. + current_blockcache_number--; + } +} + +void set_lru_block(int block_num, struct block_info* input_block) { + if(get_block(block_num) == NULL) { + // printf("Key not found\n"); + //Determines whether a key needs to be removed. + evict_block(); + enqueue_block(input_block); + put_block_to_hashtable(block_num, input_block); + current_blockcache_number++; + return; + }else{ + + remove_queue_block(get_block(block_num)->block_data); + enqueue_block(input_block); + put_block_to_hashtable(block_num, input_block); + + return; + } + +} + +void clear_lru_block() { + int i; + for (i = 0;i block_number = 1; + x1->dirty = 0; + + struct block_info *x2 = (struct block_info*) malloc(sizeof(struct block_info)); + x2->block_number = 2; + x2->dirty = 1; + struct block_info *x3 = (struct block_info*) malloc(sizeof(struct block_info)); + x3->block_number = 3; + x3->dirty = 1; + struct block_info *x4 = (struct block_info*) malloc(sizeof(struct block_info)); + x4->block_number = 4; + x4->dirty = 1; + struct block_info *x5 = (struct block_info*) malloc(sizeof(struct block_info)); + x5->block_number = 5; + + set_lru_block(1, x1); + set_lru_block(2, x2); + // set_lru_block(3, x3); + // set_lru_block(4, x4); + // set_lru_block(5, x5); + + // printf("%d\n", current_blockcache_number); + // print_cache(); + //Test case 0: + printf("----test case 0----\n"); + printf("%d\n", get_lru_block(1)->block_number); + set_lru_block(3, x3); + printf("%d\n", get_lru_block(2)->block_number); + set_lru_block(4, x4); + printf("%d\n", get_lru_block(1)->block_number); + printf("%d\n", get_lru_block(3)->block_number); + printf("%d\n", get_lru_block(4)->block_number); + // Print(); + + + //Test case 1: + printf("----test case 1----\n"); + enqueue_block(x1); + enqueue_block(x2); + enqueue_block(x3); + enqueue_block(x4); + enqueue_block(x5); + if(block_front->prev == NULL && block_rear->next == NULL) { + printf("There is nothing in block_front of the linked list and after the linked list.\n"); + } + //Prints the list. + Print(); + printf("----test case 2----\n"); + //Result should be 1, 2, 3, 4, 5 + + //Test case 2: + dequeue_block(); + if(block_front->prev == NULL && block_rear->next == NULL) { + printf("There is nothing in block_front of the linked list and after the linked list.\n"); + } + + Print(); + //Result should be 2, 3 + //Test case 3; + printf("----test case 3----\n"); + remove_queue_block(block_front); + if(block_front->prev == NULL && block_rear->next == NULL) { + printf("There is nothing in block_front of the linked list and after the linked list.\n"); + } + Print(); + //Result should be 3, 4, 5 + printf("----test case 4----\n"); + remove_queue_block(block_front); + if(block_front->prev == NULL && block_rear->next == NULL) { + printf("There is nothing in block_front of the linked list and after the linked list.\n"); + } + Print(); + + + printf("----test case 5----\n"); + remove_queue_block(block_rear); + if(block_front->prev == NULL && block_rear->next == NULL) { + printf("There is nothing in block_front of the linked list and after the linked list.\n"); + } + Print(); + + printf("----test case 6----\n"); + enqueue_block(x1); + enqueue_block(x2); + enqueue_block(x3); + remove_queue_block(block_front->next->next); + if(block_front->prev == NULL && block_rear->next == NULL) { + printf("There is nothing in block_front of the linked list and after the linked list.\n"); + } + Print(); + + clear_lru_block(); + printf("----test case 7----\n"); + set_lru_block(1, x1); + set_lru_block(2, x2); + printf("goodm\n"); + struct block_info* tmp = get_lru_block(1); + printf("%d\n", tmp->block_number); + printf("%d\n", tmp->dirty); + printf("-------------------\n"); + set_lru_block(1, x3); + Print(); + +} diff --git a/lru_inode.c b/lru_inode.c new file mode 100755 index 0000000..20c5929 --- /dev/null +++ b/lru_inode.c @@ -0,0 +1,348 @@ +#include +#include +#include +#include + +#define SIZE 100 +#define BLOCKSIZE 32 +#define INODE_CACHESIZE 2 // Needs to be modified to another number. +int current_inodecache_number; + + +//Dirty = 1 means it is dirty +//Dirty = 0 means it is not dirty + +struct inode_info { + int dirty; + int inode_number; + struct inode_info *next; + struct inode_info *prev; + struct inode *inode_val; //From the filesystem.h + char data[BLOCKSIZE]; +}; + +struct inode_wrap { + int key; + struct inode_info* inode_data; +}; +struct inode_info* inode_front; +struct inode_info* inode_rear; + +struct inode_wrap* inode_hashtable[SIZE]; +struct inode_wrap* default_inode_wrap; +struct inode_info* default_inode_info; +// struct inode_wrap* item; + +int generate_hash_code(int key) { + //Hash code generator. + return key % SIZE; +} + +struct inode_wrap *get_inode(int key) { + //Obtains the hash code. + int hash_index = generate_hash_code(key); + + while(inode_hashtable[hash_index] != NULL) { + + if(inode_hashtable[hash_index]->key == key){ + return inode_hashtable[hash_index]; + } + + ++hash_index; + + hash_index %= SIZE; + } + + return NULL; +} + +void put_inode_to_hashtable(int key, struct inode_info* data_input) { + + struct inode_wrap *item = (struct inode_wrap*) malloc(sizeof(struct inode_wrap)); + item->inode_data = data_input; + item->key = key; + + int hash_index = generate_hash_code(key); + + while(inode_hashtable[hash_index] != NULL && inode_hashtable[hash_index]->key != -1) { + ++hash_index; + + hash_index %= SIZE; + } + + inode_hashtable[hash_index] = item; +} + +struct inode_wrap* remove_inode_from_hashtable(int inode_num) { + + int hash_index = generate_hash_code(inode_num); + + while(inode_hashtable[hash_index] != NULL) { + + if(inode_hashtable[hash_index]->key == inode_num) { + struct inode_wrap* temp = inode_hashtable[hash_index]; + + inode_hashtable[hash_index] = default_inode_wrap; + + return temp; + } + + ++hash_index; + + hash_index %= SIZE; + } + + return NULL; +} + +void print_cache() { + int i = 0; + + for(i = 0; ikey,inode_hashtable[i]->key); + else + printf(" ~~ "); + } + + printf("\n"); +} + + +void enqueue_inode(struct inode_info * x) { + //Puts to end. + if(inode_front == NULL && inode_rear == NULL){ + inode_front = inode_rear = x; + inode_front->prev = NULL; + inode_rear->next = NULL; + return; + } + inode_rear->next = x; + x->prev = inode_rear; + inode_rear = x; + inode_rear->next = NULL; +} + + +void dequeue_inode() { + //Eliminate the inode_front; + if(inode_front == NULL) { + printf("Queue is Empty\n"); + return; + } + if(inode_front == inode_rear) { + inode_front = inode_rear = NULL; + }else { + inode_front->next->prev = NULL; + inode_front = inode_front->next; + inode_front->prev = NULL; + } + +} + +void remove_queue_inode(struct inode_info * x) { + if(x->prev != NULL && x->next != NULL){ + + x->prev->next = x->next; + x->next->prev = x->prev; + }else if(x->prev != NULL && x->next == NULL) { + // printf("good\n"); + inode_rear = inode_rear->prev; + inode_rear->next = NULL; + }else if(x->prev == NULL && x->next != NULL) { + dequeue_inode(); + } +} + +void Print() { + struct inode_info* temp = inode_front; + while(temp != NULL) { + printf("%d\n",temp->inode_number); + temp = temp->next; + } + free(temp); +} + + +void init() { + current_inodecache_number = 0; + inode_front = NULL; + inode_rear = NULL; + default_inode_wrap = (struct inode_wrap*) malloc(sizeof(struct inode_wrap)); + default_inode_wrap->key = -1; + + default_inode_info = (struct inode_info*) malloc(sizeof(struct inode_info)); + default_inode_info->inode_number = -1; +} + +struct inode_info* get_lru_inode(int inode_num) { + struct inode_wrap* result = get_inode(inode_num); + if(result == NULL) { + return default_inode_info; + }else{ + //Recently used. + remove_queue_inode(result->inode_data); + enqueue_inode(result->inode_data); + // put_to_inode_front(result); + + return result->inode_data; + } +} + +void evict_inode(){ + //Test whether there is a key to be evict_inodeed. + if(current_inodecache_number == INODE_CACHESIZE) { + int to_be_removed_key = inode_front->inode_number; + //Here should be another method sync to write inode back to the disk. + + + + + + // if(inode_front->dirty == 1) { + // WriteSector(inode_front->inode_number, (void*)(inode_front->data)); + // } + dequeue_inode(); + remove_inode_from_hashtable(to_be_removed_key); + //Decrement the current block cache number by 1. + current_inodecache_number--; + } +} + +void set_lru_inode(int inode_num, struct inode_info* input_inode) { + if(get_inode(inode_num) == NULL) { + //Determines whether a key needs to be removed. + evict_inode(); + enqueue_inode(input_inode); + put_inode_to_hashtable(inode_num, input_inode); + current_inodecache_number++; + return; + }else{ + + remove_queue_inode(get_inode(inode_num)->inode_data); + enqueue_inode(input_inode); + put_inode_to_hashtable(inode_num, input_inode); + + return; + } + +} + +void clear_lru_inode() { + int i; + for (i = 0;i inode_number = 1; + + struct inode_info *x2 = (struct inode_info*) malloc(sizeof(struct inode_info)); + x2->inode_number = 2; + + struct inode_info *x3 = (struct inode_info*) malloc(sizeof(struct inode_info)); + x3->inode_number = 3; + + struct inode_info *x4 = (struct inode_info*) malloc(sizeof(struct inode_info)); + x4->inode_number = 4; + + struct inode_info *x5 = (struct inode_info*) malloc(sizeof(struct inode_info)); + x5->inode_number = 5; + + set_lru_inode(1, x1); + set_lru_inode(2, x2); + // set_lru_inode(3, x3); + // set_lru_inode(4, x4); + // set_lru_inode(5, x5); + + // printf("%d\n", current_inodecache_number); + // print_cache(); + //Test case 0: + // printf("----test case 0----\n"); + // printf("%d\n", get_lru_inode(1)->inode_number); + // set_lru_inode(3, x3); + // printf("%d\n", get_lru_inode(2)->inode_number); + // set_lru_inode(4, x4); + // printf("%d\n", get_lru_inode(1)->inode_number); + // printf("%d\n", get_lru_inode(3)->inode_number); + // printf("%d\n", get_lru_inode(4)->inode_number); + // set_lru_inode(4, x1); + // printf("%d\n", get_lru_inode(4)->inode_number); + // Print(); + + + //Test case 1: + printf("----test case 1----\n"); + enqueue_inode(x1); + enqueue_inode(x2); + enqueue_inode(x3); + enqueue_inode(x4); + enqueue_inode(x5); + if(inode_front->prev == NULL && inode_rear->next == NULL) { + printf("There is nothing in inode_front of the linked list and after the linked list.\n"); + } + //Prints the list. + Print(); + printf("----test case 2----\n"); + //Result should be 1, 2, 3, 4, 5 + + //Test case 2: + dequeue_inode(); + if(inode_front->prev == NULL && inode_rear->next == NULL) { + printf("There is nothing in inode_front of the linked list and after the linked list.\n"); + } + + Print(); + //Result should be 2, 3 + //Test case 3; + printf("----test case 3----\n"); + remove_queue_inode(inode_front); + if(inode_front->prev == NULL && inode_rear->next == NULL) { + printf("There is nothing in inode_front of the linked list and after the linked list.\n"); + } + Print(); + //Result should be 3, 4, 5 + printf("----test case 4----\n"); + remove_queue_inode(inode_front); + if(inode_front->prev == NULL && inode_rear->next == NULL) { + printf("There is nothing in inode_front of the linked list and after the linked list.\n"); + } + Print(); + + + printf("----test case 5----\n"); + remove_queue_inode(inode_rear); + if(inode_front->prev == NULL && inode_rear->next == NULL) { + printf("There is nothing in inode_front of the linked list and after the linked list.\n"); + } + Print(); + + printf("----test case 6----\n"); + enqueue_inode(x1); + enqueue_inode(x2); + enqueue_inode(x3); + remove_queue_inode(inode_front->next->next); + if(inode_front->prev == NULL && inode_rear->next == NULL) { + printf("There is nothing in inode_front of the linked list and after the linked list.\n"); + } + Print(); + clear_lru_inode(); + printf("----test case 7----\n"); + set_lru_inode(1, x1); + set_lru_inode(2, x2); + printf("goodm\n"); + printf("%d\n", get_lru_inode(1)->inode_number); + printf("-------------------\n"); + set_lru_inode(1, x4); + Print(); + +} \ No newline at end of file diff --git a/sample1 b/sample1 new file mode 100755 index 0000000..a3ede3b Binary files /dev/null and b/sample1 differ diff --git a/sample1.c b/sample1.c new file mode 100755 index 0000000..98722fb --- /dev/null +++ b/sample1.c @@ -0,0 +1,36 @@ +#include +#include + +int +main() +{ + int fd; + + fd = Create("a"); + Write(fd, "aaaaaaaaaaaaaaaa", 16); + Close(fd); + + fd = Create("b"); + Write(fd, "bbbbbbbbbbbbbbbb", 16); + Close(fd); + + fd = Create("c"); + Write(fd, "cccccccccccccccc", 16); + Close(fd); + + MkDir("dir"); + + fd = Create("/dir/x"); + Write(fd, "xxxxxxxxxxxxxxxx", 16); + Close(fd); + + fd = Create("/dir/y"); + Write(fd, "yyyyyyyyyyyyyyyy", 16); + Close(fd); + + fd = Create("/dir/z"); + Write(fd, "zzzzzzzzzzzzzzzz", 16); + Close(fd); + + Shutdown(); +} diff --git a/sample2 b/sample2 new file mode 100755 index 0000000..85ddb56 Binary files /dev/null and b/sample2 differ diff --git a/sample2.c b/sample2.c new file mode 100755 index 0000000..5bcde5c --- /dev/null +++ b/sample2.c @@ -0,0 +1,60 @@ +#include + +#include +#include + +/* + * Create empty files named "file00" through "file31" in "/". + */ +int +main() +{ + int fd; + int i; + char name[7]; + char* msg1 = " Hello, world! It's a great day to be writing yalnix file systems\n"; + printf("strlen %d\n", strlen(msg1)); + + for (i = 0; i < 1; i++) { + sprintf(name, "file%02d", i); + fd = Create(name); + Close(fd); + } + + + for (i = 0; i < 1; i+= 2) { + printf("Starting file %d\n", i); + sprintf(name, "file%02d", i); + fd = Open(name); + char* msg0 = " Hello, world! It's a great day to be writing yalnix file systems\n"; + char msg[strlen(msg0) + 1]; + memcpy(msg, msg0, strlen(msg0)); + int j; + int bytes_written = 0; + for(j = 0; j < 25 * 512 / strlen(msg); j++){ + msg[0] = '0' + j / 100; + msg[1] = '0' + (j % 100) / 10; + msg[2] = '0' + j % 10; + bytes_written += Write(fd, msg, strlen(msg)); + } + printf("Bytes Written: %d\n", bytes_written); + Seek(fd, 0, SEEK_SET); + int bytes_read = 0; + while(1){ + int len = 13000; + char read[len + 1]; + memset(read, '\0', len+1); + int result = Read(fd, read, len); + bytes_read += result; + // printf("\nbytes read %d\n\n", result); + printf("%s", read); + if(result == 0) + break; + } + printf("\n"); + printf("Bytes Read: %d\n", bytes_read); + Close(fd); + } + + Shutdown(); +} diff --git a/sample2.c~ b/sample2.c~ new file mode 100755 index 0000000..adf1684 --- /dev/null +++ b/sample2.c~ @@ -0,0 +1,34 @@ +#include + +#include +#include + +/* + * Create empty files named "file00" through "file31" in "/". + */ +int +main() +{ + int fd; + int i; + char name[7]; + + for (i = 0; i < 32; i+= 2) { + printf("starting file %d\n", i); + sprintf(name, "file%02d", i); + fd = Open(name); + char* msg = "Hello, world! It's a great day to be writing yalnix file systems\n"; + int j; + while(1){ + char read[100]; + read[0] = '\0'; + Read(fd, read, 100); + printf("%s", read); + if(strlen(read) == 0) + break; + } + Close(fd); + } + + Shutdown(); +} diff --git a/stdfLDbr b/stdfLDbr new file mode 100755 index 0000000..e69de29 diff --git a/tcreate b/tcreate new file mode 100755 index 0000000..7b045f2 Binary files /dev/null and b/tcreate differ diff --git a/tcreate.c b/tcreate.c new file mode 100755 index 0000000..54393c6 --- /dev/null +++ b/tcreate.c @@ -0,0 +1,23 @@ +#include +#include +#include + +#include +#include + +int +main() +{ + int err; + write(2, "A\n", 2); + err = Create("/foo"); + fprintf(stderr, "Create returned %d\n", err); + + Sync(); + Delay(3); + fprintf(stderr, "Done with Sync\n"); + +/* Shutdown(); */ + + exit(0); +} diff --git a/tcreate2 b/tcreate2 new file mode 100755 index 0000000..7bbc5ce Binary files /dev/null and b/tcreate2 differ diff --git a/tcreate2.c b/tcreate2.c new file mode 100755 index 0000000..59ce038 --- /dev/null +++ b/tcreate2.c @@ -0,0 +1,17 @@ +#include + +#include +#include + +/* After running this, try topen2 and/or tunlink2 */ + +int +main() +{ + printf("\n%d\n\n", Create("/foo")); + printf("\n%d\n\n", Create("/bar")); + printf("\n%d\n\n", Create("/foo")); + printf("\n%d\n\n", Create("/foo/zzz")); + + Shutdown(); +} diff --git a/test1 b/test1 new file mode 100755 index 0000000..eb7a05f Binary files /dev/null and b/test1 differ diff --git a/test1.c b/test1.c new file mode 100755 index 0000000..1720fbd --- /dev/null +++ b/test1.c @@ -0,0 +1,39 @@ +#include +#include +#include + +#include +#include +#include + +int main(int argc, char** argv){ + + printf("Starting Test 1\n"); + + char* dir_name1 = "/spam1"; + char* dir_name2 = "/spam1/spam2"; + char* file_name1 = "/spam1/spam2/foo1"; + char* file_name2 = "foo2"; + + int result1 = MkDir(dir_name1); + int result2 = MkDir(dir_name2); + int fd1 = Create(file_name1); + int fd2 = Create(file_name2); + + printf("result %d\n", result1); + printf("result %d\n", result2); + printf("result %d\n", fd1); + printf("result %d\n", fd2); + + char* write1 = "Hello, world!\n"; + Write(fd1, write1, strlen(write1)); + + Close(fd1); + int fd1B = Open(file_name1); + + char read1[100]; + Read(fd1B, read1, 5); + printf("File contents %s\n", read1); + + return 0; +} diff --git a/test1.c~ b/test1.c~ new file mode 100755 index 0000000..8a01dc0 --- /dev/null +++ b/test1.c~ @@ -0,0 +1,73 @@ +#include +#include +#include + +#include +#include +#include + +int main(int argc, char** argv){ + + int buflen = 100; + char buf[buflen]; + char* buf2 = "contents to be written"; + + char* pathname1 = "/home/thien-nam/Documents"; + char* pathname2 = "/usr/bin"; + int fd; + struct Stat stat; + + printf("\nopening file\n"); + fd = Open(pathname1); + + printf("\nclosing file\n"); + Close(fd); + + printf("\ncreating file\n"); + fd = Create(pathname2); + + printf("\nreading file\n"); + Read(fd, buf, buflen); + + printf("\nwriting file\n"); + Write(fd, buf2, strlen(buf2)); + + printf("\nseeking file\n"); + Seek(fd, 15, SEEK_END); + + printf("\nlinking paths\n"); + Link(pathname1, pathname2); + + printf("\nunlinking path\n"); + Unlink(pathname2); + + printf("\nsymlinking paths\n"); + SymLink(pathname1, pathname2); + + printf("\nreading link\n"); + ReadLink(pathname1, buf, buflen); + + printf("\nmaking dir\n"); + MkDir(pathname1); + + printf("\nremoving dir\n"); + RmDir(pathname1); + + printf("\nchanging dir\n"); + ChDir(pathname1); + + printf("\nreading stat\n"); + Stat(pathname1, &stat); + + printf("\nsynching\n"); + Sync(); + + printf("\nshutting down\n"); + Shutdown(); + + while(1){ + Pause(); + printf("idling\n"); + } + return 0; +} diff --git a/test2 b/test2 new file mode 100755 index 0000000..7976ef6 Binary files /dev/null and b/test2 differ diff --git a/test2.c b/test2.c new file mode 100755 index 0000000..358becc --- /dev/null +++ b/test2.c @@ -0,0 +1,27 @@ +#include +#include +#include + +#include +#include +#include + +int main(int argc, char** argv){ + + printf("Starting Test 2\n"); + + int fd = Create("foo1"); + + char* msg1 = "Hello, world!\n"; + char* msg2 = "This should not be overwriting!\n"; + + Write(fd, msg1, strlen(msg1)); + Write(fd, msg2, strlen(msg2)); + + char readbuf[100]; + Seek(fd, 0, SEEK_SET); + int result = Read(fd, readbuf, 100); + printf("Read %d: %s\n", result, readbuf); + Shutdown(); + return 0; +} diff --git a/test2.c~ b/test2.c~ new file mode 100755 index 0000000..cbf2127 --- /dev/null +++ b/test2.c~ @@ -0,0 +1,27 @@ +#include +#include +#include + +#include +#include +#include + +int main(int argc, char** argv){ + + printf("Starting Test 2\n"); + + int fd = Create("foo1"); + + char* msg1 = "Hello, world!\n"; + char* msg1 = "This should not be overwriting!\n"; + + Write(fd, msg1, strlen(msg1)); + Write(fd, msg2, strlen(msg2)); + + char readbuf[100]; + Read(fd, readbuf, 100); + + printf("Read: %s\n", readbuf); + + return 0; +} diff --git a/tests/lru_cache.c b/tests/lru_cache.c new file mode 100755 index 0000000..9c40160 --- /dev/null +++ b/tests/lru_cache.c @@ -0,0 +1,349 @@ +#include +#include +#include +#include + +#define SIZE 100 +#define BLOCKSIZE 32 +#define BLOCK_CACHESIZE 2 // Needs to be modified to another number. +int current_blockcache_number; + + +//Dirty = 1 means it is dirty +//Dirty = 0 means it is not dirty + +struct block_info { + int dirty; + int block_number; + struct block_info *next; + struct block_info *prev; + char data[BLOCKSIZE]; +}; + +struct block_wrap { + int key; + struct block_info* block_data; +}; +struct block_info* block_front; +struct block_info* block_rear; + +struct block_wrap* block_hashtable[SIZE]; +struct block_wrap* default_block_wrap; +struct block_info* default_block_info; +// struct block_wrap* item; + +int generate_hash_code(int key) { + //Hash code generator. + return key % SIZE; +} + +struct block_wrap *get_block(int key) { + //Obtains the hash code. + int hash_index = generate_hash_code(key); + + while(block_hashtable[hash_index] != NULL) { + + if(block_hashtable[hash_index]->key == key){ + return block_hashtable[hash_index]; + } + + ++hash_index; + + hash_index %= SIZE; + } + + return NULL; +} + +void put_block_to_hashtable(int key, struct block_info* data_input) { + + struct block_wrap *item = (struct block_wrap*) malloc(sizeof(struct block_wrap)); + item->block_data = data_input; + item->key = key; + + int hash_index = generate_hash_code(key); + + while(block_hashtable[hash_index] != NULL && block_hashtable[hash_index]->key != -1) { + ++hash_index; + + hash_index %= SIZE; + } + + block_hashtable[hash_index] = item; +} + +struct block_wrap* remove_block_from_hashtable(int block_num) { + + int hash_index = generate_hash_code(block_num); + + while(block_hashtable[hash_index] != NULL) { + + if(block_hashtable[hash_index]->key == block_num) { + struct block_wrap* temp = block_hashtable[hash_index]; + + block_hashtable[hash_index] = default_block_wrap; + + return temp; + } + + ++hash_index; + + hash_index %= SIZE; + } + + return NULL; +} + +void print_cache() { + int i = 0; + + for(i = 0; ikey,block_hashtable[i]->key); + else + printf(" ~~ "); + } + + printf("\n"); +} + + +void enqueue_block(struct block_info * x) { + //Puts to end. + if(block_front == NULL && block_rear == NULL){ + block_front = block_rear = x; + block_front->prev = NULL; + block_rear->next = NULL; + return; + } + block_rear->next = x; + x->prev = block_rear; + block_rear = x; + block_rear->next = NULL; +} + + +void dequeue_block() { + //Eliminate the block_front; + if(block_front == NULL) { + printf("Queue is Empty\n"); + return; + } + if(block_front == block_rear) { + block_front = block_rear = NULL; + }else { + block_front->next->prev = NULL; + block_front = block_front->next; + block_front->prev = NULL; + } + +} + +void remove_queue_block(struct block_info * x) { + if(x->prev != NULL && x->next != NULL){ + x->prev->next = x->next; + x->next->prev = x->prev; + }else if(x->prev != NULL && x->next == NULL) { + block_rear = block_rear->prev; + block_rear->next = NULL; + }else if(x->prev == NULL && x->next != NULL) { + dequeue_block(); + } +} + +void Print() { + struct block_info* temp = block_front; + while(temp != NULL) { + printf("%d\n",temp->block_number); + temp = temp->next; + } + free(temp); +} + + +void init() { + current_blockcache_number = 0; + block_front = NULL; + block_rear = NULL; + default_block_wrap = (struct block_wrap*) malloc(sizeof(struct block_wrap)); + default_block_wrap->key = -1; + + default_block_info = (struct block_info*) malloc(sizeof(struct block_info)); + default_block_info->block_number = -1; +} + +struct block_info* get_lru_block(int block_num) { + struct block_wrap* result = get_block(block_num); + if(result == NULL) { + return default_block_info; + }else{ + //Recently used. + remove_queue_block(result->block_data); + enqueue_block(result->block_data); + // put_to_block_front(result); + + return result->block_data; + } +} + +void evict_block(){ + //Test whether there is a key to be evict_blocked. + if(current_blockcache_number == BLOCK_CACHESIZE) { + int to_be_removed_key = block_front->block_number; + //Here should be another method sync to write inode back to the disk. + + + + + + // if(block_front->dirty == 1) { + // WriteSector(block_front->block_number, (void*)(block_front->data)); + // } + dequeue_block(); + remove_block_from_hashtable(to_be_removed_key); + //Decrement the current block cache number by 1. + current_blockcache_number--; + } +} + +void set_lru_block(int block_num, struct block_info* input_block) { + if(get_block(block_num) == NULL) { + // printf("Key not found\n"); + //Determines whether a key needs to be removed. + evict_block(); + enqueue_block(input_block); + put_block_to_hashtable(block_num, input_block); + current_blockcache_number++; + return; + }else{ + + remove_queue_block(get_block(block_num)->block_data); + enqueue_block(input_block); + put_block_to_hashtable(block_num, input_block); + + return; + } + +} + +void clear_lru_block() { + int i; + for (i = 0;i block_number = 1; + x1->dirty = 0; + + struct block_info *x2 = (struct block_info*) malloc(sizeof(struct block_info)); + x2->block_number = 2; + x2->dirty = 1; + struct block_info *x3 = (struct block_info*) malloc(sizeof(struct block_info)); + x3->block_number = 3; + x3->dirty = 1; + struct block_info *x4 = (struct block_info*) malloc(sizeof(struct block_info)); + x4->block_number = 4; + x4->dirty = 1; + struct block_info *x5 = (struct block_info*) malloc(sizeof(struct block_info)); + x5->block_number = 5; + + set_lru_block(1, x1); + set_lru_block(2, x2); + // set_lru_block(3, x3); + // set_lru_block(4, x4); + // set_lru_block(5, x5); + + // printf("%d\n", current_blockcache_number); + // print_cache(); + //Test case 0: + printf("----test case 0----\n"); + printf("%d\n", get_lru_block(1)->block_number); + set_lru_block(3, x3); + printf("%d\n", get_lru_block(2)->block_number); + set_lru_block(4, x4); + printf("%d\n", get_lru_block(1)->block_number); + printf("%d\n", get_lru_block(3)->block_number); + printf("%d\n", get_lru_block(4)->block_number); + // Print(); + + + //Test case 1: + printf("----test case 1----\n"); + enqueue_block(x1); + enqueue_block(x2); + enqueue_block(x3); + enqueue_block(x4); + enqueue_block(x5); + if(block_front->prev == NULL && block_rear->next == NULL) { + printf("There is nothing in block_front of the linked list and after the linked list.\n"); + } + //Prints the list. + Print(); + printf("----test case 2----\n"); + //Result should be 1, 2, 3, 4, 5 + + //Test case 2: + dequeue_block(); + if(block_front->prev == NULL && block_rear->next == NULL) { + printf("There is nothing in block_front of the linked list and after the linked list.\n"); + } + + Print(); + //Result should be 2, 3 + //Test case 3; + printf("----test case 3----\n"); + remove_queue_block(block_front); + if(block_front->prev == NULL && block_rear->next == NULL) { + printf("There is nothing in block_front of the linked list and after the linked list.\n"); + } + Print(); + //Result should be 3, 4, 5 + printf("----test case 4----\n"); + remove_queue_block(block_front); + if(block_front->prev == NULL && block_rear->next == NULL) { + printf("There is nothing in block_front of the linked list and after the linked list.\n"); + } + Print(); + + + printf("----test case 5----\n"); + remove_queue_block(block_rear); + if(block_front->prev == NULL && block_rear->next == NULL) { + printf("There is nothing in block_front of the linked list and after the linked list.\n"); + } + Print(); + + printf("----test case 6----\n"); + enqueue_block(x1); + enqueue_block(x2); + enqueue_block(x3); + remove_queue_block(block_front->next->next); + if(block_front->prev == NULL && block_rear->next == NULL) { + printf("There is nothing in block_front of the linked list and after the linked list.\n"); + } + Print(); + + clear_lru_block(); + printf("----test case 7----\n"); + set_lru_block(1, x1); + set_lru_block(2, x2); + printf("goodm\n"); + struct block_info* tmp = get_lru_block(1); + printf("%d\n", tmp->block_number); + printf("%d\n", tmp->dirty); + printf("-------------------\n"); + set_lru_block(1, x3); + Print(); + +} diff --git a/tests/lru_inode.c b/tests/lru_inode.c new file mode 100755 index 0000000..20c5929 --- /dev/null +++ b/tests/lru_inode.c @@ -0,0 +1,348 @@ +#include +#include +#include +#include + +#define SIZE 100 +#define BLOCKSIZE 32 +#define INODE_CACHESIZE 2 // Needs to be modified to another number. +int current_inodecache_number; + + +//Dirty = 1 means it is dirty +//Dirty = 0 means it is not dirty + +struct inode_info { + int dirty; + int inode_number; + struct inode_info *next; + struct inode_info *prev; + struct inode *inode_val; //From the filesystem.h + char data[BLOCKSIZE]; +}; + +struct inode_wrap { + int key; + struct inode_info* inode_data; +}; +struct inode_info* inode_front; +struct inode_info* inode_rear; + +struct inode_wrap* inode_hashtable[SIZE]; +struct inode_wrap* default_inode_wrap; +struct inode_info* default_inode_info; +// struct inode_wrap* item; + +int generate_hash_code(int key) { + //Hash code generator. + return key % SIZE; +} + +struct inode_wrap *get_inode(int key) { + //Obtains the hash code. + int hash_index = generate_hash_code(key); + + while(inode_hashtable[hash_index] != NULL) { + + if(inode_hashtable[hash_index]->key == key){ + return inode_hashtable[hash_index]; + } + + ++hash_index; + + hash_index %= SIZE; + } + + return NULL; +} + +void put_inode_to_hashtable(int key, struct inode_info* data_input) { + + struct inode_wrap *item = (struct inode_wrap*) malloc(sizeof(struct inode_wrap)); + item->inode_data = data_input; + item->key = key; + + int hash_index = generate_hash_code(key); + + while(inode_hashtable[hash_index] != NULL && inode_hashtable[hash_index]->key != -1) { + ++hash_index; + + hash_index %= SIZE; + } + + inode_hashtable[hash_index] = item; +} + +struct inode_wrap* remove_inode_from_hashtable(int inode_num) { + + int hash_index = generate_hash_code(inode_num); + + while(inode_hashtable[hash_index] != NULL) { + + if(inode_hashtable[hash_index]->key == inode_num) { + struct inode_wrap* temp = inode_hashtable[hash_index]; + + inode_hashtable[hash_index] = default_inode_wrap; + + return temp; + } + + ++hash_index; + + hash_index %= SIZE; + } + + return NULL; +} + +void print_cache() { + int i = 0; + + for(i = 0; ikey,inode_hashtable[i]->key); + else + printf(" ~~ "); + } + + printf("\n"); +} + + +void enqueue_inode(struct inode_info * x) { + //Puts to end. + if(inode_front == NULL && inode_rear == NULL){ + inode_front = inode_rear = x; + inode_front->prev = NULL; + inode_rear->next = NULL; + return; + } + inode_rear->next = x; + x->prev = inode_rear; + inode_rear = x; + inode_rear->next = NULL; +} + + +void dequeue_inode() { + //Eliminate the inode_front; + if(inode_front == NULL) { + printf("Queue is Empty\n"); + return; + } + if(inode_front == inode_rear) { + inode_front = inode_rear = NULL; + }else { + inode_front->next->prev = NULL; + inode_front = inode_front->next; + inode_front->prev = NULL; + } + +} + +void remove_queue_inode(struct inode_info * x) { + if(x->prev != NULL && x->next != NULL){ + + x->prev->next = x->next; + x->next->prev = x->prev; + }else if(x->prev != NULL && x->next == NULL) { + // printf("good\n"); + inode_rear = inode_rear->prev; + inode_rear->next = NULL; + }else if(x->prev == NULL && x->next != NULL) { + dequeue_inode(); + } +} + +void Print() { + struct inode_info* temp = inode_front; + while(temp != NULL) { + printf("%d\n",temp->inode_number); + temp = temp->next; + } + free(temp); +} + + +void init() { + current_inodecache_number = 0; + inode_front = NULL; + inode_rear = NULL; + default_inode_wrap = (struct inode_wrap*) malloc(sizeof(struct inode_wrap)); + default_inode_wrap->key = -1; + + default_inode_info = (struct inode_info*) malloc(sizeof(struct inode_info)); + default_inode_info->inode_number = -1; +} + +struct inode_info* get_lru_inode(int inode_num) { + struct inode_wrap* result = get_inode(inode_num); + if(result == NULL) { + return default_inode_info; + }else{ + //Recently used. + remove_queue_inode(result->inode_data); + enqueue_inode(result->inode_data); + // put_to_inode_front(result); + + return result->inode_data; + } +} + +void evict_inode(){ + //Test whether there is a key to be evict_inodeed. + if(current_inodecache_number == INODE_CACHESIZE) { + int to_be_removed_key = inode_front->inode_number; + //Here should be another method sync to write inode back to the disk. + + + + + + // if(inode_front->dirty == 1) { + // WriteSector(inode_front->inode_number, (void*)(inode_front->data)); + // } + dequeue_inode(); + remove_inode_from_hashtable(to_be_removed_key); + //Decrement the current block cache number by 1. + current_inodecache_number--; + } +} + +void set_lru_inode(int inode_num, struct inode_info* input_inode) { + if(get_inode(inode_num) == NULL) { + //Determines whether a key needs to be removed. + evict_inode(); + enqueue_inode(input_inode); + put_inode_to_hashtable(inode_num, input_inode); + current_inodecache_number++; + return; + }else{ + + remove_queue_inode(get_inode(inode_num)->inode_data); + enqueue_inode(input_inode); + put_inode_to_hashtable(inode_num, input_inode); + + return; + } + +} + +void clear_lru_inode() { + int i; + for (i = 0;i inode_number = 1; + + struct inode_info *x2 = (struct inode_info*) malloc(sizeof(struct inode_info)); + x2->inode_number = 2; + + struct inode_info *x3 = (struct inode_info*) malloc(sizeof(struct inode_info)); + x3->inode_number = 3; + + struct inode_info *x4 = (struct inode_info*) malloc(sizeof(struct inode_info)); + x4->inode_number = 4; + + struct inode_info *x5 = (struct inode_info*) malloc(sizeof(struct inode_info)); + x5->inode_number = 5; + + set_lru_inode(1, x1); + set_lru_inode(2, x2); + // set_lru_inode(3, x3); + // set_lru_inode(4, x4); + // set_lru_inode(5, x5); + + // printf("%d\n", current_inodecache_number); + // print_cache(); + //Test case 0: + // printf("----test case 0----\n"); + // printf("%d\n", get_lru_inode(1)->inode_number); + // set_lru_inode(3, x3); + // printf("%d\n", get_lru_inode(2)->inode_number); + // set_lru_inode(4, x4); + // printf("%d\n", get_lru_inode(1)->inode_number); + // printf("%d\n", get_lru_inode(3)->inode_number); + // printf("%d\n", get_lru_inode(4)->inode_number); + // set_lru_inode(4, x1); + // printf("%d\n", get_lru_inode(4)->inode_number); + // Print(); + + + //Test case 1: + printf("----test case 1----\n"); + enqueue_inode(x1); + enqueue_inode(x2); + enqueue_inode(x3); + enqueue_inode(x4); + enqueue_inode(x5); + if(inode_front->prev == NULL && inode_rear->next == NULL) { + printf("There is nothing in inode_front of the linked list and after the linked list.\n"); + } + //Prints the list. + Print(); + printf("----test case 2----\n"); + //Result should be 1, 2, 3, 4, 5 + + //Test case 2: + dequeue_inode(); + if(inode_front->prev == NULL && inode_rear->next == NULL) { + printf("There is nothing in inode_front of the linked list and after the linked list.\n"); + } + + Print(); + //Result should be 2, 3 + //Test case 3; + printf("----test case 3----\n"); + remove_queue_inode(inode_front); + if(inode_front->prev == NULL && inode_rear->next == NULL) { + printf("There is nothing in inode_front of the linked list and after the linked list.\n"); + } + Print(); + //Result should be 3, 4, 5 + printf("----test case 4----\n"); + remove_queue_inode(inode_front); + if(inode_front->prev == NULL && inode_rear->next == NULL) { + printf("There is nothing in inode_front of the linked list and after the linked list.\n"); + } + Print(); + + + printf("----test case 5----\n"); + remove_queue_inode(inode_rear); + if(inode_front->prev == NULL && inode_rear->next == NULL) { + printf("There is nothing in inode_front of the linked list and after the linked list.\n"); + } + Print(); + + printf("----test case 6----\n"); + enqueue_inode(x1); + enqueue_inode(x2); + enqueue_inode(x3); + remove_queue_inode(inode_front->next->next); + if(inode_front->prev == NULL && inode_rear->next == NULL) { + printf("There is nothing in inode_front of the linked list and after the linked list.\n"); + } + Print(); + clear_lru_inode(); + printf("----test case 7----\n"); + set_lru_inode(1, x1); + set_lru_inode(2, x2); + printf("goodm\n"); + printf("%d\n", get_lru_inode(1)->inode_number); + printf("-------------------\n"); + set_lru_inode(1, x4); + Print(); + +} \ No newline at end of file diff --git a/tests/sample1 b/tests/sample1 new file mode 100755 index 0000000..194721e Binary files /dev/null and b/tests/sample1 differ diff --git a/tests/sample1.c b/tests/sample1.c new file mode 100755 index 0000000..98722fb --- /dev/null +++ b/tests/sample1.c @@ -0,0 +1,36 @@ +#include +#include + +int +main() +{ + int fd; + + fd = Create("a"); + Write(fd, "aaaaaaaaaaaaaaaa", 16); + Close(fd); + + fd = Create("b"); + Write(fd, "bbbbbbbbbbbbbbbb", 16); + Close(fd); + + fd = Create("c"); + Write(fd, "cccccccccccccccc", 16); + Close(fd); + + MkDir("dir"); + + fd = Create("/dir/x"); + Write(fd, "xxxxxxxxxxxxxxxx", 16); + Close(fd); + + fd = Create("/dir/y"); + Write(fd, "yyyyyyyyyyyyyyyy", 16); + Close(fd); + + fd = Create("/dir/z"); + Write(fd, "zzzzzzzzzzzzzzzz", 16); + Close(fd); + + Shutdown(); +} diff --git a/tests/sample2 b/tests/sample2 new file mode 100755 index 0000000..f885ee9 Binary files /dev/null and b/tests/sample2 differ diff --git a/tests/sample2.c b/tests/sample2.c new file mode 100755 index 0000000..5bcde5c --- /dev/null +++ b/tests/sample2.c @@ -0,0 +1,60 @@ +#include + +#include +#include + +/* + * Create empty files named "file00" through "file31" in "/". + */ +int +main() +{ + int fd; + int i; + char name[7]; + char* msg1 = " Hello, world! It's a great day to be writing yalnix file systems\n"; + printf("strlen %d\n", strlen(msg1)); + + for (i = 0; i < 1; i++) { + sprintf(name, "file%02d", i); + fd = Create(name); + Close(fd); + } + + + for (i = 0; i < 1; i+= 2) { + printf("Starting file %d\n", i); + sprintf(name, "file%02d", i); + fd = Open(name); + char* msg0 = " Hello, world! It's a great day to be writing yalnix file systems\n"; + char msg[strlen(msg0) + 1]; + memcpy(msg, msg0, strlen(msg0)); + int j; + int bytes_written = 0; + for(j = 0; j < 25 * 512 / strlen(msg); j++){ + msg[0] = '0' + j / 100; + msg[1] = '0' + (j % 100) / 10; + msg[2] = '0' + j % 10; + bytes_written += Write(fd, msg, strlen(msg)); + } + printf("Bytes Written: %d\n", bytes_written); + Seek(fd, 0, SEEK_SET); + int bytes_read = 0; + while(1){ + int len = 13000; + char read[len + 1]; + memset(read, '\0', len+1); + int result = Read(fd, read, len); + bytes_read += result; + // printf("\nbytes read %d\n\n", result); + printf("%s", read); + if(result == 0) + break; + } + printf("\n"); + printf("Bytes Read: %d\n", bytes_read); + Close(fd); + } + + Shutdown(); +} diff --git a/tests/tcreate b/tests/tcreate new file mode 100755 index 0000000..4afe04d Binary files /dev/null and b/tests/tcreate differ diff --git a/tests/tcreate.c b/tests/tcreate.c new file mode 100755 index 0000000..54393c6 --- /dev/null +++ b/tests/tcreate.c @@ -0,0 +1,23 @@ +#include +#include +#include + +#include +#include + +int +main() +{ + int err; + write(2, "A\n", 2); + err = Create("/foo"); + fprintf(stderr, "Create returned %d\n", err); + + Sync(); + Delay(3); + fprintf(stderr, "Done with Sync\n"); + +/* Shutdown(); */ + + exit(0); +} diff --git a/tests/tcreate2 b/tests/tcreate2 new file mode 100755 index 0000000..109b55c Binary files /dev/null and b/tests/tcreate2 differ diff --git a/tests/tcreate2.c b/tests/tcreate2.c new file mode 100755 index 0000000..59ce038 --- /dev/null +++ b/tests/tcreate2.c @@ -0,0 +1,17 @@ +#include + +#include +#include + +/* After running this, try topen2 and/or tunlink2 */ + +int +main() +{ + printf("\n%d\n\n", Create("/foo")); + printf("\n%d\n\n", Create("/bar")); + printf("\n%d\n\n", Create("/foo")); + printf("\n%d\n\n", Create("/foo/zzz")); + + Shutdown(); +} diff --git a/tests/test1 b/tests/test1 new file mode 100755 index 0000000..1f28365 Binary files /dev/null and b/tests/test1 differ diff --git a/tests/test1.c b/tests/test1.c new file mode 100755 index 0000000..8df5e05 --- /dev/null +++ b/tests/test1.c @@ -0,0 +1,39 @@ +#include +#include +#include + +#include +#include +#include + +int main(int argc, char** argv){ + + printf("Starting Test 1\n"); + + char* dir_name1 = "/spam1"; + char* dir_name2 = "/spam1/spam2"; + char* file_name1 = "/spam1/spam2/foo1"; + char* file_name2 = "foo2"; + + int result1 = MkDir(dir_name1); + int result2 = MkDir(dir_name2); + int fd1 = Create(file_name1); + int fd2 = Create(file_name2); + + printf("result %d\n", result1); + printf("result %d\n", result2); + printf("result %d\n", fd1); + printf("result %d\n", fd2); + + char* write1 = "Hello, world!\n"; + Write(fd1, write1, strlen(write1)); + + Close(fd1); + int fd1B = Open(file_name1); + + char read1[100]; + Read(fd1B, read1, 5); + printf("File contents %s\n", read1); + Shutdown(); + return 0; +} diff --git a/tests/test2 b/tests/test2 new file mode 100755 index 0000000..937f19e Binary files /dev/null and b/tests/test2 differ diff --git a/tests/test2.c b/tests/test2.c new file mode 100755 index 0000000..358becc --- /dev/null +++ b/tests/test2.c @@ -0,0 +1,27 @@ +#include +#include +#include + +#include +#include +#include + +int main(int argc, char** argv){ + + printf("Starting Test 2\n"); + + int fd = Create("foo1"); + + char* msg1 = "Hello, world!\n"; + char* msg2 = "This should not be overwriting!\n"; + + Write(fd, msg1, strlen(msg1)); + Write(fd, msg2, strlen(msg2)); + + char readbuf[100]; + Seek(fd, 0, SEEK_SET); + int result = Read(fd, readbuf, 100); + printf("Read %d: %s\n", result, readbuf); + Shutdown(); + return 0; +} diff --git a/tests/tlink b/tests/tlink new file mode 100755 index 0000000..543c1d7 Binary files /dev/null and b/tests/tlink differ diff --git a/tests/tlink.c b/tests/tlink.c new file mode 100755 index 0000000..105b756 --- /dev/null +++ b/tests/tlink.c @@ -0,0 +1,18 @@ +#include + +#include +#include + +int +main() +{ + int status; + + status = Create("/a"); + printf("Create status %d\n", status); + + status = Link("/a", "/b"); + printf("Link status %d\n", status); + + Shutdown(); +} diff --git a/tests/tls b/tests/tls new file mode 100755 index 0000000..da6511a Binary files /dev/null and b/tests/tls differ diff --git a/tests/tls.c b/tests/tls.c new file mode 100755 index 0000000..fd28b32 --- /dev/null +++ b/tests/tls.c @@ -0,0 +1,93 @@ +#include +#include + +#include +#include +#include + +/* + * Works like "ls". + * + * Uncomment #define below to test symbolic links too. + */ + +#define TEST_SYMLINKS + +int +main(int argc, char **argv) +{ + int fd; + int nch; + struct dir_entry entry; + char *name; + struct Stat sb; + char buffer[DIRNAMELEN+1]; +#ifdef TEST_SYMLINKS + char link[MAXPATHNAMELEN+1]; +#endif + char typechar; + + name = (argc > 1) ? argv[1] : "."; + if (ChDir(name) == ERROR) { + fprintf(stderr, "Can't ChDir to %s\n", name); + Shutdown(); + Exit(1); + } + + if ((fd = Open(".")) == ERROR) { + fprintf(stderr, "Can't Open . in %s\n", name); + Shutdown(); + Exit(1); + } + + while (1) { + nch = Read(fd, (char *)&entry, sizeof(entry)); + if (nch == 0) + break; + else if (nch < 0) { + fprintf(stderr, "ERROR Reading from directory\n"); + Shutdown(); + Exit(1); + } else if (nch != sizeof(entry)) { + fprintf(stderr, "Read wrong byte count %d\n", nch); + Shutdown(); + Exit(1); + } + if (entry.inum == 0) continue; + bcopy(entry.name, buffer, DIRNAMELEN); + buffer[DIRNAMELEN] = '\0'; + /* was LinkStat, when supporting symlinks ??? */ + if (Stat(buffer, &sb) == ERROR) { + fprintf(stderr, "Can't LinkStat %s\n", buffer); + Shutdown(); + Exit(1); + } + switch (sb.type) { + case INODE_REGULAR: typechar = ' '; break; + case INODE_DIRECTORY: typechar = 'd'; break; +#ifdef TEST_SYMLINKS + case INODE_SYMLINK: typechar = 's'; break; +#endif + default: typechar = '?'; break; + } + printf("%4d %c %3d %5d %s", + entry.inum, typechar, sb.nlink, sb.size, buffer); +#ifdef TEST_SYMLINKS + if (sb.type == INODE_SYMLINK) { + nch = ReadLink(buffer, link, sizeof(link)); + if (nch == ERROR) { + fprintf(stderr, "Can't ReadLink %s\n", + buffer); + Shutdown(); + Exit(1); + } + link[nch] = '\0'; + printf(" -> %s\n", link); + } + else +#endif + printf("\n"); + } + + Shutdown(); +} diff --git a/tests/topen2 b/tests/topen2 new file mode 100755 index 0000000..2fe914b Binary files /dev/null and b/tests/topen2 differ diff --git a/tests/topen2.c b/tests/topen2.c new file mode 100755 index 0000000..ad5bf84 --- /dev/null +++ b/tests/topen2.c @@ -0,0 +1,17 @@ +#include + +#include +#include + +/* Try tcreate2 before this, or try this just by itself */ + +int +main() +{ + printf("\n%d\n\n", Open("/foo")); + printf("\n%d\n\n", Open("/bar")); + printf("\n%d\n\n", Open("/foo")); + printf("\n%d\n\n", Open("/foo/zzz")); + + Shutdown(); +} diff --git a/tests/tsymlink b/tests/tsymlink new file mode 100755 index 0000000..2a4c4ff Binary files /dev/null and b/tests/tsymlink differ diff --git a/tests/tsymlink.c b/tests/tsymlink.c new file mode 100755 index 0000000..08eeaac --- /dev/null +++ b/tests/tsymlink.c @@ -0,0 +1,54 @@ +#include + +#include +#include + +int +main() +{ + int status; + static char buffer[1024]; + struct Stat sb; + int fd; + + status = Create("/a"); + printf("Create status %d\n", status); + + status = SymLink("/a", "/b"); + printf("SymLink status %d\n", status); + + status = ReadLink("/b", buffer, sizeof(buffer)); + printf("ReadLink status %d\n", status); + printf("link = '%s'\n", buffer); + + status = Stat("/a", &sb); + printf("Stat status %d\n", status); + printf("/a: inum %d type %d size %d nlink %d\n\n", + sb.inum, sb.type, sb.size, sb.nlink); + + status = Stat("/b", &sb); + printf("Stat status %d\n", status); + printf("/b: inum %d type %d size %d nlink %d\n", + sb.inum, sb.type, sb.size, sb.nlink); + + status = SymLink("/00/11/22/33/44/55/66/77/88/99", "/xxx"); + printf("SymLink status %d\n", status); + + status = SymLink("00/11/22/33/44/55/66/77/88/99", "yyy"); + printf("SymLink status %d\n", status); + + fd = Open("/a"); + printf("Open /a status %d\n", fd); + + status = Write(fd, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 27); + printf("Write /a status %d\n", status); + + fd = Open("b"); + printf("Open b status %d\n", fd); + + status = Read(fd, buffer, sizeof(buffer)); + printf("Read b status %d\n", status); + printf("buffer = '%s'\n", buffer); + + Shutdown(); +} diff --git a/tests/tunlink2 b/tests/tunlink2 new file mode 100755 index 0000000..9cc9771 Binary files /dev/null and b/tests/tunlink2 differ diff --git a/tests/tunlink2.c b/tests/tunlink2.c new file mode 100755 index 0000000..c40a54e --- /dev/null +++ b/tests/tunlink2.c @@ -0,0 +1,17 @@ +#include + +#include +#include + +/* Try tcreate2 before this, or try this just by itself */ + +int +main() +{ + printf("\n%d\n\n", Unlink("/bar")); + printf("\n%d\n\n", Unlink("/bar")); + printf("\n%d\n\n", Unlink("/foo/abc")); + printf("\n%d\n\n", Unlink("/foo")); + + Shutdown(); +} diff --git a/tests/writeread b/tests/writeread new file mode 100755 index 0000000..540f5eb Binary files /dev/null and b/tests/writeread differ diff --git a/tests/writeread.c b/tests/writeread.c new file mode 100755 index 0000000..d606dcc --- /dev/null +++ b/tests/writeread.c @@ -0,0 +1,43 @@ +#include + +#include +#include + +int +main() +{ + int fd; + int nch; + int status; + char ch; + + fd = Create("/xxxxxx"); + printf("Create fd %d\n", fd); + + nch = Write(fd, "abcdefghijklmnopqrstuvwxyz", 26); + printf("Write nch %d\n", nch); + + nch = Write(fd, "0123456789", 10); + printf("Write nch %d\n", nch); + + status = Close(fd); + printf("Close status %d\n", status); + + Sync(); + + fd = Open("/xxxxxx"); + printf("Open fd %d\n", fd); + + while (1) { + nch = Read(fd, &ch, 1); + printf("Read nch %d\n", nch); + if (nch <= 0) + break; + printf("ch 0x%x '%c'\n", ch, ch); + } + + status = Close(fd); + printf("Close status %d\n", status); + + Shutdown(); +} diff --git a/tlink b/tlink new file mode 100755 index 0000000..debf7c2 Binary files /dev/null and b/tlink differ diff --git a/tlink.c b/tlink.c new file mode 100755 index 0000000..105b756 --- /dev/null +++ b/tlink.c @@ -0,0 +1,18 @@ +#include + +#include +#include + +int +main() +{ + int status; + + status = Create("/a"); + printf("Create status %d\n", status); + + status = Link("/a", "/b"); + printf("Link status %d\n", status); + + Shutdown(); +} diff --git a/tls b/tls new file mode 100755 index 0000000..8e1f2fa Binary files /dev/null and b/tls differ diff --git a/tls.c b/tls.c new file mode 100755 index 0000000..bca9efb --- /dev/null +++ b/tls.c @@ -0,0 +1,94 @@ +#include +#include + +#include +#include +#include + +/* + * Works like "ls". + * + * Uncomment #define below to test symbolic links too. + */ + +/* #define TEST_SYMLINKS */ + +int +main(int argc, char **argv) +{ + int fd; + int nch; + struct dir_entry entry; + char *name; + struct Stat sb; + char buffer[DIRNAMELEN+1]; +#ifdef TEST_SYMLINKS + char link[MAXPATHNAMELEN+1]; +#endif + char typechar; + + name = (argc > 1) ? argv[1] : "."; + + if (ChDir(name) == ERROR) { + fprintf(stderr, "Can't ChDir to %s\n", name); + Shutdown(); + Exit(1); + } + + if ((fd = Open(".")) == ERROR) { + fprintf(stderr, "Can't Open . in %s\n", name); + Shutdown(); + Exit(1); + } + + while (1) { + nch = Read(fd, (char *)&entry, sizeof(entry)); + if (nch == 0) + break; + else if (nch < 0) { + fprintf(stderr, "ERROR Reading from directory\n"); + Shutdown(); + Exit(1); + } else if (nch != sizeof(entry)) { + fprintf(stderr, "Read wrong byte count %d\n", nch); + Shutdown(); + Exit(1); + } + if (entry.inum == 0) continue; + bcopy(entry.name, buffer, DIRNAMELEN); + buffer[DIRNAMELEN] = '\0'; + /* was LinkStat, when supporting symlinks ??? */ + if (Stat(buffer, &sb) == ERROR) { + fprintf(stderr, "Can't LinkStat %s\n", buffer); + Shutdown(); + Exit(1); + } + switch (sb.type) { + case INODE_REGULAR: typechar = ' '; break; + case INODE_DIRECTORY: typechar = 'd'; break; +#ifdef TEST_SYMLINKS + case INODE_SYMLINK: typechar = 's'; break; +#endif + default: typechar = '?'; break; + } + printf("%4d %c %3d %5d %s", + entry.inum, typechar, sb.nlink, sb.size, buffer); +#ifdef TEST_SYMLINKS + if (sb.type == INODE_SYMLINK) { + nch = ReadLink(buffer, link, sizeof(link)); + if (nch == ERROR) { + fprintf(stderr, "Can't ReadLink %s\n", + buffer); + Shutdown(); + Exit(1); + } + link[nch] = '\0'; + printf(" -> %s\n", link); + } + else +#endif + printf("\n"); + } + + Shutdown(); +} diff --git a/topen2 b/topen2 new file mode 100755 index 0000000..eac2ef9 Binary files /dev/null and b/topen2 differ diff --git a/topen2.c b/topen2.c new file mode 100755 index 0000000..ad5bf84 --- /dev/null +++ b/topen2.c @@ -0,0 +1,17 @@ +#include + +#include +#include + +/* Try tcreate2 before this, or try this just by itself */ + +int +main() +{ + printf("\n%d\n\n", Open("/foo")); + printf("\n%d\n\n", Open("/bar")); + printf("\n%d\n\n", Open("/foo")); + printf("\n%d\n\n", Open("/foo/zzz")); + + Shutdown(); +} diff --git a/tsymlink b/tsymlink new file mode 100755 index 0000000..91cbeca Binary files /dev/null and b/tsymlink differ diff --git a/tsymlink.c b/tsymlink.c new file mode 100755 index 0000000..c5276c5 --- /dev/null +++ b/tsymlink.c @@ -0,0 +1,54 @@ +#include + +#include +#include + +int +main() +{ + int status; + static char buffer[1024]; + struct Stat sb; + int fd; + + status = Create("/a"); + printf("Create status %d\n", status); + + status = SymLink("/a", "/b"); + printf("SymLink status %d\n", status); + + status = ReadLink("/b", buffer, sizeof(buffer)); + printf("ReadLink status %d\n", status); + printf("link = '%s'\n", buffer); + + status = Stat("/a", &sb); + printf("Stat status %d\n", status); + printf("/a: inum %d type %d size %d nlink %d\n", + sb.inum, sb.type, sb.size, sb.nlink); + + status = Stat("/b", &sb); + printf("Stat status %d\n", status); + printf("/b: inum %d type %d size %d nlink %d\n", + sb.inum, sb.type, sb.size, sb.nlink); + + status = SymLink("/00/11/22/33/44/55/66/77/88/99", "/xxx"); + printf("SymLink status %d\n", status); + + status = SymLink("00/11/22/33/44/55/66/77/88/99", "yyy"); + printf("SymLink status %d\n", status); + + fd = Open("/a"); + printf("Open /a status %d\n", fd); + + status = Write(fd, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 27); + printf("Write /a status %d\n", status); + + fd = Open("b"); + printf("Open b status %d\n", fd); + + status = Read(fd, buffer, sizeof(buffer)); + printf("Read b status %d\n", status); + printf("buffer = '%s'\n", buffer); + + Shutdown(); +} diff --git a/tunlink2 b/tunlink2 new file mode 100755 index 0000000..d1b7883 Binary files /dev/null and b/tunlink2 differ diff --git a/tunlink2.c b/tunlink2.c new file mode 100755 index 0000000..c40a54e --- /dev/null +++ b/tunlink2.c @@ -0,0 +1,17 @@ +#include + +#include +#include + +/* Try tcreate2 before this, or try this just by itself */ + +int +main() +{ + printf("\n%d\n\n", Unlink("/bar")); + printf("\n%d\n\n", Unlink("/bar")); + printf("\n%d\n\n", Unlink("/foo/abc")); + printf("\n%d\n\n", Unlink("/foo")); + + Shutdown(); +} diff --git a/writeread b/writeread new file mode 100755 index 0000000..3ecc2e0 Binary files /dev/null and b/writeread differ diff --git a/writeread.c b/writeread.c new file mode 100755 index 0000000..d606dcc --- /dev/null +++ b/writeread.c @@ -0,0 +1,43 @@ +#include + +#include +#include + +int +main() +{ + int fd; + int nch; + int status; + char ch; + + fd = Create("/xxxxxx"); + printf("Create fd %d\n", fd); + + nch = Write(fd, "abcdefghijklmnopqrstuvwxyz", 26); + printf("Write nch %d\n", nch); + + nch = Write(fd, "0123456789", 10); + printf("Write nch %d\n", nch); + + status = Close(fd); + printf("Close status %d\n", status); + + Sync(); + + fd = Open("/xxxxxx"); + printf("Open fd %d\n", fd); + + while (1) { + nch = Read(fd, &ch, 1); + printf("Read nch %d\n", nch); + if (nch <= 0) + break; + printf("ch 0x%x '%c'\n", ch, ch); + } + + status = Close(fd); + printf("Close status %d\n", status); + + Shutdown(); +} diff --git a/yfs b/yfs new file mode 100755 index 0000000..4b91104 Binary files /dev/null and b/yfs differ diff --git a/yfs.c b/yfs.c new file mode 100755 index 0000000..39f0f1d --- /dev/null +++ b/yfs.c @@ -0,0 +1,949 @@ +#include "yfs.h" + +struct dir_entry create_entry(short inum, char* filename){ + + struct dir_entry entry; + entry.inum = inum; + + memset(&entry.name, '\0', DIRNAMELEN); + int namelen = strlen(filename); + if(namelen > DIRNAMELEN) + namelen = DIRNAMELEN; + + memcpy(&entry.name, filename, namelen); + return entry; +} + + +int check_dir(int dir_inum, char* filename){ + + struct inode_info* info = read_inode_from_disk(dir_inum); + if(info->inode_number == ERROR){ + fprintf(stderr, "ERROR: could not read directory\n"); + return ERROR; + } + + struct dir_entry entry; + int num_entries = info->inode_val->size / sizeof(struct dir_entry); + + int i; + for(i = 0; i < num_entries; i++){ + if(FSRead((void*)&entry, sizeof(entry), dir_inum, i * sizeof(struct dir_entry)) == ERROR){ + return ERROR; + } + if(strncmp(filename, entry.name, DIRNAMELEN) == 0){ + return entry.inum; + } + + } + return 0; +} + +int remove_from_dir(int dir_inum, int file_inum){ + struct inode_info* info = read_inode_from_disk(dir_inum); + if(info->inode_number == ERROR){ + fprintf(stderr, "ERROR: could not read directory\n"); + return ERROR; + } + + struct dir_entry entry; + int num_entries = info->inode_val->size / sizeof(struct dir_entry); + int i; + for(i = 2; i < num_entries; i++){ + if(FSRead((void*)&entry, sizeof(entry), dir_inum, i * sizeof(struct dir_entry)) == ERROR){ + return ERROR; + } + if(file_inum == entry.inum){ + char* null_str = "\0"; + struct dir_entry blank = create_entry(0, null_str); + FSWrite((void*)&blank, sizeof(blank), dir_inum, i * sizeof(struct dir_entry)); + return 0; + } + } + return ERROR; +} + +int convert_pathname_to_inode_number(char *pathname, int proc_inum) { + if(pathname == NULL ) { + return proc_inum; + } + int cur_inode; + char node_name[DIRNAMELEN + 1]; + memset(node_name,'\0',DIRNAMELEN + 1); + int sym_link_cnt = 0; + + //Means that it is an absolute pathname, so it starts with ROOTINODE. + if(pathname[0] == '/') { + cur_inode = ROOTINODE; + } + else{ + cur_inode = proc_inum; + } + + //Kills all the initial slashes. + while(*pathname == '/'){ + pathname++; + } + + while(strlen(pathname) != 0) { + int len_path = strlen(pathname); + memset(node_name,'\0',DIRNAMELEN + 1); + + while(len_path > 0 && *pathname == '/') { + pathname++; + len_path--; + } + int i = 0; + while(len_path > 0 && *pathname != '/') { + node_name[i] = *pathname; + i++; + pathname++; + len_path--; + } + struct inode_info* n; + int sub_inum = check_dir(cur_inode, node_name); + if (sub_inum<=0) { + fprintf(stderr, "ERROR: failed to parse given path\n"); + return ERROR; + } + n = read_inode_from_disk(sub_inum); + //If the sub inode is a symbolic link. + if(n->inode_val->type == INODE_SYMLINK) { + if(sym_link_cnt >= MAXSYMLINKS) { + fprintf(stderr, "ERROR: too many symlinks in pathname\n"); + return ERROR; + }else{ + int data_size = n->inode_val->size; + char* new_pathname = (char*)calloc(sizeof(char) * data_size + len_path + 1, 1); + struct block_info* b = read_block_from_disk(n->inode_val->direct[0]); + memcpy(new_pathname, b->data, data_size); + + // append the rest of the unprocessed path name + if(len_path > 0){ + strcat(new_pathname, "/"); + strcat(new_pathname, pathname); + } + pathname = new_pathname; + + sym_link_cnt++; + // if symlink points to absolute, then reset current node to root + if(new_pathname[0] == '/'){ + cur_inode = ROOTINODE; + continue; + } + } + } + cur_inode = sub_inum; + } + return cur_inode; +} + +void print_dir(int dir_inum){ + + struct inode_info* info = read_inode_from_disk(dir_inum); + if(info->inode_number == ERROR){ + fprintf(stderr, "ERROR: could not read directory\n"); + } + + struct dir_entry entry; + int num_entries = info->inode_val->size / sizeof(struct dir_entry); + + printf("\n---- directory %d ----\n", dir_inum); + + int i; + for(i = 0; i < num_entries; i++){ + FSRead((void*)&entry, sizeof(entry), dir_inum, i * sizeof(struct dir_entry)); + printf("%d - %s\n", entry.inum, entry.name); + } + printf("----------------------\n\n"); +} + + +void print_file_blocks(short inum){ + struct inode_info* info = read_inode_from_disk(inum); + int num_blocks = info->inode_val->size / BLOCKSIZE; + + printf("---- Blocks allocated for file %d -----\n", inum); + + int i; + for(i = 0; i < num_blocks && i < NUM_DIRECT; i++){ + printf("%d : %d\n", i, info->inode_val->direct[i]); + } + + if(i >= num_blocks) + return; + + struct block_info* indirect_info = read_block_from_disk(info->inode_val->indirect); + int* indirect = (int*)indirect_info->data; + for(; i < num_blocks; i++){ + printf("%d : %d\n", i, indirect[i-NUM_DIRECT]); + } +} + +int get_free_block() { + int i ; + for ( i = 0; i < NUM_BLOCKS; ++i){ + if(free_blocks[i] == FREE) { + free_blocks[i] = TAKEN; + return i; + } + + } + // if no free blocks found, attempt to claim blocks from deleted files + sync(); + init_free(); + for ( i = 0; i < NUM_BLOCKS; ++i){ + if(free_blocks[i] == FREE) { + return i; + } + } + + fprintf(stderr, "ERROR: No space left on file system\n"); + return ERROR; +} + +// allocate space for the file_inode to hold up to "newsize" data +int grow_file(struct inode_info* info, int newsize){ + struct inode* file_inode = info->inode_val; + info->dirty = 1; + if(newsize < file_inode->size){ + return 0; + } + + info->dirty = 1; + // round filesize up to the next blocksize + int current = ((file_inode->size + (BLOCKSIZE-1)) / BLOCKSIZE) * BLOCKSIZE; + // fill up direct blocks first + if(current < BLOCKSIZE * NUM_DIRECT){ + while(current < BLOCKSIZE * NUM_DIRECT && current < newsize){ + // assign a new block in direct + int free_block = get_free_block(); + if(free_block == ERROR) { + return ERROR; + } + + struct block_info* info = read_block_from_disk(free_block); + info->dirty = 1; + memset(info->data, '\0', BLOCKSIZE); + + file_inode->direct[current / BLOCKSIZE] = free_block; + current += BLOCKSIZE; + } + } + + // If this is the first time growing into indirect size then allocate indirect block + if(current < newsize && current == BLOCKSIZE * NUM_DIRECT){ + int new_indirect = get_free_block(); + if(new_indirect == ERROR) + return ERROR; + file_inode->indirect = new_indirect; + } + + // if direct blocks not enough, then access indirect blocks + if(current < newsize){ + int big_block_num = file_inode->indirect; + struct block_info * block_indirect = read_block_from_disk(big_block_num); + block_indirect->dirty = 1; + int * int_array = (int*)(block_indirect->data); + + while(current < BLOCKSIZE * (NUM_DIRECT + BLOCKSIZE / sizeof(int)) && current < newsize ) { + int free_block = get_free_block(); + if(free_block == ERROR) { + return ERROR; + } + int_array[current / BLOCKSIZE - NUM_DIRECT] = free_block; + current += BLOCKSIZE; + } + } + file_inode->size = newsize; + return 0; +} + +// returns a pointer to the data starting at "position" in the file described by "file_inode" +char* get_data_at_position(struct inode_info* info, int position, int set_dirty){ + struct inode* file_inode = info->inode_val; + if(position > file_inode->size){ + fprintf(stderr, "ERROR: trying to read past size of file"); + return NULL; + } + + int file_block_num = position / BLOCKSIZE; + + // if position is within direct blocks + if(file_block_num < NUM_DIRECT){ + struct block_info* direct_info = read_block_from_disk(file_inode->direct[file_block_num]); + if(direct_info->dirty != 1 && set_dirty == 1) + direct_info->dirty = set_dirty; + return direct_info->data + position % BLOCKSIZE; + } + + // if position is within indirect blocks + struct block_info* indirect_info = read_block_from_disk(file_inode->indirect); + int target_num = ((int*)(indirect_info->data))[file_block_num - NUM_DIRECT]; + + struct block_info* target_info = read_block_from_disk(target_num); + target_info->dirty = set_dirty; + return ((char*)(target_info->data)) + position % BLOCKSIZE; +} + +int add_directory_entry(short dir_inum, struct dir_entry new_entry){ + struct inode_info* dir_info = read_inode_from_disk(dir_inum); + dir_info->dirty = 1; + + if(dir_info->inode_number == -1 || dir_info->inode_val->type != INODE_DIRECTORY){ + fprintf(stderr, "ERROR: not a valid directory inode number\n"); + } + + int dir_size = dir_info->inode_val->size; + int position = 0; + struct dir_entry old_entry; + + // look for a blank entry in the middle of the directory first and overwrite with new entry + while(position < dir_size){ + FSRead(&old_entry, sizeof(old_entry), dir_inum, position); + if(old_entry.inum == 0){ + int success = FSWrite(&new_entry, sizeof(new_entry), dir_inum, position); + if(success != ERROR){ + struct inode_info* info = read_inode_from_disk(new_entry.inum); + info->inode_val->nlink++; + info->dirty = 1; + return success; + } + else{ + return ERROR; + } + } + position += sizeof(old_entry); + } + + // if none available, write new entry at the end of the file + int success = FSWrite(&new_entry, sizeof(new_entry), dir_inum, position); + + if(success != ERROR){ + struct inode_info* info = read_inode_from_disk(new_entry.inum); + info->inode_val->nlink++; + info->dirty = 1; + return success; + } + else{ + return ERROR; + } +} + +int get_parent_inum(char* pathname, short current_dir){ + // parse backwards and look for last '/' + int i; + for(i = strlen(pathname) - 1; i >= 0; i--){ + if(pathname[i] == '/'){ + break; + } + } + int parent_path_len = i + 1; + + // attempt to get inode of parent directory + char* parent_path = (char*)malloc(parent_path_len + 1); + memcpy(parent_path, pathname, parent_path_len); + parent_path[parent_path_len] = '\0'; + + // strip the trailing '/' unless the parent directory is root + if(!(parent_path_len == 1 && parent_path[0] == '/')){ + parent_path[parent_path_len-1] = '\0'; + } + + short parent_inum = convert_pathname_to_inode_number(parent_path, current_dir); + free(parent_path); + + if(parent_inum == ERROR){ + fprintf(stderr, "ERROR: failed to obtain path to parent directory\n"); + return ERROR; + } + return parent_inum; +} + +// takes a pathname and returns a pointer to the name of the last file in the path +// note that the pointer points to a section of the original parameter +char* get_filename(char* pathname){ + int i; + for(i = strlen(pathname) - 1; i >= 0; i--){ + if(pathname[i] == '/'){ + return pathname + i + 1; + } + } + return pathname; +} + +// creates a new file under the given parent directory +int create_file(char* filename, short parent_inum, int type){ + short file_inum = check_dir(parent_inum, filename); + + if(file_inum == ERROR){ + return ERROR; + } + else if(file_inum != 0){ + fprintf(stderr, "ERROR: file already exists\n"); + return ERROR; + } + + // allocate new inode for file + short i; + for(i = 0; i < NUM_INODES; i++){ + if(free_inodes[i] == FREE){ + file_inum = i; + break; + } + } + if(file_inum == NUM_INODES){ + fprintf(stderr, "ERROR: no more inodes left for new file\n"); + return ERROR; + } + + free_inodes[i] = TAKEN; + + struct inode_info* file_info = read_inode_from_disk(file_inum); + struct inode* file_inode = file_info->inode_val; + file_inode->type = type; + file_inode->nlink = 0; + file_inode->reuse++; + file_inode->size = 0; + file_info->dirty = 1; + + // create and populate new directory entry + struct dir_entry entry = create_entry(file_inum, filename); + + if(add_directory_entry(parent_inum, entry) == ERROR){ + // undo prior process to create inode for the file + free_inodes[file_inum] = FREE; + file_inode->type = INODE_FREE; + file_inode->nlink = 0; + file_inode->reuse--; + + fprintf(stderr, "ERROR: failed to add file to directory\n"); + return ERROR; + } + return file_inum; +} + +void init_free(){ + + struct inode_info* i_info = read_inode_from_disk(0); + struct fs_header* header = (struct fs_header*)(i_info->inode_val); + + NUM_INODES = header->num_inodes; + NUM_BLOCKS = header->num_blocks; + + free_inodes = (short*)malloc(NUM_INODES * sizeof(short)); + free_blocks = (short*)malloc(NUM_BLOCKS * sizeof(short)); + + int i; + for (i = 0; i < NUM_BLOCKS; ++i){ + free_blocks[i] = FREE; + } + for (i = 0; i < NUM_INODES; ++i){ + free_inodes[i] = FREE; + } + + free_inodes[0] = TAKEN; // fs_header inode is taken + free_inodes[1] = TAKEN; // root inode taken + free_blocks[0] = TAKEN; // boot block is taken + // inode blocks are taken + for(i = 1; i < 1 + ((NUM_INODES + 1) * INODESIZE) / BLOCKSIZE; i++){ + free_blocks[i] = TAKEN; + } + + // loop through all inodes + for(i = 1; i < NUM_INODES + 1; i++){ + struct inode* current_inode = read_inode_from_disk(i)->inode_val; + + if(current_inode->type != INODE_FREE){ + free_inodes[i] = TAKEN; + int j = 0; + // loop through direct blocks + while(j < NUM_DIRECT && j * BLOCKSIZE < current_inode->size){ + free_blocks[current_inode->direct[j]] = TAKEN; + j++; + } + + // if file still has more blocks, explore indirect block as well + if(j * BLOCKSIZE < current_inode->size){ + int* indirect_block = (int*)(read_block_from_disk(current_inode->indirect)->data); + free_blocks[current_inode->indirect] = TAKEN; + int last_block = (current_inode->size + (BLOCKSIZE-1)) / BLOCKSIZE; + + while(j < last_block){ + free_blocks[indirect_block[j - NUM_DIRECT]] = TAKEN; + j++; + } + + } + } + } +} + +int FSOpen(char *pathname, short current_dir){ + return convert_pathname_to_inode_number(pathname, current_dir); +} + +int FSCreate(char *pathname, short current_dir){ + short parent_inum = get_parent_inum(pathname, current_dir); + char* filename = get_filename(pathname); + return create_file(filename, parent_inum, INODE_REGULAR); +} + +int FSRead(void *buf, int size, short inode, int position){ + struct inode_info* info = read_inode_from_disk(inode); + if(info->inode_number == -1){ + fprintf(stderr, "ERROR: not a valid inode number\n"); + return ERROR; + } + struct inode* file_inode = info->inode_val; + + int offset = 0; + // keep reading while buf is not full and we have not reached the end of the file + while(offset < size && position + offset < file_inode->size){ + char* data = get_data_at_position(info, position + offset, 0); + // readable size is min of space left in the block, buffer, and file + int readable_size = readable_size = BLOCKSIZE - (position + offset) % BLOCKSIZE; + if(size - offset < readable_size) + readable_size = size - offset; + if(file_inode->size - (position + offset) < readable_size) + readable_size = file_inode->size - (position + offset); + memcpy(buf + offset, data, readable_size); + offset += readable_size; + } + + return offset; +} + +int FSWrite(void *buf, int size, short inum, int position){ + struct inode_info* info = read_inode_from_disk(inum); + info->dirty = 1; + if(info->inode_number == -1){ + fprintf(stderr, "ERROR: not a valid inode number\n"); + return ERROR; + } + // if writing past the size of the current file then we need to expand it first + if(grow_file(info, position + size) == ERROR){ + fprintf(stderr, "ERROR: failed to grow file in write operation\n"); + return ERROR; + } + + int offset = 0; + while(offset < size && position + offset < info->inode_val->size){ + char * data = get_data_at_position(info, position + offset, 1); + + // writeable size is min of blocksize and space left in the buf + int writeable_size = BLOCKSIZE - (position + offset) % BLOCKSIZE; + if(size - offset < writeable_size) + writeable_size = size - offset; + + memcpy(data, buf + offset, writeable_size); + offset += writeable_size; + } + return offset; +} + +// This just returns the size of a given file... it's only necessary for a particular case of +// seek in the iolib +int FSSeek(short inode){ + struct inode_info* info = read_inode_from_disk(inode); + if(info->inode_number == -1){ + fprintf(stderr, "ERROR: not a valid inode number\n"); + return ERROR; + } + return info->inode_val->size; +} + +int FSLink(char *oldname, char *newname, short current_dir){ + + short old_inum = convert_pathname_to_inode_number(oldname, current_dir); + + struct inode_info* old_info = read_inode_from_disk(old_inum); + if(old_info->inode_number == -1 || old_info->inode_val->type == INODE_DIRECTORY){ + fprintf(stderr, "ERROR: cannot create link to given file\n"); + return ERROR; + } + + short parent_inum = get_parent_inum(newname, current_dir); + char* new_filename = get_filename(newname); + + struct dir_entry entry = create_entry(old_inum, new_filename); + add_directory_entry(parent_inum, entry); + + old_info->inode_val->nlink++; + old_info->dirty = 1; + return 0; +} + +int FSUnlink(char *pathname, short current_dir){ + + short inum = convert_pathname_to_inode_number(pathname, current_dir); + struct inode_info* info = read_inode_from_disk(inum); + if(info->inode_number == -1 || info->inode_val->type == INODE_DIRECTORY){ + fprintf(stderr, "ERROR: cannot read link to given file\n"); + return ERROR; + } + + short parent_inum = get_parent_inum(pathname, current_dir); + remove_from_dir(parent_inum, inum); + + info->inode_val->nlink--; + info->dirty = 1; + + return 0; +} + +int FSSymLink(char *oldname, char *newname, short current_dir){ + short parent_inum = get_parent_inum(newname, current_dir); + char* filename = get_filename(newname); + short inum = create_file(filename, parent_inum, INODE_SYMLINK); + if(inum == ERROR) + return ERROR; + + int result = FSWrite((void*)oldname, strlen(oldname), inum, 0); + return result; +} + +int FSReadLink(char *pathname, char *buf, int len, short current_dir){ + short parent_inum = get_parent_inum(pathname, current_dir); + char* filename = get_filename(pathname); + short inum = check_dir(parent_inum, filename); + return FSRead(buf, len, inum, 0); +} + +int FSMkDir(char *pathname, short current_dir){ + short parent_inum = get_parent_inum(pathname, current_dir); + char* filename = get_filename(pathname); + short inum = create_file(filename, parent_inum, INODE_DIRECTORY); + if(inum == ERROR) + return ERROR; + + char* strdot = "."; + char* strdotdot = ".."; + + struct dir_entry dot = create_entry(inum, strdot); + struct dir_entry dotdot = create_entry(parent_inum, strdotdot); + + add_directory_entry(inum, dot); + add_directory_entry(inum, dotdot); + + return 0; +} + +int FSRmDir(char *pathname, short current_dir){ + + if(strcmp(pathname, "/") * strcmp(pathname, ".") * strcmp(pathname, "..") == 0){ + fprintf(stderr, "ERROR: attempting to remove protected path name\n"); + return ERROR; + } + + short inum = convert_pathname_to_inode_number(pathname, current_dir); + struct inode_info* info = read_inode_from_disk(inum); + + if(info->inode_number == -1 || info->inode_val->type != INODE_DIRECTORY){ + fprintf(stderr, "ERROR: given pathname is not a valid directory\n"); + return ERROR; + } + + // check to make sure that any entries in directory after . and .. are empty + int i; + for(i = 2; i < info->inode_val->size / sizeof(struct dir_entry); i++){ + struct dir_entry entry; + FSRead((void*)&entry, sizeof(entry), inum, i * sizeof(entry)); + if(entry.inum != 0){ + fprintf(stderr, "ERROR: cannot remove non-empty directory\n"); + return ERROR; + } + } + + short parent_inum = get_parent_inum(pathname, current_dir); + remove_from_dir(parent_inum, inum); + + info->inode_val->type = INODE_FREE; + free_inodes[inum] = FREE; + info->dirty = 1; + + return 0; +} + +int FSChDir(char *pathname, short current_dir){ + short inum = convert_pathname_to_inode_number(pathname, current_dir); + if(read_inode_from_disk(inum)->inode_val->type != INODE_DIRECTORY){ + fprintf(stderr, "ERROR: pathname does not lead to directory\n"); + return ERROR; + } + return inum; +} + +int FSStat(char *pathname, struct Stat* statbuf, short current_dir){ + short inum = convert_pathname_to_inode_number(pathname, current_dir); + struct inode_info* info = read_inode_from_disk(inum); + if(info->inode_number == -1){ + fprintf(stderr, "ERROR: pathname not valid\n"); + return ERROR; + } + statbuf->inum = info->inode_number; + statbuf->type = info->inode_val->type; + statbuf->size = info->inode_val->size; + statbuf->nlink = info->inode_val->nlink; + + return 0; +} + +int FSSync(void){ + return sync(); +} + +int FSShutdown(void){ + sync(); + return 0; +} + +int Redirect_Call(char* msg, int pid){ +#pragma GCC diagnostic push /*ignore unavoidable gcc warning caused by unconventional casting */ +#pragma GCC diagnostic ignored "-Wint-to-pointer-cast" + + char* current = msg; + uint8_t code = (uint8_t)(msg[0]); + int result; + + switch(code){ + case CODE_OPEN:{ + char* upathname; int upathname_size; short ucurrent_dir; + memcpy(&upathname, current += sizeof(code), sizeof(upathname)); + memcpy(&upathname_size, current += sizeof(upathname), sizeof(upathname_size)); + memcpy(&ucurrent_dir, current += sizeof(upathname_size), sizeof(ucurrent_dir)); + + char* pathname = (char*)calloc(upathname_size + 1, sizeof(char)); + CopyFrom(pid, pathname, upathname, upathname_size + 1); + result = FSOpen(pathname, ucurrent_dir); + free(pathname); + break; + } + case CODE_CREATE:{ + char* upathname; int upathname_size; short ucurrent_dir; + memcpy(&upathname, current += sizeof(code), sizeof(upathname)); + memcpy(&upathname_size, current += sizeof(upathname), sizeof(upathname_size)); + memcpy(&ucurrent_dir, current += sizeof(upathname_size), sizeof(ucurrent_dir)); + + char* pathname = (char*)calloc(upathname_size + 1, sizeof(char)); + CopyFrom(pid, pathname, upathname, upathname_size + 1); + result = FSCreate(pathname, ucurrent_dir); + free(pathname); + break; + } + case CODE_READ:{ + char* ubuf; int usize; short uinode; int uposition; + memcpy(&ubuf, current += sizeof(code), sizeof(ubuf)); + memcpy(&usize, current += sizeof(ubuf), sizeof(usize)); + memcpy(&uinode, current += sizeof(usize), sizeof(uinode)); + memcpy(&uposition, current += sizeof(uinode), sizeof(uposition)); + + char* buf = calloc(usize + 1, sizeof(char)); + result = FSRead(buf, usize, uinode, uposition); + CopyTo(pid, ubuf, buf, usize + 1); + free(buf); + break; + } + case CODE_WRITE:{ + char* ubuf; int usize; short uinode; int uposition; + memcpy(&ubuf, current += sizeof(code), sizeof(ubuf)); + memcpy(&usize, current += sizeof(ubuf), sizeof(usize)); + memcpy(&uinode, current += sizeof(usize), sizeof(uinode)); + memcpy(&uposition, current += sizeof(uinode), sizeof(uposition)); + + char* buf = calloc(usize + 1, sizeof(char)); + CopyFrom(pid, buf, ubuf, usize + 1); + result = FSWrite(buf, usize, uinode, uposition); + free(buf); + break; + } + case CODE_SEEK:{ + short inode; + memcpy(&inode, current += sizeof(code), sizeof(inode)); + result = FSSeek(inode); + break; + } + case CODE_LINK:{ + char* uoldname; int uoldname_size; char* unewname; int unewname_size; + short ucurrent_dir; + memcpy(&uoldname, current += sizeof(code), sizeof(uoldname)); + memcpy(&uoldname_size, current += sizeof(uoldname), sizeof(uoldname_size)); + memcpy(&unewname, current += sizeof(unewname_size), sizeof(unewname)); + memcpy(&unewname_size, current += sizeof(unewname), sizeof(unewname_size)); + memcpy(&ucurrent_dir, current += sizeof(unewname_size), sizeof(ucurrent_dir)); + + char* oldname = calloc(uoldname_size + 1, sizeof(char)); + char* newname = calloc(unewname_size + 1, sizeof(char)); + CopyFrom(pid, oldname, uoldname, uoldname_size + 1); + CopyFrom(pid, newname, unewname, unewname_size + 1); + result = FSLink(oldname, newname, ucurrent_dir); + break; + } + case CODE_UNLINK:{ + char* upathname; int upathname_size; short ucurrent_dir; + memcpy(&upathname, current += sizeof(code), sizeof(upathname)); + memcpy(&upathname_size, current += sizeof(upathname), sizeof(upathname_size)); + memcpy(&ucurrent_dir, current += sizeof(upathname_size), sizeof(ucurrent_dir)); + + char* pathname = (char*)calloc(upathname_size + 1, sizeof(char)); + CopyFrom(pid, pathname, upathname, upathname_size + 1); + result = FSUnlink(pathname, ucurrent_dir); + free(pathname); + break; + } + case CODE_SYMLINK:{ + char* uoldname; int uoldname_size; char* unewname; int unewname_size; + short ucurrent_dir; + memcpy(&uoldname, current += sizeof(code), sizeof(uoldname)); + memcpy(&uoldname_size, current += sizeof(uoldname), sizeof(uoldname_size)); + memcpy(&unewname, current += sizeof(unewname_size), sizeof(unewname)); + memcpy(&unewname_size, current += sizeof(unewname), sizeof(unewname_size)); + memcpy(&ucurrent_dir, current += sizeof(unewname_size), sizeof(ucurrent_dir)); + + char* oldname = calloc(uoldname_size + 1, sizeof(char)); + char* newname = calloc(unewname_size + 1, sizeof(char)); + CopyFrom(pid, oldname, uoldname, uoldname_size + 1); + CopyFrom(pid, newname, unewname, unewname_size + 1); + result = FSSymLink(oldname, newname, ucurrent_dir); + break; + } + case CODE_READLINK:{ + char* upathname; int upathname_size; char* ubuf; int ulen; short ucurrent_dir; + memcpy(&upathname, current += sizeof(code), sizeof(upathname)); + memcpy(&upathname_size, current += sizeof(upathname), sizeof(upathname_size)); + memcpy(&ubuf, current += sizeof(upathname_size), sizeof(ubuf)); + memcpy(&ulen, current += sizeof(ubuf), sizeof(ulen)); + memcpy(&ucurrent_dir, current += sizeof(ulen), sizeof(ucurrent_dir)); + + char* pathname = calloc(upathname_size + 1, sizeof(char)); + char* buf = calloc(ulen + 1, sizeof(char)); + CopyFrom(pid, pathname, upathname, upathname_size + 1); + result = FSReadLink(pathname, buf, ulen, ucurrent_dir); + CopyTo(pid, ubuf, buf, ulen + 1); + free(pathname); + free(buf); + break; + } + case CODE_MKDIR:{ + char* upathname; int upathname_size; short ucurrent_dir; + memcpy(&upathname, current += sizeof(code), sizeof(upathname)); + memcpy(&upathname_size, current += sizeof(upathname), sizeof(upathname_size)); + memcpy(&ucurrent_dir, current += sizeof(upathname_size), sizeof(ucurrent_dir)); + + char* pathname = (char*)calloc(upathname_size + 1, sizeof(char)); + CopyFrom(pid, pathname, upathname, upathname_size + 1); + result = FSMkDir(pathname, ucurrent_dir); + free(pathname); + break; + } + case CODE_RMDIR:{ + char* upathname; int upathname_size; short ucurrent_dir; + memcpy(&upathname, current += sizeof(code), sizeof(upathname)); + memcpy(&upathname_size, current += sizeof(upathname), sizeof(upathname_size)); + memcpy(&ucurrent_dir, current += sizeof(upathname_size), sizeof(ucurrent_dir)); + + char* pathname = (char*)calloc(upathname_size + 1, sizeof(char)); + CopyFrom(pid, pathname, upathname, upathname_size + 1); + result = FSRmDir(pathname, ucurrent_dir); + free(pathname); + break; + } + case CODE_CHDIR:{ + char* upathname; int upathname_size; short ucurrent_dir; + memcpy(&upathname, current += sizeof(code), sizeof(upathname)); + memcpy(&upathname_size, current += sizeof(upathname), sizeof(upathname_size)); + memcpy(&ucurrent_dir, current += sizeof(upathname_size), sizeof(ucurrent_dir)); + + char* pathname = (char*)calloc(upathname_size + 1, sizeof(char)); + CopyFrom(pid, pathname, upathname, upathname_size + 1); + result = FSChDir(pathname, ucurrent_dir); + free(pathname); + break; + } + case CODE_STAT:{ + char* upathname; int upathname_size; struct Stat* ustatbuf; short ucurrent_dir; + memcpy(&upathname, current += sizeof(code), sizeof(upathname)); + memcpy(&upathname_size, current += sizeof(upathname), sizeof(upathname_size)); + memcpy(&ustatbuf, current += sizeof(upathname_size), sizeof(ustatbuf)); + memcpy(&ucurrent_dir, current += sizeof(ustatbuf), sizeof(ucurrent_dir)); + + char* pathname = (char*)calloc(upathname_size + 1, sizeof(char)); + struct Stat* statbuf = (struct Stat*)calloc(1, sizeof(struct Stat)); + CopyFrom(pid, pathname, upathname, upathname_size + 1); + result = FSStat(pathname, statbuf, ucurrent_dir); + CopyTo(pid, ustatbuf, statbuf, sizeof(struct Stat)); + free(pathname); + free(statbuf); + break; + } + case CODE_SYNC:{ + result = FSSync(); + break; + } + case CODE_SHUTDOWN:{ + result = FSShutdown(); + if(result == 0){ + // clean msg + int i; + for(i = 0; i < MESSAGE_SIZE; i++){ + msg[i] = '\0'; + } + // copy in result and reply + memcpy(msg, &result, sizeof(result)); + Reply(msg, pid); + printf("\nShutdown request successful. Terminating Yalnix File System.\n"); + Exit(0); + } + break; + } + default:{ + result = ERROR; + } + + } + return result; +#pragma GCC diagnostic pop /*pop -Wint-to-pointer-cast ignore warning*/ +} + +int main(int argc, char** argv){ + + init(); + init_free(); + Register(FILE_SERVER); + printf("Initialized File System\n"); + + int pid = Fork(); + if(pid == 0){ + Exec(argv[1], argv + 1); + printf("No init file provided. Halting machine new\n"); + Halt(); + } + + // stand by and simply route messages from here on out + while(1){ + char msg[MESSAGE_SIZE]; + int pid = Receive(msg); + if(pid == -1){ + fprintf(stderr, "Receive() returned error\n"); + continue; + } + if(pid == 0){ + Pause(); + fprintf(stderr, "Recieve() returned 0 to avoid deadlock\n"); + continue; + } + + int result = Redirect_Call(msg, pid); + + // clean msg + int i; + for(i = 0; i < MESSAGE_SIZE; i++){ + msg[i] = '\0'; + } + + // copy in result and reply + memcpy(msg, &result, sizeof(result)); + Reply(msg, pid); + } + return 0; +} diff --git a/yfs.h b/yfs.h new file mode 100755 index 0000000..3074a60 --- /dev/null +++ b/yfs.h @@ -0,0 +1,140 @@ +#ifndef _yfs_h +#define _yfs_h + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define FILE_SYSTEM 1 + +#define MESSAGE_SIZE 32 + +#define CODE_OPEN 1 +#define CODE_CLOSE 2 +#define CODE_CREATE 3 +#define CODE_READ 4 +#define CODE_WRITE 5 +#define CODE_SEEK 6 +#define CODE_LINK 7 +#define CODE_UNLINK 8 +#define CODE_SYMLINK 9 +#define CODE_READLINK 10 +#define CODE_MKDIR 11 +#define CODE_RMDIR 12 +#define CODE_CHDIR 13 +#define CODE_STAT 14 +#define CODE_SYNC 15 +#define CODE_SHUTDOWN 16 + +#define FREE 0 +#define TAKEN 1 + +//#define SIZE 100 +//#define CACHESIZE 32 // Needs to be modified to another number. + +int NUM_INODES; +int NUM_BLOCKS; + +short* free_inodes; +short* free_blocks; + +//Block variables: +int current_blockcache_number; +struct block_info { + int dirty; + int block_number; + struct block_info *next; + struct block_info *prev; + char data[BLOCKSIZE]; +}; + +struct block_wrap { + int key; + struct block_info* block_data; +}; + +struct block_info* block_front; +struct block_info* block_rear; + +struct block_wrap* block_hashtable[BLOCK_CACHESIZE]; +struct block_wrap* default_block_wrap; +struct block_info* default_block_info; + +//Inode variable +int current_inodecache_number; + +struct inode_info { + int dirty; + int inode_number; + struct inode_info *next; + struct inode_info *prev; + struct inode *inode_val; //From the filesystem.h +}; + +struct inode_wrap { + int key; + struct inode_info* inode_data; +}; +struct inode_info* inode_front; +struct inode_info* inode_rear; + +struct inode_wrap* inode_hashtable[INODE_CACHESIZE]; +struct inode_wrap* default_inode_wrap; +struct inode_info* default_inode_info; + + +void Print(); +void init(); +int calculate_inode_to_block_number(int inode_number); +int generate_hash_code_inode(int key); +int generate_hash_code_block(int key); +struct block_wrap *get_block(int key); +void put_block_to_hashtable(int key, struct block_info* data_input); +struct block_wrap* remove_block_from_hashtable(int block_num); +void enqueue_block(struct block_info * x); +void dequeue_block(); +void remove_queue_block(struct block_info * x); +struct block_info* get_lru_block(int block_num); +int sync(); +void evict_block(); +void set_lru_block(int block_num, struct block_info* input_block); +struct inode_wrap *get_inode(int key); +void put_inode_to_hashtable(int key, struct inode_info* data_input); +struct inode_wrap* remove_inode_from_hashtable(int inode_num); +void enqueue_inode(struct inode_info * x); +void dequeue_inode(); +void remove_queue_inode(struct inode_info * x); +struct inode_info* get_lru_inode(int inode_num); +struct block_info* read_block_from_disk(int block_num); +struct inode_info* read_inode_from_disk(int inode_num); +void set_lru_inode(int inode_num, struct inode_info* input_inode); + + +void init_free(); +int FSOpen(char *pathname, short current_dir); +int FSCreate(char *pathname, short current_dir); +int FSRead(void *buf, int size, short inode, int position); +int FSWrite(void *buf, int size, short inode, int position); +int FSSeek(short inode); +int FSLink(char *oldname, char *newname, short current_dir); +int FSUnlink(char *pathname, short current_dir); +int FSSymLink(char *oldname, char *newname, short current_dir); +int FSReadLink(char *pathname, char *buf, int len, short current_dir); +int FSMkDir(char *pathname, short current_dir); +int FSRmDir(char *pathname, short current_dir); +int FSChDir(char *pathname, short current_dir); +int FSStat(char *pathname, struct Stat* statbuf, short current_dir); +int FSSync(void); +int FSShutdown(void); +int Redirect_Call(char* msg, int pid); + +void set_lru_inode(int inode_num, struct inode_info* input_inode); + +#endif /*!_yfs_h*/ diff --git a/yfs.o b/yfs.o new file mode 100755 index 0000000..c07d627 Binary files /dev/null and b/yfs.o differ