MFS_DIR_ENTRY_PTR MFS_Find_directory_entry ( MFS_DRIVE_STRUCT_PTR drive_ptr, /*[IN] drive context */ char *file_ptr, /*[IN] specific name to search for, if NULL then first dir entry */ uint32_t *start_cluster_ptr, /*[IN] start searching in this cluster **[OUT] set to the cluster number in which search was satisfied */ uint32_t *dir_index_ptr, /*[IN] start searching at this directory entry **[OUT] if entry is found the index of the next entry is returned */ uint32_t *prev_cluster_ptr, /* [IN] set to the cluster number previous to start_cluster ** [OUT] set to the cluster number previous to *dir_cluster_ptr */ unsigned char attribute, /*[IN] search attribute, as per Find_first_file */ _mfs_error_ptr error_ptr /* The pointer carries the error infomation */ ) { MFS_DIR_ENTRY_PTR dir_entry_ptr = NULL; char *lfn_ptr = NULL; bool found; bool lfn_flag; bool maybe = FALSE; bool found_lfn = FALSE; uint32_t current_cluster, current_index; _mfs_error error_code; uint32_t lfn_len = 0; uint16_t entries_per_sector; uint16_t k, i; char lfn_entry[40]; /* LFN entry contains up to 13 UTF16 characters, up to 40 bytes including null term are necessary when encoded using UTF8 */ char fs_file[SFILENAME_SIZE + 1]; uint32_t prev_cluster = *prev_cluster_ptr; uint32_t dirname = 0; error_code = MFS_NO_ERROR; entries_per_sector = drive_ptr->ENTRIES_PER_SECTOR; current_cluster = *start_cluster_ptr; current_index = *dir_index_ptr; found = FALSE; lfn_flag = FALSE; /* If the name is a LFN, it will be treated differently */ if ( file_ptr && *file_ptr && !MFS_Dirname_valid(file_ptr) ) { lfn_flag = TRUE; lfn_len = _strnlen(file_ptr, PATHNAME_SIZE); /* Set pointer just behind the end of the filename */ lfn_ptr = file_ptr + lfn_len; maybe = TRUE; found_lfn = FALSE; /* We also need special treatement for a directory name */ if ( attribute == (ATTR_EXCLUSIVE | MFS_ATTR_DIR_NAME) ) { attribute = MFS_ATTR_LFN; dirname = 1; } } else if ( file_ptr && *file_ptr ) { MFS_Expand_dotfile(file_ptr, fs_file); } /* ** Search in all clusters within this directory */ do { /* ** Search in all sectors within this cluster */ for ( k = (uint16_t) INDEX_TO_SECTOR(current_index); ((current_cluster == 0) || (k < drive_ptr->BPB.SECTORS_PER_CLUSTER)) && found == FALSE && current_cluster != CLUSTER_EOF; k++ ) { dir_entry_ptr = MFS_Read_directory_sector(drive_ptr,current_cluster, k, &error_code); if ( dir_entry_ptr == NULL ) { break; } /* ** Search in all entries within this sector */ for ( i = (uint16_t) INDEX_TO_OFFSET(current_index), dir_entry_ptr += i ; i < entries_per_sector && found == FALSE; i++ ) { if ( *dir_entry_ptr->NAME == '\0' ) /* if NEVER USED entry */ { if ( file_ptr ) /* If not NULL */ { if ( !*file_ptr ) /* but "" */ { /* we found it */ found = TRUE; break; } } return(NULL); /* Anyway, stop here-never used entry */ /* if the entry is relevant at all */ } else if ( (unsigned char) *dir_entry_ptr->NAME == MFS_DEL_FILE ) { /* If DELETED */ if ( file_ptr ) /* If not NULL */ { if ( !*file_ptr ) /* but "" */ { found = TRUE; /* we found it */ break; } } } else /* If REGULAR ENTRY */ { if ( file_ptr == NULL || *file_ptr ) { if ( MFS_Attribute_match(mqx_dtohc(dir_entry_ptr->ATTRIBUTE), attribute) == TRUE ) { if ( !file_ptr ) { found = TRUE; break; } else if ( lfn_flag ) /* Searching for a long name */ { if ( found_lfn ) { found = TRUE; break; } if ( !MFS_Attribute_match(mqx_dtohc(dir_entry_ptr->ATTRIBUTE), MFS_ATTR_LFN) ) { maybe = TRUE; /* Reset maybe */ dir_entry_ptr++; current_index++; continue; /* Not an LFN entry, skip it */ } if ( !maybe ) { dir_entry_ptr++; current_index++; continue; } int chunk_len; chunk_len = MFS_lfn_extract((MFS_LNAME_ENTRY_PTR)dir_entry_ptr, lfn_entry); if(lfn_ptr >= (file_ptr + chunk_len)) { lfn_ptr -= chunk_len; if ( strncmp(lfn_entry, lfn_ptr, chunk_len) ) { lfn_ptr = file_ptr + lfn_len; /* reset ptr */ maybe = FALSE; dir_entry_ptr++; current_index++; continue; /* Strings don't match */ } if ( lfn_ptr == file_ptr ) { found_lfn = TRUE; if ( dirname ) { attribute = ATTR_EXCLUSIVE | MFS_ATTR_DIR_NAME; } } } else { maybe = FALSE; lfn_ptr = file_ptr + lfn_len; /* reset ptr */ } } else /* Searching for a short name */ { found = MFS_Wildcard_match(fs_file, dir_entry_ptr->NAME); } } else { if ( lfn_flag ) { attribute = MFS_ATTR_LFN; lfn_ptr = file_ptr + lfn_len; /* reset ptr */ maybe = TRUE; found_lfn = FALSE; } } } } if ( found == FALSE ) { dir_entry_ptr++; current_index++; } } } if ( found == FALSE ) { error_code = MFS_Increment_dir_index(drive_ptr, ¤t_cluster, ¤t_index, &prev_cluster); if ( error_code ) { break; } } } while ( found == FALSE && dir_entry_ptr && current_cluster != CLUSTER_EOF && current_cluster != CLUSTER_INVALID ); if ( found == FALSE ) { dir_entry_ptr = NULL; } else { *start_cluster_ptr = current_cluster; *prev_cluster_ptr = prev_cluster; *dir_index_ptr = current_index; } if ( error_ptr ) { *error_ptr = error_code; } return(dir_entry_ptr); }
_mfs_error MFS_Increment_dir_index ( MFS_DRIVE_STRUCT_PTR drive_ptr, /*[IN] the drive on which to operate */ uint_32_ptr cluster_ptr, /*[IN/OUT] the initial/next cluster # */ uint_32_ptr index_ptr, /*[IN/OUT] the initial/next index */ uint_32_ptr prev_cluster_ptr /*[IN/OUT] the prev cluster # */ ) { uint_32 index; uint_32 cluster; _mfs_error error_code; error_code = MFS_NO_ERROR; index = *index_ptr; cluster = *cluster_ptr; index++; if ( !(index & (drive_ptr->ENTRIES_PER_SECTOR-1)) ) { /* ** if the index count LSB's wrapped to 0 (new sector) */ if ( cluster != 0 ) { if ( INDEX_TO_SECTOR (index) >= drive_ptr->BPB.SECTORS_PER_CLUSTER ) { /* ** If we are over the size of a cluster */ error_code = MFS_get_cluster_from_fat(drive_ptr,cluster, &cluster); if ( error_code == MFS_NO_ERROR ) { index = 0; } } } else { if ( index >= drive_ptr->BPB.ROOT_ENTRIES ) { index = 0; cluster = CLUSTER_INVALID; } } } if ( (cluster != *cluster_ptr) && (cluster != CLUSTER_INVALID) ) { if ( prev_cluster_ptr != NULL ) { *prev_cluster_ptr = *cluster_ptr; } } *index_ptr = index; *cluster_ptr = cluster; return(error_code); }