/* msdos_find_node_by_cluster_num_in_fat_file -- * Find node with specified number of cluster in fat-file. * * PARAMETERS: * mt_entry - mount table entry * fat_fd - fat-file descriptor * cl4find - number of cluster to find * paux - identify a node location on the disk - * cluster num and offset inside the cluster * dir_entry - placeholder for found node * * RETURNS: * RC_OK on success, or error code if error occured * */ int msdos_find_node_by_cluster_num_in_fat_file( rtems_filesystem_mount_table_entry_t *mt_entry, fat_file_fd_t *fat_fd, uint32_t cl4find, fat_auxiliary_t *paux, char *dir_entry ) { int rc = RC_OK; ssize_t ret = 0; msdos_fs_info_t *fs_info = mt_entry->fs_info; uint32_t bts2rd = 0; uint32_t i = 0, j = 0; if (FAT_FD_OF_ROOT_DIR(fat_fd) && (fs_info->fat.vol.type & (FAT_FAT12 | FAT_FAT16))) bts2rd = fat_fd->fat_file_size; else bts2rd = fs_info->fat.vol.bpc; while ((ret = fat_file_read(mt_entry, fat_fd, j * bts2rd, bts2rd, fs_info->cl_buf)) != FAT_EOF) { if ( ret < MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE ) set_errno_and_return_minus_one( EIO ); assert(ret == bts2rd); for (i = 0; i < bts2rd; i += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE) { /* if this and all rest entries are empty - return not-found */ if ((*MSDOS_DIR_NAME(fs_info->cl_buf + i)) == MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY) return MSDOS_NAME_NOT_FOUND_ERR; /* have to look at the DIR_NAME as "raw" 8-bit data */ /* if this entry is empty - skip it */ if ((*(uint8_t *)MSDOS_DIR_NAME(fs_info->cl_buf + i)) == MSDOS_THIS_DIR_ENTRY_EMPTY) continue; /* if get a non-empty entry - compare clusters num */ if (MSDOS_EXTRACT_CLUSTER_NUM((fs_info->cl_buf + i)) == cl4find) { /* on success fill aux structure and copy all 32 bytes */ rc = fat_file_ioctl(mt_entry, fat_fd, F_CLU_NUM, j * bts2rd, &paux->cln); if (rc != RC_OK) return rc; paux->ofs = i; memcpy(dir_entry, fs_info->cl_buf + i, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE); return RC_OK; } } j++; } return MSDOS_NAME_NOT_FOUND_ERR; }
/* fat_file_read -- * Read 'count' bytes from 'start' position from fat-file. This * interface hides the architecture of fat-file, represents it as * linear file * * PARAMETERS: * mt_entry - mount table entry * fat_fd - fat-file descriptor * start - offset in fat-file (in bytes) to read from * count - count of bytes to read * buf - buffer provided by user * * RETURNS: * the number of bytes read on success, or -1 if error occured (errno * set appropriately) */ ssize_t fat_file_read( rtems_filesystem_mount_table_entry_t *mt_entry, fat_file_fd_t *fat_fd, uint32_t start, uint32_t count, uint8_t *buf ) { int rc = RC_OK; ssize_t ret = 0; fat_fs_info_t *fs_info = mt_entry->fs_info; uint32_t cmpltd = 0; uint32_t cur_cln = 0; uint32_t cl_start = 0; uint32_t save_cln = 0; uint32_t ofs = 0; uint32_t save_ofs; uint32_t sec = 0; uint32_t byte = 0; uint32_t c = 0; /* it couldn't be removed - otherwise cache update will be broken */ if (count == 0) return cmpltd; /* * >= because start is offset and computed from 0 and file_size * computed from 1 */ if ( start >= fat_fd->fat_file_size ) return FAT_EOF; if ((count > fat_fd->fat_file_size) || (start > fat_fd->fat_file_size - count)) count = fat_fd->fat_file_size - start; if ((FAT_FD_OF_ROOT_DIR(fat_fd)) && (fs_info->vol.type & (FAT_FAT12 | FAT_FAT16))) { sec = fat_cluster_num_to_sector_num(mt_entry, fat_fd->cln); sec += (start >> fs_info->vol.sec_log2); byte = start & (fs_info->vol.bps - 1); ret = _fat_block_read(mt_entry, sec, byte, count, buf); if ( ret < 0 ) return -1; return ret; }
/* msdos_find_name_in_fat_file -- * This routine is used in two ways: for a new mode creation (a) or for * search the node which correspondes to the 'name' parameter (b). * In case (a) name should be set up to NULL and 'name_dir_entry' should * point to initialized 32 bytes structure described a new node. * In case (b) 'name' should contain a valid string. * * (a): reading fat-file corresponded to directory we are going to create * node in. If found free slot write contents of name_dir_entry into * it. * * (b): reading fat-file corresponded to directory and trying to find slot * with the name field == name parameter * * PARAMETERS: * mt_entry - mount table entry * fat_fd - fat-file descriptor * name - NULL or name to find * paux - identify a node location on the disk - * number of cluster and offset inside the cluster * name_dir_entry - node to create/placeholder for found node * * RETURNS: * RC_OK on success, or error code if error occured (errno set * appropriately) * */ int msdos_find_name_in_fat_file( rtems_filesystem_mount_table_entry_t *mt_entry, fat_file_fd_t *fat_fd, char *name, fat_auxiliary_t *paux, char *name_dir_entry ) { int rc = RC_OK; ssize_t ret = 0; msdos_fs_info_t *fs_info = mt_entry->fs_info; uint32_t i = 0, j = 0; uint32_t bts2rd = 0; if (FAT_FD_OF_ROOT_DIR(fat_fd) && (fs_info->fat.vol.type & (FAT_FAT12 | FAT_FAT16))) bts2rd = fat_fd->fat_file_size; else bts2rd = fs_info->fat.vol.bpc; while ((ret = fat_file_read(mt_entry, fat_fd, (j * bts2rd), bts2rd, fs_info->cl_buf)) != FAT_EOF) { if (ret < MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE) set_errno_and_return_minus_one(EIO); assert(ret == bts2rd); /* have to look at the DIR_NAME as "raw" 8-bit data */ for (i = 0; i < bts2rd; i += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE) { /* is the entry empty ? */ if (((*(uint8_t *)MSDOS_DIR_NAME(fs_info->cl_buf + i)) == MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY) || ((*(uint8_t *)MSDOS_DIR_NAME(fs_info->cl_buf + i)) == MSDOS_THIS_DIR_ENTRY_EMPTY)) { /* whether we are looking for an empty entry */ if (name == NULL) { /* get current cluster number */ rc = fat_file_ioctl(mt_entry, fat_fd, F_CLU_NUM, j * bts2rd, &paux->cln); if (rc != RC_OK) return rc; /* offset is computed in bytes */ paux->ofs = i; /* write new node entry */ ret = fat_file_write(mt_entry, fat_fd, j * bts2rd + i, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE, (uint8_t *)name_dir_entry); if (ret != MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE) return -1; /* * we don't update fat_file_size here - it should not * increase */ return RC_OK; } /* * if name != NULL and there is no more entries in the * directory - return name-not-found */ if (((*MSDOS_DIR_NAME(fs_info->cl_buf + i)) == MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY)) return MSDOS_NAME_NOT_FOUND_ERR; } else { /* entry not empty and name != NULL -> compare names */ if (name != NULL) { if (strncmp(MSDOS_DIR_NAME((fs_info->cl_buf + i)), name, MSDOS_SHORT_NAME_LEN) == 0) { /* * we get the entry we looked for - fill auxiliary * structure and copy all 32 bytes of the entry */ rc = fat_file_ioctl(mt_entry, fat_fd, F_CLU_NUM, j * bts2rd, &paux->cln); if (rc != RC_OK) return rc; /* offset is computed in bytes */ paux->ofs = i; memcpy(name_dir_entry,(fs_info->cl_buf + i), MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE); return RC_OK; } } } } j++; } return MSDOS_NAME_NOT_FOUND_ERR; }