skip file format

This commit is contained in:
DaniTheSkunk 2023-02-09 18:36:39 +00:00
parent 732acde1e6
commit bf7b89c05a
2 changed files with 161 additions and 0 deletions

57
include/skip.h Normal file
View File

@ -0,0 +1,57 @@
/******************************************************************************/
/* Skip File Format, skunkworks zip */
/* */
/* little-endian */
/* */
/* Main Header: */
/* */
/* bytes | what */
/* ------+------------------------------------------------------------------- */
/* 4 | 'SWZP' */
/* 1 | version, currently 0x00 */
/* 1 | compression format, currently only 0 supported, uncompressed */
/* 4 | size of uncompressed data chunk */
/* 4 | size of compressed data chunk (same as compressed if format 0) */
/* 2 | file count */
/* */
/* File Header (appears 'file count' times in a row): */
/* */
/* bytes | what */
/* ------+------------------------------------------------------------------- */
/* 4 | offset from beginning of data chunk */
/* 4 | file size (uncompressed) */
/* 1 | length of filename */
/* * | filename (not zero terminated) */
/* */
/* Rest of File: */
/* */
/* bytes | what */
/* ------+------------------------------------------------------------------- */
/* * | data chunk */
/* 4 | length of file total (to easily find header if file is attached to */
/* an executable) */
/******************************************************************************/
#ifndef GUARD_62F584E45B48B8F6069643FC44702ED5
#define GUARD_62F584E45B48B8F6069643FC44702ED5
#include "types.h"
struct sw_skip {
u32 data_size;
u8 *data;
u16 file_count;
struct {
u32 offset;
u32 size;
char *name;
} *files;
};
struct sw_skip *sw_skip_create();
struct sw_skip *sw_skip_load(char *filename);
void sw_skip_destroy(struct sw_skip *skip);
void sw_skip_save(struct sw_skip *skip, char *filename);
#endif /* GUARD_62F584E45B48B8F6069643FC44702ED5 */

104
src/skip.c Normal file
View File

@ -0,0 +1,104 @@
#include "skip.h"
#include "error.h"
#include "file.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct sw_skip *sw_skip_create() {
struct sw_skip *skip;
skip = calloc(1, sizeof(struct sw_skip));
return skip;
}
struct sw_skip *sw_skip_load(char *filename) {
FILE *fil;
struct sw_skip *skip;
char magic[5] = {0};
u8 version, compression;
u16 i;
char str[257];
u8 str_len;
skip = sw_skip_create();
fil = fopen(filename, "rb");
fread(magic, 1, 4, fil);
if(strcmp("SWZP", magic) != 0) {
sw_error("not a .skip file");
}
fread(&version, 1, 1, fil);
if(version > 0) {
sw_error("version %i of .skip not supported", version);
}
fread(&compression, 1, 1, fil);
if(compression > 0) {
sw_error("unsupported .skip compression method");
}
fread(&skip->data_size, 1, 4, fil);
fseek(fil, 4, SEEK_CUR); /* ignore compressed size */
fread(&skip->file_count, 1, 2, fil);
skip->files = malloc(sizeof(skip->files[0]) * skip->file_count);
for(i = 0; i < skip->file_count; ++i) {
memset(str, 0, 257);
fread(&skip->files[i].offset, 1, 4, fil);
fread(&skip->files[i].size, 1, 4, fil);
fread(&str_len, 1, 1, fil);
fread(str, str_len, 1, fil);
str[str_len] = 0;
skip->files[i].name = malloc(str_len + 1);
strcpy(skip->files[i].name, str);
}
fclose(fil);
return skip;
}
void sw_skip_destroy(struct sw_skip *skip) {
i32 i;
for(i = 0; i < skip->file_count; ++i) {
free(skip->files[i].name);
}
free(skip->files);
free(skip->data);
free(skip);
}
void sw_skip_save(struct sw_skip *skip, char *filename) {
FILE *fil;
u32 size;
u16 i;
size = 0;
for(i = 0; i < skip->file_count; ++i) {
size += skip->files[i].size;
}
fil = fopen(filename, "wb");
sw_fwrite_str_nozero(fil, "SWZP");
sw_fwrite_u8(fil, 0); /* version */
sw_fwrite_u8(fil, 0); /* compression */
sw_fwrite_u32(fil, size); /* uncompressed size */
sw_fwrite_u32(fil, size); /* compressed size */
sw_fwrite_u16(fil, skip->file_count); /* file count */
for(i = 0; i < skip->file_count; ++i) {
sw_fwrite_u32(fil, skip->files[i].offset); /* offset */
sw_fwrite_u32(fil, skip->files[i].size); /* file size */
sw_fwrite_str_prefix8(fil, skip->files[i].name); /* file name */
}
sw_fwrite_u32(fil, ftell(fil) + 4); /* file length */
fclose(fil);
}