static int tifiles_file_has_ti_header(const char *filename) { FILE *f; char buf[9]; char *p; f = g_fopen(filename, "rb"); if (f == NULL) return 0; fread_8_chars(f, buf); for(p = buf; *p != '\0'; p++) *p = toupper(*p); if (!strcmp(buf, "**TI73**") || !strcmp(buf, "**TI82**") || !strcmp(buf, "**TI83**") || !strcmp(buf, "**TI83F*") || !strcmp(buf, "**TI85**") || !strcmp(buf, "**TI86**") || !strcmp(buf, "**TI89**") || !strcmp(buf, "**TI92**") || !strcmp(buf, "**TI92P*") || !strcmp(buf, "**V200**") || !strcmp(buf, "**TIFL**")) { fclose(f); return !0; } if(!strncmp(buf, "*TI", 3)) { fclose(f); return !0; } fclose(f); return 0; }
/** * ti9x_file_read_regular: * @filename: name of single/group file to open. * @content: where to store the file content. * * Load the single/group file into a Ti9xRegular structure. * * Structure content must be freed with #tifiles_content_delete_regular when * no longer used. If error occurs, the structure content is released for you. * * Return value: an error code, 0 otherwise. **/ int ti9x_file_read_regular(const char *filename, Ti9xRegular *content) { FILE *f; long cur_pos; char default_folder[FLDNAME_MAX]; char current_folder[FLDNAME_MAX]; uint32_t curr_offset = 0; uint32_t next_offset = 0; uint32_t file_size; uint16_t tmp; unsigned int i, j; char signature[9]; char varname[VARNAME_MAX]; int ret = ERR_FILE_IO; if (content == NULL) { tifiles_critical("%s: an argument is NULL", __FUNCTION__); return ERR_INVALID_FILE; } if (!tifiles_file_is_regular(filename)) { ret = ERR_INVALID_FILE; goto tfrr2; } f = g_fopen(filename, "rb"); if (f == NULL) { ret = ERR_FILE_OPEN; goto tfrr2; } // Get file size, then rewind. if (fseek(f, 0, SEEK_END) < 0) goto tfrr; cur_pos = ftell(f); if (cur_pos < 0) goto tfrr; if (fseek(f, 0, SEEK_SET) < 0) goto tfrr; // The TI-68k series' members have at best 4 MB of Flash (TODO: modify this code if this no longer holds). // Regular / group files larger than that size are highly dubious, files larger than twice that size are insane. if (cur_pos >= (8L << 20)) { ret = ERR_INVALID_FILE; goto tfrr; } file_size = (uint32_t)cur_pos; if (fread_8_chars(f, signature) < 0) goto tfrr; // Offset 0 content->model = tifiles_signature2calctype(signature); if (content->model == CALC_NONE) { ret = ERR_INVALID_FILE; goto tfrr; } if (content->model_dst == CALC_NONE) { content->model_dst = content->model; } if (fread_word(f, NULL) < 0) goto tfrr; // Offset 0x8 if (fread_8_chars(f, default_folder) < 0) goto tfrr; // Offset 0xA ticonv_varname_from_tifile_sn(content->model_dst, default_folder, content->default_folder, sizeof(content->default_folder), -1); strncpy(current_folder, content->default_folder, sizeof(current_folder) - 1); current_folder[sizeof(current_folder) - 1] = 0; if (fread_n_chars(f, 40, content->comment) < 0) goto tfrr; // Offset 0x12 if (fread_word(f, &tmp) < 0) goto tfrr; // Offset 0x3A content->num_entries = tmp; content->entries = g_malloc0((content->num_entries + 1) * sizeof(VarEntry*)); if (content->entries == NULL) { ret = ERR_MALLOC; goto tfrr; } for (i = 0, j = 0; i < content->num_entries; i++) { VarEntry *entry = content->entries[j] = g_malloc0(sizeof(VarEntry)); if (fread_long(f, &curr_offset) < 0) goto tfrr; // Offset N, 0x3C for the first entry if (curr_offset > file_size) { ret = ERR_INVALID_FILE; goto tfrr; } if (fread_8_chars(f, varname) < 0) goto tfrr; // Offset N+4, 0x40 for the first entry ticonv_varname_from_tifile_sn(content->model_dst, varname, entry->name, sizeof(entry->name), entry->type); if (fread_byte(f, &(entry->type)) < 0) goto tfrr; // Offset N+12, 0x48 for the first entry if (fread_byte(f, &(entry->attr)) < 0) goto tfrr; // Offset N+13, 0x49 for the first entry entry->attr = (entry->attr == 2 || entry->attr == 3) ? ATTRB_ARCHIVED : entry->attr; if (fread_word(f, NULL) < 0) goto tfrr; // Offset N+14, 0x4A for the first entry if (entry->type == TI92_DIR) // same as TI89_DIR, TI89t_DIR, ... { strncpy(current_folder, entry->name,sizeof(current_folder) - 1); current_folder[sizeof(current_folder) - 1] = 0; g_free(entry); continue; // folder: skip entry } else { uint16_t checksum, sum = 0; j++; strncpy(entry->folder, current_folder, sizeof(entry->folder) - 1); current_folder[sizeof(entry->folder) - 1] = 0; cur_pos = ftell(f); if (cur_pos < 0) goto tfrr; if (fread_long(f, &next_offset) < 0) goto tfrr; // Offset N+16, 0x4C for the first entry if (next_offset > file_size) { ret = ERR_INVALID_FILE; goto tfrr; } entry->size = next_offset - curr_offset - 4 - 2; if (entry->size > file_size) { ret = ERR_INVALID_FILE; goto tfrr; } entry->data = (uint8_t *)g_malloc0(entry->size); if (entry->data == NULL) { ret = ERR_MALLOC; goto tfrr; } if (fseek(f, curr_offset, SEEK_SET)) goto tfrr; if (fread_long(f, NULL) < 0) goto tfrr; // Normally: offset N+22, 0x52 for the first entry if (fread(entry->data, 1, entry->size, f) < entry->size) goto tfrr; // Normally: offset N+26, 0x56 for the first entry if (fread_word(f, &checksum) < 0) goto tfrr; if (fseek(f, cur_pos, SEEK_SET)) goto tfrr; sum = tifiles_checksum(entry->data, entry->size); if (sum != checksum) { ret = ERR_FILE_CHECKSUM; goto tfrr; } content->checksum += sum; // sum of all checksums but unused } } content->num_entries = j; content->entries = g_realloc(content->entries, content->num_entries * sizeof(VarEntry*)); //fread_long(f, &next_offset); //fseek(f, next_offset - 2, SEEK_SET); //fread_word(f, &(content->checksum)); fclose(f); return 0; tfrr: // release on exit tifiles_critical("%s: error reading / understanding file %s", __FUNCTION__, filename); fclose(f); tfrr2: tifiles_content_delete_regular(content); return ret; }
/** * ti9x_file_read_flash: * @filename: name of flash file to open. * @content: where to store the file content. * * Load the flash file into a #FlashContent structure. * * Structure content must be freed with #tifiles_content_delete_flash when * no longer used. If error occurs, the structure content is released for you. * * Return value: an error code, 0 otherwise. **/ int ti9x_file_read_flash(const char *filename, Ti9xFlash *head) { FILE *f; Ti9xFlash *content = head; long cur_pos = 0; int tib = 0; char signature[9]; int ret = ERR_FILE_IO; if (head == NULL) { tifiles_critical("%s: an argument is NULL", __FUNCTION__); return ERR_INVALID_FILE; } if (!tifiles_file_is_flash(filename) && !tifiles_file_is_tib(filename)) { ret = ERR_INVALID_FILE; goto tfrf2; } // detect file type (old or new format) tib = tifiles_file_is_tib(filename); f = g_fopen(filename, "rb"); if (f == NULL) { tifiles_info("Unable to open this file: %s", filename); ret = ERR_FILE_OPEN; goto tfrf2; } if (fseek(f, 0, SEEK_END)) goto tfrf; cur_pos = ftell(f); if (cur_pos < 0) goto tfrf; if (fseek(f, 0, SEEK_SET)) goto tfrf; // The TI-68k series' members have at best 4 MB of Flash. // TIB files larger than that size are insane. if (cur_pos >= (4L << 20)) { ret = ERR_INVALID_FILE; goto tfrf; } if (tib) { // tib is an old format but mainly used by developers memset(content, 0, sizeof(Ti9xFlash)); content->data_length = (uint32_t)cur_pos; strncpy(content->name, "basecode", sizeof(content->name) - 1); content->name[sizeof(content->name) - 1] = 0; content->data_type = 0x23; // FLASH os content->data_part = (uint8_t *)g_malloc0(content->data_length); if (content->data_part == NULL) { ret = ERR_MALLOC; goto tfrf; } if (fread(content->data_part, 1, content->data_length, f) < content->data_length) goto tfrf; switch(content->data_part[8]) { case 1: content->device_type = DEVICE_TYPE_92P; break; // TI92+ case 3: content->device_type = DEVICE_TYPE_89; break; // TI89 // value added by the TI community according to HWID parameter // doesn't have any 'legal' existence. case 8: content->device_type = DEVICE_TYPE_92P; break; // V200PLT case 9: content->device_type = DEVICE_TYPE_89; break; // Titanium } content->next = NULL; } else { for (content = head;; content = content->next) { if (fread_8_chars(f, signature) < 0) goto tfrf; content->model = tifiles_file_get_model(filename); if (fread_byte(f, &(content->revision_major)) < 0) goto tfrf; if (fread_byte(f, &(content->revision_minor)) < 0) goto tfrf; if (fread_byte(f, &(content->flags)) < 0) goto tfrf; if (fread_byte(f, &(content->object_type)) < 0) goto tfrf; if (fread_byte(f, &(content->revision_day)) < 0) goto tfrf; if (fread_byte(f, &(content->revision_month)) < 0) goto tfrf; if (fread_word(f, &(content->revision_year)) < 0) goto tfrf; if (fskip(f, 1) < 0) goto tfrf; if (fread_8_chars(f, content->name) < 0) goto tfrf; if (fskip(f, 23) < 0) goto tfrf; if (fread_byte(f, &(content->device_type)) < 0) goto tfrf; if (fread_byte(f, &(content->data_type)) < 0) goto tfrf; if (fskip(f, 23) < 0) goto tfrf; if (fread_byte(f, &(content->hw_id)) < 0) goto tfrf; if (fread_long(f, &(content->data_length)) < 0) goto tfrf; if (content->data_type != TI89_LICENSE && !check_device_type(content->device_type)) { ret = ERR_INVALID_FILE; goto tfrf; } if (!check_data_type(content->data_type)) { ret = ERR_INVALID_FILE; goto tfrf; } // TODO: modify this code if TI ever makes a TI-eZ80 model with more than 4 MB of Flash memory... if (content->data_length > 4U * 1024 * 1024 - 65536U) { // Data length larger than Flash memory size - boot code sector size doesn't look right. ret = ERR_INVALID_FILE; goto tfrf; } content->data_part = (uint8_t *)g_malloc0(content->data_length); if (content->data_part == NULL) { ret = ERR_MALLOC; goto tfrf; } if (fread(content->data_part, 1, content->data_length, f) < content->data_length) goto tfrf; if ( (content->data_type == TI83p_AMS && content->data_part[0] != 0x80) || (content->data_type == TI83p_APPL && content->data_part[0] != 0x81)) { ret = ERR_INVALID_FILE; goto tfrf; } content->next = NULL; // check for end of file if (fread_8_chars(f, signature) < 0) { break; } if (strcmp(signature, "**TIFL**") || feof(f)) { break; } if (fseek(f, -8, SEEK_CUR)) goto tfrf; content->next = (Ti9xFlash *)g_malloc0(sizeof(Ti9xFlash)); if (content->next == NULL) { ret = ERR_MALLOC; goto tfrf; } } } fclose(f); return 0; tfrf: // release on exit tifiles_critical("%s: error reading / understanding file %s", __FUNCTION__, filename); fclose(f); tfrf2: tifiles_content_delete_flash(content); return ret; }
/** * ti9x_file_read_backup: * @filename: name of backup file to open. * @content: where to store the file content. * * Load the backup file into a Ti9xBackup structure. * * Structure content must be freed with #tifiles_content_delete_backup when * no longer used. If error occurs, the structure content is released for you. * * Return value: an error code, 0 otherwise. **/ int ti9x_file_read_backup(const char *filename, Ti9xBackup *content) { FILE *f; long cur_pos = 0; uint32_t file_size; char signature[9]; uint16_t sum; int ret = ERR_FILE_IO; if (content == NULL) { tifiles_critical("%s: an argument is NULL", __FUNCTION__); return ERR_INVALID_FILE; } if (!tifiles_file_is_backup(filename)) { ret = ERR_INVALID_FILE; goto tfrb2; } f = g_fopen(filename, "rb"); if (f == NULL) { tifiles_info( "Unable to open this file: %s", filename); ret = ERR_FILE_OPEN; goto tfrb2; } // Get file size, then rewind. if (fseek(f, 0, SEEK_END) < 0) goto tfrb; cur_pos = ftell(f); if (cur_pos < 0) goto tfrb; if (fseek(f, 0, SEEK_SET) < 0) goto tfrb; // The TI-68k series' members have at best 4 MB of Flash (TODO: modify this code if this no longer holds). // Backup files larger than that size are highly dubious, files larger than twice that size are insane. if (cur_pos >= (8L << 20)) { ret = ERR_INVALID_FILE; goto tfrb; } if (fread_8_chars(f, signature) < 0) goto tfrb; content->model = tifiles_signature2calctype(signature); if (content->model == CALC_NONE) { ret = ERR_INVALID_FILE; } if (fread_word(f, NULL) < 0) goto tfrb; if (fread_8_chars(f, NULL) < 0) goto tfrb; if (fread_n_chars(f, 40, content->comment) < 0) goto tfrb; if (fread_word(f, NULL) < 0) goto tfrb; if (fread_long(f, NULL) < 0) goto tfrb; if (fread_8_chars(f, content->rom_version) < 0) goto tfrb; if (fread_byte(f, &(content->type)) < 0) goto tfrb; if (fread_byte(f, NULL) < 0) goto tfrb; if (fread_word(f, NULL) < 0) goto tfrb; if (fread_long(f, &file_size) < 0) goto tfrb; if (file_size > (uint32_t)cur_pos) { ret = ERR_INVALID_FILE; goto tfrb; } content->data_length = file_size - 0x52 - 2; if (fread_word(f, NULL) < 0) goto tfrb; content->data_part = (uint8_t *)g_malloc0(content->data_length); if (content->data_part == NULL) { ret = ERR_MALLOC; goto tfrb; } if (fread(content->data_part, 1, content->data_length, f) < content->data_length) goto tfrb; if (fread_word(f, &(content->checksum)) < 0) goto tfrb; sum = tifiles_checksum(content->data_part, content->data_length); #if defined(CHECKSUM_ENABLED) if (sum != content->checksum) { ret = ERR_FILE_CHECKSUM; goto tfrb; } #endif fclose(f); return 0; tfrb: // release on exit tifiles_critical("%s: error reading / understanding file %s", __FUNCTION__, filename); fclose(f); tfrb2: tifiles_content_delete_backup(content); return ret; }
/** * ti9x_file_read_regular: * @filename: name of single/group file to open. * @content: where to store the file content. * * Load the single/group file into a Ti9xRegular structure. * * Structure content must be freed with #tifiles_content_delete_regular when * no longer used. If error occurs, the structure content is released for you. * * Return value: an error code, 0 otherwise. **/ int ti9x_file_read_regular(const char *filename, Ti9xRegular *content) { FILE *f; long cur_pos = 0; char default_folder[FLDNAME_MAX]; char current_folder[FLDNAME_MAX]; uint32_t curr_offset = 0; uint32_t next_offset = 0; uint16_t tmp; int i, j; char signature[9]; char varname[VARNAME_MAX]; if (!tifiles_file_is_regular(filename)) { return ERR_INVALID_FILE; } if (content == NULL) { tifiles_critical("%s: an argument is NULL", __FUNCTION__); return ERR_INVALID_FILE; } f = g_fopen(filename, "rb"); if (f == NULL) { tifiles_info( "Unable to open this file: %s", filename); return ERR_FILE_OPEN; } if(fread_8_chars(f, signature) < 0) goto tffr; content->model = tifiles_signature2calctype(signature); if (content->model == CALC_NONE) { return ERR_INVALID_FILE; } if(content->model_dst == CALC_NONE) { content->model_dst = content->model; } if(fread_word(f, NULL) < 0) goto tffr; if(fread_8_chars(f, default_folder) < 0) goto tffr; ticonv_varname_from_tifile_s(content->model_dst, default_folder, content->default_folder, -1); strcpy(current_folder, content->default_folder); if(fread_n_chars(f, 40, content->comment) < 0) goto tffr; if(fread_word(f, &tmp) < 0) goto tffr; content->num_entries = tmp; content->entries = g_malloc0((content->num_entries + 1) * sizeof(VarEntry*)); if (content->entries == NULL) { fclose(f); return ERR_MALLOC; } for (i = 0, j = 0; i < content->num_entries; i++) { VarEntry *entry = content->entries[j] = g_malloc0(sizeof(VarEntry)); if(fread_long(f, &curr_offset) < 0) goto tffr; if(fread_8_chars(f, varname) < 0) goto tffr; ticonv_varname_from_tifile_s(content->model_dst, varname, entry->name, entry->type); if(fread_byte(f, &(entry->type)) < 0) goto tffr; if(fread_byte(f, &(entry->attr)) < 0) goto tffr; entry->attr = (entry->attr == 2 || entry->attr == 3) ? ATTRB_ARCHIVED : entry->attr; if(fread_word(f, NULL) < 0) goto tffr; if (entry->type == TI92_DIR) // same as TI89_DIR, TI89t_DIR, ... { strcpy(current_folder, entry->name); g_free(entry); continue; // folder: skip entry } else { uint16_t checksum, sum = 0; j++; strcpy(entry->folder, current_folder); cur_pos = ftell(f); if(cur_pos == -1L) goto tffr; if(fread_long(f, &next_offset) < 0) goto tffr; entry->size = next_offset - curr_offset - 4 - 2; entry->data = (uint8_t *)g_malloc0(entry->size); if (entry->data == NULL) { fclose(f); tifiles_content_delete_regular(content); return ERR_MALLOC; } if(fseek(f, curr_offset, SEEK_SET)) goto tffr; if(fread_long(f, NULL) < 0) goto tffr; // 4 bytes (NULL) if(fread(entry->data, 1, entry->size, f) < entry->size) goto tffr; if(fread_word(f, &checksum) < 0) goto tffr; if(fseek(f, cur_pos, SEEK_SET)) goto tffr; sum = tifiles_checksum(entry->data, entry->size); if(sum != checksum) { fclose(f); tifiles_content_delete_regular(content); return ERR_FILE_CHECKSUM; } content->checksum += sum; // sum of all checksums but unused } } content->num_entries = j; content->entries = g_realloc(content->entries, content->num_entries * sizeof(VarEntry*)); //fread_long(f, &next_offset); //fseek(f, next_offset - 2, SEEK_SET); //fread_word(f, &(content->checksum)); fclose(f); return 0; tffr: // release on exit tifiles_critical("%s: error reading / understanding file %s", __FUNCTION__, filename); fclose(f); tifiles_content_delete_regular(content); return ERR_FILE_IO; }
/** * ti9x_file_read_flash: * @filename: name of flash file to open. * @content: where to store the file content. * * Load the flash file into a #FlashContent structure. * * Structure content must be freed with #tifiles_content_delete_flash when * no longer used. If error occurs, the structure content is released for you. * * Return value: an error code, 0 otherwise. **/ int ti9x_file_read_flash(const char *filename, Ti9xFlash *head) { FILE *f; Ti9xFlash *content = head; int tib = 0; char signature[9]; if (!tifiles_file_is_flash(filename) && !tifiles_file_is_tib(filename)) { return ERR_INVALID_FILE; } if (head == NULL) { tifiles_critical("%s: an argument is NULL", __FUNCTION__); return ERR_INVALID_FILE; } // detect file type (old or new format) tib = tifiles_file_is_tib(filename); f = g_fopen(filename, "rb"); if (f == NULL) { tifiles_info("Unable to open this file: %s\n", filename); return ERR_FILE_OPEN; } if (tib) { // tib is an old format but mainly used by developers memset(content, 0, sizeof(Ti9xFlash)); if(fseek(f, 0, SEEK_END)) goto tfrf; content->data_length = (uint32_t) ftell(f); if(fseek(f, 0, SEEK_SET)) goto tfrf; strcpy(content->name, "basecode"); content->data_type = 0x23; // FLASH os content->data_part = (uint8_t *)g_malloc0(content->data_length); if (content->data_part == NULL) { fclose(f); return ERR_MALLOC; } if(fread(content->data_part, 1, content->data_length, f) < content->data_length) goto tfrf; switch(content->data_part[8]) { case 1: content->device_type = DEVICE_TYPE_92P; break; // TI92+ case 3: content->device_type = DEVICE_TYPE_89; break; // TI89 // value added by the TI community according to HWID parameter // doesn't have any 'legal' existence. case 8: content->device_type = DEVICE_TYPE_92P; break; // V200PLT case 9: content->device_type = DEVICE_TYPE_89; break; // Titanium } content->next = NULL; } else { for (content = head;; content = content->next) { if(fread_8_chars(f, signature) < 0) goto tfrf; content->model = tifiles_file_get_model(filename); if(fread_byte(f, &(content->revision_major)) < 0) goto tfrf; if(fread_byte(f, &(content->revision_minor)) < 0) goto tfrf; if(fread_byte(f, &(content->flags)) < 0) goto tfrf; if(fread_byte(f, &(content->object_type)) < 0) goto tfrf; if(fread_byte(f, &(content->revision_day)) < 0) goto tfrf; if(fread_byte(f, &(content->revision_month)) < 0) goto tfrf; if(fread_word(f, &(content->revision_year)) < 0) goto tfrf; if(fskip(f, 1) < 0) goto tfrf; if(fread_8_chars(f, content->name) < 0) goto tfrf; if(fskip(f, 23) < 0) goto tfrf; if(fread_byte(f, &(content->device_type)) < 0) goto tfrf; if(fread_byte(f, &(content->data_type)) < 0) goto tfrf; if(fskip(f, 23) < 0) goto tfrf; if(fread_byte(f, &(content->hw_id)) < 0) goto tfrf; if(fread_long(f, &(content->data_length)) < 0) goto tfrf; if(content->data_type != TI89_LICENSE && !check_device_type(content->device_type)) { return ERR_INVALID_FILE; } if(!check_data_type(content->data_type)) { return ERR_INVALID_FILE; } content->data_part = (uint8_t *)g_malloc0(content->data_length); if (content->data_part == NULL) { fclose(f); tifiles_content_delete_flash(content); return ERR_MALLOC; } if(fread(content->data_part, 1, content->data_length, f) < content->data_length) goto tfrf; content->next = NULL; // check for end of file if(fread_8_chars(f, signature) < 0) { break; } if(strcmp(signature, "**TIFL**") || feof(f)) { break; } if(fseek(f, -8, SEEK_CUR)) goto tfrf; content->next = (Ti9xFlash *)g_malloc0(sizeof(Ti9xFlash)); if (content->next == NULL) { fclose(f); tifiles_content_delete_flash(content); return ERR_MALLOC; } } } fclose(f); return 0; tfrf: // release on exit tifiles_critical("%s: error reading / understanding file %s", __FUNCTION__, filename); fclose(f); tifiles_content_delete_flash(content); return ERR_FILE_IO; }
/** * ti9x_file_read_backup: * @filename: name of backup file to open. * @content: where to store the file content. * * Load the backup file into a Ti9xBackup structure. * * Structure content must be freed with #tifiles_content_delete_backup when * no longer used. If error occurs, the structure content is released for you. * * Return value: an error code, 0 otherwise. **/ int ti9x_file_read_backup(const char *filename, Ti9xBackup *content) { FILE *f; uint32_t file_size; char signature[9]; uint16_t sum; if (!tifiles_file_is_backup(filename)) { return ERR_INVALID_FILE; } f = g_fopen(filename, "rb"); if (f == NULL) { tifiles_info( "Unable to open this file: %s", filename); return ERR_FILE_OPEN; } if (content == NULL) { tifiles_critical("%s: an argument is NULL", __FUNCTION__); return ERR_INVALID_FILE; } if(fread_8_chars(f, signature) < 0) goto tfrb; content->model = tifiles_signature2calctype(signature); if (content->model == CALC_NONE) { return ERR_INVALID_FILE; } if(fread_word(f, NULL) < 0) goto tfrb; if(fread_8_chars(f, NULL) < 0) goto tfrb; if(fread_n_chars(f, 40, content->comment) < 0) goto tfrb; if(fread_word(f, NULL) < 0) goto tfrb; if(fread_long(f, NULL) < 0) goto tfrb; if(fread_8_chars(f, content->rom_version) < 0) goto tfrb; if(fread_byte(f, &(content->type)) < 0) goto tfrb; if(fread_byte(f, NULL) < 0) goto tfrb; if(fread_word(f, NULL) < 0) goto tfrb; if(fread_long(f, &file_size) < 0) goto tfrb; content->data_length = file_size - 0x52 - 2; if(fread_word(f, NULL) < 0) goto tfrb; content->data_part = (uint8_t *)g_malloc0(content->data_length); if (content->data_part == NULL) { fclose(f); tifiles_content_delete_backup(content); return ERR_MALLOC; } if(fread(content->data_part, 1, content->data_length, f) < content->data_length) goto tfrb; if(fread_word(f, &(content->checksum)) < 0) goto tfrb; sum = tifiles_checksum(content->data_part, content->data_length); #if defined(CHECKSUM_ENABLED) if(sum != content->checksum) { fclose(f); tifiles_content_delete_backup(content); return ERR_FILE_CHECKSUM; } #endif fclose(f); return 0; tfrb: // release on exit tifiles_critical("%s: error reading / understanding file %s", __FUNCTION__, filename); fclose(f); tifiles_content_delete_backup(content); return ERR_FILE_IO; }