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