Example #1
0
/**
 * rename from_file to to_file
 * works for dirs as well as files
 * cannot rename to something that already exists
 * @param from_file
 * @param to_file
 * @return 1 on success, 0 on failure
 */
int mfs_rename_file(char *from_file, char *to_file) {
  int from_dir_block;
  int to_dir_block;
  int from_dir_index;
  int to_dir_index;
  int reuse_block = -1;
  int reuse_index = -1;
  if (get_dir_ent(from_file, &from_dir_block, &from_dir_index, &reuse_block, &reuse_index) &&
      !get_dir_ent(to_file, &to_dir_block, &to_dir_index, &reuse_block, &reuse_index)) {
    set_filename(mfs_file_system[from_dir_block].u.dir_data.dir_ent[from_dir_index].name, get_basename(to_file));
    return 1;
  }
  return 0;
}
Example #2
0
/**
 * open a file
 * @param filename is the name of the file to open
 * @param mode is MFS_MODE_READ or MFS_MODE_WRITE or MFS_MODE_CREATE
 * this function should be used for FILEs and not DIRs
 * no error checking (is this FILE and not DIR?) is done for MFS_MODE_READ
 * MFS_MODE_CREATE automatically creates a FILE and not a DIR
 * MFS_MODE_WRITE fails if the specified file is a DIR
 * @return index of file in array mfs_open_files or -1
 */
int mfs_file_open(const char *filename, int mode) {
  int dir_block;
  int dir_index;
  int current_index;
  int reuse_block = -1;
  int reuse_index = -1;
  //xil_printf("In mfs_file_open\r\n");

  if (mfs_num_open_files >= MFS_MAX_OPEN_FILES) {/* cannot open any more files */
    //xil_printf("case 1\r\n");
    return -1;
  }
  if (mode == MFS_MODE_READ || mode == MFS_MODE_WRITE) { /* look for existing file */
    if (get_dir_ent(filename, &dir_block, &dir_index, &reuse_block, &reuse_index)) { /* found it */
      if (mode == MFS_MODE_WRITE && mfs_file_system[mfs_file_system[dir_block].u.dir_data.dir_ent[dir_index].index].block_type != MFS_BLOCK_TYPE_FILE) {
	/* cannot open anything other than FILE for write */
	//xil_printf("case 2\r\n");
	return -1;
      }
      mfs_num_open_files++;
      current_index = get_first_free_ftab_index();
      mfs_open_files[current_index].first_block = mfs_file_system[dir_block].u.dir_data.dir_ent[dir_index].index;
      mfs_open_files[current_index].current_block = mfs_open_files[current_index].first_block;
      mfs_open_files[current_index].mode = mode;
      mfs_open_files[current_index].offset = 0;
      return current_index;
    }
    else {
       //file/dir not found, open it in create mode
       if (mode == MFS_MODE_WRITE)
          mode = MFS_MODE_CREATE;
    }
  }

  if (mode == MFS_MODE_CREATE) { /* create a new file */
     dir_block = create_file(filename, MFS_BLOCK_TYPE_FILE);
    if (dir_block == 0) { /* failed to create the file */
      //xil_printf("case 3\r\n");
      return -1;
    }
    mfs_num_open_files++;
    current_index = get_first_free_ftab_index();
    mfs_open_files[current_index].first_block = dir_block;
    mfs_open_files[current_index].current_block = dir_block;
    mfs_open_files[current_index].mode = MFS_MODE_WRITE;
    mfs_open_files[current_index].offset = 0;
    //xil_printf("case 4, current_index is %d\r\n",current_index);
    return current_index;
  }
  //xil_printf("case 5\r\n");
  return -1;
}
Example #3
0
/**
 * modify global mfs_current_dir to index of newdir if it exists
 * mfs_current_dir is not modified otherwise
 * @param newdir is the name of the new directory
 * @return 1 for success and 0 for failure
 */
int mfs_change_dir(const char *newdir) {
  /* search current dir for newdir and change current dir if found */
  /* return 1 for success, 0 for failure */
  int new_dir_block;
  int new_dir_index;
  int reuse_block = -1;
  int reuse_index = -1;
  if (get_dir_ent(newdir, &new_dir_block, &new_dir_index, &reuse_block, &reuse_index)) {
    mfs_current_dir = mfs_file_system[new_dir_block].u.dir_data.dir_ent[new_dir_index].index;
    return 1;
  }
  return 0;
}
Example #4
0
/**
 * check if a file exists
 * @param filename is the name of the file
 * @return 0 if filename is not a file in the current directory
 * @return 1 if filename is a file in the current directory
 * @return 2 if filename is a directory in the current directory
 */
