0% found this document useful (0 votes)
7 views10 pages

Package

The document contains C code for a package management system that allows for the opening, creation, saving, and manipulation of package files. It defines structures and functions to handle file entries, including reading and writing data, managing memory, and applying XOR encryption for data security. The code includes error handling for file operations and memory allocation issues.

Uploaded by

Maciek K
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
7 views10 pages

Package

The document contains C code for a package management system that allows for the opening, creation, saving, and manipulation of package files. It defines structures and functions to handle file entries, including reading and writing data, managing memory, and applying XOR encryption for data security. The code includes error handling for file operations and memory allocation issues.

Uploaded by

Maciek K
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 10

#include <stdlib.

h>
#include <string.h>
#include <stdio.h>

#include <package.h>

#include "xor.h"

#define PACKAGE_MAGIC 0x544c41 // "ALT"

struct package_file_t
{
file_entry_t entry;
uint32_t pos;
uint8_t *data;
};

uint32_t package_open(package_t *package, const char *package_path)


{
uint32_t i;
uint32_t magic;
uint32_t entry_table_size;
uint32_t data_offset;
uint32_t file_size;
file_entry_t *entries;
FILE *package_file;
package_file_t *file;
uint8_t *file_data;

if (package == NULL)
{
return 1;
}

// init the package


memset(package, 0, sizeof(package_t));

// open the file


package_file = fopen(package_path, "rb");
if (package_file == NULL)
{
// File not found
return 1;
}

// get the file size


fseek(package_file, 0, SEEK_END);
file_size = ftell(package_file);
fseek(package_file, 0, SEEK_SET);

// read the magic


if (fread(&magic, sizeof(uint32_t), 1, package_file) != 1 || magic !=
PACKAGE_MAGIC)
{
// Not a package file
fclose(package_file);
package_close(package);
return 1;
}
// read the entry count
if (fseek(package_file, file_size - sizeof(uint32_t), SEEK_SET))
{
// Package file corrupted
fclose(package_file);
package_close(package);
return 1;
}

if (fread(&package->num_entries, sizeof(uint32_t), 1, package_file) != 1)


{
// Package file corrupted
fclose(package_file);
package_close(package);
return 1;
}

// read the entry table


entry_table_size = sizeof(file_entry_t) * package->num_entries;
data_offset = file_size - entry_table_size - 4;
if (fseek(package_file, data_offset, SEEK_SET))
{
// Package file corrupted
fclose(package_file);
package_close(package);
return 1;
}

package->entries = (package_file_t **)malloc(sizeof(package_file_t *) *


package->num_entries);
if (package->entries == NULL)
{
// Out of memory
fclose(package_file);
package_close(package);
return 1;
}

entries = (file_entry_t *)malloc(sizeof(file_entry_t) * package->num_entries);


if (entries == NULL)
{
// Out of memory
fclose(package_file);
package_close(package);
return 1;
}

for (i = 0; i != package->num_entries; ++i)


{
if (fseek(package_file, data_offset + i * sizeof(file_entry_t), SEEK_SET))
{
// Package file corrupted
free(entries);
fclose(package_file);
package_close(package);
return 1;
}
if (fread(&entries[i], sizeof(file_entry_t), 1, package_file) != 1)
{
// Package file corrupted
free(entries);
fclose(package_file);
package_close(package);
return 1;
}

xor_file_entry((uint8_t *)&entries[i], i, package->num_entries, file_size);

// add the data


if (entries[i].offset + entries[i].size > data_offset)
{
// Package file corrupted
free(entries);
fclose(package_file);
package_close(package);
return 1;
}

file_data = (uint8_t *)malloc(entries[i].size);


if (file_data == NULL)
{
// Out of memory
free(entries);
fclose(package_file);
package_close(package);
return 1;
}

// read the file data


if (fseek(package_file, entries[i].offset, SEEK_SET))
{
// Package file corrupted
free(file_data);
free(entries);
fclose(package_file);
package_close(package);
return 1;
}

if (fread(file_data, 1, entries[i].size, package_file) != entries[i].size)


{
// Package file corrupted
free(file_data);
free(entries);
fclose(package_file);
package_close(package);
return 1;
}

xor_file_data(&entries[i], file_data);

file = (package_file_t *)malloc(sizeof(package_file_t));


if (file == NULL)
{
// Out of memory
free(file_data);
free(entries);
fclose(package_file);
package_close(package);
return 1;
}

memset(file, 0, sizeof(package_file_t));
file->entry = entries[i];
file->data = file_data;
package->entries[i] = file;
}

free(entries);
fclose(package_file);

return 0;
}

uint32_t package_create(package_t *package)


{
// create a new package
memset(package, 0, sizeof(package_t));

// init the package package


package->num_entries = 0;
package->entries = NULL;

return 0;
}

// save a package to disk


