static int newfs_utimens(const char *path, const struct timespec ts[2]){ char message[1024]; sprintf(message, "newfs_utimens: path = %s\n", path); write_log_fuse(message); /* split the path up into its parts */ char tokens[1024][NAME_MAX]; int count; tokenize_path(tokens, path, &count); /* traverse the file system looking for the file */ fcb current; uuid_t current_key; int rec = get_fcb_from_tokens(¤t, ¤t_key, tokens, count); if(rec != 0){ if(rec == -ENOENT) write_log_fuse("newfs_utimens: failure ENOENT\n"); if(rec == -ENOTDIR) write_log_fuse("newfs_utimens: failure ENOTDIR\n"); return rec; } /* update the times */ current.atime = ts[0].tv_nsec; current.mtime = ts[1].tv_nsec; /* store the updated fcb */ store_fcb(current, current_key); write_log_fuse("newfs_utimens: success\n"); return 0; }
static int newfs_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi){ char message[1024]; sprintf(message, "newfs_read: path = %s\n", path); write_log_fuse(message); /* split the path up into its parts */ char tokens[1024][NAME_MAX]; int count; tokenize_path(tokens, path, &count); /* traverse the file system to find the file */ fcb current; int rec = get_fcb_from_tokens(¤t, NULL, tokens, count); if(rec != 0){ if(rec == -ENOENT) write_log_fuse("newfs_read: failure ENOENT\n"); if(rec == -ENOTDIR) write_log_fuse("newfs_read: failure ENOTDIR\n"); return rec; } /* read from the file into buf */ int amount_read = fetch_filedata(buf, ¤t, size, offset); write_log_fuse("newfs_read: success\n"); return amount_read; }
static int newfs_chown(const char *path, uid_t uid, gid_t gid){ char message[1024]; sprintf(message, "newfs_chown: path = %s\n", path); write_log_fuse(message); /* split the path up into its parts */ char tokens[1024][NAME_MAX]; int count; tokenize_path(tokens, path, &count); /* traverse the file system looking for the final file in path */ fcb current; uuid_t current_key; int rec = get_fcb_from_tokens(¤t, ¤t_key, tokens, count); if(rec != 0){ if(rec == -ENOENT) write_log_fuse("newfs_chown: failure ENOENT\n"); if(rec == -ENOTDIR) write_log_fuse("newfs_chown: failure ENOTDIR\n"); return rec; } /* update the file owners */ current.uid = uid; current.gid = gid; /* store the updated fcb */ store_fcb(current, current_key); write_log_fuse("newfs_chown: success\n"); return 0; }
static int newfs_open(const char *path, struct fuse_file_info * fi){ char message[1024]; sprintf(message, "newfs_open: path = %s\n", path); write_log_fuse(message); /* split the path up into its parts */ char tokens[1024][NAME_MAX]; int count; tokenize_path(tokens, path, &count); /* look for the file to check that it exists */ fcb current; int rec = get_fcb_from_tokens(¤t, NULL, tokens, count); if(rec != 0){ if(rec == -ENOENT) write_log_fuse("newfs_open: failure ENOENT\n"); if(rec == -ENOTDIR) write_log_fuse("newfs_open: failure ENOTDIR\n"); return rec; } /* we don't use file handles so as long as the file exists we're good */ write_log_fuse("newfs_open: success\n"); return 0; }
static int newfs_getattr(const char *path, struct stat *stbuf){ char message[1024]; sprintf(message, "newfs_getattr: path = %s\n", path); write_log_fuse(message); /* split path into its parts */ char tokens[1024][NAME_MAX]; int count; tokenize_path(tokens, path, &count); /* traverse the file system to find the relevent fcb */ fcb current; int rec = get_fcb_from_tokens(¤t, NULL, tokens, count); if(rec != 0){ if(rec == -ENOENT) write_log_fuse("newfs_getattr: failure ENOENT\n"); if(rec == -ENOTDIR) write_log_fuse("newfs_getattr: failure ENOTDIR\n"); return rec; } /* copy the meta data from the fcb into stbuf */ set_stat_from_fcb(¤t, stbuf); write_log_fuse("newfs_getattr: success\n"); return 0; }
static int newfs_mkdir(const char *path, mode_t mode){ char message[1024]; sprintf(message, "newfs_mkdir: path = %s\n", path); write_log_fuse(message); /* split path into its parts */ char tokens[1024][NAME_MAX]; int count; tokenize_path(tokens, path, &count); /* traverse the file system to find the fcb above where we want to add a dir */ fcb parent; uuid_t parent_key; int rec = get_fcb_from_tokens(&parent, &parent_key, tokens, count - 1); if(rec != 0){ if(rec == -ENOENT) write_log_fuse("newfs_mkdir: failure ENOENT\n"); if(rec == -ENOTDIR) write_log_fuse("newfs_mkdir: failure ENOTDIR\n"); return rec; } /* if the fcb above our target is not a directory, fail */ if(!parent.dir){ write_log_fuse("newfs_mkdir: failure ENOTDIR\n"); return -ENOTDIR; } /* get the directory entries */ dir_entry *dirs = malloc(sizeof(dir_entry) * parent.num_files); fetch_dirdata(dirs, parent.datakey, parent.num_files); int found=0, i=0; for(i = 0; i != parent.num_files; i++){ // look for our target in this directory if(strcmp(dirs[i].name, tokens[count-1]) == 0){ found++; } } /* if the directory is found, then it can't be created */ if(found){ write_log_fuse("newfs_mkdir: failure EEXIST\n"); return -EEXIST; } /* add one directory entry to the parent directory */ uuid_t child_key; uuid_generate(child_key); init_dir_fcb(child_key, parent_key); parent.num_files++; dirs = realloc(dirs, sizeof(dir_entry) * parent.num_files); strcpy(dirs[parent.num_files-1].name, tokens[count-1]); uuid_copy(dirs[parent.num_files-1].key, child_key); store_dirdata(dirs, parent.datakey, parent.num_files); parent.size = sizeof(dir_entry) * parent.num_files; store_fcb(parent, parent_key); write_log_fuse("newfs_mkdir: success\n"); return 0; }
static int newfs_create(const char *path, mode_t mode, struct fuse_file_info *fi){ char message[1024]; sprintf(message, "newfs_create: path = %s\n", path); write_log_fuse(message); /* split the path up into its parts */ char tokens[1024][NAME_MAX]; int count; tokenize_path(tokens, path, &count); /* traverse the file system looking for the directory above our target file */ fcb parent; uuid_t parent_key; int rec = get_fcb_from_tokens(&parent, &parent_key, tokens, count - 1); if(rec != 0){ if(rec == -ENOENT) write_log_fuse("newfs_create: failure ENOENT\n"); if(rec == -ENOTDIR) write_log_fuse("newfs_create: failure ENOTDIR\n"); return rec; } if(!parent.dir){ write_log_fuse("newfs_create: failure ENOTDIR\n"); return -ENOTDIR; } /* get the directory data and look for the target */ dir_entry *dirs = malloc(sizeof(dir_entry) * parent.num_files); fetch_dirdata(dirs, parent.datakey, parent.num_files); int found=0, i=0; for(i = 0; i != parent.num_files; i++){ if(strcmp(dirs[i].name, tokens[count-1]) == 0){ found++; } } if(found){ write_log_fuse("newfs_create: failure EEXIST\n"); return -EEXIST; } /* if all is well, create a new file and store the updated fcb */ uuid_t child_key; uuid_generate(child_key); init_file_fcb(child_key); parent.num_files++; dirs = realloc(dirs, sizeof(dir_entry) * parent.num_files); strcpy(dirs[parent.num_files-1].name, tokens[count-1]); uuid_copy(dirs[parent.num_files-1].key, child_key); store_dirdata(dirs, parent.datakey, parent.num_files); parent.size = sizeof(dir_entry) * parent.num_files; store_fcb(parent, parent_key); write_log_fuse("newfs_create: success\n"); return 0; }
static int newfs_write(const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi){ char message[1024]; sprintf(message, "newfs_write: path = %s\n", path); write_log_fuse(message); /* split the path up into its parts */ char tokens[1024][NAME_MAX]; int count; tokenize_path(tokens, path, &count); /* traverse the file system to find the file */ fcb current; uuid_t current_key; int rec = get_fcb_from_tokens(¤t, ¤t_key, tokens, count); if(rec != 0){ if(rec == -ENOENT) write_log_fuse("newfs_write: failure ENOENT\n"); if(rec == -ENOTDIR) write_log_fuse("newfs_write: failure ENOTDIR\n"); return rec; } /* calculate what size the file will be after the write */ unsigned int final_file_size; unsigned int temp = offset + size; // offset is a signed type so weird stuff happens if(temp > current.size){ final_file_size = (unsigned int)offset + size; } else { final_file_size = current.size; } /* put the current file data into a buffer */ char *filedata = malloc(final_file_size); fetch_filedata(filedata, ¤t, final_file_size, 0); /* copy the data from the buf into the same buffer as our current file data */ memcpy(filedata + (unsigned int)offset, buf, size); current.size = final_file_size; /* store the now updated file data and fcb */ store_filedata(filedata, current.datakey, current.size); store_fcb(current, current_key); free(filedata); write_log_fuse("newfs_write: success\n"); return size; }
static int newfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi){ char message[1024]; sprintf(message, "newfs_readdir: path = %s\n", path); write_log_fuse(message); /* split the path up into its parts */ char tokens[1024][NAME_MAX]; int count; tokenize_path(tokens, path, &count); /* traverse the file system to find the current directory */ fcb current; int rec = get_fcb_from_tokens(¤t, NULL, tokens, count); if(rec != 0){ if(rec == -ENOENT) write_log_fuse("newfs_readdir: failure ENOENT\n"); if(rec == -ENOTDIR) write_log_fuse("newfs_readdir: failure ENOTDIR\n"); return rec; } if(!current.dir){ write_log_fuse("newfs_readdir: failure ENOTDIR\n"); return -ENOTDIR; } /* get the directory entries */ dir_entry *dirs = malloc(sizeof(dir_entry) * current.num_files); fetch_dirdata(dirs, current.datakey, current.num_files); int i; for(i = 0; i != current.num_files; i++){ fcb child = fetch_fcb(dirs[i].key); struct stat child_stat; set_stat_from_fcb(&child, &child_stat); // set a stat for each file in the directory int rec = filler(buf, dirs[i].name, &child_stat, 0); // use filler to fill the buf with this information if(rec != 0){ write_log_fuse("newfs_readdir: failure (filler failed)\n"); return rec; } } free(dirs); write_log_fuse("newfs_readdir: success\n"); return 0; }
static int newfs_truncate(const char * path, off_t size){ char message[1024]; sprintf(message, "newfs_truncate: path = %s\n", path); write_log_fuse(message); /* split the path up into its parts */ char tokens[1024][NAME_MAX]; int count; tokenize_path(tokens, path, &count); /* traverse the file system looking for the file */ fcb current; uuid_t current_key; int rec = get_fcb_from_tokens(¤t, ¤t_key, tokens, count); if(rec != 0){ if(rec == -ENOENT) write_log_fuse("newfs_truncate: failure ENOENT\n"); if(rec == -ENOTDIR) write_log_fuse("newfs_truncate: failure ENOTDIR\n"); return rec; } /* decide if the file should be bigged or smaller */ int max_size = current.size; // the minimum the buffer can be is the current size because we need to fetch all the data if(size > current.size){ max_size = size; } /* get the file data from the store */ char *filedata = malloc(max_size); fetch_filedata(filedata, ¤t, current.size, 0); /* update the size */ current.size = size; /* store the updated file data and fcb */ store_filedata(filedata, current.datakey, current.size); store_fcb(current, current_key); free(filedata); write_log_fuse("newfs_truncate: success\n"); return size; }
int sfs_delete(char *pathname) { char** tokens; uint32_t* parent_location = NULL; locations index_block = {NULL}; locations inode_loc = (locations) calloc(2, sizeof(uint32_t)); int type = -1; if(strlen(pathname) == 1) { print_error(INVALID_PATH); return -1; } /* * Parse the pathname */ tokens = tokenize_path(pathname); if(tokens == NULL) { print_error(INVALID_PATH); return 0; } /* * Traverse the file system to find the desired inode * get the inode above the one you desired */ parent_location = traverse_file_system(tokens, true); if(parent_location == NULL) { /* * Parent not found */ print_error(PARENT_NOT_FOUND); return -1; } /*if (parent_location[0] = get_root() && tokens[parent_location[1]] == NULL) { print_error(INVALID_PARAMETER); return -1; }*/ index_block = iterate_index(get_index_block(parent_location[0]), NULL); if(index_block == NULL) { /* * Empty or no index block */ print_error(INDEX_ALLOCATION_ERROR); return 0; } /* * Find the inode of the file or directory with the given file name in the * given index block list */ inode_loc[0] = find_inode(index_block, tokens[parent_location[1]]); if(inode_loc[0] == NULL) { /* * Inode not found */ print_error(FILE_NOT_FOUND); return 0; } /* * Check if it is a directory */ type = get_type(inode_loc[0]); index_block = iterate_index(get_index_block(inode_loc[0]), NULL); if(index_block == NULL) { /* * Invalid index block */ print_error(INDEX_ALLOCATION_ERROR); return -1; } if (type == 1) { if(index_block[0] != NULL) { /* * Directory has children */ print_error(DIRECTORY_HAS_CHILDREN); return 0; } } /* * Delete all swoft entries for the given file */ printf("Number swoft entries remove: %d\n",find_and_remove(inode_loc[0])); if(unlink_inode_from_parent(parent_location[0], inode_loc[0]) < 0) { if(reset_fbl() == NULL) { print_error(ERROR_UPDATING_FBL); return -2; } print_error(ERROR_BLOCK_LINKAGE); return -1; } else if(type == 0) { /* * Delete the data blocks (each time update the free_block list) */ if(update_fbl(NULL, index_block) == NULL) { print_error(ERROR_UPDATING_FBL); return -1; } } /* * Delete the index blocks (each time update the free_block list) */ if(update_fbl(NULL, index_block_locations(get_index_block(inode_loc[0]), NULL)) == NULL) { print_error(ERROR_UPDATING_FBL); return -1; } /* * Delete the Inode block (update the free_block list) */ if(update_fbl(NULL, inode_loc) == NULL) { print_error(ERROR_UPDATING_FBL); return -1; } /* * Sync FBL, write FBL in memory to disk */ if(sync_fbl() == NULL) { print_error(ERROR_UPDATING_FBL); return -1; } /* * return value > 0 then the file was deleted successfully. * return value <= 0 then the file failed to be delete. */ print_error(SUCCESS); return 1; }
static void sanitize_path(char *buffer, size_t buffer_size, size_t input_length) { char scratch[512]; int i; int segcount; int dotdot_drops = 0; strseg segments[64]; strcpy(scratch, buffer); segcount = tokenize_path(scratch, segments, sizeof(segments) / sizeof(segments[0])); for (i = segcount - 1; i >= 0; --i) { if (segments[i].drop) continue; if (segments[i].dotdot) { ++dotdot_drops; segments[i].drop = 1; } else if (dotdot_drops > 0) { --dotdot_drops; segments[i].drop = 1; } } /* Format the resulting path. It can never get longer by this operation, so * there's no need to check the buffer size. */ { int emit_slash = 0; char *cursor = buffer; /* Emit all leading ".." tokens we've got left */ for (i = 0; i < dotdot_drops; ++i) { memcpy(cursor, ".." TD_PATHSEP_STR, 3); cursor += 3; } /* Emit all remaining tokens. */ for (i = 0; i < segcount; ++i) { int len = segments[i].len; const char *seg = segments[i].ptr; if (segments[i].drop) continue; if (emit_slash) *cursor++ = TD_PATHSEP; emit_slash = 1; memcpy(cursor, seg, len); cursor += len; } *cursor = 0; } }
static int newfs_access(const char * path, int mask){ char message[1024]; sprintf(message, "newfs_access: path = %s\n", path); write_log_fuse(message); /* split the path up into its parts */ char tokens[1024][NAME_MAX]; int count; tokenize_path(tokens, path, &count); /* traverse the file system to find the file */ fcb current; uuid_t current_key; int rec = get_fcb_from_tokens(¤t, ¤t_key, tokens, count); if(rec != 0){ if(rec == -ENOENT) write_log_fuse("newfs_access: failure ENOENT\n"); if(rec == -ENOTDIR) write_log_fuse("newfs_access: failure ENOTDIR\n"); return rec; } /* if we're just checking that the file exists, return ok because at this point it definitely does */ if(mask == F_OK){ return 0; } /* get the fuse uid and gid */ struct fuse_context *context = fuse_get_context(); uid_t r_uid = context->uid; gid_t r_gid = context->gid; int want_read = R_OK & mask; int want_write = W_OK & mask; int want_exe = X_OK & mask; /* for each of the tasks, check that the user is allowed to perform them (if they want to) */ if(want_read){ if(current.mode & S_IROTH) goto check_write; if((r_gid == current.gid) && (current.mode & S_IRGRP)) goto check_write; if((r_uid == current.uid) && (current.mode & S_IRUSR)) goto check_write; return -EACCES; } check_write: if(want_write){ if(current.mode & S_IWOTH) goto check_exe; if((r_gid == current.gid) && (current.mode & S_IWGRP)) goto check_exe; if((r_uid == current.uid) && (current.mode & S_IWUSR)) goto check_exe; return -EACCES; } check_exe: if(want_exe){ if(current.mode & S_IXOTH) return 0; if((r_gid == current.gid) && (current.mode & S_IXGRP)) return 0; if((r_uid == current.uid) && (current.mode & S_IXUSR)) return 0; return -EACCES; } return 0; }
static int newfs_rename(const char *path, const char *to){ char message[1024]; sprintf(message, "newfs_rename: path = %s\n", path); write_log_fuse(message); /* split the path up into its parts */ char tokens[1024][NAME_MAX]; int count; tokenize_path(tokens, path, &count); /* get the directory above the target file */ fcb parent; uuid_t parent_key; int rec = get_fcb_from_tokens(&parent, &parent_key, tokens, count - 1); if(rec != 0){ if(rec == -ENOENT) write_log_fuse("newfs_rename: failure ENOENT\n"); if(rec == -ENOTDIR) write_log_fuse("newfs_rename: failure ENOTDIR\n"); return rec; } int to_remove = 0; uuid_t move_key; /* get the directory data for this directory */ dir_entry *dirs = malloc(sizeof(dir_entry) * parent.num_files); fetch_dirdata(dirs, parent.datakey, parent.num_files); int found=0, i=0; for(i = 0; i != parent.num_files; i++){ // look for the target if(strcmp(dirs[i].name, tokens[count-1]) == 0){ // if it is found, remember found++; to_remove = i; uuid_copy(move_key, dirs[i].key); } } if(!found){ write_log_fuse("newfs_rmdir: failure ENOENT\n"); return -ENOENT; } /* reconstruct the dirdata, skipping the file to be moved */ int offset = 0; dir_entry *newdirs = malloc(sizeof(dir_entry) * (parent.num_files - 1)); for(i = 0; i != parent.num_files; i++){ if(i == to_remove){ continue; } strcpy(newdirs[offset].name, dirs[i].name); uuid_copy(newdirs[offset].key, dirs[i].key); offset++; } /* update the original parent directory */ parent.num_files--; store_dirdata(newdirs, parent.datakey, parent.num_files); parent.size = sizeof(dir_entry) * parent.num_files; store_fcb(parent, parent_key); free(dirs); free(newdirs); /* split the target path up into its parts */ tokenize_path(tokens, to, &count); rec = get_fcb_from_tokens(&parent, &parent_key, tokens, count - 1); if(rec != 0){ if(rec == -ENOENT) write_log_fuse("newfs_rename: failure ENOENT\n"); if(rec == -ENOTDIR) write_log_fuse("newfs_rename: failure ENOTDIR\n"); return rec; } /* get the new directory data for the target */ dirs = malloc(sizeof(dir_entry) * parent.num_files); fetch_dirdata(dirs, parent.datakey, parent.num_files); for(i = 0; i != parent.num_files; i++){ if(strcmp(dirs[i].name, tokens[count-1]) == 0){ write_log_fuse("newfs_rename: failure EEXIST"); return -EEXIST; } } /* add the file to the new directory and update the new parent */ parent.num_files++; dirs = realloc(dirs, sizeof(dir_entry) * parent.num_files); strcpy(dirs[parent.num_files-1].name, tokens[count-1]); uuid_copy(dirs[parent.num_files-1].key, move_key); store_dirdata(dirs, parent.datakey, parent.num_files); parent.size = sizeof(dir_entry) * parent.num_files; store_fcb(parent, parent_key); write_log_fuse("newfs_rename: success\n"); return 0; }
static int newfs_rmdir(const char *path){ char message[1024]; sprintf(message, "newfs_rmdir: path = %s\n", path); write_log_fuse(message); /* split the path up into its parts */ char tokens[1024][NAME_MAX]; int count; tokenize_path(tokens, path, &count); /* get the directory above the target */ fcb parent; uuid_t parent_key; int rec = get_fcb_from_tokens(&parent, &parent_key, tokens, count - 1); if(rec != 0){ if(rec == -ENOENT) write_log_fuse("newfs_rmdir: failure ENOENT\n"); if(rec == -ENOTDIR) write_log_fuse("newfs_rmdir: failure ENOTDIR\n"); return rec; } if(!parent.dir){ write_log_fuse("newfs_rmdir: failure ENOTDIR\n"); return -ENOTDIR; } int to_remove = 0; int size_to_remove = 0; /* get the directory entries for the directory */ dir_entry *dirs = malloc(sizeof(dir_entry) * parent.num_files); fetch_dirdata(dirs, parent.datakey, parent.num_files); int found=0, i=0; for(i = 0; i != parent.num_files; i++){ // look for the target if(strcmp(dirs[i].name, tokens[count-1]) == 0){ // if it is found, remember found++; to_remove = i; fcb fcb_to_remove = fetch_fcb(dirs[i].key); size_to_remove = fcb_to_remove.size; } } if(!found){ write_log_fuse("newfs_rmdir: failure ENOENT\n"); return -ENOENT; } /* if the target contains anything, do not remove it */ if(size_to_remove > sizeof(dir_entry) * 2){ write_log_fuse("newfs_rmdir: failure ENOTEMPTY\n"); return -ENOTEMPTY; } /* reconstruct the directory data, skipping the target */ int offset = 0; dir_entry *newdirs = malloc(sizeof(dir_entry) * (parent.num_files - 1)); for(i = 0; i != parent.num_files; i++){ if(i == to_remove){ continue; } strcpy(newdirs[offset].name, dirs[i].name); uuid_copy(newdirs[offset].key, dirs[i].key); offset++; } /* update the parent fcb */ parent.num_files--; store_dirdata(newdirs, parent.datakey, parent.num_files); parent.size = sizeof(dir_entry) * parent.num_files; store_fcb(parent, parent_key); write_log_fuse("newfs_rmdir: success\n"); return 0; }
int sfs_getsize(char *pathname) { int type = -1; int i = 1; uint32_t index_block = 0; locations inode_location = NULL; locations index_locations = NULL; char** tokens = NULL; int size = 0; /* Parse the pathname */ tokens = tokenize_path(pathname); if(tokens == NULL) { /* Invalid pathname */ print_error(INVALID_PATH); return -1; } /* Traverse the file system to find the desired inode */ inode_location = traverse_file_system(tokens, false); if(inode_location == NULL) { /* Invalid path or file/directory not found */ print_error(FILE_NOT_FOUND); return -1; } /* * Check if it is a file or directory * - If directory: * Count entries * - If file: * get size */ type = get_type(inode_location[0]); index_locations = index_block_locations(inode_location[0], NULL); if(index_locations == NULL) { /* * Invalid index block */ print_error(INDEX_ALLOCATION_ERROR); return -1; } /* * Count the number of index blocks */ while(index_locations[i+1] != NULL) { i++; } /* Add the inode */ i++; /* print out the number of index blocks + the inode block */ printf("Overhead Size = %d\n", i*BLKSIZE); if(type == 0) { /* Get the size of the file from the Inode return the * size of the file */ size = get_size(inode_location[0]); printf("Data Size = %d\n", size); return size; } else if(type == 1) { /* Get the index block's location */ index_block = get_index_block(inode_location[0]); /* Return the number of locations found in the index block(s) */ size = count_files_in_dir(index_block); printf("Size = %d\n", size); print_error(SUCCESS); return size; } print_error(INVALID_FILE_TYPE); return -1; }