Lab 04: Debugging with Valgrind and simplefs
Table of Contents
Part 3: Implementing simplefs
Task 4
In this part of the lab you will program a simple filesystem that consists of a single directory containing files. You will be provided a small shell-like program to test your file system, and your filesystem must be able to handle the following operations:
- mkdir : create the single filesystem directory
- rmdir : remove the single filesystem directory
- touch : create a file or update it's timestamp
- rm : remove a file
- ls : list all the current files
Your filesystem implementation must manage memory properly — no memory leaks or memory violations — and must be able to handle an arbitrary number of files.
You will complete the functions listed in filseystem.c
with
descriptions found in filesystem.h
. You do not need to edit any
other files. You can test your filesystem with testfs.c
program,
which should catch common mistakes. When complete, you can interact
with your filesystem with the shell
program, source found in
shell.c
. You do not need to, nor should you, edit shell.c.
Compilation will be done using make
. To compile the test program
testfs
, run
make testfs
To compile the shell enviroment for simplefs
make shell
To compile everything, type:
make
Solution
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/errno.h> #include <time.h> #include "filesystem.h" dir_t * myfs_mkdir(){ //allocate the directory, initialize size dir_t * dir = malloc(sizeof(dir_t)); dir->size = INIT_SIZE; dir->nfiles = 0; //allocate the list of files dir->flist = calloc(dir->size, sizeof(file_t *)); return dir; } void myfs_rmdir(dir_t * dir){ int i; //iterate through each file for(i = 0 ; i < dir->size; i++){ if(dir->flist[i] != NULL){ //deallocate file and the fname free(dir->flist[i]->fname); free(dir->flist[i]); } } //deallocate the array of file_t's free(dir->flist); //deallocate the directory itself free(dir); } int myfs_rm(dir_t * dir, char *fname){ int i; if(fname == NULL){ fprintf(stderr, "ERROR: rm: require file name\n"); } //search for file by name for(i = 0; i < dir->size ; i++){ if(dir->flist[i] == NULL) continue; if(strcmp(fname, dir->flist[i]->fname) == 0){ //found, now remove free(dir->flist[i]->fname); free(dir->flist[i]); //rest that place to null dir->flist[i] = NULL; //decrement the number of files in list dir->nfiles--; return 1;//file found } } fprintf(stderr, "ERROR: rm: no file `%s'\n",fname); return 0; //file not found } void myfs_ls(dir_t * dir){ int i; for(i = 0; i < dir->size; i++){ if(dir->flist[i] != NULL){ //check for null so don't segfault printf(" %s\t%s", dir->flist[i]->fname, ctime(&(dir->flist[i]->last))); } } } void myfs_ls_sorttime(dir_t * dir){ //not completed in solutuion } void myfs_ls_sortname(dir_t * dir){ //not completed in solution } file_t * myfs_touch(dir_t * dir, char *fname){ int i; if(fname == NULL){ fprintf(stderr, "ERROR: touch: require filename"); } for(i=0; i < dir->size; i++){ //check for file exists if(dir->flist[i] != NULL){ if(strcmp(dir->flist[i]->fname, fname) == 0){ dir->flist[i]->last = time(NULL); //update time if it does return dir->flist[i]; } } } //check if we need to resize array if( dir->size == dir->nfiles ){ //resize array file_t ** new_flist = (file_t **) calloc(dir->size*2,sizeof(file_t *)); //copy data over for(i=0;i<dir->size;i++){ new_flist[i] = dir->flist[i]; } //free old array free(dir->flist); //reset values dir->flist = new_flist; dir->size *= 2; } //create new file for(i = 0;i < dir->size; i++){ if(dir->flist[i] == NULL){ dir->flist[i] = malloc(sizeof(file_t)); //allocate the file dir->flist[i]->fname = strdup(fname); //duplicate file name! dir->flist[i]->last = time(NULL); //set the timestamp dir->nfiles++; //increment the number of iles return dir->flist[i]; } } return NULL; //shouldn't get here }