int mfs_exists_file(char *filename) {
  int dir_block;
  int dir_index;
  int file_block;
  int reuse_block = -1;
  int reuse_index = -1;
  if (get_dir_ent(filename, &dir_block, &dir_index, &reuse_block, &reuse_index)) {
    file_block = mfs_file_system[dir_block].u.dir_data.dir_ent[dir_index].index;
    if (mfs_file_system[file_block].block_type == MFS_BLOCK_TYPE_DIR)
      return 2;
    else if (mfs_file_system[file_block].block_type == MFS_BLOCK_TYPE_FILE)
      return 1;
    else return 0;
  }
  return 0;
}
Example #5
0
/**
 * delete a file
 * @param filename is the name of the file to be deleted
 * delete the data blocks corresponding to the file and then delete the
 * file entry from its directory
 * @return 1 on success, 0 on failure
 * delete will not work on a directory unless the directory is empty
 */
int mfs_delete_file (char *filename) {
  int dir_block;
  int dir_index;
  int entry_index;
  int first_dir_block;
  int reuse_block = -1;
  int reuse_index = -1;

  if (!get_dir_ent(filename, &dir_block, &dir_index, &reuse_block, &reuse_index)) {
    /* file does not exist */
    return 0 ; /* cannot delete file if it does not exist */
  }
  entry_index = mfs_file_system[dir_block].u.dir_data.dir_ent[dir_index].index;
  if (delete_data_in_file(entry_index)) {
    /* now delete the file entry from the directory */
    mfs_file_system[dir_block].u.dir_data.dir_ent[dir_index].deleted = 'y';
    mfs_file_system[dir_block].u.dir_data.num_deleted += 1;
    first_dir_block = get_first_dir_block(dir_block);
    if (dir_block != first_dir_block)
      mfs_file_system[first_dir_block].u.dir_data.num_deleted += 1;
  }
  return 1;
}
Example #6
0
int load(char* fn, void* data, size_t ds){
    struct fs *the_fs = malloc(sizeof(struct fs));
    int ret = 5;
    load_fs(the_fs);
    struct dir_ent file_ent;
    if(get_dir_ent(&the_fs->root_dir, fn, &file_ent)) {
        ret = NOT_FOUND;
        goto error;
    }

    unsigned short addr = file_ent.file_addr;
    unsigned short next_addr = 0;
    size_t offset = 0;
    int cyl, sect;
    while(!get_next_addr(&the_fs->the_fat, addr, &next_addr) && offset < ds) {
        cyl = to_cylinder_number(addr);
        sect = to_sector_number(addr);
        read_sector(cyl, sect, data + offset);
        offset += BYTES_PER_SECTOR;
        addr = next_addr;
    }
    if(offset >= ds) {
        printf("looks like data cant hold the whole file!\n");
        goto error;
    }
    cyl = to_cylinder_number(addr);
    sect = to_sector_number(addr);
    char leftover[BYTES_PER_SECTOR];
    read_sector(cyl, sect, leftover);
    size_t to_read = (ds - offset > BYTES_PER_SECTOR) ? BYTES_PER_SECTOR-1 : ds - offset;
    memcpy(data + offset, leftover, to_read);
    ret = 0;

error:
    free(the_fs);
    return ret;
}
Example #7
0
int save(char* fn, void* data, size_t ds){
    struct fs *the_fs = malloc(sizeof(struct fs));
    int ret = 5;
    load_fs(the_fs);
    struct dir_ent file_ent;
    unsigned short n = ds / BYTES_PER_SECTOR + 1;
    unsigned short *free_sectors = malloc(sizeof(unsigned short) * n);
    
    if(!get_dir_ent(&the_fs->root_dir, fn, &file_ent)) {
        ret = NAME_CONFLICT;
        goto error;
    };
    
    if(getn_free_sectors(&the_fs->the_fat, n, free_sectors)) {
        //printf("Looks like there aren't %d sectors available!\n", n);
        ret = NO_SPACE;
        goto error;
    }

    // now we actually store our file
    size_t offset = 0;
    unsigned short addr, next_addr;
    int cyl, sect;
    addr = free_sectors[0];
    // set the initial root_dir entry
    if(set_dir_ent(&the_fs->root_dir, fn, addr)) {
        printf("So we couldn't find an available space in our root_dir\n");
        ret = NO_SPACE;
        goto error;
    }

    for(int i = 0; i < n-1; ++i) {
        addr = free_sectors[i];
        next_addr = free_sectors[i+1];
        cyl = to_cylinder_number(addr);
        sect = to_sector_number(addr);
        if(set_fat_entry_value(&the_fs->the_fat, addr, next_addr)) {
            printf("Apparently %d is not a valid address!\n", next_addr);
            goto error;
        }

        if(write_sector(cyl, sect, data + offset)) {
            printf("Something went wrong with write_sector\n");
            goto error;
        }
        offset += BYTES_PER_SECTOR;
    }
    char leftover[BYTES_PER_SECTOR];
    memcpy(leftover, data + offset, ds - offset);
    addr = free_sectors[n-1];
    cyl = to_cylinder_number(addr);
    sect = to_sector_number(addr);
    if(set_fat_entry_value(&the_fs->the_fat, addr, END_OF_FILE)) {
        printf("We couldn't set the last addr to END_OF_FILE!\n");
        goto error;
    }

    if(write_sector(cyl, sect, leftover)) {
        printf("Something went wrong with writing the last bit of data!\n");
        goto error;
    }
    ret = 0;

error:
    store_fs(the_fs);
    free(the_fs);
    free(free_sectors);
	return ret;
}
Example #8
0
/**
 * Create a new file or dir  named filename
 * If a dir or file of the same name exists, return 0
 * If there is no space on the file system to create file, return 0
 * else create the new file or dir, add entry in current dir table
 * and return index of first block of file or dir
 * @param filename is name of file to create
 * @param file_type is either MFS_BLOCK_TYPE_DIR (for directory) or MFS_BLOCK_TYPE_FILE (for a regular file)
 * @return 1 for success and 0 for failure
 */
