int32_t MFS_Close_file ( MFS_HANDLE_PTR handle, MFS_DRIVE_STRUCT_PTR drive_ptr ) { TIME_STRUCT time; DATE_STRUCT clk_time; _mfs_error error_code; error_code = MFS_lock_dos_disk( drive_ptr ); if ( error_code != MFS_NO_ERROR ) { return error_code; } #if !MFSCFG_READ_ONLY #if MFSCFG_READ_ONLY_CHECK if (MFS_is_read_only (drive_ptr)) { error_code = MFS_DISK_IS_WRITE_PROTECTED; } #endif if ((handle->TOUCHED) && (error_code == MFS_NO_ERROR)) { _time_get(&time); _time_to_date(&time, &clk_time); NORMALIZE_DATE(&clk_time); mqx_htods(handle->DIR_ENTRY.TIME, PACK_TIME(clk_time)); mqx_htods(handle->DIR_ENTRY.DATE, PACK_DATE(clk_time)); error_code = MFS_Update_entry(drive_ptr, handle); } #endif MFS_Free_handle(drive_ptr, handle); MFS_unlock(drive_ptr,TRUE); return(int32_t) error_code; }
void *MFS_Create_file ( MFS_DRIVE_STRUCT_PTR drive_ptr, unsigned char attr, /*[IN] attribute for created file*/ char *pathname, /*[IN] directory and filename of the file to be created */ _mfs_error_ptr error_ptr /*[IN/OUT] error code is written to this address */ ) { MFS_HANDLE_PTR handle; MFS_HANDLE_PTR next_handle; MFS_DIR_ENTRY_PTR dir_entry_ptr; TIME_STRUCT time; DATE_STRUCT clk_time; uint32_t dir_cluster; uint32_t dir_index; char access; _mfs_error error_code, saved_code = 0; if ( (pathname == NULL) || (*pathname == '\0') ) { *error_ptr = MFS_INVALID_PARAMETER; return( NULL ); } #if MFSCFG_READ_ONLY_CHECK if (MFS_is_read_only (drive_ptr)) { *error_ptr = MFS_DISK_IS_WRITE_PROTECTED; return NULL; } #endif error_code = MFS_lock_dos_disk( drive_ptr ); if ( error_code != MFS_NO_ERROR ) { *error_ptr = error_code; return( NULL ); } handle = NULL; attr &= (MFS_ATTR_READ_ONLY | MFS_ATTR_HIDDEN_FILE | MFS_ATTR_SYSTEM_FILE | MFS_ATTR_ARCHIVE | MFS_ATTR_VOLUME_NAME); attr |= MFS_ATTR_ARCHIVE; access = (attr & MFS_ATTR_READ_ONLY) ? MFS_ACCESS_READ_ONLY : MFS_ACCESS_READ_WRITE; dir_entry_ptr = MFS_Create_entry_slave(drive_ptr, attr, pathname, &dir_cluster, &dir_index, &error_code, TRUE); if ( (dir_entry_ptr != NULL) && !(attr & MFS_ATTR_VOLUME_NAME) ) { handle = MFS_Get_handle(drive_ptr,dir_entry_ptr); if ( handle != NULL ) { handle->DIR_CLUSTER = dir_cluster; handle->DIR_INDEX = dir_index; handle->ACCESS = access; handle->CURRENT_CLUSTER = 0; handle->PREVIOUS_CLUSTER = 0; /* ** If file exists, overwrite and set size to 0 */ if ( error_code == MFS_FILE_EXISTS ) { _time_get(&time); _time_to_date(&time, &clk_time); NORMALIZE_DATE(&clk_time); saved_code = MFS_Release_chain(drive_ptr, clustoh(handle->DIR_ENTRY.HFIRST_CLUSTER, handle->DIR_ENTRY.LFIRST_CLUSTER)); if ( saved_code == MFS_NO_ERROR || saved_code == MFS_LOST_CHAIN ) { clustod(handle->DIR_ENTRY.HFIRST_CLUSTER, handle->DIR_ENTRY.LFIRST_CLUSTER, 0); mqx_htodl(handle->DIR_ENTRY.FILE_SIZE, 0L); mqx_htodc(handle->DIR_ENTRY.ATTRIBUTE, attr); mqx_htods(handle->DIR_ENTRY.TIME, PACK_TIME(clk_time)); mqx_htods(handle->DIR_ENTRY.DATE, PACK_DATE(clk_time)); error_code = MFS_Update_entry(drive_ptr, handle); /* ** If the same file is already open, mark it as 'freshly ** truncated' so reads and writes don't clobber any data. */ if ( error_code == MFS_NO_ERROR ) { next_handle = (MFS_HANDLE_PTR) _queue_head(&drive_ptr->HANDLE_LIST); while ( next_handle ) { if ( next_handle->DIR_CLUSTER == dir_cluster && next_handle->DIR_INDEX == dir_index ) { next_handle->CURRENT_CLUSTER = 0; next_handle->PREVIOUS_CLUSTER = 0; } next_handle = (MFS_HANDLE_PTR) _queue_next(&drive_ptr->HANDLE_LIST, (QUEUE_ELEMENT_STRUCT_PTR) next_handle); } } } } /* ** No need to update the disk image if we didn't change anything. */ if ( (mqx_dtohc(handle->DIR_ENTRY.ATTRIBUTE) != attr) && (error_code == MFS_NO_ERROR) ) { mqx_htodc(handle->DIR_ENTRY.ATTRIBUTE, attr); error_code = MFS_Update_entry(drive_ptr, handle); } } else { error_code = MFS_INSUFFICIENT_MEMORY; } } MFS_unlock(drive_ptr,FALSE); if ( error_code == MFS_NO_ERROR && saved_code == MFS_LOST_CHAIN ) { *error_ptr = saved_code; } else { *error_ptr = error_code; } return((void *)handle); }
MFS_DIR_ENTRY_PTR MFS_Create_directory_entry ( MFS_DRIVE_STRUCT_PTR drive_ptr, /*[IN] the drive on which to operate */ char_ptr filename_ptr, /*[IN] pointer to the file's name */ char attribute, /*[IN] attribute to be assigned to the file */ uint_32_ptr dir_cluster_ptr, /*[IN/OUT] indicates cluster in which the entry was put.*/ uint_32_ptr dir_index_ptr, /*[IN/OUT] index of the location of new file within the directory */ uint_32_ptr error_ptr /*[IN/OUT] error_return_address */ ) { MFS_DIR_ENTRY_PTR dir_entry_ptr, dir_entry_ptr1; MFS_DIR_ENTRY_PTR temp_entry_ptr; TIME_STRUCT time; DATE_STRUCT clk_time; uint_32 dir_index, saved_index, temp_index; uint_32 entry_cluster, saved_cluster, temp_cluster; uint_32 needed_entries, i; int_32 length; boolean found_all = FALSE; char temp_name[SFILENAME_SIZE+1], short_name[SFILENAME_SIZE+1]; uchar checksum = 0; uint_32 prev_cluster= CLUSTER_INVALID, saved_prev_cluster, temp_prev_cluster; dir_entry_ptr = NULL; entry_cluster = *dir_cluster_ptr; dir_index = 0; /* ** Check for duplicate file */ if ( filename_ptr == NULL ) { *error_ptr = MFS_INVALID_PARAMETER; } else if ( *filename_ptr == '\0' ) { *error_ptr = MFS_FILE_NOT_FOUND; } #if MFSCFG_READ_ONLY_CHECK else if (MFS_is_read_only (NULL, drive_ptr)) { *error_ptr = MFS_DISK_IS_WRITE_PROTECTED; } #endif else if ( (dir_entry_ptr = MFS_Find_directory_entry(drive_ptr, filename_ptr, &entry_cluster, &dir_index, &prev_cluster, MFS_ATTR_ANY, error_ptr)) != NULL ) { *error_ptr = MFS_FILE_EXISTS; } else { /* ** Search for an empty slot */ dir_index = 0; dir_entry_ptr = MFS_Find_directory_entry(drive_ptr, "", &entry_cluster, &dir_index, &prev_cluster, attribute, error_ptr); if ( MFS_Dirname_valid(filename_ptr) ) { found_all = TRUE; } if ( dir_entry_ptr == NULL && !*error_ptr ) { found_all = TRUE; } /* ** Save it now because we might not go into the while loop ** If we don't go into while, we lose original values when these ** variables are restored after the while loop */ saved_cluster = entry_cluster; saved_index = dir_index; while ( !found_all ) { /* Calculate the amount of extra entries needed for LFN's */ saved_cluster = entry_cluster; saved_index = dir_index; for ( needed_entries = (strlen(filename_ptr) + 12) / 13; needed_entries >= 1 && !found_all; needed_entries-- ) { *error_ptr = MFS_Increment_dir_index(drive_ptr, &entry_cluster, &dir_index, NULL); if ( entry_cluster == CLUSTER_EOF && !*error_ptr ) { /* This means the LFN will span a cluster. */ found_all = TRUE; break; } temp_index = dir_index; temp_cluster = entry_cluster; temp_entry_ptr = MFS_Find_directory_entry(drive_ptr, "", &entry_cluster, &dir_index, &prev_cluster, MFS_ATTR_ANY,error_ptr); if ( *error_ptr ) { return NULL; } if ( !temp_entry_ptr ) { found_all = TRUE; dir_entry_ptr = NULL; break; } else if ( dir_index == temp_index && temp_cluster == entry_cluster ) { continue; } else { break; } } if ( needed_entries == 0 ) { found_all = TRUE; } if ( found_all ) { dir_entry_ptr = MFS_Find_directory_entry(drive_ptr, "", &saved_cluster, &saved_index, &saved_prev_cluster, MFS_ATTR_ANY,error_ptr); } } entry_cluster = saved_cluster; dir_index = saved_index; if ( dir_entry_ptr == NULL && !*error_ptr ) { /* ** Empty spot not found... get a new cluster and use the first entry. */ dir_index = 0; if ( entry_cluster == 0 ) { *error_ptr = MFS_ROOT_DIR_FULL; return(NULL); } else { *error_ptr = MFS_Add_cluster_to_chain(drive_ptr, entry_cluster, &entry_cluster); if ( *error_ptr == MFS_NO_ERROR ) { *error_ptr = MFS_Clear_cluster(drive_ptr, entry_cluster); if ( *error_ptr ) { return(NULL); } dir_entry_ptr = (pointer) drive_ptr->DIR_SECTOR_PTR; *error_ptr = MFS_Write_back_fat(drive_ptr); if ( *error_ptr ) { return(NULL); } } } } } if ( *error_ptr == MFS_NO_ERROR ) { /* At this point we have one of the following cases ** ** 1. We have a normal 8.3 filename and an empty slot for it ** 2. We have a LFN, and a slot which has enough consecutive free slots ** to store the LFN, followed by the actual entry */ /* If the file is a normal 8.3 file */ if ( MFS_Dirname_valid(filename_ptr) ) { _mem_zero(dir_entry_ptr, sizeof (MFS_DIR_ENTRY)); htodc(dir_entry_ptr->ATTRIBUTE, attribute); MFS_Expand_dotfile(filename_ptr, dir_entry_ptr->NAME); _time_get(&time); _time_to_date(&time, &clk_time); NORMALIZE_DATE(&clk_time); htods(dir_entry_ptr->TIME, PACK_TIME(clk_time)); htods(dir_entry_ptr->DATE, PACK_DATE(clk_time)); drive_ptr->DIR_SECTOR_DIRTY = TRUE; } else { /* Case where the file is a LFN */ length = strlen(filename_ptr); /* Get the 8.3 name and calculate the checksum */ temp_index = 0; temp_cluster = *dir_cluster_ptr; *error_ptr = MFS_lfn_to_sfn(filename_ptr, temp_name); if ( !*error_ptr ) { do { dir_entry_ptr1 = MFS_Find_directory_entry(drive_ptr, temp_name, &temp_cluster, &temp_index, &temp_prev_cluster, MFS_ATTR_ANY, error_ptr); if ( !*error_ptr && dir_entry_ptr1 != NULL ) { MFS_increment_lfn(temp_name); temp_index = 0; } } while ( !*error_ptr && dir_entry_ptr1 != NULL ); dir_entry_ptr = MFS_Find_directory_entry(drive_ptr, "", &entry_cluster, &dir_index, &prev_cluster, attribute, error_ptr); /* ** The memory should be cleared after finding the directory entry. */ _mem_zero(dir_entry_ptr, sizeof (MFS_DIR_ENTRY)); /* Setup the final slot */ ((MFS_LNAME_ENTRY_PTR) dir_entry_ptr)->ID |= MFS_LFN_END; drive_ptr->DIR_SECTOR_DIRTY = TRUE; MFS_Expand_dotfile(temp_name,short_name); checksum = MFS_lfn_checksum(short_name); } while ( length && !*error_ptr ) { i = length - ((length -1) % 13 + 1); *error_ptr = MFS_lfn_name_to_entry(filename_ptr + i, (MFS_LNAME_ENTRY_PTR) dir_entry_ptr); /* Set the entry number, the checksum value and the attribute */ ((MFS_LNAME_ENTRY_PTR) dir_entry_ptr)->ID |= (length + 12) / 13; ((MFS_LNAME_ENTRY_PTR) dir_entry_ptr)->ALIAS_CHECKSUM= checksum; ((MFS_LNAME_ENTRY_PTR) dir_entry_ptr)->ATTR = MFS_ATTR_LFN; drive_ptr->DIR_SECTOR_DIRTY = TRUE; length -= (length - i); if ( length < 0 ) { length = 0; } if ( length && !*error_ptr ) { dir_entry_ptr = MFS_Find_directory_entry(drive_ptr, "", &entry_cluster, &dir_index, &prev_cluster, attribute, error_ptr); if ( dir_entry_ptr == NULL && !*error_ptr ) { /* No empty spots... We need to get a new cluster */ dir_index = 0; if ( entry_cluster == 0 ) { *error_ptr = MFS_ROOT_DIR_FULL; return(NULL); } else { *error_ptr = MFS_Add_cluster_to_chain( drive_ptr, entry_cluster, &entry_cluster); if ( *error_ptr == MFS_NO_ERROR ) { *error_ptr = MFS_Clear_cluster(drive_ptr, entry_cluster); if ( *error_ptr ) { return(NULL); } dir_entry_ptr = (pointer) drive_ptr->DIR_SECTOR_PTR; *error_ptr = MFS_Write_back_fat(drive_ptr); if ( *error_ptr ) { return(NULL); } } } } _mem_zero(dir_entry_ptr, sizeof (MFS_DIR_ENTRY)); drive_ptr->DIR_SECTOR_DIRTY = TRUE; } } /* LFN is written, so write the actual entry */ if ( !*error_ptr ) { dir_entry_ptr = MFS_Find_directory_entry(drive_ptr, "", &entry_cluster, &dir_index, &prev_cluster, attribute, error_ptr); if ( dir_entry_ptr == NULL && !*error_ptr ) { dir_index = 0; if ( entry_cluster == 0 ) { *error_ptr = MFS_ROOT_DIR_FULL; return(NULL); } else { *error_ptr = MFS_Add_cluster_to_chain( drive_ptr, entry_cluster, &entry_cluster); if ( *error_ptr == MFS_NO_ERROR ) { *error_ptr = MFS_Clear_cluster(drive_ptr, entry_cluster); if ( *error_ptr ) { return(NULL); } dir_entry_ptr = (pointer) drive_ptr->DIR_SECTOR_PTR; *error_ptr = MFS_Write_back_fat(drive_ptr); if ( *error_ptr ) { return(NULL); } } } } _mem_zero(dir_entry_ptr, sizeof (MFS_DIR_ENTRY)); htodc(dir_entry_ptr->ATTRIBUTE, attribute); MFS_Expand_dotfile(temp_name, dir_entry_ptr->NAME); _time_get(&time); _time_to_date(&time, &clk_time); NORMALIZE_DATE(&clk_time); htods(dir_entry_ptr->TIME, PACK_TIME(clk_time)); htods(dir_entry_ptr->DATE, PACK_DATE(clk_time)); drive_ptr->DIR_SECTOR_DIRTY = TRUE; } } if ( *error_ptr ) { return(NULL); } } *dir_cluster_ptr = entry_cluster; *dir_index_ptr = dir_index; return(dir_entry_ptr); }