/*
* RabbitSign - Tools for signing TI graphing calculator software
* Copyright (C) 2009 Benjamin Moody
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#ifdef HAVE_CONFIG_H
# include
#endif
#include
#ifdef HAVE_STRING_H
# include
#else
# ifdef HAVE_STRINGS_H
# include
# endif
#endif
#include "rabbitsign.h"
#include "internal.h"
/*
* Create a new program.
*/
RSProgram* rs_program_new()
{
RSProgram* prgm = rs_malloc(sizeof(RSProgram));
if (!prgm)
return NULL;
prgm->filename = NULL;
prgm->calctype = 0;
prgm->datatype = 0;
prgm->data = NULL;
prgm->length = 0;
prgm->length_a = 0;
prgm->header = NULL;
prgm->header_length = 0;
prgm->signature = NULL;
prgm->signature_length = 0;
prgm->pagenums = NULL;
prgm->npagenums = 0;
return prgm;
}
/*
* Create a new program by wrapping an existing data buffer.
*
* If buffer_size is zero, data will be copied from the source buffer
* into the new program.
*
* If buffer_size is nonzero, then the source buffer must have been
* allocated using malloc(); buffer_size is the total amount of memory
* allocated. The data will not be copied, and the new program object
* assumes ownership of the buffer.
*/
RSProgram* rs_program_new_with_data(RSCalcType ctype, /* calc type */
RSDataType dtype, /* data type */
void* data, /* source buffer */
unsigned long length, /* length of data */
unsigned long buffer_size) /* amount of
memory
allocated */
{
RSProgram* prgm = rs_program_new();
if (!prgm)
return NULL;
prgm->calctype = ctype;
prgm->datatype = dtype;
if (data) {
if (buffer_size) {
prgm->data = data;
prgm->length = length;
prgm->length_a = buffer_size;
}
else {
if (rs_program_append_data(prgm, data, length)) {
rs_program_free(prgm);
return NULL;
}
}
}
return prgm;
}
/*
* Free program data.
*/
void rs_program_free(RSProgram* prgm)
{
if (!prgm)
return;
rs_free(prgm->filename);
rs_free(prgm->data);
rs_free(prgm->header);
rs_free(prgm->signature);
rs_free(prgm->pagenums);
rs_free(prgm);
}
/*
* Truncate or extend program.
*
* If length is less than the program's current length, the program is
* truncated. If length is greater than the current size of the
* program, additional space is added. The extra space is padded with
* 0xFF, with the exception of bytes that fall at the start of a page.
*/
int rs_program_set_length(RSProgram* prgm, /* program */
unsigned long length) /* new length of program */
{
unsigned long length_a, i;
unsigned char* dptr;
if (length <= prgm->length) {
prgm->length = length;
return RS_SUCCESS;
}
else {
if (length > prgm->length_a) {
length_a = length + 16384;
dptr = rs_realloc(prgm->data, length_a);
if (!dptr)
return RS_ERR_OUT_OF_MEMORY;
prgm->data = dptr;
prgm->length_a = length_a;
}
memset(prgm->data + prgm->length, 0xff, length - prgm->length);
for (i = ((prgm->length + 0x3fff) & ~0x3fff);
i < length;
i += 0x4000)
prgm->data[i] = 0x42;
prgm->length = length;
return RS_SUCCESS;
}
}
/*
* Add data to the end of the program.
*/
int rs_program_append_data(RSProgram* prgm, /* program */
const unsigned char* data, /* data */
unsigned long length) /* size of data */
{
unsigned long nlength, length_a;
unsigned char* dptr;
nlength = prgm->length + length;
if (nlength > prgm->length_a) {
length_a = nlength + 16384;
dptr = rs_realloc(prgm->data, length_a);
if (!dptr)
return RS_ERR_OUT_OF_MEMORY;
prgm->data = dptr;
prgm->length_a = length_a;
}
memcpy(prgm->data + prgm->length, data, length);
prgm->length = nlength;
return RS_SUCCESS;
}