/* msdos_find_name -- * Find the node which correspondes to the name, open fat-file which * correspondes to the found node and close fat-file which correspondes * to the node we searched in. * * PARAMETERS: * parent_loc - parent node description * name - name to find * * RETURNS: * RC_OK and updated 'parent_loc' on success, or -1 if error * occured (errno set apropriately) * */ int msdos_find_name( rtems_filesystem_location_info_t *parent_loc, char *name ) { int rc = RC_OK; msdos_fs_info_t *fs_info = parent_loc->mt_entry->fs_info; fat_file_fd_t *fat_fd = NULL; fat_auxiliary_t aux; unsigned short time_val = 0; unsigned short date = 0; char node_entry[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE]; memset(node_entry, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE); /* * find the node which correspondes to the name in the directory pointed by * 'parent_loc' */ rc = msdos_get_name_node(parent_loc, name, &aux, node_entry); if (rc != RC_OK) return rc; /* open fat-file corresponded to the found node */ rc = fat_file_open(parent_loc->mt_entry, aux.cln, aux.ofs, &fat_fd); if (rc != RC_OK) return rc; /* * I don't like this if, but: we should do it , or should write new file * size and first cluster num to the disk after each write operation * (even if one byte is written - that is TOO non-optimize) because * otherwise real values of these fields stored in fat-file descriptor * may be accidentely rewritten with wrong values stored on the disk */ if (fat_fd->links_num == 1) { fat_fd->info_cln = aux.cln; fat_fd->info_ofs = aux.ofs; fat_fd->cln = MSDOS_EXTRACT_CLUSTER_NUM(node_entry); fat_fd->first_char = *MSDOS_DIR_NAME(node_entry); time_val = *MSDOS_DIR_WRITE_TIME(node_entry); date = *MSDOS_DIR_WRITE_DATE(node_entry); fat_fd->mtime = msdos_date_dos2unix(CF_LE_W(time_val), CF_LE_W(date)); if ((*MSDOS_DIR_ATTR(node_entry)) & MSDOS_ATTR_DIRECTORY) { fat_fd->fat_file_type = FAT_DIRECTORY; fat_fd->size_limit = MSDOS_MAX_DIR_LENGHT; rc = fat_file_size(parent_loc->mt_entry, fat_fd); if (rc != RC_OK) { fat_file_close(parent_loc->mt_entry, fat_fd); return rc; } } else { fat_fd->fat_file_size = CF_LE_L(*MSDOS_DIR_FILE_SIZE(node_entry)); fat_fd->fat_file_type = FAT_FILE; fat_fd->size_limit = MSDOS_MAX_FILE_SIZE; } /* these data is not actual for zero-length fat-file */ fat_fd->map.file_cln = 0; fat_fd->map.disk_cln = fat_fd->cln; if ((fat_fd->fat_file_size != 0) && (fat_fd->fat_file_size <= fs_info->fat.vol.bpc)) { fat_fd->map.last_cln = fat_fd->cln; } else { fat_fd->map.last_cln = FAT_UNDEFINED_VALUE; } } /* close fat-file corresponded to the node we searched in */ rc = fat_file_close(parent_loc->mt_entry, parent_loc->node_access); if (rc != RC_OK) { fat_file_close(parent_loc->mt_entry, fat_fd); return rc; } /* update node_info_ptr field */ parent_loc->node_access = fat_fd; return rc; }
/* msdos_get_dotdot_dir_info_cluster_num_and_offset -- * Get cluster num and offset not of ".." slot, but slot which correspondes * to real directory name. * * PARAMETERS: * mt_entry - mount table entry * cln - data cluster num extracted drom ".." slot * paux - identify a node location on the disk - * number of cluster and offset inside the cluster * dir_entry - placeholder for found node * * RETURNS: * RC_OK, filled 'paux' and 'dir_entry' on success, or -1 if error occured * (errno set apropriately) * */ int msdos_get_dotdot_dir_info_cluster_num_and_offset( rtems_filesystem_mount_table_entry_t *mt_entry, uint32_t cln, fat_auxiliary_t *paux, char *dir_entry ) { int rc = RC_OK; msdos_fs_info_t *fs_info = mt_entry->fs_info; fat_file_fd_t *fat_fd = NULL; char dot_node[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE]; char dotdot_node[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE]; uint32_t cl4find = 0; memset(dot_node, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE); memset(dotdot_node, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE); /* * open fat-file corresponded to ".." */ rc = fat_file_open(mt_entry, paux->cln, paux->ofs, &fat_fd); if (rc != RC_OK) return rc; fat_fd->info_cln = paux->cln; fat_fd->info_ofs = paux->ofs; fat_fd->cln = cln; fat_fd->fat_file_type = FAT_DIRECTORY; fat_fd->size_limit = MSDOS_MAX_DIR_LENGHT; fat_fd->map.file_cln = 0; fat_fd->map.disk_cln = fat_fd->cln; rc = fat_file_size(mt_entry, fat_fd); if (rc != RC_OK) { fat_file_close(mt_entry, fat_fd); return rc; } /* find "." node in opened directory */ rc = msdos_find_name_in_fat_file(mt_entry, fat_fd, MSDOS_DOT_NAME, paux, dot_node); if (rc != RC_OK) { fat_file_close(mt_entry, fat_fd); return rc; } /* find ".." node in opened directory */ rc = msdos_find_name_in_fat_file(mt_entry, fat_fd, MSDOS_DOTDOT_NAME, paux, dotdot_node); if (rc != RC_OK) { fat_file_close(mt_entry, fat_fd); return rc; } cl4find = MSDOS_EXTRACT_CLUSTER_NUM(dot_node); /* close fat-file corresponded to ".." directory */ rc = fat_file_close(mt_entry, fat_fd); if ( rc != RC_OK ) return rc; if ( (MSDOS_EXTRACT_CLUSTER_NUM(dotdot_node)) == 0) { /* * we handle root dir for all FAT types in the same way with the * ordinary directories ( through fat_file_* calls ) */ paux->cln = FAT_ROOTDIR_CLUSTER_NUM; paux->ofs = 0; } /* open fat-file corresponded to second ".." */ rc = fat_file_open(mt_entry, paux->cln, paux->ofs, &fat_fd); if (rc != RC_OK) return rc; fat_fd->info_cln = paux->cln; fat_fd->info_ofs = paux->ofs; if ((MSDOS_EXTRACT_CLUSTER_NUM(dotdot_node)) == 0) fat_fd->cln = fs_info->fat.vol.rdir_cl; else fat_fd->cln = MSDOS_EXTRACT_CLUSTER_NUM(dotdot_node); fat_fd->fat_file_type = FAT_DIRECTORY; fat_fd->size_limit = MSDOS_MAX_DIR_LENGHT; fat_fd->map.file_cln = 0; fat_fd->map.disk_cln = fat_fd->cln; rc = fat_file_size(mt_entry, fat_fd); if (rc != RC_OK) { fat_file_close(mt_entry, fat_fd); return rc; } /* in this directory find slot with specified cluster num */ rc = msdos_find_node_by_cluster_num_in_fat_file(mt_entry, fat_fd, cl4find, paux, dir_entry); if (rc != RC_OK) { fat_file_close(mt_entry, fat_fd); return rc; } rc = fat_file_close(mt_entry, fat_fd); return rc; }
/* msdos_initialize_support -- * MSDOS filesystem initialization * * PARAMETERS: * temp_mt_entry - mount table entry * op_table - filesystem operations table * file_handlers - file operations table * directory_handlers - directory operations table * * RETURNS: * RC_OK and filled temp_mt_entry on success, or -1 if error occured * (errno set apropriately) * */ int msdos_initialize_support( rtems_filesystem_mount_table_entry_t *temp_mt_entry, const rtems_filesystem_operations_table *op_table, const rtems_filesystem_file_handlers_r *file_handlers, const rtems_filesystem_file_handlers_r *directory_handlers, rtems_dosfs_convert_control *converter ) { int rc = RC_OK; rtems_status_code sc = RTEMS_SUCCESSFUL; msdos_fs_info_t *fs_info = NULL; fat_file_fd_t *fat_fd = NULL; fat_dir_pos_t root_pos; uint32_t cl_buf_size; fs_info = (msdos_fs_info_t *)calloc(1, sizeof(msdos_fs_info_t)); if (!fs_info) rtems_set_errno_and_return_minus_one(ENOMEM); temp_mt_entry->fs_info = fs_info; fs_info->converter = converter; rc = fat_init_volume_info(&fs_info->fat, temp_mt_entry->dev); if (rc != RC_OK) { free(fs_info); return rc; } fs_info->file_handlers = file_handlers; fs_info->directory_handlers = directory_handlers; /* * open fat-file which correspondes to root directory * (so inode number 0x00000010 is always used for root directory) */ fat_dir_pos_init(&root_pos); root_pos.sname.cln = FAT_ROOTDIR_CLUSTER_NUM; rc = fat_file_open(&fs_info->fat, &root_pos, &fat_fd); if (rc != RC_OK) { fat_shutdown_drive(&fs_info->fat); free(fs_info); return rc; } /* again: unfortunately "fat-file" is just almost fat file :( */ fat_fd->fat_file_type = FAT_DIRECTORY; fat_fd->size_limit = MSDOS_MAX_DIR_LENGTH; fat_fd->cln = fs_info->fat.vol.rdir_cl; fat_fd->map.file_cln = 0; fat_fd->map.disk_cln = fat_fd->cln; /* if we have FAT12/16 */ if ( fat_fd->cln == 0 ) { fat_fd->fat_file_size = fs_info->fat.vol.rdir_size; cl_buf_size = (fs_info->fat.vol.bpc > fs_info->fat.vol.rdir_size) ? fs_info->fat.vol.bpc : fs_info->fat.vol.rdir_size; } else { rc = fat_file_size(&fs_info->fat, fat_fd); if ( rc != RC_OK ) { fat_file_close(&fs_info->fat, fat_fd); fat_shutdown_drive(&fs_info->fat); free(fs_info); return rc; } cl_buf_size = fs_info->fat.vol.bpc; } fs_info->cl_buf = (uint8_t *)calloc(cl_buf_size, sizeof(char)); if (fs_info->cl_buf == NULL) { fat_file_close(&fs_info->fat, fat_fd); fat_shutdown_drive(&fs_info->fat); free(fs_info); rtems_set_errno_and_return_minus_one(ENOMEM); } sc = rtems_semaphore_create(3, 1, RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY, 0, &fs_info->vol_sema); if (sc != RTEMS_SUCCESSFUL) { fat_file_close(&fs_info->fat, fat_fd); fat_shutdown_drive(&fs_info->fat); free(fs_info->cl_buf); free(fs_info); rtems_set_errno_and_return_minus_one( EIO ); } temp_mt_entry->mt_fs_root->location.node_access = fat_fd; temp_mt_entry->mt_fs_root->location.handlers = directory_handlers; temp_mt_entry->ops = op_table; return rc; }