static int create_file(const char *filename, int file_type) {
  int new_dir_block;
  int new_dir_index;
  int new_entry_index;
  int new_block;
  int first_dir_block;
  int reuse_block = -1;
  int reuse_index = -1;
  int reusing = 0;

  if (get_dir_ent(filename, &new_dir_block, &new_dir_index, &reuse_block, &reuse_index)) {
    //xil_printf("Case 10\r\n");
    /* file already exists */
    return 0 ; /* cannot create file if it already exists */
  }
  else if (new_dir_block == -1 || new_dir_index == -1) {
    /* file does not exist but path prefix does not exist either */
    //xil_printf("Case 11\r\n");
    return 0; /* cannot create file because its parent dir does not exist */
  }
  else { /* create the file */
    /* first check if there is a reusable entry */
	if ((reuse_block != -1) && (reuse_index != -1)) {
	  /* found an entry to reuse */
	  new_dir_index = reuse_index;
	  new_dir_block = reuse_block;
	  reusing = 1;
	}
    else {
	  /* check if the current dir block is full and
         allocate a new dir block if needed */

      if (new_dir_index == MFS_MAX_LOCAL_ENT) {
        /* create a new dir block linked from this one */
        if (get_next_free_block(&new_block)) { /* found a free block */
	      mfs_file_system[new_block].prev_block = new_dir_block;
	      mfs_file_system[new_block].next_block = 0;
	      mfs_file_system[new_block].block_type = MFS_BLOCK_TYPE_DIR;
	      mfs_file_system[new_block].u.dir_data.num_entries = 0;
	      mfs_file_system[new_block].u.dir_data.num_deleted = 0;
	      mfs_file_system[new_dir_block].next_block = new_block;
	      new_dir_block = new_block;
	      new_dir_index = 0;
        }
        else { /* no space for new block  - return failure */
	      //xil_printf("Case 12\r\n");
	      return 0;
        }
      }
    }
    /* at this point new_dir_index and new_dir_block both point to
       the first free entry */
    first_dir_block = get_first_dir_block(new_dir_block);
    if (!create_new_file(file_type, &new_entry_index, first_dir_block)) { /* cannot create new file */
      //xil_printf("Case 13\r\n");
      return 0; /* failure */
    };

	if (reusing != 1) {
      /* update number of entries in current block */
      mfs_file_system[new_dir_block].u.dir_data.num_entries += 1;
      /* update number of entries in directory if it is different than current block */

      if (new_dir_block != first_dir_block)
        mfs_file_system[first_dir_block].u.dir_data.num_entries += 1;
	}
    mfs_file_system[new_dir_block].u.dir_data.dir_ent[new_dir_index].index = new_entry_index;
    set_filename(mfs_file_system[new_dir_block].u.dir_data.dir_ent[new_dir_index].name, get_basename(filename));
    mfs_file_system[new_dir_block].u.dir_data.dir_ent[new_dir_index].deleted = 'n';
    //xil_printf("Case 14\r\n");
    return new_entry_index;
  }
}