static int fat32fs_open(vfs_fd *vfd, const char *path, int flags, mode_t mode) { fat_file *file = fat_file_open(ins, path); if (!file) return -1; vfd->private_data =( void *)file; return 0; }
static int fat32fs_opendir(vfs_fd *vfd, const char *name) { MESSAGE_DEBUG("vfd:%p name:%s\n", vfd, name); fat_file *dir = fat_file_open(ins, name); if (!dir) { MESSAGE_DEBUG("return:-1\n"); return -1; } vfd->private_data =(void *)dir; MESSAGE_DEBUG("return:0\n"); return 0; }
void handle_connection(mailbox_id_type *reply_mailbox_id) { system_thread_name_set("Handling connection"); message_parameter_type message_parameter; bool done = FALSE; bool mounted = FALSE; fat_info_type fat_info; ipc_structure_type ipc_structure; uint8_t *data; uint8_t **data_pointer = &data; unsigned int data_size = 16384; memory_allocate((void **) data_pointer, data_size); // Accept the connection. ipc_structure.output_mailbox_id = *reply_mailbox_id; if (ipc_connection_establish(&ipc_structure) != IPC_RETURN_SUCCESS) { return; } message_parameter.block = TRUE; while (!done) { message_parameter.data = data; message_parameter.protocol = IPC_PROTOCOL_FILE; message_parameter.message_class = IPC_CLASS_NONE; message_parameter.length = data_size; if (ipc_receive(ipc_structure.input_mailbox_id, &message_parameter, &data_size) != IPC_RETURN_SUCCESS) { continue; } switch (message_parameter.message_class) { // Read one or more directory entries. case IPC_FILE_DIRECTORY_ENTRY_READ: { if (mounted) { file_directory_entry_read_type *directory_entry_read = (file_directory_entry_read_type *) data; if (!fat_directory_entry_read(directory_entry_read, &fat_info)) { directory_entry_read->entries = 0; } message_parameter.length = sizeof(file_directory_entry_read_type) + sizeof(file_directory_entry_type) * directory_entry_read->entries ; // log_print_formatted (0, PACKAGE, "Successfully read %u entries", // directory_entry_read->entries); // log_print_formatted (0, PACKAGE, "max: %u\n", directory_entry_read->entries); ipc_send(ipc_structure.output_mailbox_id, &message_parameter); } break; } case IPC_FILE_GET_INFO: { if (mounted) { file_verbose_directory_entry_type *directory_entry = (file_verbose_directory_entry_type *) data; if (!fat_file_get_info(&fat_info, directory_entry)) { return_type return_value = FILE_RETURN_FILE_ABSENT; log_print_formatted(&log_structure, LOG_URGENCY_ERROR, "IPC_FILE_GET_INFO failed"); message_parameter.message_class = IPC_FILE_RETURN_VALUE; message_parameter.data = &return_value; message_parameter.length = sizeof(return_type); } ipc_send(ipc_structure.output_mailbox_id, &message_parameter); } break; } case IPC_FILE_MOUNT_VOLUME: { mailbox_id_type *mailbox = (mailbox_id_type *) data; fat_info.block_structure.output_mailbox_id = *mailbox; if (ipc_service_connection_request(&fat_info.block_structure) != IPC_RETURN_SUCCESS) { break; } // Check if we have a FAT file system at this location. if (!detect_fat(&fat_info)) { log_print(&log_structure, LOG_URGENCY_ERROR, "No FAT filesystem detected."); break; } mounted = TRUE; break; } case IPC_FILE_OPEN: { ipc_file_open_type *open = (ipc_file_open_type *) data; if (!fat_file_open(&fat_info, open)) { log_print(&log_structure, LOG_URGENCY_ERROR, "Failed to open file."); } ipc_send(ipc_structure.output_mailbox_id, &message_parameter); break; } case IPC_FILE_READ: { file_read_type *read = (file_read_type *) data; uint8_t *read_buffer; uint8_t **read_buffer_pointer = &read_buffer; memory_allocate((void **) read_buffer_pointer, read->bytes); if (!fat_file_read(&fat_info, read->file_handle, read_buffer, read->bytes)) { log_print(&log_structure, LOG_URGENCY_ERROR, "Failed to read from file."); } message_parameter.data = read_buffer; message_parameter.length = read->bytes; #ifdef DEBUG log_print_formatted(&log_structure, LOG_URGENCY_DEBUG, "Sending %lu", read->bytes); #endif ipc_send(ipc_structure.output_mailbox_id, &message_parameter); memory_deallocate((void **) read_buffer_pointer); break; } // Unsupported functions. case IPC_FILE_CLOSE: case IPC_FILE_SEEK: case IPC_FILE_WRITE: case IPC_FILE_ACL_READ: case IPC_FILE_ACL_WRITE: case IPC_FILE_UNMOUNT_VOLUME: default: { return_type return_value = IPC_RETURN_FILE_FUNCTION_UNSUPPORTED; message_parameter.data = &return_value; message_parameter.length = sizeof(return_type); ipc_send(ipc_structure.output_mailbox_id, &message_parameter); break; } } } }
/* 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_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; }
/*********************************************************************** * * Function: srec_parse * * Purpose: Load and parse an S-record file * * Processing: * See function. * * Parameters: * fdata : Pointer to file data to fill * src : Data source * filename : Filename (sd cards only) * * Outputs: None * * Returns: E if the file was parsed and loaded, otherwise FALSE * * Notes: None * **********************************************************************/ BOOL_32 srec_parse(FILE_DATA_T *ft, SRC_LOAD_T src, UNS_8 *filename) { UNS_8 line[384]; int idx; BOOL_32 fop = FALSE, parsed = TRUE, done = FALSE; ft->loadaddr = 0xFFFFFFFF; ft->flt = FLT_RAW; /* Loaded as an S-record, saved as RAW */ ft->num_bytes = 0; ft->startaddr = (PFV) 0xFFFFFFFF; ft->contiguous = TRUE; ft->loaded = FALSE; /* Attempt to open file if from SD source */ if (src == SRC_BLKDEV) { /* Init FAT filesystem and block device */ if (fat_init() == FALSE) { term_dat_out(blkdeverr_msg); done = TRUE; } else { /* Try to open file */ parsed = fat_file_open(filename); fop = TRUE; if (parsed == FALSE) { term_dat_out_crlf(nofilmsg); done = TRUE; } } } else if (src == SRC_NAND) { /* Initialize NAND streamer */ if (stream_flash_init() == FALSE) { term_dat_out_crlf(noiif_msg); done = TRUE; } } else { term_dat_out_crlf(rawdl_msg); } while ((done == FALSE) && (ft->loaded == FALSE)) { /* Read line from device */ parsed = readline(line, src); if (parsed == TRUE) { /* Skip whitespace */ idx = skip_whitespace(line, 0); parsed &= srec_parse_line(&line [idx], ft); } if (parsed == FALSE) { done = TRUE; } } if (fop == TRUE) { fat_deinit(); } return parsed; }
/*********************************************************************** * * Function: raw_load * * Purpose: Load a raw file from a source to memory * * Processing: * See function. * * Parameters: * fdata : Pointer to file data to fill * addr : Address to load data * filename : Filename (sd cards only) * src : Data source * * Outputs: None * * Returns: TRUE if the file was loaded, otherwise FALSE * * Notes: None * **********************************************************************/ BOOL_32 raw_load(FILE_DATA_T *fdata, UNS_32 addr, UNS_8 *filename, SRC_LOAD_T src) { UNS_32 rb, bytes = 0; UNS_8 ch, *ptr8 = (UNS_8 *) addr; BOOL_32 readloop, loaded = FALSE; if (src == SRC_TERM) { term_dat_out_crlf(rawdl_msg); /* Read data from terminal until a break is encountered */ while (term_break() == FALSE) { if (term_dat_in(&ch, 1) > 0) { bytes++; *ptr8 = ch; ptr8++; } } fdata->num_bytes = bytes; fdata->contiguous = TRUE; loaded = TRUE; } else if (src == SRC_NAND) { /* Move image in NAND to memory */ term_dat_out_crlf(rawnanddlns_msg); } else if (src == SRC_BLKDEV) { /* Initialize FAT interface first */ if (fat_init() == FALSE) { term_dat_out(blkdeverr_msg); } /* Try to open file */ else if (fat_file_open(filename) == FALSE) { term_dat_out_crlf(nofilmsg); } else { fdata->num_bytes = 0; readloop = TRUE; while (readloop == TRUE) { rb = fat_file_read(ptr8, 8); fdata->num_bytes += rb; ptr8 += 8; if (rb != 8) { readloop = FALSE; } } fdata->contiguous = TRUE; loaded = TRUE; } fat_deinit(); } return loaded; }
/* 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; }