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