// Implements EMPTY directory deletion void myrmdir(char *path){ // if it's an abs path then return to root if (path[0] == '/'){ mychdir("root"); } // if the folder is empty, i.e. the first item is it's list is the ENDOFDIR tag if (strcmp(mylistdir(path)[1], "ENDOFDIR") == 0) { // keep a track of where we start the process as the current dir changes in here, somewhere... int initial_current_dir_index = current_dir_index; int initial_current_dir_first_block = current_dir->first_block; // calculate the parent of the dir to remove and chdir to it char *target = strstr(path, last_entry_in_path(path_to_array(path))); int position = target - path; char parent_path[position+1]; for(int i = 0; i < position + 1; i++){ parent_path[i] = '\0'; } strncpy(parent_path, path, position); if(strcmp(parent_path,"") != 0) { mychdir(parent_path); } // find the entry for the dir to be deleted int entrylist_target = file_entry_index(last_entry_in_path(path_to_array(path))); // find the start of it's block chain int block_chain_target = virtual_disk[current_dir_index].dir.entrylist[entrylist_target].first_block; // clear the dir entry and it's name ready for reuse (still don't have that feature) direntry_t *dir_entry = &virtual_disk[current_dir_index].dir.entrylist[entrylist_target]; dir_entry->first_block = 0; dir_entry->unused = 1; int length = strlen(dir_entry->name); for (int i = 0; i < length; i++){ dir_entry->name[i] = '\0'; } // clear the dirs block chain and update the fat int next_block_chain_target; while(1){ next_block_chain_target = FAT[block_chain_target]; FAT[block_chain_target] = UNUSED; if (next_block_chain_target == ENDOFCHAIN) break; block_chain_target = next_block_chain_target; } copy_fat(FAT); // go back to where we started! current_dir_index = initial_current_dir_index; current_dir->first_block = initial_current_dir_first_block; } else { printf("That directory has content and cannot be deleted.\n"); } }
// Implements the opening of files in various modes (r,w,a) my_file_t *myfopen(char *path, char *mode) { int initial_current_dir_index = current_dir_index; int initial_current_dir_first_block = current_dir->first_block; // only cd if we have a path with many levels if(number_of_entries_in_path(path_to_array(path)) > 1){ mychdir(path); } char filename[MAXNAME]; strcpy(filename, last_entry_in_path(path_to_array(path))); strcat(filename, "\0"); int dir_entry_index = file_entry_index(filename); // if it doesn't exist then create it if(dir_entry_index == -1 && strncmp(mode, "r", 1) != 0){ printf("File did not exist. Creating new file: %s\n", path); // create a block for it on the disk int block_index = next_unallocated_block(); create_block(block_index, DATA); // create a dir entry for it in the current directory dir_entry_index = add_block_to_directory(block_index, filename, FALSE); } // load up it's dir entry direntry_t dir_entry = virtual_disk[current_dir_index].dir.entrylist[dir_entry_index]; // create a file object to return my_file_t *file = malloc(sizeof(my_file_t)); file->pos = 0; file->writing = 0; memcpy(file->mode, mode, strlen(mode)); file->blockno = dir_entry.first_block; file->buffer = virtual_disk[dir_entry.first_block]; // move to the end if in append mode if(strncmp(file->mode, "a", 1) == 0){ move_pos_to_end(file); } current_dir_index = initial_current_dir_index; current_dir->first_block = initial_current_dir_first_block; return file; }
int tagfs_rename(const char *path, const char *newpath) { char **tag_array = NULL; int file_id = 0; int i = 0; int num_tags = 0; int retstat = 0; DEBUG(ENTRY); INFO("Moving %s to %s", path, newpath); file_id = file_id_from_path(path); remove_tags(file_id); if(strcmp(dirname(newpath), "/") != 0) { /* deleting will put the file at root. Nothing to add */ num_tags = path_to_array(dirname(newpath), &tag_array); for(i = 0; i < num_tags; i++) { add_tag_to_file(tag_id_from_tag_name(tag_array[i]), file_id); } free_double_ptr((void ***)&tag_array, num_tags); } DEBUG(EXIT); return retstat; }
// Implements file deletion for a given path void myremove(char *path){ int initial_current_dir_index = current_dir_index; int initial_current_dir_first_block = current_dir->first_block; mychdir(path); // set the file name char filename[MAXNAME]; strcpy(filename, last_entry_in_path(path_to_array(path))); strcat(filename, "\0"); int location = file_entry_index(filename); if (location == -1) { printf("File not found.\n"); return; } // clear the fat entries int block_index = virtual_disk[current_dir_index].dir.entrylist[location].first_block; int next_block_index; while(1){ next_block_index = FAT[block_index]; FAT[block_index] = UNUSED; if (next_block_index == ENDOFCHAIN) break; block_index = next_block_index; } copy_fat(FAT); // clear the dir_entry direntry_t *dir_entry = &virtual_disk[current_dir_index].dir.entrylist[location]; dir_entry->first_block = 0; dir_entry->unused = 1; int length = strlen(dir_entry->name); for (int i = 0; i < length; i++){ dir_entry->name[i] = '\0'; } current_dir_index = initial_current_dir_index; current_dir->first_block = initial_current_dir_first_block; }
/** * Read directory * * This supersedes the old getdir() interface. New applications should use this. * * The filesystem may choose between two modes of operation: * * 1) The readdir implementation ignores the offset parameter, and passes zero * to the filler function's offset. The filler function will not return '1' * (unless an error happens), so the whole directory is read in a single readdir * operation. This works just like the old getdir() method. * * 2) The readdir implementation keeps track of the offsets of the directory * entries. It uses the offset parameter and always passes non-zero offset to * the filler function. When the buffer is full (or an error happens) the filler * function will return '1'. * * Introduced in version 2.3 */ int tagfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi) { char **path_array = NULL; char *file_name = NULL; char *folder_name = NULL; int *files = NULL; int *folders = NULL; int file_id = 0; int filler_ret = 0; int i = 0; int num_files = 0; int num_folders = 0; int path_count = 0; int retstat = 0; int tag_id = 0; DEBUG(ENTRY); INFO("Reading directory %s", path); filler(buf, ".", NULL, 0); filler(buf, "..", NULL, 0); /* add files */ num_files = files_at_location(path, &files); if(num_files > 0) { for(i = 0; i < num_files; i++) { file_id = files[i]; file_name = file_name_from_id(file_id); filler_ret = filler(buf, file_name, NULL, 0); if(filler_ret != 0) { DEBUG("filler returned %d", filler_ret); WARN("An error occured while loading files. Out of memory?"); retstat = -ENOMEM; } free_single_ptr((void **)&file_name); } } /* if there are files at the requested location, or we are at root, show folders */ if(num_files > 0 || strcmp("/", path) == 0) { /* add folders */ num_folders = folders_at_location(path, files, num_files, &folders); if(files != NULL) /* if at root with no files */ { free_single_ptr((void **)&files); } if(num_folders > 0) { path_count = path_to_array(path, &path_array); for(i = 0; i < num_folders; i++) { tag_id = folders[i]; folder_name = tag_name_from_tag_id(tag_id); /* filter tags out of path */ if(!array_contains_string((const char **)path_array, folder_name, path_count)) { filler_ret = filler(buf, folder_name, NULL, 0); } free_single_ptr((void **)&folder_name); if(filler_ret != 0) { DEBUG("filler returned %d", filler_ret); WARN("An error occured while loading tags. Out of memory?"); retstat = -ENOMEM; } } free_single_ptr((void **)&folders); if(path_array != NULL) { free_double_ptr((void ***)&path_array, path_count); } } } DEBUG(EXIT); return retstat; } /* tagfs_readdir */