MFS_DIR_ENTRY_PTR MFS_Find_entry_on_disk ( MFS_DRIVE_STRUCT_PTR drive_ptr, /*[IN] drive context */ char *pathname, /*[IN] pathname of the file */ _mfs_error_ptr error_ptr, /*[IN/OUT] resulting error code is written to this address*/ uint32_t *dir_cluster_ptr, /*[OUT] the cluster in which the dir entry is located */ uint32_t *dir_index_ptr, /*[OUT] the index within the dir cluster where the entry is located */ uint32_t *prev_cluster_ptr /*[OUT] the cluster previous to dir cluster */ ) { MFS_DIR_ENTRY_PTR dir_entry_ptr; char *temp_dirname; char *temp_filename; uint32_t first_cluster; *error_ptr = MFS_alloc_2paths(&temp_dirname,&temp_filename); if ( *error_ptr != MFS_NO_ERROR ) { return( NULL ); } *error_ptr = MFS_NO_ERROR; dir_entry_ptr = NULL; if ( pathname ) { MFS_Parse_pathname(temp_dirname, temp_filename, pathname); /* ** Is this a relative or an absolute file search ? */ if ( *pathname == '\\' || *pathname == '/' ) { first_cluster = ROOT_CLUSTER(drive_ptr); } else { first_cluster = drive_ptr->CUR_DIR_CLUSTER; } /* first_cluster will now store the current_cluster # */ first_cluster = MFS_Find_directory(drive_ptr, temp_dirname, first_cluster); *prev_cluster_ptr = CLUSTER_INVALID; if ( first_cluster == CLUSTER_INVALID ) { *error_ptr = MFS_PATH_NOT_FOUND; } else { *dir_index_ptr = 0; *dir_cluster_ptr = first_cluster; /* ** Checking for the superset of filename chars will allow ** finding something like \mydir\.. */ if ( !MFS_lfn_dirname_valid(temp_filename) ) { dir_entry_ptr = NULL; *error_ptr = MFS_INVALID_PARAMETER; } else { dir_entry_ptr = MFS_Find_directory_entry(drive_ptr, temp_filename, dir_cluster_ptr, dir_index_ptr, prev_cluster_ptr, MFS_ATTR_ANY, error_ptr); if ( dir_entry_ptr == NULL && !*error_ptr ) { *error_ptr = MFS_FILE_NOT_FOUND; } } } } else { *error_ptr = MFS_INVALID_PARAMETER; } MFS_free_path(temp_dirname); MFS_free_path(temp_filename); return(dir_entry_ptr); }
_mfs_error MFS_Find_first_file ( MFS_DRIVE_STRUCT_PTR drive_ptr, unsigned char attribute, /*[IN] type of file to find, Search attributes */ char *pathname, /*[IN] optionally the directory and filename to search for */ MFS_SEARCH_DATA_PTR transfer_ptr /*[IN] address of search data block into which the results of the search are put */ ) { MFS_INTERNAL_SEARCH_PTR internal_search_ptr; char *temp_dirname; char *temp_filename; uint32_t current_cluster; _mfs_error error_code; uint32_t i; char c; if ( (pathname==NULL) || (*pathname=='\0') ) { return MFS_INVALID_PARAMETER; } if ( transfer_ptr == NULL ) { return MFS_INVALID_MEMORY_BLOCK_ADDRESS; } error_code = MFS_alloc_2paths(&temp_dirname,&temp_filename); if ( error_code != MFS_NO_ERROR ) { return( error_code ); } error_code = MFS_lock_dos_disk( drive_ptr ); if ( error_code != MFS_NO_ERROR ) { MFS_free_path(temp_dirname); MFS_free_path(temp_filename); return error_code; } _mem_zero(transfer_ptr, sizeof (MFS_SEARCH_DATA)); transfer_ptr->DRIVE_PTR = drive_ptr; MFS_Parse_pathname(temp_dirname, temp_filename, pathname); current_cluster = drive_ptr->CUR_DIR_CLUSTER; current_cluster = MFS_Find_directory(drive_ptr, temp_dirname, current_cluster); if ( current_cluster == CLUSTER_INVALID ) { error_code = MFS_PATH_NOT_FOUND; } else { /* ** The internal search is only initialised if the directory exists. */ internal_search_ptr = &transfer_ptr->INTERNAL_SEARCH_DATA; internal_search_ptr->CURRENT_CLUSTER = current_cluster; internal_search_ptr->PREV_CLUSTER = CLUSTER_INVALID; internal_search_ptr->DIR_ENTRY_INDEX = 0; MFS_Expand_wildcard(temp_filename, internal_search_ptr->FILENAME); internal_search_ptr->FULLNAME = temp_filename; i = _strnlen(pathname, PATHNAME_SIZE + FILENAME_SIZE + 1); c = pathname[--i]; while ( (c != '\\') && (c != '/') && (c != ':') && i ) { i--; c = pathname[i]; } if ( i || c == '\\' || c == '/' ) { i++; } internal_search_ptr->SRC_PTR = pathname + i; internal_search_ptr->ATTRIBUTE = attribute; error_code = MFS_Find_next_slave(drive_ptr, transfer_ptr); } MFS_free_path(temp_dirname); MFS_free_path(temp_filename); MFS_unlock(drive_ptr,FALSE); return(error_code); }
_mfs_error MFS_Change_current_dir ( MFS_DRIVE_STRUCT_PTR drive_ptr, char *pathname /*[IN] pathname of the directory to become the current dir */ ) { uint32_t dir_cluster; uint16_t length; _mfs_error error_code; char *directory; char *temp_cur; register char *src, *dest, *dest_start; if ( (pathname == NULL) || (*pathname == '\0') ) { return MFS_INVALID_PARAMETER; } error_code = MFS_alloc_2paths(&directory,&temp_cur); if ( error_code != MFS_NO_ERROR ) { return( error_code ); } error_code = MFS_lock_dos_disk( drive_ptr ); if ( error_code != MFS_NO_ERROR ) { MFS_free_path(directory); MFS_free_path(temp_cur); return error_code; } dir_cluster = drive_ptr->CUR_DIR_CLUSTER; dir_cluster = MFS_Find_directory(drive_ptr, pathname, dir_cluster); if ( dir_cluster != CLUSTER_INVALID ) { src = pathname; dest = temp_cur; if ( *src == '\\' || *src == '/' ) { temp_cur[0] = '\\'; temp_cur[1] = '\0'; src++; } else { strcpy (temp_cur, drive_ptr->CURRENT_DIR); dest = temp_cur + strlen(temp_cur) - 1; } dest_start = temp_cur; length = strlen(dest_start); while ( src ) { if ( *src ) { src = MFS_Parse_next_filename(src, directory); if ( src != NULL ) { MFS_strupr(directory); } if ( directory[0] == '.' && directory[1] == '.' ) { if ( dest != dest_start ) { while ( dest != dest_start && *dest != '\\' ) { dest--; } /* Erase the previous backslash, unless it is the ** first (root directory). */ if ( dest != dest_start ) { *dest-- = '\0'; } else { *(dest+1) = '\0'; } } else { /* ** The check for underflow is redundant, because the path ** has been found already. */ error_code = MFS_PATH_NOT_FOUND; break; } } else if ( directory[0] && directory[0] != '.' ) { if ( *dest != '\\' ) { *(++dest) = '\\'; length++; } length += strlen(directory); if ( length < sizeof (drive_ptr->CURRENT_DIR) ) { strcpy (++dest, directory); dest = temp_cur + length - 1; } else { error_code = MFS_INVALID_LENGTH_IN_DISK_OPERATION; break; } } } else { break; } } if ( error_code == MFS_NO_ERROR ) { strcpy (drive_ptr->CURRENT_DIR, dest_start); drive_ptr->CUR_DIR_CLUSTER = dir_cluster; } } else { error_code = MFS_PATH_NOT_FOUND; } MFS_free_path(directory); MFS_free_path(temp_cur); MFS_unlock(drive_ptr,FALSE); return(error_code); }
_mfs_error MFS_Create_subdir ( MFS_DRIVE_STRUCT_PTR drive_ptr, char *pathname /*[IN] pathname of the directory to be created */ ) { MFS_DIR_ENTRY_PTR dir_entry_ptr; uint32_t dir_cluster; uint32_t parent_cluster; uint32_t free_cluster; uint32_t dir_index; _mfs_error error_code; char *temp_dirname; char *temp_filename; if ( (pathname == NULL) || (*pathname == '\0') ) { return MFS_INVALID_PARAMETER; } #if MFSCFG_READ_ONLY_CHECK if (MFS_is_read_only (drive_ptr)) { return MFS_DISK_IS_WRITE_PROTECTED; } #endif error_code = MFS_alloc_2paths(&temp_dirname,&temp_filename); if ( error_code != MFS_NO_ERROR ) { return( error_code ); } error_code = MFS_lock_dos_disk( drive_ptr ); if ( error_code != MFS_NO_ERROR ) { MFS_free_path(temp_dirname); MFS_free_path(temp_filename); return error_code; } MFS_Parse_pathname (temp_dirname, temp_filename, pathname); dir_cluster = drive_ptr->CUR_DIR_CLUSTER; parent_cluster = MFS_Find_directory (drive_ptr, temp_dirname, dir_cluster); dir_cluster = parent_cluster; if ( MFS_is_valid_lfn(temp_filename) ) { if ( dir_cluster != CLUSTER_INVALID ) { /* ** We'll obtain a cluster for the new directory first. If we ** cannot create the directory afterwards, it is easier to re-free ** the cluster than to remove the new entry. */ free_cluster = MFS_Find_unused_cluster_from(drive_ptr, drive_ptr->NEXT_FREE_CLUSTER); if ( free_cluster != CLUSTER_INVALID ) { error_code = MFS_Clear_cluster(drive_ptr, free_cluster); if ( error_code ) { MFS_unlock(drive_ptr,TRUE); MFS_free_path(temp_dirname); MFS_free_path(temp_filename); return( error_code ); } error_code = MFS_Put_fat(drive_ptr, free_cluster, CLUSTER_EOF); dir_entry_ptr = MFS_Create_directory_entry(drive_ptr, temp_filename, MFS_ATTR_DIR_NAME, &dir_cluster, &dir_index, &error_code); if ( error_code == MFS_NO_ERROR ) { clustod(dir_entry_ptr->HFIRST_CLUSTER, dir_entry_ptr->LFIRST_CLUSTER, free_cluster); drive_ptr->DIR_SECTOR_DIRTY = TRUE; /* ** We shall now create the "." and ".." entries. */ dir_cluster = free_cluster; dir_entry_ptr = MFS_Create_directory_entry(drive_ptr,".", MFS_ATTR_DIR_NAME, &dir_cluster, &dir_index, &error_code); if ( error_code == MFS_NO_ERROR ) { clustod(dir_entry_ptr->HFIRST_CLUSTER, dir_entry_ptr->LFIRST_CLUSTER, free_cluster); drive_ptr->DIR_SECTOR_DIRTY = TRUE; dir_entry_ptr = MFS_Create_directory_entry(drive_ptr,"..", MFS_ATTR_DIR_NAME, &dir_cluster, &dir_index, &error_code); if ( error_code == MFS_NO_ERROR ) { if ( drive_ptr->FAT_TYPE == MFS_FAT32 ) { if ( drive_ptr->BPB32.ROOT_CLUSTER == parent_cluster ) { /* ** Even though the FAT32 root sector can be ** anywhere, it is identified as 0 when referenced ** through a directory entry */ parent_cluster = 0; } } clustod(dir_entry_ptr->HFIRST_CLUSTER, dir_entry_ptr->LFIRST_CLUSTER, parent_cluster); drive_ptr->DIR_SECTOR_DIRTY = TRUE; } } } else { MFS_Put_fat(drive_ptr, free_cluster, CLUSTER_UNUSED); } } else { error_code = MFS_DISK_FULL; } } else { error_code = MFS_PATH_NOT_FOUND; } } else if ( MFS_lfn_dirname_valid(temp_filename) ) { if ( dir_cluster ) { error_code = MFS_FILE_EXISTS; } else { error_code = MFS_CANNOT_CREATE_DIRECTORY; } } else { error_code = MFS_INVALID_PARAMETER; } MFS_free_path(temp_dirname); MFS_free_path(temp_filename); MFS_unlock(drive_ptr,TRUE); return(error_code); }
MFS_DIR_ENTRY_PTR MFS_Create_entry_slave ( MFS_DRIVE_STRUCT_PTR drive_ptr, /*[IN] the drive on which to operate */ uchar attr, /*[IN] attribute to be given to the new file */ char_ptr pathname, /*[IN] directory and file name to be given to the new file */ uint_32_ptr cluster_ptr, /*[OUT] cluster # in the directory where the entry was created */ uint_32_ptr index_ptr, /*[OUT] index # in the directory where the entry was created*/ _mfs_error_ptr error_ptr, /*[IN/OUT] error code is written to this address */ boolean overwrite /*[IN] if TRUE, we will overwrite an existing entry w/the same name */ ) { MFS_DIR_ENTRY_PTR dir_entry_ptr; char_ptr temp_dirname; char_ptr temp_filename; uchar at; uint_32 dir_cluster; uint_32 dir_index; uint_32 vol_cluster, vol_index; _mfs_error error_code; uint_32 prev_cluster; #if MFSCFG_READ_ONLY_CHECK if (MFS_is_read_only (NULL, drive_ptr)) { if ( error_ptr ) { *error_ptr = MFS_DISK_IS_WRITE_PROTECTED; } return NULL; } #endif dir_index = 0; dir_cluster = drive_ptr->CUR_DIR_CLUSTER; dir_entry_ptr = NULL; error_code = MFS_alloc_2paths(&temp_dirname,&temp_filename); if ( error_code ) { return( NULL ); } error_code = MFS_Parse_pathname(temp_dirname, temp_filename, pathname); if ( error_code == MFS_NO_ERROR ) { dir_cluster = MFS_Find_directory(drive_ptr, temp_dirname, dir_cluster); if ( dir_cluster == CLUSTER_INVALID ) { error_code = MFS_PATH_NOT_FOUND; } else { if ( MFS_is_valid_lfn(temp_filename) ) { if ( attr & MFS_ATTR_VOLUME_NAME ) { /* ** If creating a volume label, it must be in the root ** directory. */ if ( dir_cluster == 0 ) { vol_cluster = 0; vol_index = 0; dir_entry_ptr = MFS_Find_directory_entry(drive_ptr, NULL, &vol_cluster, &vol_index, &prev_cluster, MFS_ATTR_VOLUME_NAME, &error_code); if ( dir_entry_ptr ) { error_code = MFS_ALREADY_ASSIGNED; } } else { error_code = MFS_ACCESS_DENIED; } } if ( error_code == MFS_NO_ERROR ) { dir_entry_ptr = MFS_Create_directory_entry(drive_ptr, temp_filename, attr, &dir_cluster, &dir_index, &error_code); /* if dir_entry_ptr == NULL ** we couldn't create a new entry. ** if not NULL, it may be a brand new entry (MFS_NO_ERROR) or ** an old one (MFS_FILE_EXISTS) */ if ( dir_entry_ptr != NULL ) { at = dtohc(dir_entry_ptr->ATTRIBUTE); if ( (error_code != MFS_NO_ERROR) && (overwrite == FALSE) ) { dir_entry_ptr = NULL; } else if ( (error_code == MFS_FILE_EXISTS) && ((at & MFS_ATTR_DIR_NAME) != (attr & MFS_ATTR_DIR_NAME)) || ((at & MFS_ATTR_VOLUME_NAME) != (attr & MFS_ATTR_VOLUME_NAME)) ) { error_code = MFS_WRITE_FAULT; dir_entry_ptr = NULL; } else if ( at & MFS_ATTR_READ_ONLY && error_code != MFS_NO_ERROR ) { /* ** If not freshly created */ error_code = MFS_ACCESS_DENIED; dir_entry_ptr = NULL; } } *cluster_ptr = dir_cluster; *index_ptr = dir_index; } } else { error_code = MFS_INVALID_PARAMETER; dir_entry_ptr = NULL; } } } if ( error_ptr ) { *error_ptr = error_code; } MFS_free_path(temp_filename); MFS_free_path(temp_dirname); return(dir_entry_ptr); }