sauce.c (3584B)
1 /* 2 * sauce.c 3 * Ansilove 4.1.6 4 * https://www.ansilove.org 5 * 6 * Copyright (c) 2011-2022 Stefan Vogt, Brian Cassidy, and Frederic Cambus 7 * All rights reserved. 8 * 9 * Ansilove is licensed under the BSD 2-Clause license. 10 * See LICENSE file for details. 11 * 12 * SPDX-License-Identifier: BSD-2-Clause 13 */ 14 15 #include <stdint.h> 16 #include <stdlib.h> 17 #include <string.h> 18 19 #include "sauce.h" 20 21 /* Reads SAUCE via a filename. */ 22 struct sauce * 23 sauceReadFileName(char *fileName) 24 { 25 FILE *file = fopen(fileName, "r"); 26 if (file == NULL) { 27 return NULL; 28 } 29 30 struct sauce *record = sauceReadFile(file); 31 fclose(file); 32 return record; 33 } 34 35 /* Read SAUCE via a FILE pointer. */ 36 struct sauce * 37 sauceReadFile(FILE *file) 38 { 39 struct sauce *record; 40 record = malloc(sizeof *record); 41 42 if (record != NULL) { 43 memset(record, 0, sizeof *record); 44 readRecord(file, record); 45 } 46 return record; 47 } 48 49 #define READ_RECORD(record, size) \ 50 read_status = fread(record, size, 1, file); \ 51 if (read_status != 1) \ 52 return; 53 54 void 55 readRecord(FILE *file, struct sauce *record) 56 { 57 size_t read_status; 58 59 if (fseek(file, 0 - RECORD_SIZE, SEEK_END) != 0) { 60 return; 61 } 62 63 read_status = fread(record->ID, sizeof (record->ID) - 1, 1, file); 64 record->ID[sizeof (record->ID) - 1] = '\0'; 65 66 if (read_status != 1 || strcmp(record->ID, SAUCE_ID) != 0) { 67 return; 68 } 69 READ_RECORD(record->version, sizeof(record->version) - 1); 70 record->version[sizeof (record->version) - 1] = '\0'; 71 READ_RECORD(record->title, sizeof(record->title) - 1); 72 record->title[sizeof (record->title) - 1] = '\0'; 73 READ_RECORD(record->author, sizeof(record->author) -1); 74 record->author[sizeof (record->author) - 1] = '\0'; 75 READ_RECORD(record->group, sizeof(record->group) - 1); 76 record->group[sizeof (record->group) - 1] = '\0'; 77 READ_RECORD(record->date, sizeof(record->date) - 1); 78 record->date[sizeof (record->date) - 1] = '\0'; 79 READ_RECORD(&(record->fileSize), sizeof (record->fileSize)); 80 READ_RECORD(&(record->dataType), sizeof (record->dataType)); 81 READ_RECORD(&(record->fileType), sizeof (record->fileType)); 82 READ_RECORD(&(record->tinfo1), sizeof (record->tinfo1)); 83 READ_RECORD(&(record->tinfo2), sizeof (record->tinfo2)); 84 READ_RECORD(&(record->tinfo3), sizeof (record->tinfo3)); 85 READ_RECORD(&(record->tinfo4), sizeof (record->tinfo4)); 86 READ_RECORD(&(record->comments), sizeof (record->comments)); 87 READ_RECORD(&(record->flags), sizeof (record->flags)); 88 READ_RECORD(record->tinfos, sizeof(record->tinfos) - 1); 89 record->tinfos[sizeof (record->tinfos) - 1] = '\0'; 90 91 if (ferror(file) != 0) { 92 return; 93 } 94 95 if (record->comments > 0) { 96 record->comment_lines = malloc(record->comments *sizeof (*record->comment_lines)); 97 98 if (record->comment_lines != NULL) { 99 if (readComments(file, record->comment_lines, record->comments) == -1) { 100 record->comments = 0; 101 } 102 } 103 } 104 } 105 106 int 107 readComments(FILE *file, char **comment_lines, int32_t comments) 108 { 109 int32_t i; 110 size_t read_status; 111 112 if (fseek(file, 0 - (RECORD_SIZE + 5 + COMMENT_SIZE *comments), SEEK_END) == 0) { 113 char ID[6]; 114 read_status = fread(ID, sizeof (ID) - 1, 1, file); 115 if (read_status != 1) 116 return -1; 117 118 ID[sizeof (ID) - 1] = '\0'; 119 120 if (strcmp(ID, COMMENT_ID) != 0) { 121 return -1; 122 } 123 124 for (i = 0; i < comments; i++) { 125 char buf[COMMENT_SIZE + 1] = ""; 126 127 read_status = fread(buf, COMMENT_SIZE, 1, file); 128 if (read_status != 1) 129 return -1; 130 131 buf[COMMENT_SIZE] = '\0'; 132 133 if (ferror(file) == 0) { 134 comment_lines[i] = strdup(buf); 135 if (comment_lines[i] == NULL) { 136 return -1; 137 } 138 } else { 139 return -1; 140 } 141 } 142 return 0; 143 } 144 return -1; 145 }