uint32_t package_save(package_t *package, const char *path)
{
FILE *package_file;
package_file_t *file;
uint32_t entry_table_size;
uint32_t data_offset;
uint32_t file_size;
uint32_t magic;
uint32_t i;
size_t written;

// open the file


package_file = fopen(path, "wb");
if (package_file == NULL)
{
// File not found
return 1;
}

// calculate the file size


entry_table_size = sizeof(file_entry_t) * package->num_entries;

// calculate the data offset


data_offset = 4;
for (i = 0; i != package->num_entries; ++i)
{
data_offset += package->entries[i]->entry.size;
}
// calculate the file size
file_size = data_offset + entry_table_size + 4;

// write the magic


magic = PACKAGE_MAGIC;
if (fwrite(&magic, sizeof(uint32_t), 1, package_file) != 1)
{
// Failed to write to file
return 1;
}

// write the file data


for (i = 0; i != package->num_entries; ++i)
{
file = package->entries[i];
file->entry.offset = ftell(package_file);
if (file->data)
{
xor_file_data(&file->entry, file->data);
written = fwrite(file->data, 1, file->entry.size, package_file);
xor_file_data(&file->entry, file->data);

if (written != file->entry.size)
{
// Failed to write to file
fclose(package_file);
return 1;
}
}
}

// write the entry table


for (i = 0; i != package->num_entries; ++i)
{
file = package->entries[i];
xor_file_entry((uint8_t *)&file->entry, i, package->num_entries,
file_size);
written = fwrite(&file->entry, sizeof(file_entry_t), 1, package_file);
xor_file_entry((uint8_t *)&file->entry, i, package->num_entries,
file_size);

if (written != 1)
{
// Failed to write to file
fclose(package_file);
return 1;
}
}

// write the entry count


if (fwrite(&package->num_entries, sizeof(uint32_t), 1, package_file) != 1)
{
// Failed to write to file
fclose(package_file);
return 1;
}

fclose(package_file);
return 0;
}

void package_close(package_t *package)


{
uint32_t i;

if (package->entries)
{
for (i = 0; i != package->num_entries; ++i)
{
if (package->entries[i]->data)
{
free(package->entries[i]->data);
}

free(package->entries[i]);
}

free(package->entries);
}

memset(package, 0, sizeof(package_t));
}

package_file_t *package_open_file_idx(package_t *package, uint32_t index)


{
if (index >= package->num_entries)
{
return NULL;
}

return package->entries[index];
}

package_file_t *package_open_file_hash(package_t *package, altv_hash_t hash)


{
uint32_t i;

for (i = 0; i < package->num_entries; ++i)


{
if (package->entries[i]->entry.hash.value == hash.value)
{
return package->entries[i];
}
}

return NULL;
}

package_file_t *package_open_file_cstr(package_t *package, const char *file_name)


{
return package_open_file_hash(package, altv_hash(file_name,
strlen(file_name)));
}

package_file_t *package_create_file(package_t *package, const char *file_name)


{
package_file_t *entry;
package_file_t **new_entries;

// if there are no entries, allocate the entries


if (package->entries == NULL)
{
new_entries = (package_file_t **)malloc(sizeof(package_file_t *));
if (new_entries == NULL)
{
return NULL;
}

package->entries = new_entries;

package->entries[0] = (package_file_t *)malloc(sizeof(package_file_t));


if (package->entries[0] == NULL)
{
free(package->entries);
return NULL;
}

memset(package->entries[0], 0, sizeof(package_file_t));
}
else
{
// realloc the entries
new_entries = (package_file_t **)realloc(package->entries,
sizeof(package_file_t *) * (package->num_entries + 1));
if (new_entries == NULL)
{
return NULL;
}

package->entries = new_entries;

package->entries[package->num_entries] = (package_file_t
*)malloc(sizeof(package_file_t));
if (package->entries[package->num_entries] == NULL)
{
free(package->entries);
return NULL;
}

memset(package->entries[package->num_entries], 0, sizeof(package_file_t));
}

// set the new entry


entry = package->entries[package->num_entries];

entry->entry.hash = altv_hash(file_name, strlen(file_name));

// increase the entry count


++package->num_entries;

// return the entry


return entry;
}

uint32_t package_file_seek(package_file_t *entry, uint32_t offset, int origin)


{
switch (origin)
{
case SEEK_SET:
entry->pos = offset;
break;
case SEEK_CUR:
entry->pos += offset;
break;
case SEEK_END:
entry->pos = entry->entry.size - offset;
break;
default:
return 1;
}

return 0;
}

uint32_t package_file_read(package_file_t *entry, uint8_t *buffer, uint32_t size)


{
// the file is smaller than the requested size
if (entry->pos + size > entry->entry.size)
{
if (entry->pos >= entry->entry.size)
{
return 0;
}

size = entry->entry.size - entry->pos;


}

memcpy(buffer, &entry->data[entry->pos], size);

entry->pos += size;

return size;
}

uint32_t package_file_write(package_file_t *entry, uint8_t *buffer, uint32_t size)


{
uint8_t *new_data;

if (entry->pos + size > entry->entry.size)


{
// if there is no data, allocate the data
if (entry->data == NULL)
{
entry->data = (uint8_t *)malloc(entry->pos + size);
if (entry->data == NULL)
{
return 0;
}
}
else
{
// realloc the data
new_data = (uint8_t *)realloc(entry->data, entry->pos + size);
if (new_data == NULL)
{
return 0;
}

entry->data = new_data;
}

entry->entry.size = entry->pos + size;


}

memcpy(&entry->data[entry->pos], buffer, size);

entry->pos += size;

return size;
}

uint32_t package_file_tell(package_file_t *file)


{
return file->pos;
}

uint32_t package_file_truncate(package_file_t *file, uint32_t size)


{
uint8_t *new_data;

if (size > file->entry.size)


{
return 0;
}

file->entry.size = size;

// only realloc if the size is less than 1/4 of the current size
if (size < file->entry.size / 4)
{
new_data = (uint8_t *)realloc(file->data, size);
if (new_data == NULL)
{
return 0;
}

file->data = new_data;
}

return size;
}

uint32_t package_file_size(package_file_t *file)


{
return file->entry.size;
}

altv_hash_t package_file_hash(package_file_t *file)


{
return file->entry.hash;
}

const uint8_t *package_file_data(package_file_t *file)


{
return file->data;
}

You might also like