source: thomson/tools/xk5.c@ 5b27b9f

main
Last change on this file since 5b27b9f was 5b27b9f, checked in by Adrien Destugues <pulkomandy@…>, 9 years ago

xk5: fix off-by-one error in snprintf length.

  • The length includes the string terminator, 8+3+1+1=13.

git-svn-id: svn://localhost/thomson@56 85ae3b6b-dc8f-4344-a89d-598714f2e4e5

  • Property mode set to 100644
File size: 6.7 KB
Line 
1/*
2 * xk5 :
3 * Extraction des fichiers à partir d'un fichier K7 (format MO)
4 *
5 * Copyright (c) 2011 Puls
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22
23#include <stdio.h>
24#include <string.h>
25#include <stdint.h>
26#include <stdlib.h>
27
28typedef enum { FALSE, TRUE } bool_t;
29
30enum {
31 E_CANT_READ_FILE = -100,
32 E_CANT_WRITE_FILE,
33 E_CHECKSUM,
34 E_END_OF_CASSETTE ,
35 E_READ_ERROR,
36 E_MEMORY
37};
38
39
40static const struct {
41 int err;
42 char str[33];
43 } elist [] = {
44 { E_CANT_READ_FILE ,"Cannot read file" },
45 { E_CANT_WRITE_FILE ,"Cannot write file" },
46 { E_CHECKSUM ,"Checksum error" },
47 { E_END_OF_CASSETTE ,"End of cassette reached" },
48 { E_READ_ERROR ,"Read error" },
49 { E_MEMORY ,"Memory error" },
50 { 0 ,"Ok" }
51};
52
53
54static void
55display_error (char *message, int err) {
56 int i = 0;
57
58 while ((err != elist[i].err) && (elist[i].err < 0))
59 i++;
60 (void)printf ("%s : %s\n", message, (char *)elist[i].str);
61}
62
63
64static void
65clean_string (char *str) {
66 int i;
67
68 for (i=(int)strlen(str)-1; (i>=0)&&(str[i]<=' '); i--)
69 str[i] = '\0';
70}
71
72
73static int
74k5_read_byte (FILE *file, uint8_t *byte)
75/*@globals errno@*/ {
76 int err = 0;
77
78 *byte = (uint8_t)fgetc (file);
79 if ( feof (file) != 0) err = E_END_OF_CASSETTE;
80 if (ferror (file) != 0) err = E_READ_ERROR;
81 return err;
82}
83
84
85static int
86k5_read_block (FILE *file, uint8_t *buf, uint8_t *size, uint8_t *type)
87/*@globals errno@*/ {
88 int err = 0;
89
90 err = k5_read_byte (file, type);
91 if (err == 0) {
92 err = k5_read_byte (file, size);
93 *size -= 2;
94 if ((err == 0) && (*size != 0)) {
95 if (fread (buf, 1, *size, file) != *size) {
96 if ( feof (file) != 0) err = E_END_OF_CASSETTE;
97 if (ferror (file) != 0) err = E_READ_ERROR;
98 }
99 }
100 }
101 return err;
102}
103
104
105static int
106k5_search_gap (FILE *file)
107/*@globals errno@*/ {
108 int err = 0;
109 uint8_t byte = 0;
110 int count = 0;
111
112 while ((count < 5) && (err == 0)) {
113 err = k5_read_byte (file, &byte);
114 if (byte == 0x01) count++; else count = 0;
115 }
116 return err;
117}
118
119
120static uint8_t
121k5_checksum (uint8_t *buf, uint8_t size){
122 uint8_t i;
123 uint8_t checksum ;
124
125 checksum = 0;
126 for (i = 0; i < size; i++)
127 checksum += buf[i];
128 return -checksum;
129}
130
131
132static int
133k5_find_block (FILE *file, uint8_t *buf, uint8_t *size, uint8_t *type, uint8_t *checksum)
134/*@globals errno@*/ {
135 int err = 0;
136 uint8_t byte = 0;
137 bool_t block_found = FALSE;
138
139 while ((err == 0) && (block_found == FALSE)) {
140 err = k5_search_gap (file);
141 byte = 0x01;
142 while ((err == 0) && (byte == 0x01))
143 err = k5_read_byte (file, &byte);
144 if ((err == 0) && (byte == 0x3c)) {
145 err = k5_read_byte (file, &byte);
146 if ((err == 0) && (byte == 0x5a)) {
147 err = k5_read_block (file, buf, size, type);
148 }
149 }
150 if (err == 0) {
151 *checksum = (uint8_t)fgetc (file);
152 if (ferror (file) != 0) err = E_READ_ERROR;
153 else block_found = TRUE;
154 }
155 }
156 return err;
157}
158
159
160static void
161k5_pc_filename (uint8_t *buf, char *name) {
162 char pc_name[9] = "";
163 char pc_ext[4] = "";
164
165 strncat (pc_name, (char *)buf, 8);
166 strncat (pc_ext, (char *)buf+8, 3);
167 clean_string (pc_name);
168 clean_string (pc_ext);
169 *name = '\0';
170 (void)snprintf (name, 13, "%8s.%3s", pc_name, pc_ext);
171}
172
173
174static int
175k5_searching (FILE *file, char *name)
176/*@globals errno@*/ {
177 int err = 0;
178 uint8_t type = 0x01;
179 uint8_t size = 0;
180 uint8_t checksum = 0;
181 uint8_t buf[255];
182
183 memset (buf, 0x00, sizeof (&buf));
184 while ((type != 0x00) && (err == 0)) {
185 err = k5_find_block (file, buf, &size, &type, &checksum);
186 if (err == 0) {
187 if (checksum != k5_checksum (buf, size))
188 err = E_CHECKSUM;
189 k5_pc_filename (buf, name);
190 }
191 }
192 return err;
193}
194
195
196static int
197k5_fload (FILE *file, uint8_t *buf, size_t *index, char *name)
198/*@globals errno@*/ {
199 int err = 0;
200 uint8_t type = 0x01;
201 uint8_t size = 0;
202 uint8_t checksum = 0;
203
204 if ((file != NULL) && (buf != NULL)) {
205 err = k5_searching (file, name);
206 *index = 0;
207 while ((type != 0xff) && (err == 0)) {
208 err = k5_find_block (file, buf + *index, &size, &type, &checksum);
209 *index += (size_t)size;
210 }
211 }
212 return err;
213}
214
215
216static int
217k5_extract (char *name)
218/*@globals errno,stdout@*/ {
219 static FILE /*@dependent@*//*@null@*/*file = NULL;
220 static FILE /*@dependent@*//*@null@*/*fd_dest = NULL;
221 uint8_t *buf = NULL;
222 size_t size = 0;
223 int err = 0;
224 long int pos = 0;
225 char dstName[20] = "";
226
227 buf = (uint8_t*)calloc (1, 100000);
228 if (buf != NULL) {
229 file = fopen(name, "rb");
230 if (file != NULL) {
231 while (err == 0) {
232 err = k5_fload (file, buf, &size, dstName);
233 if (err == 0) {
234 pos = ftell (file);
235 (void)printf ("%07d '%s' (%d bytes)\n", (int)pos, dstName, (int)size);
236 fd_dest = fopen (dstName, "wb");
237 if (fd_dest != NULL) {
238 if (fwrite (buf, 1, size, fd_dest) != size)
239 err = E_READ_ERROR;
240 (void)fclose (fd_dest);
241 } else err = E_CANT_WRITE_FILE;
242 }
243 }
244 (void)fclose (file);
245 } else err = E_CANT_READ_FILE;
246 free (buf);
247 } else err = E_MEMORY;
248 return err;
249}
250
251
252int
253main(int argc, char *argv[])
254/*@globals errno,stdout@*/ {
255 char name[300+1] = "";
256
257 if (argc != 2) {
258 (void)printf (" xk5 version 0.1 (c) oct 2011 Puls\n");
259 (void)printf (" Usage : xk5 <k5file>\n");
260 } else {
261 (void)snprintf (name, 300, "%s", argv[1]);
262 clean_string (name);
263 display_error (name, k5_extract (name));
264 }
265 return EXIT_SUCCESS;
266}
267
Note: See TracBrowser for help on using the repository browser.