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