1 /* repair.c */
2
3 /* Written by Stefan Parmark. */
4
5 #include <stdio.h>
6 #ifdef AMIGA
7 #include <stdlib.h>
8 #include <string.h>
9 #endif AMIGA
10
11 #include "btoa.h"
12
13 /* File names. */
14 BYTE *diagnosisname = "btoa.dia";
15 BYTE *repairname = "btoa.rep";
16 BYTE *repairedname = "btoa.rdy";
17
18 /* File headers. */
19 BYTE *diagnosisheader = "xdiagnosis\n";
20 BYTE *repairheader = "xrepair\n";
21
22
23 /* Produce diagnosis file from diagnoses records created by atob(). */
24 /* It contains the lines immediately before and after the error */
25 /* sequence. */
producediagnosis(diagnosislist,infile)26 void producediagnosis(diagnosislist, infile)
27 register struct Diagnosis *diagnosislist;
28 register FILE *infile;
29 {
30 register FILE *diagnosisfile;
31 LONG startpos, endpos;
32 register LONG currentpos;
33 extern BYTE *diagnosisname, *diagnosisheader, buffer[BUFSIZE];
34
35 currentpos = ftell(infile);
36
37 if ((diagnosisfile = fopen_write(diagnosisname)) != NULL)
38 {
39 fprintf(stderr, "btoa: Diagnosis output to '%s'.\n", diagnosisname);
40
41 fputs(diagnosisheader, diagnosisfile);
42 do
43 {
44 /* Extract startpos & endpos from diagnosislist. */
45 outdiagnosislist(diagnosislist, &startpos, &endpos);
46
47 if (startpos != -1)
48 {
49 /* Print line before error. */
50 fseek(infile, startpos, 0);
51 fgets(buffer, BUFSIZE, infile);
52 fputs(buffer, diagnosisfile);
53
54 /* Print line after error. */
55 fseek(infile, endpos, 0);
56 fgets(buffer, BUFSIZE, infile);
57 fputs(buffer, diagnosisfile);
58 }
59 }
60 while (startpos != -1);
61 fputs(diagnosisheader, diagnosisfile);
62
63 fclose(diagnosisfile);
64 }
65
66 /* Move file pointer to where it was when we entered. */
67 fseek(infile, currentpos, 0);
68 }
69
70
71 /* Insert two file positions into diagnosislist. */
intodiagnosislist(diagnosislist,startpos,endpos)72 void intodiagnosislist(diagnosislist, startpos, endpos)
73 register struct Diagnosis *diagnosislist;
74 register LONG startpos, endpos;
75 {
76 register struct Diagnosis *diagnosisitem, *lastitem;
77
78 diagnosisitem = (struct Diagnosis *)malloc(sizeof(struct Diagnosis));
79 diagnosisitem->startpos = startpos;
80 diagnosisitem->endpos = endpos;
81 diagnosisitem->next = NULL;
82
83 if ((lastitem = diagnosislist->last) == NULL) /* List is empty */
84 diagnosislist->next = diagnosislist->last = diagnosisitem;
85 else
86 {
87 if (lastitem->endpos >= startpos)
88 {
89 lastitem->endpos = endpos;
90 free((BYTE *) diagnosisitem);
91 }
92 else
93 {
94 lastitem->next = diagnosisitem;
95 diagnosislist->last = diagnosisitem;
96 }
97 }
98 }
99
100
101 /* Extract two file positions from diagnosislist. */
outdiagnosislist(diagnosislist,startpos,endpos)102 void outdiagnosislist(diagnosislist, startpos, endpos)
103 register struct Diagnosis *diagnosislist;
104 LONG *startpos, *endpos;
105 {
106 register struct Diagnosis *diagnosisitem;
107
108 if ((diagnosisitem = diagnosislist->next) == NULL) /* List is empty */
109 *startpos = *endpos = -1;
110 else
111 {
112 *startpos = diagnosisitem->startpos;
113 *endpos = diagnosisitem->endpos;
114
115 diagnosislist->next = diagnosisitem->next;
116 free((BYTE *)diagnosisitem);
117 if (diagnosislist->next == NULL)
118 diagnosislist->last = NULL;
119 }
120 }
121
122
123 /* Copy infile to outfile until searchstring is found. If outfile */
124 /* is NULL nothing will be written. */
copyfile(infile,outfile,searchstring)125 BYTE copyfile(infile, outfile, searchstring)
126 register FILE *infile, *outfile;
127 register BYTE *searchstring;
128 {
129 register BYTE stop, error;
130 static BYTE copybuffer[BUFSIZE];
131
132 stop = error = FALSE;
133 while (!(stop || error))
134 if (readbuffer(copybuffer, "archive", infile))
135 error = TRUE;
136 else
137 {
138 if (outfile != NULL)
139 fputs(copybuffer, outfile);
140 if (strcmp(copybuffer, searchstring) == 0)
141 stop = TRUE;
142 }
143
144 return(error);
145 }
146
147
148 /* Read a line from infile into buffer. Returns TRUE if */
149 /* end-of-file has been reached. */
readbuffer(buffer,errormsg,infile)150 BYTE readbuffer(buffer, errormsg, infile)
151 register BYTE *buffer, *errormsg;
152 register FILE *infile;
153 {
154 register BYTE error;
155
156 error = FALSE;
157 if (fgets(buffer, BUFSIZE, infile) == NULL)
158 {
159 fprintf(stderr, "btoa: Unexpected end of %s file.\n", errormsg);
160 error = TRUE;
161 }
162
163 return(error);
164 }
165
166
fopen_read(filename)167 FILE *fopen_read(filename)
168 register BYTE *filename;
169 {
170 register FILE *infile;
171
172 if ((infile = fopen(filename, "r")) == NULL)
173 fprintf(stderr, "btoa: Can't open '%s' for input.\n", filename);
174
175 return(infile);
176 }
177
178
fopen_write(filename)179 FILE *fopen_write(filename)
180 register BYTE *filename;
181 {
182 register FILE *outfile;
183
184 if ((outfile = fopen(filename, "w")) == NULL)
185 fprintf(stderr, "btoa: Can't open '%s' for output.\n", filename);
186
187 return(outfile);
188 }
189
190
191 /* Extract lines from original archive to fix the damaged one. */
producerepair(infile)192 BYTE producerepair(infile)
193 register FILE *infile;
194 {
195 register FILE *repairfile, *diagnosisfile;
196 register BYTE error, stop;
197 static BYTE *errormsg = "diagnosis";
198 extern BYTE *diagnosisname, *diagnosisheader, *repairname, *repairheader,
199 buffer[BUFSIZE];
200
201 error = FALSE;
202 diagnosisfile = repairfile = NULL;
203
204 fprintf(stderr, "btoa: Repair output to '%s'.\n", repairname);
205 if ((diagnosisfile = fopen_read(diagnosisname)) == NULL)
206 error = TRUE;
207 else if ((repairfile = fopen_write(repairname)) == NULL)
208 {
209 fclose(diagnosisfile);
210 diagnosisfile = NULL;
211 error = TRUE;
212 }
213 else
214 {
215 /* Read until header is found. This makes it possible to */
216 /* have junk before the header, such as an article header. */
217 do
218 {
219 if (readbuffer(buffer, errormsg, diagnosisfile))
220 error = TRUE;
221 }
222 while (!error && strcmp(buffer, diagnosisheader) != 0);
223 fputs(repairheader, repairfile);
224 }
225
226 stop = FALSE;
227 while (!(error || stop))
228 {
229 /* Loop until header is found again. */
230
231 if (readbuffer(buffer, errormsg, diagnosisfile))
232 error = TRUE;
233 else if (strcmp(buffer, diagnosisheader) == 0)
234 stop = TRUE;
235 else
236 {
237 /* Read until line before error is found. */
238 error = copyfile(infile, NULL, buffer);
239 if (!error)
240 {
241 /* Print line before error. */
242 fputs(buffer, repairfile);
243
244 if (readbuffer(buffer, errormsg, diagnosisfile))
245 error = TRUE;
246 else
247 {
248 /* Print line after error */
249 fputs(buffer, repairfile);
250 /* Copy infile to repairfile until line after error */
251 error = copyfile(infile, repairfile, buffer);
252 }
253 }
254 }
255 }
256
257 if (!error)
258 fputs(repairheader, repairfile);
259
260 if (repairfile != NULL)
261 fclose(repairfile);
262 if (diagnosisfile != NULL)
263 fclose(diagnosisfile);
264
265 return(error);
266 }
267
268
269 /* Repair damaged archive from repair file. */
performrepair(infile)270 BYTE performrepair(infile)
271 register FILE *infile;
272 {
273 register FILE *repairfile, *outfile;
274 register BYTE error, stop;
275 static BYTE *errormsg = "repair";
276 extern BYTE *repairname, *repairedname, *repairheader, buffer[BUFSIZE];
277
278 error = FALSE;
279 repairfile = outfile = NULL;
280
281 if ((repairfile = fopen_read(repairname)) == NULL)
282 error = TRUE;
283 else if ((outfile = fopen_write(repairedname)) == NULL)
284 {
285 fclose(repairfile);
286 repairfile = NULL;
287 error = TRUE;
288 }
289 else
290 {
291 fprintf(stderr, "btoa: Repaired archive written to '%s'.\n", repairedname);
292
293 /* Read until header is found. */
294 do
295 {
296 if (readbuffer(buffer, errormsg, repairfile))
297 error = TRUE;
298 }
299 while (!error && strcmp(buffer, repairheader) != 0);
300 }
301
302 stop = FALSE;
303 while (!(error || stop))
304 {
305 /* Loop until header is found. */
306
307 if (readbuffer(buffer, errormsg, repairfile))
308 error = TRUE;
309 else if (strcmp(buffer, repairheader) == 0)
310 stop = TRUE;
311 else
312 {
313 /* Read and write until line before error. */
314 error = copyfile(infile, outfile, buffer);
315 if (!error)
316 if (readbuffer(buffer, errormsg, repairfile))
317 error = TRUE;
318 else
319 {
320 /* Read and write until line after error. */
321 error = copyfile(repairfile, outfile, buffer);
322 /* Skip until line after error */
323 copyfile(infile, NULL, buffer);
324 }
325 }
326 }
327
328 if (!error) /* Write rest of archive. */
329 while (fgets(buffer, BUFSIZE, infile) != NULL)
330 fputs(buffer, outfile);
331
332 if (outfile != NULL)
333 fclose(outfile);
334 if (repairfile != NULL)
335 fclose(repairfile);
336
337 return(error);
338 }
339