/* * Copyright (C) 2002. University of California, Irvine * All rights reserved. * * File Name : * fs_operations.c * * Description : * This file contains the implementation of the basic operations that * are performed in relation to a file over a filesystem. */ #ident "fs_operations.c" /* Module Header File Inclusion */ #include "fs_internal.h" /* Global Variable Declarations */ /* Static Variable Declarations */ /* Functions */ /* Change the prototype of this function to support var args later */ //FS_RESULT fs_create_file(UCHAR *file_name, UCHAR mode, // UINT16 primary_extent_size, // UCHAR *primary_disk_name, // UINT16 secondary_extent_size, // UCHAR *secondary_disk_name) // changed by chenli FS_RESULT fs_create_file(char *file_name, UCHAR mode, UINT16 primary_extent_size, char *primary_disk_name, UINT16 secondary_extent_size, char *secondary_disk_name) { UCHAR num_disks; UCHAR disc_desc_index; UINT16 file_desc_index; UINT16 count, start_index; UINT16 extent_index, ret_val; DISC_DESC disc_desc; DIR_DESC dir_desc; FILE_DESC file_desc; #ifdef DEBUG FS_TRC("Inside fs_create_file()\n"); #endif /* DEBUG */ if ((ret_val = read_num_discs(&num_disks)) != FS_SUCCESS) { FS_ERR("Reading the 'number of disks' parameter failed\n"); return FS_FAILURE; } /* Get the disk catalogue */ for (count=0; count= num_disks) // didn't find the file CHENLI - FIX MEM LEAK { free(active_file); return NULL; } /* Club all the information in the ACTIVE_FILE structure and return a pointer to the structure so that it can be typecasted later to retrieve all the necessary information about the file */ if (count < num_disks) { /* Fill the ACTIVE_FILE structure */ strcpy(active_file->file_name, file_name); active_file->mode = mode; /* FIXME */ active_file->block_size = disc_desc.block_size; /* Fill out the last_page field */ /* Browse thru the linked list and obtain the last page accessed */; file_desc_index = dir_desc.file[file_index].file_desc_index; if ((ret_val = load_file_desc(disc_desc_index, file_desc_index, &file_desc)) != FS_SUCCESS) { FS_ERR("Loading of File Descriptor failed\n"); return NULL; } flag = TRUE; active_file->last_page = 0; while(flag == TRUE) { // ALEX BEHM if(file_desc.num_blocks < dir_desc.file[file_index].extent[file_desc.extent_index].size) { active_file->last_page += file_desc.num_blocks; flag = FALSE; } else { active_file->last_page += dir_desc.file[file_index].extent[file_desc.extent_index].size; // ONLY if the file is extended retrieve the next file descriptor if(file_desc.status == 6) { file_desc_index = file_desc.file_desc_index; if ((ret_val = load_file_desc(disc_desc_index, file_desc_index, &file_desc)) != FS_SUCCESS) { FS_ERR("Loading of File Descriptor failed\n"); return NULL; } } else flag = FALSE; } // ORIGINAL CODE FOLLOWS: CHANGED BY ALEX BEHM /* if (file_desc.num_blocks > dir_desc.file[file_index].extent[file_desc.extent_index].size) { active_file->last_page += dir_desc.file[file_index].extent[file_desc.extent_index].size; file_desc_index = file_desc.file_desc_index; if ((ret_val = load_file_desc(disc_desc_index, file_desc_index, &file_desc)) != FS_SUCCESS) { FS_ERR("Loading of File Descriptor failed\n"); return NULL; } } else { active_file->last_page += file_desc.num_blocks; flag = FALSE; } */ } /* Fill out the num_blocks field */ file_desc_index = dir_desc.file[file_index].file_desc_index; if ((ret_val = load_file_desc(disc_desc_index, file_desc_index, &file_desc)) != FS_SUCCESS) { FS_ERR("Loading of File Descriptor failed\n"); return NULL; } active_file->num_blocks = 0; for (count=0; countblock[active_file->num_blocks + block_num] = block_num + file_desc.start_index; } /* Calculate the number of blocks */ active_file->num_blocks += dir_desc.file[file_index].extent[count].size; /* load the next file descriptor */ file_desc_index = file_desc.file_desc_index; if ((ret_val = load_file_desc(disc_desc_index, file_desc_index, &file_desc)) != FS_SUCCESS) { FS_ERR("Loading of File Descriptor failed\n"); return NULL; } } } } return (void *)active_file; } FS_RESULT fs_read_filepage(void *file_ptr, UINT16 block_number, UCHAR *blk_ptr) { UCHAR num_disks; INT16 dfd; UINT16 ret_val; UINT16 count, file_index; UINT16 disc_desc_index; DIR_DESC dir_desc; DISC_DESC disc_desc; ACTIVE_FILE *active_file; #ifdef DEBUG FS_TRC("Inside fs_read_filepage()\n"); #endif /* DEBUG */ active_file = (ACTIVE_FILE *)file_ptr; if ((ret_val = read_num_discs(&num_disks)) != FS_SUCCESS) { FS_ERR("Reading the 'number of disks' parameter failed\n"); return FS_FAILURE; } /* Get the disk catalogue of the disk containing this file */ for (count=0; countfile_name))) { disc_desc_index = count; break; } } if (file_index < MAX_FILES) { break; } } if (count < num_disks) { if ((ret_val = load_disc_desc(disc_desc_index, &disc_desc)) != FS_SUCCESS) { FS_ERR("Loading of Directory Descriptor failed\n"); return FS_FAILURE; } if (block_number > active_file->last_page) { FS_ERR("Block number %d is out of range\n", block_number); return FS_FAILURE; } dfd = open(disc_desc.name, O_RDONLY); lseek(dfd, (active_file->block[block_number]*active_file->block_size), SEEK_SET); read(dfd, blk_ptr, active_file->block_size); close(dfd); } return FS_SUCCESS; } FS_RESULT fs_write_filepage(void *file_ptr, UINT16 block_number, UCHAR *blk_ptr) { UCHAR num_disks; INT16 dfd; UINT16 ret_val; UINT16 count, file_index; UINT16 disc_desc_index; DIR_DESC dir_desc; DISC_DESC disc_desc; ACTIVE_FILE *active_file; #ifdef DEBUG FS_TRC("Inside write_filepage()\n"); #endif /* DEBUG */ /* Open the disk containing the file requested */ active_file = (ACTIVE_FILE *)file_ptr; /* Do some error checking */ if (active_file->mode & READ) { FS_ERR("Invalid Operation: The file is READ only\n"); return FS_FAILURE; } if ((ret_val = read_num_discs(&num_disks)) != FS_SUCCESS) { FS_ERR("Reading the 'number of disks' parameter failed\n"); return FS_FAILURE; } /* Get the disk catalogue of the disk containing this file */ for (count=0; countfile_name))) { disc_desc_index = count; break; } } if (file_index < MAX_FILES) { break; } } if (count < num_disks) { if ((ret_val = load_disc_desc(disc_desc_index, &disc_desc)) != FS_SUCCESS) { FS_ERR("Loading of Directory Descriptor failed\n"); return FS_FAILURE; } dfd = open(disc_desc.name, O_RDWR); /* Ideally write should be called in conjunction with the read. Append function is normally used for addition of a page to a file. However, if one calls the write to write a new page, then make an additional check that if it is more than the current last_page then update the the last_page to that value */ //if (block_number > active_file->num_blocks) if (block_number >= active_file->num_blocks) // ALEX BEHM { FS_ERR("Block number %d is out of range\n", block_number); return FS_FAILURE; } /* FIXME. Shud this be the expected behavior */ //if (block_number > active_file->last_page) if (block_number >= active_file->last_page) //ALEX BEHM { active_file->last_page = block_number+1; } lseek(dfd, (active_file->block[block_number]*active_file->block_size), SEEK_SET); write(dfd, blk_ptr, active_file->block_size); close(dfd); } return FS_SUCCESS; } //FS_RESULT fs_append_filepage(void *file_ptr, UCHAR *blk_ptr) // ALEXBEHM FS_RESULT fs_append_filepage(void **file_ptr, UCHAR *blk_ptr) { UINT16 ret_val; ACTIVE_FILE *active_file; #ifdef DEBUG FS_TRC("Inside fs_append_filepage()\n"); #endif /* DEBUG */ active_file = (ACTIVE_FILE *)*file_ptr; /* Do some error checking */ if (active_file->mode & READ) { FS_ERR("Invalid Operation: The file is READ only\n"); return FS_FAILURE; } /* If the value of last_page field is more than the current extent's size then one can return failure indicating that there is no more space in the current extent of that file. But as per our discussion with Prof. Chen Li we can call extend_file automatically to allocate another extent */ if (active_file->last_page == active_file->num_blocks) { if ((ret_val = fs_extend_file(active_file->file_name, 2)) != FS_SUCCESS) { FS_ERR("fs_extend_file() command failed\n"); return FS_FAILURE; } FS_ERR("EXTENDING\n"); // CHANGED BY ALEX BEHM char name[200]; strcpy(name, active_file->file_name); if ((ret_val = fs_close_file(*file_ptr)) != FS_SUCCESS) { FS_ERR("fs_close_file() command failed\n"); return FS_FAILURE; } //if ((file_ptr = fs_open_file(active_file->file_name, 2)) != FS_SUCCESS) // ALEXBEHM if ((*file_ptr = fs_open_file(name, WRITE)) == NULL) { FS_ERR("fs_open_file() command failed\n"); return FS_FAILURE; } active_file = (ACTIVE_FILE *)*file_ptr; // ALEX BEHM } /* Write to the block number corresponding to the last_page field */ //if ((ret_val = fs_write_filepage(file_ptr, active_file->last_page, blk_ptr)) != FS_SUCCESS) // ALEX BEHM if ((ret_val = fs_write_filepage(file_ptr, active_file->last_page, blk_ptr)) != FS_SUCCESS) { FS_ERR("fs_writepage() command failed\n"); return FS_FAILURE; } /* Update the last_page field in the active file pointer */ active_file->last_page += 1; return FS_SUCCESS; } FS_RESULT fs_close_file(void *file_ptr) { UCHAR num_disks, flag; UINT16 ret_val, count; UINT16 file_index; UINT16 extent_index; UINT16 disc_desc_index; UINT16 file_desc_index; DIR_DESC dir_desc; FILE_DESC file_desc; ACTIVE_FILE *active_file; #ifdef DEBUG FS_TRC("Inside close_file()\n"); #endif /* DEBUG */ /* Update, in the file desc, number of pages used till now */ /* Do all the circus as in open_file, reach to the file desc and update the num_blocks field FIXME */ active_file = (ACTIVE_FILE *)file_ptr; if ((ret_val = read_num_discs(&num_disks)) != FS_SUCCESS) { FS_ERR("Reading the 'number of disks' parameter failed\n"); return FS_FAILURE; } /* Get the disk catalogue of the disk containing this file */ for (count=0; countfile_name))) { disc_desc_index = count; break; } } /* Check if this break is required FIXME */ if (file_index < MAX_FILES) { break; } } /* Find out which file descriptor is currently in use */ if (count < num_disks) { for (count=0; countlast_page > dir_desc.file[file_index].extent[count].size) { active_file->last_page -= dir_desc.file[file_index].extent[count].size; } else { extent_index = count; break; } } } /* Follow up with all the file descriptors associated with this file */ file_desc_index = dir_desc.file[file_index].file_desc_index; if ((ret_val = load_file_desc(disc_desc_index, file_desc_index, &file_desc)) != FS_SUCCESS) { FS_ERR("Loading of File Descriptor failed\n"); return FS_FAILURE; } flag = TRUE; while(flag == TRUE) { if ((file_desc.status & CONT) && (file_desc.extent_index != extent_index)) { file_desc_index = file_desc.file_desc_index; if ((ret_val = load_file_desc(disc_desc_index, file_desc_index, &file_desc)) != FS_SUCCESS) { FS_ERR("Loading of File Descriptor failed\n"); return FS_FAILURE; } } else { flag = FALSE; } } if (file_desc.extent_index == extent_index) { file_desc.num_blocks = active_file->last_page; if ((ret_val = store_file_desc(disc_desc_index, file_desc_index, &file_desc)) != FS_SUCCESS) { FS_ERR("Storing of File Descriptor failed\n"); return FS_FAILURE; } } /* Free the necessary resources */ free(file_ptr); return FS_SUCCESS; } //FS_RESULT fs_delete_file(UCHAR *file_name) // chenli FS_RESULT fs_delete_file(char *file_name) { UCHAR num_disks, *blk_ptr; UCHAR disc_desc_index, flag; UINT16 ret_val; UINT16 count, file_index; UINT16 file_desc_index; DIR_DESC dir_desc; FILE_DESC file_desc; ACTIVE_FILE *file_ptr; #ifdef DEBUG FS_TRC("Inside delete_file()\n"); #endif /* DEBUG */ if ((ret_val = read_num_discs(&num_disks)) != FS_SUCCESS) { FS_ERR("Reading the 'number of disks' parameter failed\n"); return FS_FAILURE; } /* Initialize the actual file area in the disk to white spaces */ if ((file_ptr = (ACTIVE_FILE *)fs_open_file(file_name, 0)) == NULL) { FS_ERR("fs_open_file() command failed\n"); return FS_FAILURE; } blk_ptr = (UCHAR *) malloc (file_ptr->block_size); memset(blk_ptr, ' ', file_ptr->block_size); for (count=0; countnum_blocks; count++) { if ((ret_val = fs_write_filepage(file_ptr, count, blk_ptr)) != FS_SUCCESS) { FS_ERR("fs_writepage() command failed\n"); return FS_FAILURE; } } if ((ret_val = fs_close_file(file_ptr)) != FS_SUCCESS) { FS_ERR("fs_close_file() command failed\n"); } free(blk_ptr); /* Clear off the file entry in the system disk */ /* Get the dir catalogue of the disk containing this file */ for (count=0; count