#include "skip.h" #include "error.h" #include "file.h" #include "str.h" #include #include #include 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; u32 off; skip = sw_skip_create(); fil = fopen(filename, "rb"); fseek(fil, -4, SEEK_END); fread(&off, 4, 1, fil); fseek(fil, -off, SEEK_END); 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); } skip->data = malloc(skip->data_size); fread(skip->data, 1, skip->data_size, fil); fclose(fil); return skip; } static void sw_skip_save_to(struct sw_skip *skip, FILE *fil); 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_add(struct sw_skip *skip, u8 *data, u32 data_size, char *name) { u32 off; off = skip->data_size + 1; skip->data_size += data_size; skip->data = realloc(skip->data, skip->data_size); memcpy(skip->data + off, data, data_size); skip->file_count += 1; skip->files = realloc(skip->files, sizeof(skip->files[0]) * skip->file_count); skip->files[skip->file_count - 1].name = sw_str_dup(name); skip->files[skip->file_count - 1].offset = off; skip->files[skip->file_count - 1].size = data_size; } void sw_skip_add_file(struct sw_skip *skip, char *name, char *filename) { FILE *fil; u32 len; u8 *data; fil = fopen(filename, "rb"); fseek(fil, 0, SEEK_END); len = ftell(fil); fseek(fil, 0, SEEK_SET); data = malloc(len); fread(data, 1, len, fil); fclose(fil); sw_skip_add(skip, data, len, name); free(data); } void sw_skip_attach(struct sw_skip *skip, char *filename) { FILE *fil; fil = fopen(filename, "rb+"); fseek(fil, 0, SEEK_END); sw_skip_save_to(skip, fil); } void sw_skip_dettach(char *filename) { FILE *fil; char magic[5] = {0}; u32 off; u32 len; u8 *data; fil = fopen(filename, "rb"); fseek(fil, -4, SEEK_END); fread(&off, 4, 1, fil); fseek(fil, -off, SEEK_END); fread(magic, 1, 4, fil); sw_log("magic: [%s]", magic); sw_log("off: %i", off); if(strcmp("SWZP", magic) == 0) { sw_log("detaching .skip from %s", filename); len = ftell(fil) - 4; fseek(fil, 0, SEEK_SET); data = malloc(len); fread(data, 1, len, fil); fclose(fil); fil = fopen(filename, "wb"); fwrite(data, 1, len, fil); } fclose(fil); } u8 *sw_skip_get(struct sw_skip *skip, char *name, u32 *out_size) { u32 i; for(i = 0; i < skip->file_count; ++i) { if(strcmp(name, skip->files[i].name) == 0) { if(out_size) { *out_size = skip->files[i].size; } return skip->data + skip->files[i].offset; } } return 0; } void sw_skip_save(struct sw_skip *skip, char *filename) { sw_skip_save_to(skip, fopen(filename, "wb")); } static void sw_skip_save_to(struct sw_skip *skip, FILE *fil) { u16 i; u32 start; start = ftell(fil); sw_fwrite_str_nozero(fil, "SWZP"); sw_fwrite_u8(fil, 0); /* version */ sw_fwrite_u8(fil, 0); /* compression */ sw_fwrite_u32(fil, skip->data_size); /* uncompressed size */ sw_fwrite_u32(fil, skip->data_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 */ } fwrite(skip->data, 1, skip->data_size, fil); sw_fwrite_u32(fil, ftell(fil) + 4 - start); /* file length */ fclose(fil); }