1 #ifndef LINT
2 static char sccsid[]="@(#) fiz.c 2.6 88/01/31 23:23:50";
3 #endif /* LINT */
4
5 /*
6 The contents of this file are hereby released to the public domain.
7
8 -- Rahul Dhesi 1987/02/06
9 */
10
11 /*
12 Searches for all directory entries in an archive and prints their
13 offsets. Zoo 1.41 and later may then be asked to extract a specific
14 file by supplying the offset of the file.
15 */
16
17 #include "options.h"
18 #include "zooio.h"
19 #include "various.h"
20 #include "zoofns.h"
21 #include "portable.h" /* I/O definitions */
22 #include "zoo.h"
23
24 void prtctrl ();
25 void prtch ();
26
main(argc,argv)27 main(argc,argv)
28 register int argc;
29 register char **argv;
30 {
31 char *zooname; /* name of archive to be read */
32 ZOOFILE zoo_file; /* the archive being examined opened for read */
33 int state; /* to keep track of how much of tag seen */
34 int inch; /* char just read from archive */
35
36 static char usage1[] = "Fiz 2.0 (1987/02/01) public domain Zoo archive repair utility by Rahul Dhesi\n";
37 static char usage2[] = "Usage: fiz archive[.zoo] (\"fiz -h\" for help)\n";
38
39 #ifdef SETBUF
40 /* set stdout to unbuffered */
41 setbuf (stdout, (char *) NULL);
42 #endif
43
44 if (argc < 2) {
45 printf("%s%s", usage1, usage2);
46 exit (1);
47 }
48
49 if (strcmp(argv[1],"-h") == 0)
50 goto givehelp;
51
52 zooname = argv[1];
53
54 /* Add default extension if none supplied */
55 {
56 char *p, *q;
57 p = zooname + strlen(zooname); /* point to last char */
58 while (p != zooname && *p != EXT_CH)
59 --p;
60 /* either found EXT_CH or reached beginning of zooname */
61 if (*p != EXT_CH) {
62 q = malloc(strlen(zooname) + strlen(EXT_DFLT) + 2);
63 if (q == NULL) {
64 printf("Fiz: Ran out of memory.\n");
65 exit(1);
66 }
67 strcpy(q, zooname);
68 strcat(q, EXT_DFLT);
69 zooname = q;
70 }
71 }
72
73 zoo_file = zooopen (zooname, Z_READ);
74 if (zoo_file == NOFILE) {
75 printf("Fiz: FATAL: Could not open %s.\n", zooname);
76 exit(1);
77 }
78
79 #ifdef DOUBLE_SECRET
80 { void oh_well(void); oh_well(); }
81 #endif
82
83 #define NOSTATE 1
84 #define HDR_1 0xdc
85 #define HDR_2 0xa7
86 #define HDR_3 0xc4
87 #define HDR_4 0xfd
88
89 #define DAT_1 '@'
90 #define DAT_2 ')'
91 #define DAT_3 '#'
92 #define DAT_4 '('
93
94 /* finite state machine implemented here by hand */
95
96 state = NOSTATE;
97 while ((inch = zgetc(zoo_file)) != EOF) {
98 inch = inch & 0xff;
99 if (state == NOSTATE) {
100 if (inch == HDR_1)
101 state = HDR_1;
102 else if (inch == DAT_1)
103 state = DAT_1;
104 } else if (state == HDR_1 && inch == HDR_2)
105 state = HDR_2;
106 else if (state == HDR_2 && inch == HDR_3)
107 state = HDR_3;
108 else if (state == HDR_3 && inch == HDR_4)
109 state = HDR_4;
110 else if (state == DAT_1 && inch == DAT_2)
111 state = DAT_2;
112 else if (state == DAT_2 && inch == DAT_3)
113 state = DAT_3;
114 else if (state == DAT_3 && inch == DAT_4)
115 state = DAT_4;
116 else
117 state = NOSTATE;
118
119 if (state == HDR_4) { /* found archive tag */
120 long save_pos;
121 struct direntry direntry;
122 save_pos = zootell(zoo_file);
123 zooseek(zoo_file, save_pos-4L, 0); /* back to tag pos */
124 frd_dir(&direntry, zoo_file); /* read dir entry */
125 printf("****************\n");
126
127 printf ("%8lu: DIR ", save_pos-4L);
128
129 if (direntry.dirlen > 0) {
130 printf ("[");
131 prtctrl (direntry.dirname);
132 printf ("]");
133 }
134
135 printf(" [");
136 prtctrl (direntry.fname);
137 printf ("]");
138
139 if (direntry.namlen > 0) {
140 printf (" [");
141 prtctrl (direntry.lfname);
142 printf ("]");
143 }
144 printf (" ==> %4lu", direntry.offset);
145 if (direntry.dir_crc != 0)
146 printf (" [*bad CRC*]");
147 printf ("\n");
148 fseek (zoo_file, save_pos, 0); /* try again from there */
149 } else if (state == DAT_4) { /* file data */
150 printf ("%8lu: DATA\n", zootell(zoo_file) + 1);
151 }
152 }
153 exit (0); /* don't fall through */
154
155 givehelp:
156
157 /*
158 vi macros:
159 to add printf:
160 :s/^.*$/printf("&\\n");/
161 To remove printf:
162 :s/^printf("\(.*\)\\n");/\1/
163 */
164 printf("Fiz is used to help you recover data from a damaged archive. Fiz searches\n");
165 printf("the specified archive for directory entries and stored files, and prints the\n");
166 printf("position of each one found. Each directory entry contains a number that\n");
167 printf("represents the location in the archive where the file is stored; fiz also\n");
168 printf("prints this position. All numbers printed are decimal numbers.\n\n");
169
170 printf("Use Zoo version 2.00 or higher to list or extract files in the damaged\n");
171 printf("archive starting at a position identified by fiz. For example, you can\n");
172 printf("start extracting files from archive \"badarc.zoo\" at position 1098 with the\n");
173 printf("command:\n\n");
174
175 printf(" zoo x@1098 badarc\n\n");
176
177 printf("Zoo will ignore the first 1098 bytes of the damaged archive and you should be\n");
178 printf("able to recover the undamaged files from the rest of the archive. You can\n");
179 printf("also manually specify where to look for the file data with a command like\n\n");
180
181 printf(" zoo x@1098,1153\n\n");
182
183 printf("which tells zoo to use the directory entry at position 1098, but to get the\n");
184 printf("actual file data from position 1153 (and not from where the directory entry\n");
185 printf("says the data ought to be). See the manuals for fiz and zoo for more details.\n");
186
187 exit (0);
188 }
189
190 /*
191 prtctrl() prints a string with all unprintable characters converted
192 to printable form. To avoid the program running astray trying to
193 print damaged data, no more than MAXPRT characters are printed.
194 Characters with the 8th bit set are printed preceded with ~. Control
195 characters are printed preceded with ^. Both ~ and ^ may preced
196 the character if a control character has the 8th bit set.
197 */
198 #define MAXPRT 50
199
prtctrl(str)200 void prtctrl (str)
201 char *str;
202 {
203 unsigned int ch;
204 int count;
205 count = 0;
206
207 while (count < MAXPRT && *str != '\0') {
208 ch = (unsigned) *str;
209 prtch(ch);
210 str++;
211 count++;
212 }
213 }
214
215 /*
216 Does the actual character printing for prtctrl()
217 */
prtch(ch)218 void prtch(ch)
219 unsigned int ch;
220 {
221 /* assumes ASCII character set */
222 if (ch < ' ') { /* ^@ through ^_ */
223 printf("^%c", ch + 0x40);
224 } else if (ch == 0x7f) { /* DEL */
225 printf("^?");
226 } else if (ch > 0x7f) { /* 8th bit set */
227 printf("~"); /* .. so precede with ~ */
228 prtch(ch & 0x7f); /* slick recursive call */
229 } else
230 printf("%c", ch); /* plain char */
231 }
232