Пример #1
0
static int tifiles_file_has_tib_header(const char *filename)
{
	FILE *f;
	char str[128];
	char *e = tifiles_fext_get(filename);

	if (!strcmp(e, ""))
	  return 0;

	if(g_ascii_strcasecmp(e, "tib"))
		return 0;

	f = g_fopen(filename, "rb");
	if(f == NULL)
		return 0;

	fread_n_chars(f, 22, str);
	fread_n_chars(f, strlen(TIB_SIGNATURE), str);
	str[strlen(TIB_SIGNATURE)] = '\0';
	if(!strcmp(str, TIB_SIGNATURE)) 
	{
		fclose(f);
		return !0;
	}

	return 0;
}
Пример #2
0
TIEXPORT2 int TICALL tifiles_file_has_tno_header(const char *filename)
{
	FILE *f;
	char str[128];
	char *e = tifiles_fext_get(filename);
	int ret = 0;

	if (!strcmp(e, ""))
	{
		return ret;
	}

	if(g_ascii_strcasecmp(e, "tno") && g_ascii_strcasecmp(e, "tnc") && g_ascii_strcasecmp(e, "tco") && g_ascii_strcasecmp(e, "tcc"))
	{
		return ret;
	}

	f = g_fopen(filename, "rb");
	if(f == NULL)
	{
		return ret;
	}

	if (fread_n_chars(f, 63, str) == 0)
	{
		if (   !strncmp(str, TNO_SIGNATURE, 14)
		    || !strncmp(str, TNC_SIGNATURE, 14)
		    || !strncmp(str, TNO_NOSAMPLES_SIGNATURE, 24)
		    || !strncmp(str, TCO_SIGNATURE, 14)
		    || !strncmp(str, TCC_SIGNATURE, 14)
		   )
		{
			ret = !0;
		}
	}

	fclose(f);
	return ret;
}
Пример #3
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;
}
Пример #4
0
/**
 * 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;
}
Пример #5
0
int fread_8_chars(FILE * f, char *s)
{
	return fread_n_chars(f, 8, s);
}
Пример #6
0
/**
 * tifiles_file_test:
 * @filename: a filename as string.
 * @type: type to check
 * @target: hand-held model or CALC_NONE for no filtering
 *
 * Check whether #filename is a TI file of type #type useable on a #target model.
 * This function is a generic one which overwrap and extends the tifiles_file_is_* 
 * functions.
 *
 * This is a powerful function which allows checking of a specific file type for
 * a given target.
 *
 * Return value: a boolean value.
 **/
TIEXPORT2 int TICALL tifiles_file_test(const char *filename, FileClass type, CalcModel target)
{
	char *e = tifiles_fext_get(filename);

	if (!tifiles_file_is_ti(filename))
		return 0;

	if (!strcmp(e, ""))
		return 0;

	if(target > CALC_MAX)
	{
		tifiles_critical("tifiles_file_test: invalid target argument! This is a bug.");
		return 0;
	}

	if(type & TIFILE_SINGLE)
	{
		if(target && !g_ascii_strncasecmp(e, GROUP_FILE_EXT[target], 2))
			return !0;
		else
			return tifiles_file_is_single(filename);
	}
	
	if(type & TIFILE_GROUP)
	{
		if(target && !g_ascii_strcasecmp(e, GROUP_FILE_EXT[target]))
			return !0;
		else
			return tifiles_file_is_group(filename);
	}
	
	if(type & TIFILE_REGULAR)
	{
		return tifiles_file_test(filename, TIFILE_SINGLE, target) ||
				tifiles_file_test(filename, TIFILE_GROUP, target);
	}
	
	if(type & TIFILE_BACKUP)
	{
		if(target && !g_ascii_strcasecmp(e, BACKUP_FILE_EXT[target]))
			return !0;
		else
			return tifiles_file_is_backup(filename);
	}
	
	if(type & TIFILE_OS)
	{
		if(target && !g_ascii_strcasecmp(e, FLASH_OS_FILE_EXT[target]))
			return !0;
		else if(target && tifiles_file_is_tib(filename))
		{
			FILE *f;
			uint8_t data[16];

			f = g_fopen(filename, "rb");
			if(f == NULL)
				return 0;

			fread_n_chars(f, 16, (char *)data);
			fclose(f);

			switch(data[8])
			{
			case 1: if(target != CALC_TI92P) return 0;
			case 3: if(target != CALC_TI89)  return 0;
			case 8: if(target != CALC_V200)  return 0;
			case 9: if(target != CALC_TI89T) return 0;
			}

			return !0;
		}
		else
			return tifiles_file_is_os(filename);
	}
	
	if(type & TIFILE_APP)
	{
		if(target && !g_ascii_strcasecmp(e, FLASH_APP_FILE_EXT[target]))
			return !0;
		else
			return tifiles_file_is_app(filename);
	}
	
	if(type & TIFILE_FLASH)
	{
		return tifiles_file_test(filename, TIFILE_OS, target) ||
				tifiles_file_test(filename, TIFILE_APP, target);
	}
	
	if(type & TIFILE_TIGROUP)
	{
		if(target)
		{
			// No easy/light way for this part: we have to load the whole file 
			// and to parse the TigEntry structures.
			TigContent *content;
			int ret, ok=0;
			int k;

			if(!tifiles_file_has_tig_header(filename))
				return 0;

			content = tifiles_content_create_tigroup(CALC_NONE, 0);
			ret = tifiles_file_read_tigroup(filename, content);
			if(ret) return 0;

			for (k = 0; k < content->n_apps; k++)
			{
				TigEntry *te = content->app_entries[k];

				if(tifiles_calc_are_compat(te->content.regular->model, target))
					ok++;
			}

			for (k = 0; k < content->n_vars; k++)
			{
				TigEntry *te = content->var_entries[k];

				if(tifiles_calc_are_compat(te->content.regular->model, target))
					ok++;
			}

			tifiles_content_delete_tigroup(content);
			return ok;
		}
		else
			return tifiles_file_is_tigroup(filename);
	}

	return 0;
}
Пример #7
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 = 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;
}
Пример #8
0
/**
 * 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;
}