IC221: Systems Programming (SP14)


Home Policy Calendar Syllabus Resources Piazza

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:

  1. mkdir : create the single filesystem directory
  2. rmdir : remove the single filesystem directory
  3. touch : create a file or update it's timestamp
  4. rm : remove a file
  5. 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
}