1 /* CCKDUTIL.C   (c) Copyright Greg Smith, 2000-2009                  */
2 /*              Compressed CKD Common routines                       */
3 
4 /*-------------------------------------------------------------------*/
5 /* This module contains functions for compressed CKD devices         */
6 /* used by more than 1 main program.                                 */
7 /*-------------------------------------------------------------------*/
8 
9 #include "hstdinc.h"
10 
11 #define _CCKDUTIL_C_
12 #define _HDASD_DLL_
13 
14 #include "hercules.h"
15 #include "opcode.h"
16 
17 /*-------------------------------------------------------------------*/
18 
19 typedef struct _SPCTAB {                /* Space table               */
20 BYTE            typ;                    /* Type of space             */
21 int             val;                    /* Value for space           */
22 U32             pos;                    /* Space offset              */
23 U32             len;                    /* Space length              */
24 U32             siz;                    /* Space size                */
25                } SPCTAB;
26 
27 #define SPCTAB_NONE     0               /* Ignore this space entry   */
28 #define SPCTAB_DEVHDR   1               /* Space is device header    */
29 #define SPCTAB_CDEVHDR  2               /* Space is compressed hdr   */
30 #define SPCTAB_L1       3               /* Space is level 1 table    */
31 #define SPCTAB_L2       4               /* Space is level 2 table    */
32 #define SPCTAB_TRK      5               /* Space is track image      */
33 #define SPCTAB_BLKGRP   6               /* Space is blkgrp image     */
34 #define SPCTAB_FREE     7               /* Space is free block       */
35 #define SPCTAB_EOF      8               /* Space is end-of-file      */
36 
37 /*-------------------------------------------------------------------*/
38 /* Internal functions                                                */
39 /*-------------------------------------------------------------------*/
40 static int  comp_spctab_sort(const void *a, const void *b);
41 static int  cdsk_spctab_sort(const void *a, const void *b);
42 static int  cdsk_build_free_space(SPCTAB *spctab, int s);
43 static int  cdsk_valid_trk (int trk, BYTE *buf, int heads, int len);
44 
45 /*-------------------------------------------------------------------*/
46 /* Static data areas                                                 */
47 /*-------------------------------------------------------------------*/
48 static BYTE  eighthexFF[] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
49 static char *spaces[] = { "none", "devhdr", "cdevhdr", "l1",  "l2",
50                           "trk",  "blkgrp", "free",    "eof" };
51 static char *comps[]  = { "none", "zlib",   "bzip2" };
52 
53 /*-------------------------------------------------------------------*/
54 /* Change the endianess of a compressed file                         */
55 /*-------------------------------------------------------------------*/
cckd_swapend(DEVBLK * dev)56 DLL_EXPORT int cckd_swapend (DEVBLK *dev)
57 {
58 CCKDDASD_EXT     *cckd;                 /* -> cckd extension         */
59 int               fd;                   /* File descriptor           */
60 int               rc;                   /* Return code               */
61 struct stat       fst;                  /* File status buffer        */
62 int               i;                    /* Index                     */
63 int               swapend;              /* 1=swap space              */
64 int               len;                  /* Length                    */
65 off_t             off, lopos, hipos;    /* File offsets              */
66 CCKD_DEVHDR       cdevhdr;              /* Compressed ckd header     */
67 CCKD_L1ENT       *l1 = NULL;            /* Level 1 table             */
68 CCKD_L2ENT        l2[256];              /* Level 2 table             */
69 CCKD_FREEBLK      freeblk;              /* Free block                */
70 
71     /* Get fd */
72     cckd = dev->cckd_ext;
73     if (cckd == NULL)
74         fd = dev->fd;
75     else
76         fd = cckd->fd[cckd->sfn];
77 
78     /* Get file size */
79     if (fstat (fd, &fst) < 0)
80         goto cswp_fstat_error;
81     hipos = fst.st_size;
82 
83     /* Device header */
84     off = CCKD_DEVHDR_POS;
85     if (lseek (fd, off, SEEK_SET) < 0)
86         goto cswp_lseek_error;
87     len = CCKD_DEVHDR_SIZE;
88     if ((rc = read (fd, &cdevhdr, len)) != len)
89         goto cswp_read_error;
90     swapend = (cdevhdr.options & CCKD_BIGENDIAN) != cckd_endian();
91     cckd_swapend_chdr (&cdevhdr);
92     cdevhdr.options |= CCKD_ORDWR;
93     if (lseek (fd, off, SEEK_SET) < 0)
94         goto cswp_lseek_error;
95     if ((rc = write (fd, &cdevhdr, len)) != len)
96         goto cswp_write_error;
97     if (!swapend) cckd_swapend_chdr (&cdevhdr);
98 
99     /* l1 table */
100     len = cdevhdr.numl1tab * CCKD_L1ENT_SIZE;
101     if ((l1 = malloc (len)) == NULL)
102         goto cswp_malloc_error;
103     off = CCKD_L1TAB_POS;
104     if (lseek (fd, off, SEEK_SET) < 0)
105         goto cswp_lseek_error;
106     if ((rc = read (fd, l1, len)) != len)
107         goto cswp_read_error;
108     cckd_swapend_l1 (l1, (int)cdevhdr.numl1tab);
109     if (lseek (fd, off, SEEK_SET) < 0)
110         goto cswp_lseek_error;
111     if ((rc = write (fd, l1, len)) != len)
112         goto cswp_write_error;
113     if (!swapend) cckd_swapend_l1 (l1, (int)cdevhdr.numl1tab);
114     lopos = CCKD_L1TAB_POS + len;
115 
116     /* l2 tables */
117     for (i = 0; i < cdevhdr.numl1tab; i++)
118     {
119         if (l1[i] == 0    || l1[i] == 0xffffffff
120          || l1[i] < lopos || l1[i] > hipos - CCKD_L2TAB_SIZE)
121             continue;
122         off = (off_t)l1[i];
123         if (lseek (fd, off, SEEK_SET) < 0)
124             goto cswp_lseek_error;
125         len = CCKD_L2TAB_SIZE;
126         if ((rc = read (fd, l2, len)) != len)
127             goto cswp_read_error;
128         cckd_swapend_l2 (l2);
129         if (lseek (fd, off, SEEK_SET) < 0)
130             goto cswp_lseek_error;
131         if ((rc = write (fd, l2, len)) != len)
132             goto cswp_write_error;
133     }
134 
135     free (l1);
136     l1 = NULL;
137 
138     /* free space */
139     if (cdevhdr.free && cdevhdr.free >= lopos
140      && cdevhdr.free <= hipos - CCKD_FREEBLK_SIZE)
141     {
142         off = (off_t)cdevhdr.free;
143         if (lseek (fd, off, SEEK_SET) < 0)
144             goto cswp_lseek_error;
145         len = CCKD_FREEBLK_SIZE;
146         if ((rc = read (fd, &freeblk, len)) != len)
147             goto cswp_read_error;
148         if (memcmp(&freeblk, "FREE_BLK", 8) == 0)
149         {
150             /* New format free space */
151             for (i = 0; i < cdevhdr.free_number; i++)
152             {
153                 off += CCKD_FREEBLK_SIZE;
154                 if (off > hipos - CCKD_FREEBLK_SIZE)
155                     break;
156                 if (lseek (fd, off, SEEK_SET) < 0)
157                     goto cswp_lseek_error;
158                 if ((rc = read (fd, &freeblk, len)) != len)
159                     goto cswp_read_error;
160                 cckd_swapend_free (&freeblk);
161                 if (lseek (fd, off, SEEK_SET) < 0)
162                     goto cswp_lseek_error;
163                 if ((rc = write (fd, &freeblk, len)) != len)
164                     goto cswp_write_error;
165             } /* for each free space */
166         } /* if new format free space */
167         else
168         {
169             /* Old format free space */
170             for (i = 0; i < cdevhdr.free_number; i++)
171             {
172                 if (off < lopos || off > hipos - CCKD_FREEBLK_SIZE)
173                     break;
174                 if (lseek (fd, off, SEEK_SET) < 0)
175                     goto cswp_lseek_error;
176                 if ((rc = read (fd, &freeblk, len)) != len)
177                     goto cswp_read_error;
178                 cckd_swapend_free (&freeblk);
179                 if (lseek (fd, off, SEEK_SET) < 0)
180                     goto cswp_lseek_error;
181                 if ((rc = write (fd, &freeblk, len)) != len)
182                     goto cswp_write_error;
183                 if (!swapend) cckd_swapend_free (&freeblk);
184                 off = (off_t)freeblk.pos;
185             } /* for each free space */
186         } /* else old format free space */
187     } /* if free space */
188 
189     return 0;
190 
191     /* error exits */
192 cswp_fstat_error:
193 
194     cckdumsg (dev, 701, "fstat error: %s\n", strerror(errno));
195     goto cswp_error;
196 
197 cswp_lseek_error:
198 
199     cckdumsg (dev, 702, "lseek error, offset 0x%" I64_FMT "x: %s\n",
200               (long long)off, strerror(errno));
201     goto cswp_error;
202 
203 cswp_read_error:
204 
205     cckdumsg (dev, 703, "read error rc=%d, offset 0x%" I64_FMT "x len %d: %s\n",
206               rc, (long long)off, len, rc < 0 ? strerror(errno) : "incomplete");
207     goto cswp_error;
208 
209 cswp_write_error:
210 
211     cckdumsg (dev, 704, "write error rc=%d, offset 0x%" I64_FMT "x len %d: %s\n",
212               rc, (long long)off, len, rc < 0 ? strerror(errno) : "incomplete");
213     goto cswp_error;
214 
215 cswp_malloc_error:
216 
217     cckdumsg (dev, 705, "malloc error, size %d: %s\n",
218               len, strerror(errno));
219     goto cswp_error;
220 
221 cswp_error:
222 
223     if (l1) free(l1);
224     return -1;
225 }
226 
227 /*-------------------------------------------------------------------*/
228 /* Swap endian - compressed device header                            */
229 /*-------------------------------------------------------------------*/
cckd_swapend_chdr(CCKD_DEVHDR * cdevhdr)230 DLL_EXPORT void cckd_swapend_chdr (CCKD_DEVHDR *cdevhdr)
231 {
232     /* fix the compressed ckd header */
233     cdevhdr->options ^= CCKD_BIGENDIAN;
234     cckd_swapend4 ((char *) &cdevhdr->numl1tab);
235     cckd_swapend4 ((char *) &cdevhdr->numl2tab);
236     cckd_swapend4 ((char *) &cdevhdr->size);
237     cckd_swapend4 ((char *) &cdevhdr->used);
238     cckd_swapend4 ((char *) &cdevhdr->free);
239     cckd_swapend4 ((char *) &cdevhdr->free_total);
240     cckd_swapend4 ((char *) &cdevhdr->free_largest);
241     cckd_swapend4 ((char *) &cdevhdr->free_number);
242     cckd_swapend4 ((char *) &cdevhdr->free_imbed);
243     cckd_swapend2 ((char *) &cdevhdr->compress_parm);
244 }
245 
246 /*-------------------------------------------------------------------*/
247 /* Swap endian - level 1 table                                       */
248 /*-------------------------------------------------------------------*/
cckd_swapend_l1(CCKD_L1ENT * l1,int n)249 DLL_EXPORT void cckd_swapend_l1 (CCKD_L1ENT *l1, int n)
250 {
251 int i;                                  /* Index                     */
252 
253     for (i = 0; i < n; i++)
254         cckd_swapend4 ((char *) &l1[i]);
255 }
256 
257 /*-------------------------------------------------------------------*/
258 /* Swap endian - level 2 table                                       */
259 /*-------------------------------------------------------------------*/
cckd_swapend_l2(CCKD_L2ENT * l2)260 DLL_EXPORT void cckd_swapend_l2 (CCKD_L2ENT *l2)
261 {
262 int i;                                  /* Index                     */
263 
264     for (i = 0; i < 256; i++)
265     {
266         cckd_swapend4 ((char *) &l2[i].pos);
267         cckd_swapend2 ((char *) &l2[i].len);
268         cckd_swapend2 ((char *) &l2[i].size);
269     }
270 }
271 
272 /*-------------------------------------------------------------------*/
273 /* Swap endian - free space entry                                    */
274 /*-------------------------------------------------------------------*/
cckd_swapend_free(CCKD_FREEBLK * fb)275 DLL_EXPORT void cckd_swapend_free (CCKD_FREEBLK *fb)
276 {
277     cckd_swapend4 ((char *) &fb->pos);
278     cckd_swapend4 ((char *) &fb->len);
279 }
280 
281 /*-------------------------------------------------------------------*/
282 /* Swap endian - 4 bytes                                             */
283 /*-------------------------------------------------------------------*/
cckd_swapend4(char * c)284 DLL_EXPORT void cckd_swapend4 (char *c)
285 {
286  char temp[4];
287 
288     memcpy (&temp, c, 4);
289     c[0] = temp[3];
290     c[1] = temp[2];
291     c[2] = temp[1];
292     c[3] = temp[0];
293 }
294 
295 /*-------------------------------------------------------------------*/
296 /* Swap endian - 2 bytes                                             */
297 /*-------------------------------------------------------------------*/
cckd_swapend2(char * c)298 DLL_EXPORT void cckd_swapend2 (char *c)
299 {
300  char temp[2];
301 
302     memcpy (&temp, c, 2);
303     c[0] = temp[1];
304     c[1] = temp[0];
305 }
306 
307 /*-------------------------------------------------------------------*/
308 /* Are we little or big endian?  From Harbison&Steele.               */
309 /*-------------------------------------------------------------------*/
cckd_endian()310 DLL_EXPORT int cckd_endian()
311 {
312 union
313 {
314     long l;
315     char c[sizeof (long)];
316 }   u;
317 
318     u.l = 1;
319     return u.c[sizeof (long) - 1] == 1 ? CCKD_BIGENDIAN : 0;
320 }
321 
322 /*-------------------------------------------------------------------
323  * Remove all free space from a compressed ckd file
324  *-------------------------------------------------------------------*/
cckd_comp(DEVBLK * dev)325 DLL_EXPORT int cckd_comp (DEVBLK *dev)
326 {
327 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
328 int             fd;                     /* File descriptor           */
329 struct stat     fst;                    /* File status buffer        */
330 long long       maxsize;                /* Max cckd file size        */
331 int             rc;                     /* Return code               */
332 off_t           off;                    /* File offset               */
333 off_t           l2area;                 /* Boundary for l2 tables    */
334 int             len;                    /* Length                    */
335 int             i, j, l, n;             /* Work variables            */
336 int             relocate = 0;           /* 1=spaces will be relocated*/
337 int             l1size;                 /* l1 table size             */
338 U32             next;                   /* offset of next space      */
339 int             s;                      /* space table index         */
340 CKDDASD_DEVHDR  devhdr;                 /* CKD device header         */
341 CCKD_DEVHDR     cdevhdr;                /* CCKD device header        */
342 CCKD_L1ENT     *l1=NULL;                /* -> l1 table               */
343 CCKD_L2ENT    **l2=NULL;                /* -> l2 table array         */
344 SPCTAB         *spctab=NULL;            /* -> space table            */
345 BYTE           *rbuf=NULL;              /* Relocation buffer         */
346 BYTE           *p;                      /* -> relocation buffer      */
347 int             rlen=0;                 /* Relocation buffer length  */
348 CCKD_L2ENT      zero_l2[256];           /* Empty l2 table (zeros)    */
349 CCKD_L2ENT      ff_l2[256];             /* Empty l2 table (0xff's)   */
350 BYTE            buf[65536*4];           /* Buffer                    */
351 
352     /*---------------------------------------------------------------
353      * Get fd
354      *---------------------------------------------------------------*/
355     cckd = dev->cckd_ext;
356     if (cckd == NULL)
357         fd = dev->fd;
358     else
359         fd = cckd->fd[cckd->sfn];
360 
361     /*---------------------------------------------------------------
362      * Get file statistics
363      *---------------------------------------------------------------*/
364     if (fstat (fd, &fst) < 0)
365         goto comp_fstat_error;
366     maxsize = sizeof(off_t) == 4 ? 0x7fffffffll : 0xffffffffll;
367 
368     /*---------------------------------------------------------------
369      * Read device header
370      *---------------------------------------------------------------*/
371     off = 0;
372     if (lseek (fd, off, SEEK_SET) < 0)
373         goto comp_lseek_error;
374     len = CKDDASD_DEVHDR_SIZE;
375     if ((rc = read (fd, &devhdr, len)) != len)
376         goto comp_read_error;
377     if (memcmp (devhdr.devid, "CKD_C370", 8) != 0
378      && memcmp (devhdr.devid, "CKD_S370", 8) != 0
379      && memcmp (devhdr.devid, "FBA_C370", 8) != 0
380      && memcmp (devhdr.devid, "FBA_S370", 8) != 0)
381     {
382         cckdumsg (dev, 999, "not a compressed dasd file\n");
383         goto comp_error;
384     }
385 
386 comp_restart:
387 
388     /*---------------------------------------------------------------
389      * Read compressed device header
390      *---------------------------------------------------------------*/
391     off = CCKD_DEVHDR_POS;
392     if (lseek (fd, off, SEEK_SET) < 0)
393         goto comp_lseek_error;
394     len = CCKD_DEVHDR_SIZE;
395     if ((rc = read (fd, &cdevhdr, len)) != len)
396         goto comp_read_error;
397 
398     /*---------------------------------------------------------------
399      * Check the endianess of the file
400      *---------------------------------------------------------------*/
401     if ((cdevhdr.options & CCKD_BIGENDIAN) != cckd_endian())
402     {
403         cckdumsg (dev, 101, "converting to %s\n",
404                   cckd_endian() ? "big-endian" : "little-endian");
405         if (cckd_swapend (dev) < 0)
406             goto comp_error;
407         else
408             goto comp_restart;
409     }
410 
411     /*---------------------------------------------------------------
412      * Some header checks
413      *---------------------------------------------------------------*/
414     if ((off_t)cdevhdr.size != fst.st_size
415      || cdevhdr.size != cdevhdr.used || cdevhdr.free != 0
416      || cdevhdr.free_total != 0      || cdevhdr.free_largest != 0
417      || cdevhdr.free_number != 0     || cdevhdr.free_imbed != 0)
418         relocate = 1;
419 
420     /*---------------------------------------------------------------
421      * Build empty l2 tables
422      *---------------------------------------------------------------*/
423     memset (&zero_l2, 0, CCKD_L2TAB_SIZE);
424     if (cdevhdr.nullfmt != 0)
425         for (i = 0; i < 256; i++)
426             zero_l2[i].len = zero_l2[i].size = cdevhdr.nullfmt;
427     memset (&ff_l2, 0xff, CCKD_L2TAB_SIZE);
428 
429     /*---------------------------------------------------------------
430      * Read the l1 table
431      *---------------------------------------------------------------*/
432     l1size = len = cdevhdr.numl1tab * CCKD_L1ENT_SIZE;
433     if ((l1 = malloc (len)) == NULL)
434         goto comp_malloc_error;
435     off = CCKD_L1TAB_POS;
436     if (lseek (fd, off, SEEK_SET) < 0)
437         goto comp_lseek_error;
438     if ((rc = read (fd, l1, len)) != len)
439         goto comp_read_error;
440 
441     /*---------------------------------------------------------------
442      * Build the space table
443      *---------------------------------------------------------------*/
444     n = 1 + 1 + 1 + cdevhdr.numl1tab + 1;
445     for (i = 0; i < cdevhdr.numl1tab; i++)
446         if (l1[i] != 0 && l1[i] != 0xffffffff)
447             n += 256;
448     len = sizeof(SPCTAB);
449     if ((spctab = calloc (n, len)) == NULL)
450         goto comp_calloc_error;
451     s = 0;
452     spctab[s].typ = SPCTAB_DEVHDR;
453     spctab[s].val = -1;
454     spctab[s].pos = 0;
455     spctab[s].len =
456     spctab[s].siz = CKDDASD_DEVHDR_SIZE;
457     s++;
458     spctab[s].typ = SPCTAB_CDEVHDR;
459     spctab[s].val = -1;
460     spctab[s].pos = CCKD_DEVHDR_POS;
461     spctab[s].len =
462     spctab[s].siz = CCKD_DEVHDR_SIZE;
463     s++;
464     spctab[s].typ = SPCTAB_L1;
465     spctab[s].val = -1;
466     spctab[s].pos = CCKD_L1TAB_POS;
467     spctab[s].len =
468     spctab[s].siz = l1size;
469     s++;
470     spctab[s].typ = SPCTAB_EOF;
471     spctab[s].val = -1;
472     spctab[s].pos = fst.st_size;
473     spctab[s].len =
474     spctab[s].siz = 0;
475     s++;
476 
477     for (i = 0; i < cdevhdr.numl1tab; i++)
478         if (l1[i] != 0 && l1[i] != 0xffffffff)
479         {
480             spctab[s].typ = SPCTAB_L2;
481             spctab[s].val = i;
482             spctab[s].pos = l1[i];
483             spctab[s].len =
484             spctab[s].siz = CCKD_L2TAB_SIZE;
485             s++;
486         }
487     qsort (spctab, s, sizeof(SPCTAB), comp_spctab_sort);
488 
489     /*---------------------------------------------------------------
490      * Read level 2 tables
491      *---------------------------------------------------------------*/
492     n = cdevhdr.numl1tab;
493     len = sizeof (void *);
494     if ((l2 = calloc (n, len)) == NULL)
495         goto comp_calloc_error;
496     for (i = 0; spctab[i].typ != SPCTAB_EOF; i++)
497     {
498         if (spctab[i].typ != SPCTAB_L2) continue;
499         l = spctab[i].val;
500         len = CCKD_L2TAB_SIZE;
501         if ((l2[l] = malloc (len)) == NULL)
502             goto comp_malloc_error;
503         off = (off_t)spctab[i].pos;
504         if (lseek (fd, off, SEEK_SET) < 0)
505             goto comp_lseek_error;
506         if ((rc = read (fd, l2[l], len)) != len)
507             goto comp_read_error;
508         for (j = 0; j < 256; j++)
509         {
510             if (l2[l][j].pos == 0 || l2[l][j].pos == 0xffffffff)
511                 continue;
512             spctab[s].typ = SPCTAB_TRK;
513             spctab[s].val = spctab[i].val*256 + j;
514             spctab[s].pos = l2[l][j].pos;
515             spctab[s].len = l2[l][j].len;
516             spctab[s].siz = l2[l][j].size;
517             s++;
518         } /* for each l2 entry */
519         /* check if empty l2 table */
520         if (memcmp (l2[l], &zero_l2, CCKD_L2TAB_SIZE) == 0
521          || memcmp (l2[l], &ff_l2,   CCKD_L2TAB_SIZE) == 0)
522         {
523             l1[l] = l2[l][0].pos; /* 0x00000000 or 0xffffffff */
524             spctab[i].typ = SPCTAB_NONE;
525             free (l2[l]);
526             l2[l] = NULL;
527             relocate = 1;
528         }
529     } /* for each space */
530     qsort (spctab, s, sizeof(SPCTAB), comp_spctab_sort);
531     while (spctab[s-1].typ == SPCTAB_NONE) s--;
532     /* set relocate flag if last space is free space */
533     if (spctab[s-2].pos + spctab[s-2].len != spctab[s-1].pos)
534         relocate = 1;
535 
536     /*---------------------------------------------------------------
537      * relocate l2 tables in order
538      *---------------------------------------------------------------*/
539 
540     /* determine l2 area */
541     l2area = CCKD_L1TAB_POS + l1size;
542     for (i = 0; i < cdevhdr.numl1tab; i++)
543     {
544         if (l1[i] == 0 || l1[i] == 0xffffffff) continue;
545         if (l1[i] != l2area)
546             relocate = 1;
547         l2area += CCKD_L2TAB_SIZE;
548     }
549 
550     /* quick return if all l2 tables are orderered and no free space */
551     if (!relocate)
552     {
553         for (i = 1; spctab[i].typ != SPCTAB_EOF; i++)
554             if (spctab[i-1].pos + spctab[i-1].len != spctab[i].pos)
555                 break;
556         if (spctab[i].typ == SPCTAB_EOF)
557         {
558             cckdumsg (dev, 103, "file already compressed\n");
559             goto comp_return_ok;
560         }
561     }
562 
563     /* file will be updated */
564     cdevhdr.options |= CCKD_ORDWR;
565 
566     /* calculate track size within the l2 area */
567     for (i = rlen = 0; spctab[i].pos < l2area; i++)
568         if (spctab[i].typ == SPCTAB_TRK)
569             rlen += sizeof(spctab[i].val) + sizeof(spctab[i].len)
570                  +  spctab[i].len;
571 
572     /* read any tracks in the l2area into rbuf */
573     if ((len = rlen) > 0)
574     {
575         if ((rbuf = malloc (len)) == NULL)
576             goto comp_malloc_error;
577         for (i = 0, p = rbuf; spctab[i].pos < l2area; i++)
578         {
579             if (spctab[i].typ != SPCTAB_TRK) continue;
580             memcpy (p, &spctab[i].val, sizeof(spctab[i].val));
581             p += sizeof(spctab[i].val);
582             memcpy (p, &spctab[i].len, sizeof(spctab[i].len));
583             p += sizeof(spctab[i].len);
584             off = (off_t)spctab[i].pos;
585             if (lseek (fd, off, SEEK_SET) < 0)
586                 goto comp_lseek_error;
587             len = spctab[i].len;
588             if ((rc = read (fd, p, len)) != len)
589                 goto comp_read_error;
590             p += len;
591             spctab[i].typ = SPCTAB_NONE;
592         } /* for each space in the l2 area */
593         qsort (spctab, s, sizeof(SPCTAB), comp_spctab_sort);
594         while (spctab[s-1].typ == SPCTAB_NONE) s--;
595     } /* if any tracks to relocate */
596 
597     /* remove all l2 tables from the space table */
598     for (i = 0; spctab[i].typ != SPCTAB_EOF; i++)
599         if (spctab[i].typ == SPCTAB_L2)
600             spctab[i].typ = SPCTAB_NONE;
601     qsort (spctab, s, sizeof(SPCTAB), comp_spctab_sort);
602     while (spctab[s-1].typ == SPCTAB_NONE) s--;
603 
604     /* add all l2 tables at their ordered offsets */
605     off = CCKD_L1TAB_POS + l1size;
606     for (i = 0; i < cdevhdr.numl1tab; i++)
607     {
608         if (l1[i] == 0 || l1[i] == 0xffffffff) continue;
609         spctab[s].typ = SPCTAB_L2;
610         spctab[s].val = i;
611         spctab[s].pos = (U32)off;
612         spctab[s].len =
613         spctab[s].siz = CCKD_L2TAB_SIZE;
614         s++;
615         off += CCKD_L2TAB_SIZE;
616     }
617     qsort (spctab, s, sizeof(SPCTAB), comp_spctab_sort);
618     /* set end-of-file position */
619     spctab[s-1].pos = spctab[s-2].pos + spctab[s-2].len;
620 
621     /*---------------------------------------------------------------
622      * Perform compression
623      *---------------------------------------------------------------*/
624 
625     /* move spaces left */
626     for (i = 0; spctab[i].typ != SPCTAB_EOF; i++)
627     {
628         /* ignore contiguous spaces */
629         if (spctab[i].pos + spctab[i].len == spctab[i+1].pos)
630             continue;
631 
632         /* found a gap */
633         off = (off_t)spctab[i+1].pos;
634 
635         /* figure out how much we can read */
636         for (len = 0, j = i + 1; spctab[j].typ != SPCTAB_EOF; j++)
637         {
638             if (len + spctab[j].len > sizeof(buf))
639                 break;
640             next = spctab[j].pos + spctab[j].len;
641             spctab[j].pos = spctab[i].pos + spctab[i].len + len;
642             spctab[j].siz = spctab[j].len;
643             len += spctab[j].len;
644             if (next != spctab[j+1].pos)
645                 break;
646         } /* search for contiguous spaces */
647 
648         /* this can happen if the next space is end-of-file */
649         if (len == 0)
650             continue;
651 
652         /* read the image(s) to be relocated */
653         if (lseek (fd, off, SEEK_SET) < 0)
654             goto comp_lseek_error;
655         if ((rc = read (fd, buf, len)) != len)
656             goto comp_write_error;
657 
658         /* write the images */
659         off = (off_t)spctab[i].pos + spctab[i].len;
660         if (lseek (fd, off, SEEK_SET) < 0)
661             goto comp_lseek_error;
662         if ((rc = write (fd, buf, len)) != len)
663             goto comp_write_error;
664     }
665 
666     /* adjust the size of the file */
667     spctab[s-1].pos = spctab[s-2].pos + spctab[s-2].len;
668 
669     /*---------------------------------------------------------------
670      * Write spaces relocated from the l2area to the end of the file
671      *---------------------------------------------------------------*/
672     off = (off_t)spctab[s-1].pos;
673     p = rbuf;
674     while (rlen)
675     {
676         spctab[s].typ = SPCTAB_TRK;
677         spctab[s].pos = (U32)off;
678         memcpy (&spctab[s].val, p, sizeof(spctab[s].val));
679         p += sizeof(spctab[s].val);
680         memcpy (&spctab[s].len, p, sizeof(spctab[s].len));
681         spctab[s].siz = spctab[s].len;
682         p += sizeof(spctab[s].len);
683 
684         if (lseek (fd, off, SEEK_SET) < 0)
685             goto comp_lseek_error;
686         len = spctab[s].len;
687         if ((rc = write (fd, p, len)) != len)
688             goto comp_write_error;
689 
690         p += len;
691         off += len;
692         rlen -= len + sizeof(spctab[s].val) + sizeof(spctab[s].len);
693         s++;
694     } /* for each relocated space in l2area */
695 
696     /* adjust the space table */
697     if (rbuf)
698     {
699         free (rbuf); rbuf = NULL;
700         qsort (spctab, s, sizeof(SPCTAB), comp_spctab_sort);
701         spctab[s-1].pos = spctab[s-2].pos + spctab[s-2].len;
702     }
703 
704     /*---------------------------------------------------------------
705      * Update the device header
706      *---------------------------------------------------------------*/
707     cdevhdr.size =
708     cdevhdr.used = spctab[s-1].pos;
709     cdevhdr.free =
710     cdevhdr.free_total =
711     cdevhdr.free_largest =
712     cdevhdr.free_number =
713     cdevhdr.free_imbed = 0;
714     cdevhdr.vrm[0] = CCKD_VERSION;
715     cdevhdr.vrm[1] = CCKD_RELEASE;
716     cdevhdr.vrm[2] = CCKD_MODLVL;
717 
718     /*---------------------------------------------------------------
719      * Update the lookup tables
720      *---------------------------------------------------------------*/
721     for (i = 0; spctab[i].typ != SPCTAB_EOF; i++)
722         if (spctab[i].typ == SPCTAB_L2)
723             l1[spctab[i].val] = spctab[i].pos;
724         else if (spctab[i].typ == SPCTAB_TRK)
725         {
726             l = spctab[i].val / 256;
727             j = spctab[i].val % 256;
728             l2[l][j].pos  = spctab[i].pos;
729             l2[l][j].len  =
730             l2[l][j].size = spctab[i].len;
731         }
732 
733     /*---------------------------------------------------------------
734      * Write the cdevhdr, l1 table and l2 tables
735      *---------------------------------------------------------------*/
736 
737     /* write cdevhdr */
738     off = CCKD_DEVHDR_POS;
739     if (lseek (fd, off, SEEK_SET) < 0)
740         goto comp_lseek_error;
741     len = CCKD_DEVHDR_SIZE;
742     if ((rc = write (fd, &cdevhdr, len)) != len)
743         goto comp_write_error;
744 
745     /* write l1 table */
746     off = CCKD_L1TAB_POS;
747     if (lseek (fd, off, SEEK_SET) < 0)
748         goto comp_lseek_error;
749     len = l1size;
750     if ((rc = write (fd, l1, len)) != len)
751         goto comp_write_error;
752 
753     /* write l2 tables */
754     for (i = 0; i < cdevhdr.numl1tab; i++)
755         if (l1[i] != 0 && l1[i] != 0xffffffff)
756         {
757             off = (off_t)l1[i];
758             if (lseek (fd, off, SEEK_SET) < 0)
759                 goto comp_lseek_error;
760             len = CCKD_L2TAB_SIZE;
761             if ((rc = write (fd, l2[i], len)) != len)
762                 goto comp_lseek_error;
763         }
764 
765     /* truncate the file */
766     off = (off_t)spctab[s-1].pos;
767     if (off < fst.st_size)
768     {
769         ftruncate (fd, off);
770         cckdumsg (dev, 102, "compress successful, %lld bytes released\n",
771               (long long)fst.st_size - off);
772     }
773     else
774         cckdumsg (dev, 102, "compress successful, L2 tables relocated\n");
775 
776     /*---------------------------------------------------------------
777      * Return
778      *---------------------------------------------------------------*/
779 
780 comp_return_ok:
781 
782     rc = 0;
783 
784 comp_return:
785 
786     if (rbuf) free(rbuf);
787     if (l2)
788     {
789         for (i = 0; i < cdevhdr.numl1tab; i++)
790             if (l2[i])
791                 free (l2[i]);
792         free (l2);
793     }
794     if (l1) free (l1);
795     if (spctab) free (spctab);
796 
797     return rc;
798 
799     /*---------------------------------------------------------------
800      * Error exits
801      *---------------------------------------------------------------*/
802 
803 comp_fstat_error:
804 
805     cckdumsg (dev, 701, "fstat error: %s\n",
806               strerror(errno));
807     goto comp_error;
808 
809 comp_lseek_error:
810 
811     cckdumsg (dev, 702, "lseek error, offset 0x%" I64_FMT "x: %s\n",
812               (long long)off, strerror(errno));
813     goto comp_error;
814 
815 comp_read_error:
816 
817     cckdumsg (dev, 703, "read error rc=%d, offset 0x%" I64_FMT "x len %d: %s\n",
818               rc, (long long)off, len, rc < 0 ? strerror(errno) : "incomplete");
819     goto comp_error;
820 
821 comp_write_error:
822 
823     cckdumsg (dev, 704, "write error rc=%d, offset 0x%" I64_FMT "x len %d: %s\n",
824               rc, (long long)off, len, rc < 0 ? strerror(errno) : "incomplete");
825     goto comp_error;
826 
827 comp_malloc_error:
828 
829     cckdumsg (dev, 705, "malloc error, size %d: %s\n",
830               len, strerror(errno));
831     goto comp_error;
832 
833 comp_calloc_error:
834 
835     cckdumsg (dev, 706, "calloc error, size %d: %s\n",
836               n*len, strerror(errno));
837     goto comp_error;
838 
839 comp_error:
840 
841     rc = -1;
842     goto comp_return;
843 
844 } /* cckd_comp() */
845 
846 /*-------------------------------------------------------------------
847  * cckd_comp() space table sort
848  *-------------------------------------------------------------------*/
comp_spctab_sort(const void * a,const void * b)849 static int comp_spctab_sort(const void *a, const void *b)
850 {
851 const SPCTAB *x = a, *y = b;
852 
853     if (x->typ == SPCTAB_NONE)      return  1;
854     else if (y->typ == SPCTAB_NONE) return -1;
855     else if (x->typ == SPCTAB_EOF)  return  1;
856     else if (y->typ == SPCTAB_EOF)  return -1;
857     else if (x->pos < y->pos)       return -1;
858     else                            return  1;
859 }
860 
861 /*-------------------------------------------------------------------
862  * Perform check function on a compressed ckd file
863  *
864  * check levels
865  *    -1 devhdr, cdevhdr, l1 table
866  *     0 devhdr, cdevhdr, l1 table, l2 tables
867  *     1 devhdr, cdevhdr, l1 table, l2 tables, free spaces
868  *     2 devhdr, cdevhdr, l1 table, l2 tables, free spaces, trkhdrs
869  *     3 devhdr, cdevhdr, l1 table, l2 tables, free spaces, trkimgs
870  *     4 devhdr, cdevhdr. Build everything else from recovery
871  *-------------------------------------------------------------------*/
cckd_chkdsk(DEVBLK * dev,int level)872 DLL_EXPORT int cckd_chkdsk(DEVBLK *dev, int level)
873 {
874 CCKDDASD_EXT   *cckd;                   /* -> ckd extension          */
875 int             fd;                     /* file descriptor           */
876 struct stat     fst;                    /* file status information   */
877 int             fdflags;                /* file descriptor flags     */
878 long long       maxsize;                /* max cckd file size        */
879 int             ro;                     /* 1=file opened read-only   */
880 int             f, i, j, l, n;          /* work integers             */
881 int             l1x, l2x;               /* l1, l2 table indexes      */
882 BYTE            compmask[256];          /* compression byte mask
883                                            00 - supported
884                                            0x - valid, not supported
885                                            ff - invalid              */
886 off_t           off;                    /* file offset               */
887 int             len;                    /* length to read            */
888 int             rc;                     /* function return code      */
889 int             comp;                   /* trkhdr compression byte[0]*/
890 int             cyl;                    /* trkhdr cyl      bytes[1-2]*/
891 int             head;                   /* trkhdr head     bytes[3-4]*/
892 int             trk;                    /* trkhdr calculated trk     */
893 int             cyls;                   /* number cylinders          */
894 int             heads;                  /* number heads/cylinder     */
895 int             trks;                   /* number tracks             */
896 unsigned int    trksz;                  /* track size                */
897 int             blks;                   /* number fba blocks         */
898 int             blkgrp;                 /* current block group nbr   */
899 int             blkgrps;                /* number fba block groups   */
900 unsigned int    blkgrpsz;               /* fba block group size      */
901 int             trktyp;                 /* track type (TRK, BLKGRP)  */
902 int             ckddasd=0;              /* 1=ckd                     */
903 int             fbadasd=0;              /* 1= fba                    */
904 int             shadow=0;               /* 0xff=shadow file          */
905 int             hdrerr=0;               /* non-zero: header errors   */
906 int             fsperr=0;               /* 1=rebuild free space      */
907 int             comperrs=0;             /* 1=unsupported comp found  */
908 int             recovery=0;             /* 1=perform track recovery  */
909 int             valid;                  /* 1=valid trk recovered     */
910 int             l1size;                 /* size of l1 table          */
911 int             swapend=0;              /* 1=call cckd_swapend       */
912 U32             lopos, hipos;           /* low/high file positions   */
913 int             pass;                   /* recovery pass number (fba)*/
914 int             s;                      /* space table index         */
915 SPCTAB         *spctab=NULL;            /* -> space table            */
916 BYTE           *l2errs=NULL;            /* l2 error table            */
917 BYTE           *rcvtab=NULL;            /* recovered tracks          */
918 CKDDASD_DEVHDR  devhdr;                 /* device header             */
919 CCKD_DEVHDR     cdevhdr;                /* compressed device header  */
920 CCKD_DEVHDR     cdevhdr2;               /* compressed device header 2*/
921 CCKD_L1ENT     *l1=NULL;                /* -> level 1 table          */
922 CCKD_L2ENT      l2ent;                  /* level 2 entry             */
923 CCKD_L2ENT      l2tab[256];             /* level 2 table             */
924 CCKD_L2ENT    **l2=NULL;                /* -> level 2 table array    */
925 CCKD_L2ENT      empty_l2[256];          /* Empty l2 table            */
926 CCKD_FREEBLK    freeblk;                /* free block                */
927 CCKD_FREEBLK   *fsp=NULL;               /* free blocks (new format)  */
928 BYTE            buf[4*65536];           /* buffer                    */
929 
930     /* Get fd */
931     cckd = dev->cckd_ext;
932     if (cckd == NULL)
933         fd = dev->fd;
934     else
935         fd = cckd->fd[cckd->sfn];
936 
937     /* Get some file information */
938     if ( fstat (fd, &fst) < 0 )
939         goto cdsk_fstat_error;
940     hipos = fst.st_size;
941     maxsize = sizeof(off_t) == 4 ? 0x7fffffffll : 0xffffffffll;
942     fdflags = get_file_accmode_flags(fd);
943     ro = (fdflags & O_RDWR) == 0;
944 
945     /* Build table for compression byte test */
946     memset (compmask, 0xff, 256);
947     compmask[0] = 0;
948 #if defined(HAVE_LIBZ)
949     compmask[CCKD_COMPRESS_ZLIB] = 0;
950 #else
951     compmask[CCKD_COMPRESS_ZLIB] = 1;
952 #endif
953 #if defined(CCKD_BZIP2)
954     compmask[CCKD_COMPRESS_BZIP2] = 0;
955 #else
956     compmask[CCKD_COMPRESS_BZIP2] = 2;
957 #endif
958 
959     /*---------------------------------------------------------------
960      * Header checks
961      *---------------------------------------------------------------*/
962 
963     /* Read the device header */
964     off = 0;
965     if ( lseek (fd, off, SEEK_SET) < 0)
966         goto cdsk_lseek_error;
967 
968     len = CKDDASD_DEVHDR_SIZE;
969     if ((rc = read (fd, &devhdr, len)) != len)
970         goto cdsk_read_error;
971 
972     /* Device header checks */
973     if (memcmp(devhdr.devid, "CKD_C370", 8) == 0
974      || memcmp(devhdr.devid, "CKD_S370", 8) == 0
975        )
976         ckddasd = 1;
977     else if (memcmp(devhdr.devid, "FBA_C370", 8) == 0
978           || memcmp(devhdr.devid, "FBA_S370", 8) == 0
979             )
980         fbadasd = 1;
981     else
982     {
983         cckdumsg (dev, 999, "not a compressed dasd file\n");
984         goto cdsk_error;
985     }
986     if (memcmp(devhdr.devid, "CKD_S370", 8) == 0
987      || memcmp(devhdr.devid, "FBA_S370", 8) == 0
988        )
989         shadow = 0xff;
990 
991     trktyp = ckddasd ? SPCTAB_TRK : SPCTAB_BLKGRP;
992 
993     /* Read the cckd device header */
994     off = CCKD_DEVHDR_POS;
995     if ( lseek (fd, off, SEEK_SET) < 0)
996         goto cdsk_lseek_error;
997 
998     len = CCKD_DEVHDR_SIZE;
999     if ((rc = read (fd, &cdevhdr, len)) != len)
1000         goto cdsk_read_error;
1001 
1002     /* Endianess check */
1003     if ((cdevhdr.options & CCKD_BIGENDIAN) != cckd_endian())
1004     {
1005         if (!ro)
1006         {
1007             cckdumsg (dev, 101, "converting to %s\n",
1008                       cckd_endian() ? "big-endian" : "little-endian");
1009             if (cckd_swapend (dev) < 0)
1010                 goto cdsk_error;
1011             if (level < 0) level = 0;
1012             swapend = 0;
1013         }
1014         else
1015             swapend = 1;
1016         cckd_swapend_chdr (&cdevhdr);
1017     }
1018 
1019     /* ckd checks */
1020     if (ckddasd)
1021     {
1022         CKDDEV *ckd;
1023 
1024         heads = (devhdr.heads[3] << 24)
1025               + (devhdr.heads[2] << 16)
1026               + (devhdr.heads[1] <<  8)
1027               + (devhdr.heads[0]);
1028         cyls  = (cdevhdr.cyls[3] << 24)
1029               + (cdevhdr.cyls[2] << 16)
1030               + (cdevhdr.cyls[1] <<  8)
1031               + (cdevhdr.cyls[0]);
1032         trks  = heads * cyls;
1033         trksz = (devhdr.trksize[3] << 24)
1034               + (devhdr.trksize[2] << 16)
1035               + (devhdr.trksize[1] <<  8)
1036               + (devhdr.trksize[0]);
1037 
1038         /* ckd dasd lookup */
1039         ckd = dasd_lookup (DASD_CKDDEV, NULL, devhdr.devtype, cyls);
1040         if (ckd == NULL)
1041         {
1042              cckdumsg (dev, 900, "dasd lookup error type=%2.2X cyls=%d\n",
1043                        devhdr.devtype, cyls);
1044              goto cdsk_error;
1045         }
1046 
1047         /* track size check */
1048         n = sizeof(CKDDASD_TRKHDR)
1049           + sizeof(CKDDASD_RECHDR) + 8        /* r0 length */
1050           + sizeof(CKDDASD_RECHDR) + ckd->r1  /* max data length */
1051           + sizeof(eighthexFF);
1052         n = ((n+511)/512)*512;
1053         if ((int)trksz != n)
1054         {
1055              cckdumsg (dev, 901, "bad trksize: %d, expecting %d\n",
1056                             trksz, n);
1057              goto cdsk_error;
1058         }
1059 
1060         /* number of heads check */
1061         if (heads != ckd->heads)
1062         {
1063              cckdumsg (dev, 902, "bad number of heads: %d, expecting %d\n",
1064                             heads, ckd->heads);
1065              goto cdsk_error;
1066         }
1067     } /* if (ckddasd) */
1068 
1069     /* fba checks */
1070     else
1071     {
1072         /* Note: cyls & heads are setup for ckd type hdr checks */
1073         blks = (cdevhdr.cyls[3] << 24)
1074              + (cdevhdr.cyls[2] << 16)
1075              + (cdevhdr.cyls[1] <<  8)
1076              + (cdevhdr.cyls[0]);
1077         trks = blks / CFBA_BLOCK_NUM;
1078         if (blks % CFBA_BLOCK_NUM) trks++;
1079         trksz = CFBA_BLOCK_SIZE + CKDDASD_TRKHDR_SIZE;
1080         heads = 65536;
1081         cyls = trks / heads;
1082         if (trks % heads) cyls++;
1083     }
1084 
1085     /* fba variables */
1086     blkgrps = trks;
1087     blkgrpsz = trksz;
1088 
1089     /* `numl1tab' check */
1090     n = trks / 256;
1091     if (trks % 256) n++;
1092 
1093     if (cdevhdr.numl1tab != n && cdevhdr.numl1tab != n + 1)
1094     {
1095         cckdumsg (dev, 903, "bad `numl1tab': %d, expecting %d\n",
1096                   cdevhdr.numl1tab, n);
1097         goto cdsk_error;
1098     }
1099     l1size = cdevhdr.numl1tab * CCKD_L1ENT_SIZE;
1100     if (CCKD_L1TAB_POS + l1size > fst.st_size)
1101     {
1102         cckdumsg (dev, 904, "file too small to contain L1 table: %d, need %d",
1103                   fst.st_size, CCKD_L1TAB_POS + l1size);
1104         goto cdsk_error;
1105     }
1106 
1107     /* check level 2 if SPERRS bit on */
1108     if (!ro && level < 2 && (cdevhdr.options & CCKD_SPERRS))
1109     {
1110         level = 2;
1111         cckdumsg (dev, 600, "forcing check level %d; space error bit on\n", level);
1112     }
1113 
1114     /* cdevhdr inconsistencies check */
1115     hdrerr  = 0;
1116     hdrerr |= fst.st_size  != (off_t)cdevhdr.size && cdevhdr.size != cdevhdr.free  ? 0x0001 : 0;
1117     hdrerr |= cdevhdr.size != cdevhdr.used + cdevhdr.free_total                    ? 0x0002 : 0;
1118     hdrerr |= cdevhdr.free_largest > cdevhdr.free_total - cdevhdr.free_imbed       ? 0x0004 : 0;
1119     hdrerr |= cdevhdr.free == 0 && cdevhdr.free_number != 0                        ? 0x0008 : 0;
1120     hdrerr |= cdevhdr.free == 0 && cdevhdr.free_total  != cdevhdr.free_imbed       ? 0x0010 : 0;
1121     hdrerr |= cdevhdr.free != 0 && cdevhdr.free_total  == 0                        ? 0x0020 : 0;
1122     hdrerr |= cdevhdr.free != 0 && cdevhdr.free_number == 0                        ? 0x0040 : 0;
1123     hdrerr |= cdevhdr.free_number == 0 && cdevhdr.free_total != cdevhdr.free_imbed ? 0x0080 : 0;
1124     hdrerr |= cdevhdr.free_number != 0 && cdevhdr.free_total <= cdevhdr.free_imbed ? 0x0100 : 0;
1125     hdrerr |= cdevhdr.free_imbed > cdevhdr.free_total                              ? 0x0200 : 0;
1126 
1127     /* Additional checking if header errors */
1128     if (hdrerr != 0)
1129     {
1130         cckdumsg (dev, 601, "cdevhdr inconsistencies found, code=%4.4x\n", hdrerr);
1131         if (level < 1)
1132         {
1133             level = 1;
1134             cckdumsg (dev, 600, "forcing check level %d\n", level);
1135         }
1136     }
1137 
1138     /* Additional checking if not properly closed */
1139     if (level < 1 && (cdevhdr.options & CCKD_OPENED))
1140     {
1141         level = 1;
1142         cckdumsg (dev, 600, "forcing check level %d; file not closed\n", level);
1143     }
1144 
1145     /* Additional checking if last opened for read/write */
1146     if (level < 0 && (cdevhdr.options & CCKD_ORDWR))
1147         level = 0;
1148 
1149     /* Set check level -1 */
1150     if (level == 0 && !dev->batch && !hdrerr
1151      && (cdevhdr.options & (CCKD_OPENED|CCKD_SPERRS)) == 0
1152      && ((cdevhdr.options & (CCKD_ORDWR)) == 0 || ro))
1153         level = -1;
1154 
1155     /* Build empty l2 table */
1156     memset (&empty_l2, shadow, CCKD_L2TAB_SIZE);
1157     if (shadow == 0 && cdevhdr.nullfmt != 0)
1158         for (i = 0; i < 256; i++)
1159             empty_l2[i].len = empty_l2[i].size = cdevhdr.nullfmt;
1160 
1161     /*---------------------------------------------------------------
1162      * read the level 1 table
1163      *---------------------------------------------------------------*/
1164 
1165     len = l1size;
1166     if ((l1 = malloc (len)) == NULL)
1167         goto cdsk_error;
1168     off = CCKD_L1TAB_POS;
1169     if ( lseek (fd, off, SEEK_SET) < 0)
1170         goto cdsk_lseek_error;
1171     if ((rc = read (fd, l1, len)) != len)
1172         goto cdsk_read_error;
1173     if (swapend) cckd_swapend_l1 (l1, (int)cdevhdr.numl1tab);
1174     lopos = CCKD_L1TAB_POS + l1size;
1175 
1176     /*---------------------------------------------------------------
1177      * initialize the space table
1178      *---------------------------------------------------------------*/
1179 
1180     /* find number of non-null l1 entries */
1181     for (i = n = 0; i < cdevhdr.numl1tab; i++)
1182         if (l1[i] != 0 && l1[i] != 0xffffffff)
1183             n++;
1184 
1185     if (level >= 4) n = cdevhdr.numl1tab;
1186 
1187     /* calculate max possible space table entries */
1188     n = 1 + 1 + 1                    // devhdr, cdevhdr, l1tab
1189       + n                            // l2tabs
1190       + (n * 256)                    // trk/blk images
1191       + (1 + n + (n * 256) + 1)      // max possible free spaces
1192       + 1;                           // end-of-file
1193 
1194     /* obtain the space table */
1195     len = sizeof(SPCTAB);
1196     if ((spctab = calloc (n, len)) == NULL)
1197         goto cdsk_calloc_error;
1198 
1199     /* populate the table with what we have */
1200     s = 0;
1201 
1202     /* devhdr */
1203     spctab[s].typ = SPCTAB_DEVHDR;
1204     spctab[s].val = -1;
1205     spctab[s].pos = 0;
1206     spctab[s].len =
1207     spctab[s].siz = CKDDASD_DEVHDR_SIZE;
1208     s++;
1209     /* cdevhdr */
1210     spctab[s].typ = SPCTAB_CDEVHDR;
1211     spctab[s].val = -1;
1212     spctab[s].pos = CCKD_DEVHDR_POS;
1213     spctab[s].len =
1214     spctab[s].siz = CCKD_DEVHDR_SIZE;
1215     s++;
1216     /* l1 table */
1217     spctab[s].typ = SPCTAB_L1;
1218     spctab[s].val = -1;
1219     spctab[s].pos = CCKD_L1TAB_POS;
1220     spctab[s].len =
1221     spctab[s].siz = l1size;
1222     s++;
1223     /* l2 tables */
1224     for (i = 0; i < cdevhdr.numl1tab && level < 4; i++)
1225     {
1226         if (l1[i] == 0 || l1[i] == 0xffffffff) continue;
1227         spctab[s].typ = SPCTAB_L2;
1228         spctab[s].val = i;
1229         spctab[s].pos = l1[i];
1230         spctab[s].len =
1231         spctab[s].siz = CCKD_L2TAB_SIZE;
1232         s++;
1233     }
1234     /* end-of-file */
1235     spctab[s].typ = SPCTAB_EOF;
1236     spctab[s].val = -1;
1237     spctab[s].pos = (U32)fst.st_size;
1238     spctab[s].len =
1239     spctab[s].siz = 0;
1240     s++;
1241 
1242     qsort (spctab, s, sizeof(SPCTAB), cdsk_spctab_sort);
1243 
1244     /*---------------------------------------------------------------
1245      * Quick return if level -1
1246      *---------------------------------------------------------------*/
1247 
1248     if (level < 0)
1249     {
1250         int err = 0;
1251         /* check for overlaps */
1252         for (i = 0; spctab[i].typ != SPCTAB_EOF; i++)
1253             if (spctab[i].pos + spctab[i].siz > spctab[i+1].pos)
1254                 err = 1;
1255         /* exit if no errors */
1256         if (!err) goto cdsk_return_ok;
1257     }
1258 
1259     /*---------------------------------------------------------------
1260      * obtain the l2errs table and recovery table
1261      *---------------------------------------------------------------*/
1262 
1263     len = sizeof(BYTE);
1264 
1265     n = cdevhdr.numl1tab;
1266     if ((l2errs = calloc (n, len)) == NULL)
1267         goto cdsk_calloc_error;
1268 
1269     n = trks;
1270     if ((rcvtab = calloc (n, len)) == NULL)
1271         goto cdsk_calloc_error;
1272 
1273     /*---------------------------------------------------------------
1274      * Special processing for level 4 (recover everything)
1275      *---------------------------------------------------------------*/
1276 
1277     if (level == 4)
1278     {
1279         memset (l2errs, 1, cdevhdr.numl1tab);
1280         memset (rcvtab, 1, trks);
1281         goto cdsk_recovery;
1282     }
1283 
1284     /*---------------------------------------------------------------
1285      * Read the level 2 tables
1286      *---------------------------------------------------------------*/
1287 
1288     for (i = 0; spctab[i].typ != SPCTAB_EOF; i++)
1289     {
1290         if (spctab[i].typ != SPCTAB_L2
1291          || spctab[i].pos < lopos || spctab[i].pos > hipos)
1292             continue;
1293 
1294         off = spctab[i].pos;
1295         if ( lseek (fd, off, SEEK_SET) < 0 )
1296             goto cdsk_lseek_error;
1297         len = CCKD_L2TAB_SIZE;
1298         if ((rc = read (fd, l2tab, len)) != len)
1299             goto cdsk_read_error;
1300         if (swapend) cckd_swapend_l2 (l2tab);
1301 
1302         /* add trks/blkgrps to the space table */
1303         for (j = 0; j < 256; j++)
1304         {
1305             if (l2tab[j].pos != 0 && l2tab[j].pos != 0xffffffff)
1306             {
1307                 spctab[s].typ = trktyp;
1308                 spctab[s].val = spctab[i].val * 256 + j;
1309                 spctab[s].pos = l2tab[j].pos;
1310                 spctab[s].len = l2tab[j].len;
1311                 spctab[s].siz = l2tab[j].size;
1312                 s++;
1313             }
1314         }
1315     }
1316     qsort (spctab, s, sizeof(SPCTAB), cdsk_spctab_sort);
1317 
1318     /*---------------------------------------------------------------
1319      * Consistency checks.
1320      *
1321      * The space table is now populated with everything but free
1322      * space.  Therefore we can infer what the free space should
1323      * be (ie gaps between allocated spaces).
1324      *---------------------------------------------------------------*/
1325 
1326     lopos = CCKD_L1TAB_POS + l1size;
1327     hipos = fst.st_size;
1328 
1329     /* Make adjustment if new format free space is at the end */
1330     len = spctab[s-1].pos - (spctab[s-2].pos + spctab[s-2].siz);
1331     if (len > 0
1332      && cdevhdr.size == cdevhdr.free
1333      && cdevhdr.size + len == spctab[s-1].pos)
1334     {
1335         spctab[s-1].pos -= len;
1336         hipos -= len;
1337     }
1338 
1339     memset (&cdevhdr2, 0, CCKD_DEVHDR_SIZE);
1340     for (i = 0; spctab[i].typ != SPCTAB_EOF; i++)
1341     {
1342         /* Calculate gap size */
1343         len = spctab[i+1].pos - (spctab[i].pos + spctab[i].siz);
1344 
1345         /* Update space statistics */
1346         cdevhdr2.size += spctab[i].siz + len;
1347         cdevhdr2.used += spctab[i].len;
1348         if (len > 0)
1349         {
1350             cdevhdr2.free_number++;
1351             cdevhdr2.free_total += len;
1352             if (cdevhdr2.free_largest < (U32)len)
1353                 cdevhdr2.free_largest = (U32)len;
1354         }
1355         if (spctab[i].typ == trktyp)
1356         {
1357             cdevhdr2.free_total += spctab[i].siz - spctab[i].len;
1358             cdevhdr2.free_imbed += spctab[i].siz - spctab[i].len;
1359         }
1360 
1361         /* ignore devhdr, cdevhdr and l1 (these are `out of bounds') */
1362         if (spctab[i].typ == SPCTAB_DEVHDR
1363          || spctab[i].typ == SPCTAB_CDEVHDR
1364          || spctab[i].typ == SPCTAB_L1
1365            )
1366             continue;
1367 
1368         /* check if the space is out of bounds */
1369         valid = (off_t)spctab[i].pos >= lopos
1370              && (off_t)spctab[i].pos + spctab[i].siz <= hipos;
1371 
1372         /* Overlap check */
1373         if (len < 0 || !valid)
1374         {
1375             char space1[32], space2[32];
1376             recovery = 1;
1377 
1378             /* issue error message */
1379             j = sprintf(space1, "%s", spaces[spctab[i].typ]);
1380             if (spctab[i].val >= 0)
1381                 sprintf(space1+j, "[%d]", spctab[i].val);
1382             j = sprintf(space2, "%s", spaces[spctab[i+1].typ]);
1383             if (spctab[i+1].val >= 0)
1384                 sprintf(space2+j, "[%d]", spctab[i+1].val);
1385 
1386             if (!valid)
1387                 cckdumsg(dev, 602, "%s offset 0x%" I32_FMT "x len %d is out of bounds\n",
1388                           space1, spctab[i].pos, spctab[i].siz);
1389             else
1390                 cckdumsg(dev, 603, "%s offset 0x%" I32_FMT "x len %d overlaps %s offset 0x%" I32_FMT "x\n",
1391                           space1, spctab[i].pos, spctab[i].siz, space2, spctab[i+1].pos);
1392 
1393             /* setup recovery */
1394             if (spctab[i].typ == SPCTAB_L2)
1395             {
1396                 l2errs[spctab[i].val] = 1;
1397                 /* Mark all tracks for the l2 for recovery */
1398                 memset (rcvtab + (spctab[i].val*256), 1, 256);
1399             }
1400             else if (spctab[i].typ == trktyp)
1401                 rcvtab[spctab[i].val] = 1;
1402 
1403             if (spctab[i+1].typ == SPCTAB_L2 && valid)
1404             {
1405                 l2errs[spctab[i+1].val] = 1;
1406                 memset (rcvtab + (spctab[i+1].val*256), 1, 256);
1407             }
1408             else if (spctab[i+1].typ == trktyp && valid)
1409                 rcvtab[spctab[i+1].val] = 1;
1410 
1411         } /* if overlap or out of bounds */
1412 
1413         /* Check image l2 entry consistency */
1414         else if (spctab[i].typ == trktyp
1415          && (spctab[i].len < CKDDASD_TRKHDR_SIZE
1416           || spctab[i].len > spctab[i].siz
1417           || spctab[i].len > trksz))
1418         {
1419             recovery = 1;
1420 
1421             /* issue error message */
1422             cckdumsg(dev, 604, "%s[%d] l2 inconsistency: len %d, size %d\n",
1423                      spaces[trktyp], spctab[i].val,
1424                      spctab[i].len, spctab[i].siz);
1425 
1426             /* setup recovery */
1427             rcvtab[spctab[i].val] = 1;
1428         } /* if inconsistent l2 */
1429     } /* for each space */
1430 
1431     /* remove any l2 tables or tracks in error from the space table */
1432     for (i = 0; recovery && spctab[i].typ != SPCTAB_EOF; i++)
1433         if ((spctab[i].typ == SPCTAB_L2 && l2errs[spctab[i].val])
1434          || (spctab[i].typ == trktyp    && rcvtab[spctab[i].val]))
1435             spctab[i].typ = SPCTAB_NONE;
1436 
1437     /* overlaps are serious */
1438     if (recovery && level < 3)
1439     {
1440         level = 3;
1441         cckdumsg (dev, 600, "forcing check level %d\n", level);
1442     }
1443 
1444     /* Rebuild free space if any errors */
1445     if (recovery || hdrerr
1446      || cdevhdr.size         != cdevhdr2.size
1447      || cdevhdr.used         != cdevhdr2.used
1448      || cdevhdr.free_number  != cdevhdr2.free_number
1449      || cdevhdr.free_largest != cdevhdr2.free_largest
1450      || cdevhdr.free_total   != cdevhdr2.free_total
1451      || cdevhdr.free_imbed   != cdevhdr2.free_imbed
1452        )
1453         fsperr = 1;
1454 
1455     /*---------------------------------------------------------------
1456      * read the free space
1457      *---------------------------------------------------------------*/
1458 
1459     lopos = CCKD_L1TAB_POS + l1size;
1460     hipos = fst.st_size;
1461 
1462     if (level >= 1 && !fsperr)
1463     {
1464         while (cdevhdr.free) // `while' so code can break
1465         {
1466             fsperr = 1;  // be pessimistic
1467             fsp = NULL;
1468 
1469             /* Read the free space */
1470             off = (off_t)cdevhdr.free;
1471             len = CCKD_FREEBLK_SIZE;
1472             if (off < lopos || off + CCKD_FREEBLK_SIZE > hipos
1473              || lseek (fd, off, SEEK_SET) < 0
1474              || (rc = read (fd, &freeblk, len)) != len)
1475                 break;
1476 
1477             if (memcmp (&freeblk, "FREE_BLK", 8) == 0)
1478             {
1479                 /* new format free space */
1480                 len = cdevhdr.free_number * CCKD_FREEBLK_SIZE;
1481                 if ((fsp = malloc(len)) == NULL
1482                  || (rc = read (fd, fsp, len)) != len)
1483                     break;
1484 
1485                 for (i = 0; i < cdevhdr.free_number; i++)
1486                 {
1487                     if (swapend) cckd_swapend_free (&fsp[i]);
1488                     spctab[s].typ = SPCTAB_FREE;
1489                     spctab[s].val = -1;
1490                     spctab[s].pos = fsp[i].pos;
1491                     spctab[s].len =
1492                     spctab[s].siz = fsp[i].len;
1493                     /* Free space should be ascending */
1494                     if (spctab[s].pos < lopos
1495                      || spctab[s].pos + spctab[s].siz > hipos)
1496                         break;
1497                     lopos = spctab[s].pos + spctab[s].siz;
1498                     s++;
1499                 } /* for each free space */
1500                 if (i >= cdevhdr.free_number)
1501                     fsperr = 0;
1502             } /* new format free space */
1503             else
1504             {
1505                 /* old format free space */
1506                 off = (off_t)cdevhdr.free;
1507                 len = CCKD_FREEBLK_SIZE;
1508                 for (i = 0; i < cdevhdr.free_number; i++)
1509                 {
1510                     if (off < lopos || off > hipos) break;
1511                     if (lseek (fd, off, SEEK_SET) < 0)
1512                         goto cdsk_lseek_error;
1513                     if ((rc = read (fd, &freeblk, len)) != len)
1514                         goto cdsk_read_error;
1515                     if (swapend) cckd_swapend_free (&freeblk);
1516                     spctab[s].typ = SPCTAB_FREE;
1517                     spctab[s].val = -1;
1518                     spctab[s].pos = (U32)off;
1519                     spctab[s].len =
1520                     spctab[s].siz = freeblk.len;
1521                     s++;
1522                     lopos = off + freeblk.len;
1523                     off = (off_t)freeblk.pos;
1524                 }
1525                 if (i >= cdevhdr.free_number && freeblk.pos == 0)
1526                     fsperr = 0;
1527             } /* if old format free space */
1528 
1529             if (fsp) free(fsp);
1530             fsp = NULL;
1531 
1532             /* Check for gaps/overlaps */
1533             qsort (spctab, s, sizeof(SPCTAB), cdsk_spctab_sort);
1534             for (i = 0; !fsperr && spctab[i].typ != SPCTAB_EOF; i++)
1535                 if (spctab[i].pos + spctab[i].siz != spctab[i+1].pos)
1536                     fsperr = 1;
1537             break;
1538         } /* while (cdevhdr.free) */
1539     } /* if (level >= 1 && !fsperr) */
1540 
1541     if (fsperr)
1542         cckdumsg (dev, 610, "free space errors detected\n");
1543 
1544     /*---------------------------------------------------------------
1545      * Read track headers/images
1546      *---------------------------------------------------------------*/
1547 
1548 cdsk_space_check:
1549 
1550     if (level >= 2)
1551     {
1552         for (i = 0; spctab[i].typ != SPCTAB_EOF; i++)
1553         {
1554             if (spctab[i].typ != trktyp) continue;
1555 
1556             /* read the header or image depending on the check level */
1557             off = spctab[i].pos;
1558             if ( lseek (fd, off, SEEK_SET) < 0 )
1559                 goto cdsk_lseek_error;
1560             len = level < 3 ? CKDDASD_TRKHDR_SIZE : spctab[i].len;
1561             if ((rc = read (fd, buf, len)) != len)
1562                 goto cdsk_read_error;
1563 
1564             /* Extract header info */
1565             comp = buf[0];
1566             cyl  = fetch_hw (buf + 1);
1567             head = fetch_hw (buf + 3);
1568             trk  = cyl * heads + head;
1569 
1570             /* Validate header info */
1571             if (compmask[comp] == 0xff
1572              || cyl >= cyls || head >= heads
1573              || trk != spctab[i].val)
1574             {
1575                 cckdumsg (dev, 620, "%s[%d] hdr error offset 0x%" I64_FMT
1576                           "x: %2.2x%2.2x%2.2x%2.2x%2.2x\n",
1577                           spaces[trktyp], spctab[i].val, (long long)off,
1578                           buf[0],buf[1],buf[2],buf[3],buf[4]);
1579 
1580                 /* recover this track */
1581                 rcvtab[spctab[i].val] = recovery = 1;
1582                 spctab[i].typ = SPCTAB_NONE;
1583 
1584                 /* Force level 3 checking */
1585                 if (level < 3)
1586                 {
1587                     level = 3;
1588                     cckdumsg (dev, 600, "forcing check level %d\n", level);
1589                     goto cdsk_space_check;
1590                 }
1591                 continue;
1592             } /* if invalid header info */
1593 
1594             /* Check if compression supported */
1595             if (compmask[comp])
1596             {
1597                 comperrs = 1;
1598                 cckdumsg ( dev, 621, "%s[%d] compressed using %s, not supported\n",
1599                            spaces[trktyp], trk, comps[compmask[comp]]);
1600                 continue;
1601             }
1602 
1603             /* Validate the space if check level 3 */
1604             if (level > 2)
1605             {
1606                 if (!cdsk_valid_trk (trk, buf, heads, len))
1607                 {
1608                     cckdumsg (dev, 622, "%s[%d] offset 0x%" I64_FMT
1609                           "x len %d validation error\n",
1610                           spaces[trktyp], trk, (long long)off, len);
1611 
1612                     /* recover this track */
1613                     rcvtab[trk] = recovery = 1;
1614                     spctab[i].typ = SPCTAB_NONE;
1615                 } /* if invalid space */
1616                 else
1617                     rcvtab[trk] = 0;
1618             } /* if level > 2 */
1619         } /* for each space */
1620     } /* if (level >= 2) */
1621 
1622     /*---------------------------------------------------------------
1623      * Recovery
1624      *---------------------------------------------------------------*/
1625 
1626 cdsk_recovery:
1627 
1628     if (recovery || level == 4)
1629     {
1630      U32 flen, fpos;
1631 
1632         /*-----------------------------------------------------------
1633          * Phase 1 -- recover trk/blkgrp images
1634          *-----------------------------------------------------------*/
1635 
1636         /*
1637          * Reset the end-of-file pos to the file size
1638          * It might have been changed if new format free space
1639          * occurred at the end of the file.
1640          */
1641         qsort (spctab, s, sizeof(SPCTAB), cdsk_spctab_sort);
1642         while (spctab[s-1].typ == SPCTAB_NONE) s--;
1643         spctab[s-1].pos = fst.st_size;
1644 
1645         /* count number tracks to be recovered */
1646         for (i = n = 0; i < trks; i++)
1647             if (rcvtab[i] == 1)
1648                n++;
1649 
1650         /*-----------------------------------------------------------
1651          * ckd recovery
1652          *-----------------------------------------------------------*/
1653         if (ckddasd)
1654         {
1655             /* recovery loop */
1656             s = cdsk_build_free_space (spctab, s);
1657             for (f = 0; spctab[f].typ != SPCTAB_EOF && n; )
1658             {
1659                 /* next free space if too small */
1660                 if (spctab[f].typ != SPCTAB_FREE
1661                  || spctab[f].siz <= CKDDASD_TRKHDR_SIZE+8)
1662                 {
1663                     for (f = f + 1; spctab[f].typ != SPCTAB_EOF; f++)
1664                         if (spctab[f].typ == SPCTAB_FREE)
1665                             break;
1666                     continue;
1667                 }
1668 
1669                 fpos = spctab[f].pos;
1670                 flen = spctab[f].siz;
1671 
1672                 /* length to read */
1673                 len = flen < sizeof(buf) ? flen : sizeof(buf);
1674 
1675                 /* read the free space */
1676                 off = (off_t)fpos;
1677                 if (lseek (fd, off, SEEK_SET) < 0)
1678                     goto cdsk_lseek_error;
1679                 if ((rc = read (fd, buf, len)) != len)
1680                     goto cdsk_read_error;
1681 
1682                 /* Scan the space for a trkhdr */
1683                 for (i = 0; i < len - (CKDDASD_TRKHDR_SIZE+8); i++)
1684                 {
1685                     /* Check compression byte */
1686                     if (compmask[buf[i]])
1687                         continue;
1688 
1689                     /* Fetch possible trkhdr */
1690                     comp = buf[i];
1691                     cyl  = fetch_hw (buf + i + 1);
1692                     head = fetch_hw (buf + i + 3);
1693                     trk  = cyl * heads + head;
1694 
1695                     /* Validate possible trkhdr */
1696                     if (cyl >= cyls || head >= heads || rcvtab[trk] != 1)
1697                         continue;
1698 
1699                     /* Quick validation for compress none */
1700                     if (comp == CCKD_COMPRESS_NONE
1701                      && (fetch_hw (buf + i +  5) != cyl   // r0 cyl
1702                       || fetch_hw (buf + i +  7) != head  // r0 head
1703                       || buf[i +  9] != 0                 // r0 record
1704                       || buf[i + 10] != 0                 // r0 key length
1705                       || fetch_hw (buf + i + 11) != 8     // r0 data length
1706                         )
1707                        )
1708                         continue;
1709 
1710                     /* Quick validation for zlib */
1711                     else if (comp == CCKD_COMPRESS_ZLIB
1712                      && fetch_hw(buf + i + 5) % 31 != 0)
1713                         continue;
1714 
1715                     /* Quick validation for bzip2 */
1716                     else if (comp == CCKD_COMPRESS_BZIP2
1717                      && (buf[i+5] != 'B' || buf[i+6] != 'Z'))
1718                         continue;
1719                     /*
1720                      * If we are in `borrowed space' then start over
1721                      * with the current position at the beginning
1722                      */
1723                     if (flen > (U32)len && i > len - (int)trksz)
1724                         break;
1725 
1726                     /* Checks for comp none */
1727                     if (comp == CCKD_COMPRESS_NONE)
1728                     {
1729                         l = len - i;
1730                         if ((l = cdsk_valid_trk (trk, buf+i, heads, -l)))
1731                             goto cdsk_ckd_recover;
1732                         else
1733                              continue;
1734                     }
1735 
1736                     /* Check short `length' */
1737                     if (flen == (U32)len && (l = len - i) <= 1024)
1738                     {
1739                         if (cdsk_valid_trk (trk, buf+i, heads, l))
1740                         {
1741                             while (cdsk_valid_trk (trk, buf+i, heads, --l));
1742                             l++;
1743                             goto cdsk_ckd_recover;
1744                         }
1745                     }
1746 
1747                     /* Scan for next trkhdr */
1748                     for (j = i + CKDDASD_TRKHDR_SIZE+8;
1749                          j <= len - (CKDDASD_TRKHDR_SIZE+8);
1750                          j++)
1751                     {
1752                         if (j - i > (int)trksz) break;
1753 
1754                         if (compmask[buf[j]] != 0
1755                          || fetch_hw(buf+j+1) >= cyls
1756                          || fetch_hw(buf+j+3) >= heads)
1757                             continue;
1758 
1759                         /* check uncompressed hdr */
1760                         if (buf[j] == CCKD_COMPRESS_NONE
1761                          && (fetch_hw (buf+j+5) != fetch_hw(buf+j+1)
1762                           || fetch_hw (buf+j+7) != fetch_hw(buf+j+3)
1763                           || buf[j+9] != 0      || buf[j+10] != 0
1764                           || fetch_hw(buf+j+11) != 8))
1765                                 continue;
1766                         /* check zlib compressed header */
1767                         else if (buf[j] == CCKD_COMPRESS_ZLIB
1768                          && fetch_hw(buf + j + 5) % 31 != 0)
1769                                 continue;
1770                         /* check bzip2 compressed header */
1771                         else if (buf[j] == CCKD_COMPRESS_BZIP2
1772                          && (buf[j+5] != 'B' || buf[j+6] != 'Z'))
1773                                 continue;
1774 
1775                         /* check to possible trkhdr */
1776                         l = j - i;
1777                         if (cdsk_valid_trk (trk, buf+i, heads, l))
1778                         {
1779 #if 0
1780                             while (cdsk_valid_trk (trk, buf+i, heads, --l));
1781                             l++;
1782 #endif
1783                             goto cdsk_ckd_recover;
1784                         }
1785 
1786                     } /* scan for next trkhdr */
1787 
1788                     /* Check `length' */
1789                     if (flen == (U32)len && (l = len - i) <= (int)trksz)
1790                     {
1791                         if (cdsk_valid_trk (trk, buf+i, heads, l))
1792                         {
1793                             while (cdsk_valid_trk (trk, buf+i, heads, --l));
1794                             l++;
1795                             goto cdsk_ckd_recover;
1796                         }
1797                     }
1798 
1799                     /* Scan all lengths */
1800                     for (l = CKDDASD_TRKHDR_SIZE+8; i + l <= len; l++)
1801                     {
1802                         if (l > (int)trksz)
1803                             break;
1804                         if (cdsk_valid_trk (trk, buf+i, heads, l))
1805                             goto cdsk_ckd_recover;
1806                     } /* for all lengths */
1807 
1808                     continue;
1809 
1810 cdsk_ckd_recover:
1811 
1812                     cckdumsg (dev, 301, "%s[%d] recovered offset 0x%" I64_FMT "x len %d\n",
1813                           spaces[trktyp], trk, (long long)off + i, l);
1814                     n--;
1815                     rcvtab[trk] = 2;
1816 
1817                     /* add recovered track to the space table */
1818                     spctab[s].typ = trktyp;
1819                     spctab[s].val = trk;
1820                     spctab[s].pos = fpos + i;
1821                     spctab[s].len =
1822                     spctab[s].siz = l;
1823                     s++;
1824                     /*
1825                      * adjust `i' knowing it will be incremented
1826                      * in the `for' loop above.
1827                      */
1828                     i += l - 1;
1829                 } /* for each byte in the free space */
1830 
1831                 /* Adjust the free space for what we processed */
1832                 spctab[f].pos += i;
1833                 spctab[f].len -= i;
1834                 spctab[f].siz -= i;
1835 
1836             } /* for each free space */
1837 
1838         } /* if ckddasd */
1839 
1840         /*-----------------------------------------------------------
1841          * fba recovery
1842          *-----------------------------------------------------------*/
1843 
1844         /*
1845          * FBA blkgrps are harder to recover than CKD tracks because
1846          * there is not any information within the blkgrp itself to
1847          * validate (unlike a track, which has count fields that
1848          * terminate in an end-of-track marker).
1849          *
1850          * On the first pass we recover all compressed blkgrps since
1851          * these are readily validated (they must uncompress to a
1852          * certain size, CFBA_BLOCK_SIZE+CKDDASD_TRKHDR_SIZE).  We
1853          * also recover uncompressed blkgrps if they are followed by
1854          * a valid trkhdr (and don't occur to close to the beginning
1855          * of the file).
1856          *
1857          * On the second pass we recover all uncompressed blkgrps
1858          * that weren't recovered in the first pass.  The only
1859          * criteria is that the compression byte is zero and the
1860          * 4 byte blkgrp number is in range and there are at least
1861          * CFBA_BLOCK_SIZE bytes following.
1862          */
1863 
1864         for (pass = 0; fbadasd && pass < 2; pass++)
1865         {
1866             lopos = CCKD_L1TAB_POS + (cdevhdr.numl1tab * 4);
1867             if (pass == 0)
1868                 lopos += (cdevhdr.numl1tab * CCKD_L2TAB_SIZE);
1869 
1870             /* recovery loop */
1871             s = cdsk_build_free_space (spctab, s);
1872             for (f = 0; spctab[f].typ != SPCTAB_EOF && n > 0; )
1873             {
1874                 U32 flen, fpos;
1875 
1876                 /* next free space if too small */
1877                 if (spctab[f].typ != SPCTAB_FREE
1878                  || spctab[f].siz <= CKDDASD_TRKHDR_SIZE+8
1879                  || (pass == 1 && spctab[f].siz < blkgrpsz))
1880                 {
1881                     for (f = f + 1; spctab[f].typ != SPCTAB_EOF; f++)
1882                         if (spctab[f].typ == SPCTAB_FREE)
1883                             break;
1884                     continue;
1885                 }
1886 
1887                 fpos = spctab[f].pos;
1888                 flen = spctab[f].siz;
1889                 /*
1890                  * calculate length to read
1891                  * if flen > len then we only read part of the space
1892                  */
1893                 len = flen < sizeof(buf) ? flen : sizeof(buf);
1894 
1895                 /* read the free space */
1896                 off = (off_t)fpos;
1897                 if (lseek (fd, off, SEEK_SET) < 0)
1898                     goto cdsk_lseek_error;
1899                 if ((rc = read (fd, buf, len)) != len)
1900                     goto cdsk_read_error;
1901 
1902                 /* Scan the space */
1903                 for (i = 0; i < len - (CKDDASD_TRKHDR_SIZE+8); i++)
1904                 {
1905                     /* For pass 1 the size left must be at least blkgrpsz */
1906                     if (pass == 1 && len - i < (int)blkgrpsz)
1907                         break;
1908 
1909                     /* Check compression byte */
1910                     if ((pass == 0 && compmask[buf[i]])
1911                      || (pass == 1 && buf[i] != CCKD_COMPRESS_NONE))
1912                         continue;
1913 
1914                     /* Fetch possible trkhdr */
1915                     comp = buf[i];
1916                     blkgrp = fetch_fw (buf + i + 1);
1917 
1918                     /* Validate possible trkhdr */
1919                     if (blkgrp < 0 || blkgrp >= blkgrps
1920                      || rcvtab[blkgrp] != 1)
1921                         continue;
1922 
1923                     /* Validation for compress none */
1924                     if (comp == CCKD_COMPRESS_NONE
1925                      && flen == (U32)len && len - i < (int)blkgrpsz)
1926                         continue;
1927 
1928                     /* Quick validation for zlib */
1929                     else if (comp == CCKD_COMPRESS_ZLIB
1930                      && fetch_hw(buf + i + 5) % 31 != 0)
1931                         continue;
1932 
1933                     /* Quick validation for bzip2 */
1934                     else if (comp == CCKD_COMPRESS_BZIP2
1935                      && (buf[i+5] != 'B' || buf[i+6] != 'Z'))
1936                         continue;
1937                     /*
1938                      * If we are in `borrowed space' then start over
1939                      * with the current position at the beginning
1940                      */
1941                     if (flen > (U32)len && i > len - (int)blkgrpsz)
1942                         break;
1943 
1944                     /* Checks for comp none */
1945                     if (comp == CCKD_COMPRESS_NONE)
1946                     {
1947                         l = blkgrpsz;
1948                         if (len - i < (int)blkgrpsz || fpos + i < lopos)
1949                             continue;
1950                         if (len - i == (int)blkgrpsz && flen == (U32)len)
1951                             goto cdsk_fba_recover;
1952                         /* Pass 0 checks */
1953                         if (pass == 0
1954                          && (len - i - l < CKDDASD_TRKHDR_SIZE+8
1955                           || compmask[buf[i+l]]
1956                           || fetch_fw (buf+i+l+1) >= (unsigned int)blkgrps)
1957                            )
1958                             continue;
1959                         goto cdsk_fba_recover;
1960                     }
1961 
1962                     /* The tests below are for pass 0 only */
1963                     if (pass == 1)
1964                         continue;
1965 
1966                     /* Check short `length' */
1967                     if (flen == (U32)len && (l = len - i) <= 1024)
1968                     {
1969                         if (cdsk_valid_trk (blkgrp, buf+i, heads, l))
1970                         {
1971                             while (cdsk_valid_trk (blkgrp, buf+i, heads, --l));
1972                             l++;
1973                             goto cdsk_fba_recover;
1974                         }
1975                     }
1976 
1977                     /* Scan for next trkhdr */
1978                     for (j = i + CKDDASD_TRKHDR_SIZE+8;
1979                          j <= len - (CKDDASD_TRKHDR_SIZE+8);
1980                          j++)
1981                     {
1982                         if (j - i > (int)blkgrpsz) break;
1983 
1984                         if (compmask[buf[j]] != 0
1985                          || fetch_fw(buf+j+1) >= (unsigned int)blkgrps)
1986                             continue;
1987 
1988                         /* check zlib compressed header */
1989                         if (buf[j] == CCKD_COMPRESS_ZLIB
1990                          && fetch_hw(buf + j + 5) % 31 != 0)
1991                             continue;
1992 
1993                         /* check bzip2 compressed header */
1994                         else if (buf[j] == CCKD_COMPRESS_BZIP2
1995                          && (buf[j+5] != 'B' || buf[j+6] != 'Z'))
1996                                 continue;
1997 
1998                         /* check to possible trkhdr */
1999                         l = j - i;
2000                         if (cdsk_valid_trk (blkgrp, buf+i, heads, l))
2001                         {
2002 #if 0
2003                             while (cdsk_valid_trk (blkgrp, buf+i, heads, --l));
2004                             l++;
2005 #endif
2006                             goto cdsk_fba_recover;
2007                         }
2008 
2009                     } /* scan for next trkhdr */
2010 
2011                     /* Check `length' */
2012                     l = len - i;
2013                     if (flen == (U32)len && l <= (int)blkgrpsz)
2014                     {
2015                         if (cdsk_valid_trk (blkgrp, buf+i, heads, l))
2016                         {
2017                             while (cdsk_valid_trk (blkgrp, buf+i, heads, --l));
2018                             l++;
2019                             goto cdsk_fba_recover;
2020                         }
2021                     }
2022 
2023                     /* Scan all lengths */
2024                     for (l = CKDDASD_TRKHDR_SIZE+8; i + l <= len; l++)
2025                     {
2026                         if (l > (int)blkgrpsz)
2027                             break;
2028                         if (cdsk_valid_trk (blkgrp, buf+i, heads, l))
2029                             goto cdsk_fba_recover;
2030                     } /* for all lengths */
2031 
2032                     continue;
2033 
2034 cdsk_fba_recover:
2035 
2036                     cckdumsg (dev, 301, "%s[%d] recovered offset 0x%" I64_FMT "x len %d\n",
2037                           spaces[trktyp], blkgrp, (long long)off + i, l);
2038                     n--;
2039                     rcvtab[blkgrp] = 2;
2040 
2041                     /* Enable recovery of comp 0 blkgrps for pass 0 */
2042                     if (fpos + i < lopos)
2043                         lopos = fpos + i;
2044 
2045                     /* add recovered block group to the space table */
2046                     spctab[s].typ = trktyp;
2047                     spctab[s].val = blkgrp;
2048                     spctab[s].pos = fpos + i;
2049                     spctab[s].len =
2050                     spctab[s].siz = l;
2051                     s++;
2052                     /*
2053                      * adjust `i' knowing it will be incremented
2054                      * in the `for' loop above.
2055                      */
2056                     i += l - 1;
2057                 } /* for each byte in the free space */
2058 
2059                 /* Adjust the free space for what we processed */
2060                 spctab[f].pos += i;
2061                 spctab[f].len -= i;
2062                 spctab[f].siz -= i;
2063 
2064             } /* for each free space */
2065 
2066         } /* if fbadasd */
2067 
2068         for (i = n = 0; i < trks; i++)
2069             if (rcvtab[i] == 2)
2070                 n++;
2071         cckdumsg (dev, 300, "%d %s images recovered\n",
2072                 n, spaces[trktyp]);
2073 
2074         /*-----------------------------------------------------------
2075          * Phase 2 -- rebuild affected l2 tables
2076          *-----------------------------------------------------------*/
2077 
2078         /*
2079          * Make sure there's at least one non-zero `rcvtab' entry
2080          * for l2 tables in `l2errs'.  Space validation may have
2081          * turned off all `rcvtab' entries for an l2.
2082          */
2083         for (i = 0; i < cdevhdr.numl1tab; i++)
2084             if (l2errs[i])
2085                 rcvtab[i*256] = 1;
2086 
2087         /* Get storage for the l2 table array */
2088         n = cdevhdr.numl1tab;
2089         len = sizeof(void *);
2090         if ((l2 = calloc (n, len)) == NULL)
2091             goto cdsk_calloc_error;
2092 
2093         /* Get storage for the rebuilt l2 tables */
2094         len = CCKD_L2TAB_SIZE;
2095         for (i = 0; i < trks; i++)
2096         {
2097             l1x = i / 256;
2098             if (rcvtab[i] != 0 && l2[l1x] == NULL)
2099             {
2100                 if ((l2[l1x] = malloc (len)) == NULL)
2101                     goto cdsk_malloc_error;
2102                 l1[l1x] = shadow ? 0xffffffff : 0;
2103                 memcpy (l2[l1x], &empty_l2, len);
2104             }
2105         }
2106 
2107         /* Rebuild the l2 tables */
2108         qsort (spctab, s, sizeof(SPCTAB), cdsk_spctab_sort);
2109         for (i = 0; spctab[i].typ != SPCTAB_EOF; i++)
2110         {
2111             if (spctab[i].typ == SPCTAB_L2 && l2[spctab[i].val])
2112                 spctab[i].typ = SPCTAB_NONE;
2113             else if (spctab[i].typ == trktyp && l2[spctab[i].val/256])
2114             {
2115                 l1x = spctab[i].val / 256;
2116                 l2x = spctab[i].val % 256;
2117                 l2[l1x][l2x].pos  = spctab[i].pos;
2118                 l2[l1x][l2x].len  = spctab[i].len;
2119                 l2[l1x][l2x].size = spctab[i].siz;
2120             }
2121         } /* for each space */
2122         qsort (spctab, s, sizeof(SPCTAB), cdsk_spctab_sort);
2123         while (spctab[s-1].typ == SPCTAB_NONE) s--;
2124 
2125         /* Look for empty l2 tables */
2126         for (i = 0; i < cdevhdr.numl1tab; i++)
2127             if (l2[i] != NULL
2128              && memcmp (l2[i], &empty_l2, CCKD_L2TAB_SIZE) == 0)
2129             {
2130                 free (l2[i]);
2131                 l2[i] = NULL;
2132             }
2133         /*
2134          * `s-1' indexes the SPCTAB_EOF space table entry.
2135          * Set its `pos' to the maximum allowed value to ensure
2136          * there will be free space for the rebuilt l2 tables.
2137          */
2138         spctab[s-1].pos = (U32)maxsize;
2139 
2140         /* Build the free space */
2141         s = cdsk_build_free_space (spctab, s);
2142 
2143         /* Find space for the rebuilt l2 tables */
2144         for (i = j = 0; i < cdevhdr.numl1tab; i++)
2145         {
2146             if (l2[i] == NULL) continue;
2147 
2148             /* find a free space */
2149             for ( ; spctab[j].typ != SPCTAB_EOF; j++)
2150                 if (spctab[j].typ == SPCTAB_FREE
2151                  && spctab[j].siz >= CCKD_L2TAB_SIZE)
2152                      break;
2153 
2154             /* weird error if no space */
2155             if (spctab[j].typ == SPCTAB_EOF)
2156             {
2157                 cckdumsg (dev, 905, "not enough file space for recovery\n");
2158                 goto cdsk_error;
2159             }
2160 
2161             /* add l2 space */
2162             l1[i]         = spctab[j].pos;
2163             spctab[s].typ = SPCTAB_L2;
2164             spctab[s].val = i;
2165             spctab[s].pos = spctab[j].pos;
2166             spctab[s].len =
2167             spctab[s].siz = CCKD_L2TAB_SIZE;
2168             s++;
2169 
2170             /* adjust the free space */
2171             spctab[j].pos += CCKD_L2TAB_SIZE;
2172             spctab[j].len -= CCKD_L2TAB_SIZE;
2173             spctab[j].siz -= CCKD_L2TAB_SIZE;
2174         } /* for each l2 table */
2175 
2176 
2177         /*-----------------------------------------------------------
2178          * Phase 3 -- write l1 and l2 tables
2179          *-----------------------------------------------------------*/
2180 
2181         if (ro)
2182         {
2183             cckdumsg (dev, 500, "recovery not completed, file opened read-only\n");
2184             goto cdsk_error;
2185         }
2186         if (comperrs)
2187         {
2188             cckdumsg (dev, 501, "recovery not completed, missing compression\n");
2189             goto cdsk_error;
2190         }
2191 
2192         /* Write the l1 table */
2193         off = CCKD_L1TAB_POS;
2194         if (lseek (fd, off, SEEK_SET) < 0)
2195             goto cdsk_lseek_error;
2196         len = l1size;
2197         if ((rc = write (fd, l1, len)) != len)
2198             goto cdsk_write_error;
2199 
2200         /* Write l2 tables */
2201         qsort (spctab, s, sizeof(SPCTAB), cdsk_spctab_sort);
2202         for (i = 0; spctab[i].typ != SPCTAB_EOF; i++)
2203         {
2204             l1x = spctab[i].val;
2205             if (spctab[i].typ != SPCTAB_L2 || l2[l1x] == NULL)
2206                 continue;
2207             off = (off_t)l1[l1x];
2208             if (lseek (fd, off, SEEK_SET) < 0)
2209                 goto cdsk_lseek_error;
2210             len = CCKD_L2TAB_SIZE;
2211             if ((rc = write (fd, l2[l1x], len)) != len)
2212                 goto cdsk_write_error;
2213             free (l2[l1x]);
2214             l2[l1x] = NULL;
2215         } /* for each space */
2216 
2217         /* Free recovery related storage */
2218         if (l2)
2219         {
2220             for (i = 0; i < cdevhdr.numl1tab; i++)
2221                 if (l2[i])
2222                     free (l2[i]);
2223             free (l2); l2 = NULL;
2224         }
2225         free (l2errs); l2errs = NULL;
2226         free (rcvtab); rcvtab = NULL;
2227 
2228         /* Ensure we do free space recovery */
2229         fsperr = 1;
2230 
2231     } /* if (recovery || level >= 4) */
2232 
2233     /*---------------------------------------------------------------
2234      * Rebuild free space
2235      *---------------------------------------------------------------*/
2236 
2237     if (fsperr && ro)
2238         cckdumsg (dev, 502, "free space not rebuilt, file opened read-only\n");
2239     else if (fsperr)
2240     {
2241         /*-----------------------------------------------------------
2242          * Phase 1 -- build the free space
2243          *            make sure the last space isn't free space and
2244          *            that each free space is long enough (8 bytes).
2245          *-----------------------------------------------------------*/
2246 
2247 cdsk_fsperr_retry:
2248 
2249         s = cdsk_build_free_space (spctab, s);
2250 
2251         /*
2252          * spctab[s-1] is the SPCTAB_EOF entry.
2253          * if spctab[s-2] is SPCTAB_FREE then discard it
2254          */
2255         if (spctab[s-2].typ == SPCTAB_FREE)
2256         {
2257             spctab[s-1].typ = SPCTAB_NONE;
2258             spctab[s-2].typ = SPCTAB_EOF;
2259             spctab[s-2].val = -1;
2260             spctab[s-2].len =
2261             spctab[s-2].siz = 0;
2262             s--;
2263         }
2264         /*
2265          * Check for short free spaces.
2266          * If found, shift left until the next free space or eof.
2267          */
2268         for (i = 0; spctab[i].typ != SPCTAB_EOF; i++)
2269             if (spctab[i].typ == SPCTAB_FREE
2270              && spctab[i].siz < CCKD_FREEBLK_SIZE)
2271                 break;
2272         if (spctab[i].typ != SPCTAB_EOF)
2273         {
2274             /* Shift following space left */
2275             l = spctab[i++].siz;
2276             while (spctab[i].typ != SPCTAB_FREE && spctab[i].typ != SPCTAB_EOF)
2277             {
2278                 /* Read the space and write shifted to the left */
2279                 off = (off_t)spctab[i].pos;
2280                 if (lseek (fd, off, SEEK_SET) < 0)
2281                     goto cdsk_lseek_error;
2282                 len = spctab[i].siz;
2283                 if ((rc = read (fd, buf, len)) != len)
2284                     goto cdsk_read_error;
2285                 off -= l;
2286                 if (lseek (fd, off, SEEK_SET) < 0)
2287                     goto cdsk_lseek_error;
2288                 if ((rc = write (fd, buf, len)) != len)
2289                     goto cdsk_write_error;
2290                 spctab[i].pos -= l;
2291 
2292                 /* Update the l2 or l1 table entry */
2293                 if (spctab[i].typ == trktyp)
2294                 {
2295                     l1x = spctab[i].val/256;
2296                     l2x = spctab[i].val%256;
2297                     off = (off_t)l1[l1x] + l2x * CCKD_L2ENT_SIZE;
2298                     if (lseek (fd, off, SEEK_SET) < 0)
2299                         goto cdsk_lseek_error;
2300                     len = CCKD_L2ENT_SIZE;
2301                     if ((rc = read (fd, &l2ent, len)) != len)
2302                         goto cdsk_read_error;
2303                     l2ent.pos -= l;
2304                     if (lseek (fd, off, SEEK_SET) < 0)
2305                         goto cdsk_lseek_error;
2306                     if ((rc = write (fd, &l2ent, len)) != len)
2307                         goto cdsk_write_error;
2308                 } /* trk/blkgrp relocated */
2309                 else if (spctab[i].typ == SPCTAB_L2)
2310                     l1[spctab[i].val] -= l;
2311                 i++;
2312             } /* while not FREE space or EOF */
2313             goto cdsk_fsperr_retry;
2314         } /* if short free space found */
2315 
2316         /*-----------------------------------------------------------
2317          * Phase 2 -- rebuild free space statistics
2318          *-----------------------------------------------------------*/
2319 
2320         cdevhdr.vrm[0] = CCKD_VERSION;
2321         cdevhdr.vrm[1] = CCKD_RELEASE;
2322         cdevhdr.vrm[2] = CCKD_MODLVL;
2323 
2324         cdevhdr.size        = cdevhdr.used         = cdevhdr.free =
2325         cdevhdr.free_total  = cdevhdr.free_largest =
2326         cdevhdr.free_number = cdevhdr.free_imbed   = 0;
2327         for (i = 0; spctab[i].typ != SPCTAB_EOF; i++)
2328             if (spctab[i].typ == SPCTAB_FREE)
2329             {
2330                 cdevhdr.size += spctab[i].siz;
2331                 if (spctab[i].siz > cdevhdr.free_largest)
2332                     cdevhdr.free_largest = spctab[i].siz;
2333                 cdevhdr.free_total += spctab[i].siz;
2334                 cdevhdr.free_number++;
2335             }
2336             else
2337             {
2338                 cdevhdr.size += spctab[i].siz;
2339                 cdevhdr.used += spctab[i].len;
2340                 cdevhdr.free_total += spctab[i].siz - spctab[i].len;
2341                 cdevhdr.free_imbed += spctab[i].siz - spctab[i].len;
2342              }
2343 
2344         /*-----------------------------------------------------------
2345          * Phase 3 -- write the free space
2346          *-----------------------------------------------------------*/
2347         if (cdevhdr.free_number)
2348         {
2349             /* size needed for new format free space */
2350             len = (cdevhdr.free_number+1) * CCKD_FREEBLK_SIZE;
2351 
2352             /* look for existing free space to fit new format free space */
2353             for (i = off = 0; !off && spctab[i].typ != SPCTAB_EOF; i++)
2354                 if (spctab[i].typ == SPCTAB_FREE && len <= (int)spctab[i].siz)
2355                     off = (off_t)spctab[i].pos;
2356 
2357             /* if no applicable space see if we can append to the file */
2358             if (!off && maxsize - cdevhdr.size >= len)
2359                 off = (off_t)cdevhdr.size;
2360 
2361             /* get free space buffer */
2362             if (off && (fsp = malloc (len)) == NULL)
2363                 off = 0;
2364 
2365             if (off)
2366             {
2367                 /* new format free space */
2368                 memcpy (fsp, "FREE_BLK", 8);
2369                 for (i = 0, j = 1; spctab[i].typ != SPCTAB_EOF; i++)
2370                     if (spctab[i].typ == SPCTAB_FREE)
2371                     {
2372                         fsp[j].pos = spctab[i].pos;
2373                         fsp[j++].len = spctab[i].siz;
2374                     }
2375 
2376                 /* Write the free space */
2377                 if (lseek (fd, off, SEEK_SET) < 0)
2378                     goto cdsk_lseek_error;
2379                 if ((rc = write (fd, fsp, len)) != len)
2380                     goto cdsk_write_error;
2381                 cdevhdr.free = (U32)off;
2382 
2383                 free (fsp);
2384                 fsp = NULL;
2385             } /* new format free space */
2386             else
2387             {
2388                 /* old format free space */
2389                 len = CCKD_FREEBLK_SIZE;
2390                 for (i = 0; spctab[i].typ != SPCTAB_FREE; i++);
2391                 cdevhdr.free = spctab[i].pos;
2392                 off = (off_t)spctab[i].pos;
2393                 freeblk.pos = 0;
2394                 freeblk.len = spctab[i].siz;
2395                 for (i = i + 1; spctab[i].typ != SPCTAB_EOF; i++)
2396                     if (spctab[i].typ == SPCTAB_FREE)
2397                     {
2398                         freeblk.pos = spctab[i].pos;
2399                         if (lseek (fd, off, SEEK_SET) < 0)
2400                             goto cdsk_lseek_error;
2401                         if (write (fd, &freeblk, len) != len)
2402                             goto cdsk_write_error;
2403                         off = (off_t)spctab[i].pos;
2404                         freeblk.pos = 0;
2405                         freeblk.len = spctab[i].len;
2406                     }
2407                 if (lseek (fd, off, SEEK_SET) < 0)
2408                     goto cdsk_lseek_error;
2409                 if (write (fd, &freeblk, len) != len)
2410                     goto cdsk_write_error;
2411             } /* old format free space */
2412         } /* if (cdevhdr.free_number) */
2413 
2414         /* Write cdevhdr and l1 table */
2415         off = CCKD_DEVHDR_POS;
2416         if (lseek (fd, off, SEEK_SET) < 0)
2417             goto cdsk_lseek_error;
2418         len = CCKD_DEVHDR_SIZE;
2419         if (write (fd, &cdevhdr, len) != len)
2420             goto cdsk_write_error;
2421 
2422         off = CCKD_L1TAB_POS;
2423         if (lseek (fd, off, SEEK_SET) < 0)
2424             goto cdsk_lseek_error;
2425         len = l1size;
2426         if (write (fd, l1, len) != len)
2427             goto cdsk_write_error;
2428 
2429         /* Truncate the file */
2430         off = (off_t)cdevhdr.size;
2431         if (cdevhdr.free == cdevhdr.size)
2432             off += (cdevhdr.free_number+1) * CCKD_FREEBLK_SIZE;
2433         rc = ftruncate (fd, off);
2434 
2435         cckdumsg (dev, 104, "free space rebuilt\n");
2436 
2437     } /* if (fsperr) */
2438 
2439     /*---------------------------------------------------------------
2440      * Return
2441      *---------------------------------------------------------------*/
2442 
2443 cdsk_return_ok:
2444 
2445     rc = recovery ? 2 : fsperr ? 1 : 0;
2446 
2447     if (!ro && (cdevhdr.options & (CCKD_ORDWR|CCKD_OPENED|CCKD_SPERRS)))
2448     {
2449         /*
2450          * Leave the ORDWR bit on for now.  This will prevent
2451          * old-format free space releases from doing a -1 check
2452          * on a file that has new-format free space
2453          */
2454 #if 0
2455         cdevhdr.options &= ~(CCKD_ORDWR|CCKD_OPENED|CCKD_SPERRS);
2456 #else
2457         cdevhdr.options &= ~(CCKD_OPENED|CCKD_SPERRS);
2458 #endif
2459         /* Set version.release.modlvl */
2460         cdevhdr.vrm[0] = CCKD_VERSION;
2461         cdevhdr.vrm[1] = CCKD_RELEASE;
2462         cdevhdr.vrm[2] = CCKD_MODLVL;
2463 
2464         off = CCKD_DEVHDR_POS;
2465         if (lseek (fd, CCKD_DEVHDR_POS, SEEK_SET) >= 0)
2466             write (fd, &cdevhdr, CCKD_DEVHDR_SIZE);
2467     }
2468 
2469 cdsk_return:
2470 
2471     /* free all space */
2472     if (l1)     free (l1);
2473     if (spctab) free (spctab);
2474     if (l2errs) free (l2errs);
2475     if (rcvtab) free (rcvtab);
2476     if (fsp)    free (fsp);
2477     if (l2)
2478     {
2479         for (i = 0; i < cdevhdr.numl1tab; i++)
2480             if (l2[i]) free (l2[i]);
2481         free (l2);
2482     }
2483 
2484     return rc;
2485 
2486     /*---------------------------------------------------------------
2487      * Error exits
2488      *---------------------------------------------------------------*/
2489 
2490 cdsk_fstat_error:
2491 
2492     cckdumsg (dev, 701, "fstat error: %s\n", strerror(errno));
2493     goto cdsk_error;
2494 
2495 cdsk_lseek_error:
2496 
2497     cckdumsg (dev, 702, "lseek error offset 0x%" I64_FMT "x: %s\n",
2498               (long long)off, strerror(errno));
2499     goto cdsk_error;
2500 
2501 cdsk_read_error:
2502 
2503     cckdumsg (dev, 703, "read error rc=%d offset 0x%" I64_FMT "x len %d: %s\n",
2504               rc, (long long)off, len, rc < 0 ? strerror(errno) : "incomplete");
2505     goto cdsk_error;
2506 
2507 cdsk_write_error:
2508 
2509     cckdumsg (dev, 704, "write error rc=%d offset 0x%" I64_FMT "x len %d: %s\n",
2510               rc, (long long)off, len, rc < 0 ? strerror(errno) : "incomplete");
2511     goto cdsk_error;
2512 
2513 cdsk_malloc_error:
2514 
2515     cckdumsg (dev, 705, "malloc error, size=%d: %s\n",
2516               len, strerror(errno));
2517     goto cdsk_error;
2518 
2519 cdsk_calloc_error:
2520 
2521     cckdumsg (dev, 706, "calloc error, size=%d: %s\n",
2522               n*len, strerror(errno));
2523     goto cdsk_error;
2524 
2525 cdsk_error:
2526     rc = -1;
2527     goto cdsk_return;
2528 
2529 } /* end function cckd_chkdsk */
2530 
2531 /*-------------------------------------------------------------------
2532  * cckd_chkdsk() space table sort
2533  *-------------------------------------------------------------------*/
cdsk_spctab_sort(const void * a,const void * b)2534 static int cdsk_spctab_sort(const void *a, const void *b)
2535 {
2536 const SPCTAB *x = a, *y = b;
2537 
2538     if (x->typ == SPCTAB_NONE)      return  1;
2539     else if (y->typ == SPCTAB_NONE) return -1;
2540     else if (x->typ == SPCTAB_EOF)  return  1;
2541     else if (y->typ == SPCTAB_EOF)  return -1;
2542     else if (x->pos < y->pos)       return -1;
2543     else                            return  1;
2544 } /* end function cdsk_spctab_sort */
2545 
2546 /*-------------------------------------------------------------------*/
2547 /* Build free space in the space table                               */
2548 /*-------------------------------------------------------------------*/
cdsk_build_free_space(SPCTAB * spctab,int s)2549 static int cdsk_build_free_space(SPCTAB *spctab, int s)
2550 {
2551 int i;
2552 
2553     for (i = 0; i < s; i++)
2554         if (spctab[i].typ == SPCTAB_FREE)
2555             spctab[i].typ = SPCTAB_NONE;
2556     qsort (spctab, s, sizeof(SPCTAB), cdsk_spctab_sort);
2557     while (spctab[s-1].typ == SPCTAB_NONE) s--;
2558     for (i = 0; spctab[i].typ != SPCTAB_EOF; i++)
2559         if (spctab[i].pos + spctab[i].siz < spctab[i+1].pos)
2560         {
2561             spctab[s].typ = SPCTAB_FREE;
2562             spctab[s].val = -1;
2563             spctab[s].pos = spctab[i].pos + spctab[i].siz;
2564             spctab[s].len =
2565             spctab[s].siz = spctab[i+1].pos - spctab[s].pos;
2566             s++;
2567         }
2568     qsort (spctab, s, sizeof(SPCTAB), cdsk_spctab_sort);
2569     return s;
2570 }
2571 
2572 /*-------------------------------------------------------------------*/
2573 /* Validate a track image                                            */
2574 /*                                                                   */
2575 /* If `len' is negative and compression is CCKD_COMPRESS_NONE then   */
2576 /* `len' indicates a buffer size containing the track image and the  */
2577 /* value returned is the actual track image length                   */
2578 /*-------------------------------------------------------------------*/
cdsk_valid_trk(int trk,BYTE * buf,int heads,int len)2579 static int cdsk_valid_trk (int trk, BYTE *buf, int heads, int len)
2580 {
2581 int             i;                      /* Index                     */
2582 int             len2;                   /* Positive `len'            */
2583 int             kl, dl;                 /* Key/Data lengths          */
2584 BYTE           *bufp;                   /* Buffer pointer            */
2585 int             bufl;                   /* Buffer length             */
2586 #ifdef HAVE_LIBZ
2587 uLongf          zlen;
2588 #endif
2589 #ifdef CCKD_BZIP2
2590 unsigned int    bz2len;
2591 #endif
2592 #if defined(HAVE_LIBZ) || defined(CCKD_BZIP2)
2593 int             rc;                     /* Return code               */
2594 BYTE            buf2[65536];            /* Uncompressed buffer       */
2595 #endif
2596 
2597     /* Negative len only allowed for comp none */
2598     len2 = len > 0 ? len : -len;
2599 
2600     if (len2 < CKDDASD_TRKHDR_SIZE + 8)
2601         return 0;
2602 
2603     /* Uncompress the track/block image */
2604     switch (buf[0]) {
2605 
2606     case CCKD_COMPRESS_NONE:
2607         bufp = buf;
2608         bufl = len2;
2609         break;
2610 
2611 #ifdef HAVE_LIBZ
2612     case CCKD_COMPRESS_ZLIB:
2613         if (len < 0) return 0;
2614         bufp = (BYTE *)buf2;
2615         memcpy (buf2, buf, CKDDASD_TRKHDR_SIZE);
2616         zlen = sizeof(buf2) - CKDDASD_TRKHDR_SIZE;
2617         rc = uncompress (buf2 + CKDDASD_TRKHDR_SIZE, &zlen,
2618                          buf + CKDDASD_TRKHDR_SIZE, len - CKDDASD_TRKHDR_SIZE);
2619         if (rc != Z_OK)
2620             return 0;
2621         bufl = (int)zlen + CKDDASD_TRKHDR_SIZE;
2622         break;
2623 #endif
2624 
2625 #ifdef CCKD_BZIP2
2626     case CCKD_COMPRESS_BZIP2:
2627         if (len < 0) return 0;
2628         bufp = (BYTE *)buf2;
2629         memcpy (buf2, buf, CKDDASD_TRKHDR_SIZE);
2630         bz2len = sizeof(buf2) - CKDDASD_TRKHDR_SIZE;
2631         rc = BZ2_bzBuffToBuffDecompress ( (char *)&buf2[CKDDASD_TRKHDR_SIZE], &bz2len,
2632                          (char *)&buf[CKDDASD_TRKHDR_SIZE], len - CKDDASD_TRKHDR_SIZE, 0, 0);
2633         if (rc != BZ_OK)
2634             return 0;
2635         bufl = (int)bz2len + CKDDASD_TRKHDR_SIZE;
2636         break;
2637 #endif
2638 
2639     default:
2640         return 0;
2641 
2642     } /* switch (buf[0]) */
2643 
2644     /* fba check */
2645     if (heads == 65536)
2646     {
2647         if (bufl != CFBA_BLOCK_SIZE + CKDDASD_TRKHDR_SIZE)
2648             return 0;
2649         else
2650             return len > 0 ? len : bufl;
2651     }
2652     /* Check length */
2653     if (bufl <= 5 + 8 + 8 + 8 + 8) return 0;
2654     /* Check ha */
2655     if (fetch_hw(bufp + 1) != trk / heads
2656      || fetch_hw(bufp + 3) != trk % heads)
2657         return 0;
2658     /* Check r0 */
2659     if (fetch_hw(bufp + 1) != fetch_hw(bufp + 5)
2660      || fetch_hw(bufp + 3) != fetch_hw(bufp + 7)
2661      || bufp[9] != 0       || bufp[10] != 0
2662      || fetch_hw(bufp +11) != 8)
2663         return 0;
2664     /* Check user records */
2665     for (i = 21; i < bufl - 8; i += 8 + kl + dl)
2666     {
2667         if (fetch_hw(bufp + i + 2) >= heads || bufp[i + 4] == 0)
2668             break;
2669         kl = bufp[i + 5];
2670         dl = fetch_hw(bufp + i + 6);
2671     }
2672     if (len < 0) bufl = i + 8;
2673     if (i != bufl - 8 || memcmp(bufp + i, eighthexFF, 8))
2674         return 0;
2675     return len > 0 ? len : bufl;
2676 } /* end function cdsk_valid_trk */
2677 
2678 /*-------------------------------------------------------------------*/
2679 /* Message function                                                  */
2680 /*-------------------------------------------------------------------*/
cckdumsg(DEVBLK * dev,int n,char * format,...)2681 DLL_EXPORT void cckdumsg (DEVBLK *dev, int n, char *format, ...)
2682 {
2683 CCKDDASD_EXT *cckd;
2684 int           sfx;
2685 int           i;
2686 char         *p;
2687 va_list       vl;
2688 char          msg[4096];
2689 
2690     cckd = dev->cckd_ext;
2691     sfx = cckd ? cckd->sfn : -1;
2692 
2693     i = sprintf (msg, "HHCCU%3.3d%c ",
2694                  n, n < 400 ? 'I' : n < 700 ? 'W' : 'E');
2695 
2696     if (sfx >= 0)
2697         i += sprintf (msg+i, "%4.4X file[%d]: ", dev->devnum, sfx);
2698     else
2699     {
2700         if ((p = strrchr(dev->filename,  '/')) == NULL
2701          && (p = strrchr(dev->filename, '\\')) == NULL)
2702             p = dev->filename;
2703         else
2704             p++;
2705         i += sprintf (msg+i, "%s: ", p);
2706     }
2707 
2708     va_start (vl, format);
2709     vsprintf (msg+i, format, vl);
2710     va_end (vl);
2711 
2712     if (dev->batch)
2713         fprintf(stdout,"%s",msg);
2714     else
2715         logmsg("%s",msg);
2716 }
2717