Merge /u/jrubio/cdesktopenv/ branch dtksh_include_sys_sysmacros into master
[oweals/cde.git] / cde / programs / dtksh / ksh93 / src / cmd / pax / format.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these libraries and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $XConsortium: format.c /main/3 1995/11/01 17:00:37 rswiston $ */
24 /***************************************************************
25 *                                                              *
26 *                      AT&T - PROPRIETARY                      *
27 *                                                              *
28 *         THIS IS PROPRIETARY SOURCE CODE LICENSED BY          *
29 *                          AT&T CORP.                          *
30 *                                                              *
31 *                Copyright (c) 1995 AT&T Corp.                 *
32 *                     All Rights Reserved                      *
33 *                                                              *
34 *           This software is licensed by AT&T Corp.            *
35 *       under the terms and conditions of the license in       *
36 *       http://www.research.att.com/orgs/ssr/book/reuse        *
37 *                                                              *
38 *               This software was created by the               *
39 *           Software Engineering Research Department           *
40 *                    AT&T Bell Laboratories                    *
41 *                                                              *
42 *               For further information contact                *
43 *                     gsf@research.att.com                     *
44 *                                                              *
45 ***************************************************************/
46
47 /* : : generated by proto : : */
48
49 #if !defined(__PROTO__)
50 #if defined(__STDC__) || defined(__cplusplus) || defined(_proto) || defined(c_plusplus)
51 #if defined(__cplusplus)
52 #define __MANGLE__      "C"
53 #else
54 #define __MANGLE__
55 #endif
56 #define __STDARG__
57 #define __PROTO__(x)    x
58 #define __OTORP__(x)
59 #define __PARAM__(n,o)  n
60 #if !defined(__STDC__) && !defined(__cplusplus)
61 #if !defined(c_plusplus)
62 #define const
63 #endif
64 #define signed
65 #define void            int
66 #define volatile
67 #define __V_            char
68 #else
69 #define __V_            void
70 #endif
71 #else
72 #define __PROTO__(x)    ()
73 #define __OTORP__(x)    x
74 #define __PARAM__(n,o)  o
75 #define __MANGLE__
76 #define __V_            char
77 #define const
78 #define signed
79 #define void            int
80 #define volatile
81 #endif
82 #if defined(__cplusplus) || defined(c_plusplus)
83 #define __VARARG__      ...
84 #else
85 #define __VARARG__
86 #endif
87 #if defined(__STDARG__)
88 #define __VA_START__(p,a)       va_start(p,a)
89 #else
90 #define __VA_START__(p,a)       va_start(p)
91 #endif
92 #endif
93
94 #if defined(__linux__)
95 #include <sys/sysmacros.h>
96 #endif
97
98 #include "pax.h"
99 #include "options.h"
100
101 #if __hppa__ || __hppa || hppa
102
103 /*
104  * the inline macros are apparently too much for the hp optimizer
105  * (the calls in putprologue() make the difference)
106  */
107
108 static int
109 delta_lo __PARAM__((long x), (x)) __OTORP__(long x;){
110         return(DELTA_LO(x));
111 }
112
113 #undef  DELTA_LO
114 #define DELTA_LO        delta_lo
115
116 static int
117 delta_hi __PARAM__((long x), (x)) __OTORP__(long x;){
118         return(DELTA_HI(x));
119 }
120
121 #undef  DELTA_HI
122 #define DELTA_HI        delta_hi
123
124 #endif
125
126 /*
127  * check for ASCII or EBCDIC ALAR prologue in alar_header
128  */
129
130 static int
131 isalar __PARAM__((Archive_t* ap, char* hdr), (ap, hdr)) __OTORP__(Archive_t* ap; char* hdr;){
132         char            buf[4];
133
134         if (!strneq(hdr, "VOL1", 4))
135         {
136                 memetoa(buf, hdr, 4);
137                 if (!strneq(buf, "VOL1", 4)) return(0);
138                 memetoa(hdr, hdr, ALAR_HEADER);
139                 ap->format = IBMAR;
140         }
141         else ap->format = ALAR;
142         getlabstr(hdr, 5, 6, state.id.volume);
143         getlabstr(hdr, 25, 6, state.id.format);
144         getlabstr(hdr, 31, 7, state.id.implementation);
145         getlabstr(hdr, 38, 14, state.id.owner);
146         ap->io.blocked = !bcount(ap);
147         return(1);
148 }
149
150 /*
151  * read archive prologue before files are copied
152  */
153
154 int
155 getprologue __PARAM__((Archive_t* ap), (ap)) __OTORP__(Archive_t* ap;){
156         int     n;
157         long    size;
158
159         if (ap->volume && ap->io.mode) return(0);
160         state.id.volume[0] = 0;
161         ap->format = IN_DEFAULT;
162         ap->io.offset += ap->io.count;
163         ap->io.count = 0;
164         if (bread(ap, alar_header, (long)ALAR_HEADER, (long)ALAR_HEADER, 0) <= 0)
165         {
166                 if (!bcount(ap)) return(0);
167         }
168         else if (!isalar(ap, alar_header))
169         {
170                 if (strneq(alar_header, PORTAR_MAG, PORTAR_MAGSIZ))
171                 {
172                         bunread(ap, alar_header, ALAR_HEADER - 8);
173                         if (bread(ap, &portar_header, 0L, (long)PORTAR_HEADER, 0) > 0)
174                         {
175                                 if (!strneq(portar_header.ar_fmag, PORTAR_END, PORTAR_ENDSIZ) || sscanf(portar_header.ar_size, "%ld", &size) != 1)
176                                 {
177                                         bunread(ap, &portar_header, PORTAR_HEADER);
178                                         bunread(ap, PORTAR_MAG, PORTAR_MAGSIZ);
179                                 }
180                                 else
181                                 {
182                                         size += (size & 01);
183                                         if (strmatch(portar_header.ar_name, PORTAR_SYM) && (ap->format = PORTAR) || strmatch(portar_header.ar_name, RANDAR_SYM) && (ap->format = RANDAR))
184                                         {
185                                                 if (bread(ap, NiL, 0L, size, 0) <= 0)
186                                                         error(3, "%s: invalid %s format symbol table", ap->name, format[ap->format].name);
187                                                 n = bread(ap, &portar_header, 0L, (long)PORTAR_HEADER, 0);
188                                         }
189                                         else
190                                         {
191                                                 n = portar_header.ar_date[0];
192                                                 portar_header.ar_date[0] = 0;
193                                                 ap->format = strchr(portar_header.ar_name, PORTAR_TERM) ? PORTAR : RANDAR;
194                                                 portar_header.ar_date[0] = n;
195                                                 n = 1;
196                                         }
197                                         if (n > 0)
198                                         {
199                                                 if (portar_header.ar_name[0] == PORTAR_TERM && portar_header.ar_name[1] == PORTAR_TERM && portar_header.ar_name[2] == ' ' && sscanf(portar_header.ar_size, "%ld", &size) == 1)
200                                                 {
201                                                         size += (size & 01);
202                                                         if (!(ap->names = newof(0, char, size, 0)))
203                                                                 error(3, "%s: cannot allocate %s format long name table", ap->name, format[ap->format].name);
204                                                         if (bread(ap, ap->names, 0L, size, 0) <= 0)
205                                                                 error(3, "%s: invalid %s format long name table", ap->name, format[ap->format].name);
206                                                 }
207                                                 else bunread(ap, &portar_header, PORTAR_HEADER);
208                                         }
209                                 }
210                         }
211                 }
212                 else if (strneq(alar_header, "<ar>", 4) ||      /* s5r1  */
213                         swapget(0, alar_header, 2) == 0177545 ||/* pdp11 */
214                         swapget(1, alar_header, 2) == 0177545)  /* pdp11 */
215                                 error(3, "%s: use ar(1) for library archives", ap->name);
216                 else
217                 {
218                         int     m;
219
220                         m = ((*((unsigned char*)alar_header))<<8)|(*((unsigned char*)alar_header+1));
221                         for (n = COMPRESS; n < DELTA; n++)
222                                 if (format[n].special == m)
223                                 {
224                                         ap->compress = n;
225                                         break;
226                                 }
227                         bunread(ap, alar_header, ALAR_HEADER);
228                         if (ap->compress)
229                         {
230                                 Proc_t* proc;
231                                 long    ops[3];
232                                 char*   cmd[2];
233
234                                 if (bseek(ap, 0L, SEEK_SET))
235                                         error(3, "%s: %s input must be seekable", ap->name, format[ap->compress].name);
236                                 cmd[0] = format[ap->compress].undo;
237                                 cmd[1] = 0;
238                                 ops[0] = PROC_FD_DUP(ap->io.fd, 0, PROC_FD_CHILD);
239                                 if (ap->parent && !state.ordered)
240                                 {
241                                         if ((n = open(state.tmp.file, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR)) < 0)
242                                                 error(ERROR_SYSTEM|3, "%s: cannot create %s base temporary file %s", ap->name, format[ap->compress].undo, state.tmp.file);
243                                         ops[1] = PROC_FD_DUP(n, 1, PROC_FD_CHILD);
244                                         ops[2] = 0;
245                                         proc = procopen(*cmd, cmd, NiL, ops, 0);
246                                 }
247                                 else
248                                 {
249                                         ops[1] = 0;
250                                         proc = procopen(*cmd, cmd, NiL, ops, PROC_READ);
251                                 }
252                                 if (!proc)
253                                         error(3, "%s: cannot execute %s filter", ap->name, format[ap->compress].undo);
254                                 close(ap->io.fd);
255                                 if (ap->parent && !state.ordered)
256                                 {
257                                         close(n);
258                                         if (n = procclose(proc))
259                                                 error(3, "%s: %s filter exit code %d", ap->name, format[ap->compress].undo, n);
260                                         if ((ap->io.fd = open(state.tmp.file, O_RDONLY)) < 0)
261                                                 error(ERROR_SYSTEM|3, "%s: cannot read %s base temporary file %s", ap->name, format[ap->compress].undo, state.tmp.file);
262                                         if (remove(state.tmp.file))
263                                                 error(ERROR_SYSTEM|1, "%s: cannot remove %s base temporary file %s", ap->name, format[ap->compress].undo, state.tmp.file);
264                                 }
265                                 else
266                                 {
267                                         List_t* p;
268
269                                         ap->io.fd = proc->rfd;
270                                         if (!(p = newof(0, List_t, 1, 0)))
271                                                 error(3, "out of space [state.proc]");
272                                         p->item = (__V_*)proc;
273                                         p->next = state.proc;
274                                         state.proc = p;
275                                 }
276                         }
277                 }
278         }
279         if (ap->volume++)
280         {
281                 if (ap->delta)
282                 {
283                         if (state.operation == (IN|OUT) || ap->delta->format != DELTA)
284                                 error(3, "%s: %s archive cannot be multi-volume", ap->name, ap->parent ? "base" : "delta");
285                         ap->delta = 0;
286                 }
287
288                 /*
289                  * no hard links between volumes
290                  */
291
292                 hashfree(state.linktab);
293                 if (!(state.linktab = hashalloc(NiL, HASH_set, HASH_ALLOCATE, HASH_namesize, sizeof(Fileid_t), HASH_name, "links", 0)))
294                         error(3, "cannot re-allocate hard link table");
295         }
296         ap->entry = 0;
297         return(1);
298 }
299
300 /*
301  * set pseudo file header+trailer info
302  */
303
304 static void
305 setinfo __PARAM__((Archive_t* ap, File_t* f), (ap, f)) __OTORP__(Archive_t* ap; File_t* f;){
306         long    n;
307
308         if (ap->delta)
309         {
310                 if (ap->delta->format != DELTA_IGNORE && ap->entry > 1 && f->st->st_mtime)
311                 {
312                         if ((n = f->st->st_mtime - ap->delta->index) < 0)
313                                 error(3, "%s: corrupt archive: %d extra file%s", ap->name, -n, n == -1 ? "" : "s");
314                         else if (n > 0)
315                                 error(3, "%s: corrupt archive: %d missing file%s", ap->name, n, n == 1 ? "" : "s");
316                 }
317                 ap->delta->epilogue = 1;
318         }
319 }
320
321 /*
322  * output pseudo file header+trailer
323  */
324
325 static void
326 putinfo __PARAM__((Archive_t* ap, char* file, unsigned long mtime, unsigned long checksum), (ap, file, mtime, checksum)) __OTORP__(Archive_t* ap; char* file; unsigned long mtime; unsigned long checksum;){
327         File_t* f = &ap->file;
328         Sfio_t*                 np = 0;
329
330         if (!file)
331         {
332                 np = sfstropen();
333                 if (!ap->delta || ap->delta->version == DELTA_88) sfprintf(np, "DELTA");
334                 else
335                 {
336                         sfprintf(np, "%c%s%c%c%c%s", INFO_SEP, ID, INFO_SEP, ap->delta->format == DELTA ? TYPE_DELTA : TYPE_COMPRESS, INFO_SEP, format[ap->delta->version ? ap->delta->version : DELTA].algorithm);
337                         if (state.ordered)
338                                 sfprintf(np, "%c%c", INFO_SEP, INFO_ORDERED);
339                 }
340                 sfprintf(np, "%c%c%c", INFO_SEP, INFO_SEP, INFO_SEP);
341                 file = sfstruse(np);
342         }
343         initfile(ap, f, file, X_IFREG);
344         f->skip = 1;
345         f->st->st_mtime = mtime;
346         f->st->st_uid = DELTA_LO(checksum);
347         f->st->st_gid = DELTA_HI(checksum);
348         putheader(ap, f);
349         puttrailer(ap, f);
350         if (np) sfstrclose(np);
351 }
352
353 /*
354  * write archive prologue before files are copied
355  */
356
357 void
358 putprologue __PARAM__((Archive_t* ap), (ap)) __OTORP__(Archive_t* ap;){
359         if (ap->delta && ap->delta->version == DELTA_88)
360                 ap->checksum = ap->old.checksum;
361         switch (ap->format)
362         {
363         case ALAR:
364         case IBMAR:
365 #if DEBUG
366                 if (ap->io.blok) ap->io.blocked = 1;
367                 else
368 #endif
369                 ap->io.blocked = !ap->io.unblocked;
370                 if (!state.id.owner[0])
371                 {
372                         strncpy(state.id.owner, fmtuid(getuid()), sizeof(state.id.owner) - 1);
373                         state.id.owner[sizeof(state.id.owner) - 1] = 0;
374                 }
375                 strupper(state.id.owner);
376                 if (!state.id.volume[0])
377                 {
378                         strncpy(state.id.volume, state.id.owner, sizeof(state.id.volume) - 1);
379                         state.id.volume[sizeof(state.id.volume) - 1] = 0;
380                 }
381                 strupper(state.id.volume);
382                 strncpy(state.id.format, ALAR_ID, sizeof(state.id.format) - 1);
383                 strncpy(state.id.implementation, IMPLEMENTATION, sizeof(state.id.implementation) - 1);
384                 if (ap->format == IBMAR) sfsprintf(state.id.standards, sizeof(state.id.standards), "%-5.5s%-5.5s%-5.5s%-4.4s", "ATTBL", "1", "EBCDIC", "1979");
385                 else sfsprintf(state.id.standards, sizeof(state.id.standards), "%-5.5s%-5.5s%-5.5s%-4.4s", "ISO", "646", "IRV", "1990");
386                 sfsprintf(alar_header, sizeof(alar_header), "VOL1%-6.6s              %-6.6s%-7.7s%-14.14s                            4", state.id.volume, state.id.format, state.id.implementation, state.id.owner);
387                 if (ap->format == IBMAR) mematoe(alar_header, alar_header, ALAR_HEADER);
388                 bwrite(ap, alar_header, ALAR_HEADER);
389                 sfsprintf(alar_header, sizeof(alar_header), "VOL2%-19.19s                                                        ", state.id.standards);
390                 if (ap->format == IBMAR) mematoe(alar_header, alar_header, ALAR_HEADER);
391                 bwrite(ap, alar_header, ALAR_HEADER);
392                 if (ap->delta && (ap->delta->format == COMPRESS || ap->delta->format == DELTA))
393                 {
394                         sfsprintf(alar_header, sizeof(alar_header), "UVL1 %-6.6s%c%-6.6s%010ld%010ld                                         ", ID, ap->delta->format == DELTA ? TYPE_DELTA : TYPE_COMPRESS, format[ap->delta->version ? ap->delta->version : DELTA].algorithm, state.operation == OUT ? ap->size : 0L, state.operation == OUT ? ap->checksum : 0L);
395                         if (ap->format == IBMAR) mematoe(alar_header, alar_header, ALAR_HEADER);
396                         bwrite(ap, alar_header, ALAR_HEADER);
397                 }
398                 break;
399         case VDB:
400                 state.vdb.directory = sfstropen();
401                 sfprintf(state.vdb.directory, "%c%s%c%s\n", VDB_DELIMITER, VDB_MAGIC, VDB_DELIMITER, state.id.volume);
402                 bwrite(ap, sfstrbase(state.vdb.directory), sfstrtell(state.vdb.directory));
403                 sfstrset(state.vdb.directory, 0);
404                 sfprintf(state.vdb.directory, "%s\n", VDB_DIRECTORY);
405                 break;
406         default:
407                 if (ap->delta && (ap->delta->format == COMPRESS || ap->delta->format == DELTA))
408                 {
409                         if (ap->delta->base) putinfo(ap, NiL, ap->delta->base->size, ap->delta->base->checksum);
410                         else putinfo(ap, NiL, 0, 0);
411                 }
412                 break;
413         }
414 }
415
416 /*
417  * read archive epilogue after all files have been copied
418  */
419
420 void
421 getepilogue __PARAM__((Archive_t* ap), (ap)) __OTORP__(Archive_t* ap;){
422         char*   s;
423         long    n;
424         long    i;
425
426         if (ap->delta && ap->delta->epilogue < 0)
427                 error(3, "%s: corrupt archive: missing epilogue", ap->name);
428         if (ap->io.mode) backup(ap);
429         else
430         {
431                 if (ap->names)
432                 {
433                         free(ap->names);
434                         ap->names = 0;
435                 }
436                 switch (ap->format)
437                 {
438                 case ALAR:
439                 case IBMAR:
440                 case PORTAR:
441                 case RANDAR:
442 #if SAVESET
443                 case SAVESET:
444 #endif
445                         break;
446                 case VDB:
447                         if (state.vdb.header.base)
448                         {
449                                 free(state.vdb.header.base);
450                                 state.vdb.header.base = 0;
451                         }
452                         break;
453                 default:
454                         /*
455                          * check for more volumes
456                          * volumes begin on BLOCKSIZE boundaries
457                          * separated by up to MAXBLOCKS null byte filler
458                          */
459
460                         if (ap->io.keep)
461                         {
462                                 bskip(ap);
463                                 if (ap->io.eof) ap->io.keep = 0;
464                                 else if (ap->io.keep > 0) ap->io.keep--;
465                                 ap->format = IN_DEFAULT;
466                                 message((-2, "go for next tape volume"));
467                                 return;
468                         }
469                         i = MAXBLOCKS;
470                         if (!(n = roundof(ap->io.count, BLOCKSIZE) - ap->io.count) || bread(ap, state.tmp.buffer, 0L, (long)n, 0) > 0) do
471                         {
472                                 if (*(s = state.tmp.buffer) && n == BLOCKSIZE)
473                                 {
474                                         bunread(ap, state.tmp.buffer, BLOCKSIZE);
475                                         ap->format = IN_DEFAULT;
476                                         message((-2, "go for next volume %-.32s...", state.tmp.buffer));
477                                         return;
478                                 }
479                                 while (s < state.tmp.buffer + n && !*s++);
480                                 if (s < state.tmp.buffer + n)
481                                 {
482                                         if (ap->volume > 1) error(1, "junk data after volume %d", ap->volume);
483                                         break;
484                                 }
485                                 n = BLOCKSIZE;
486                         } while (i-- > 0 && bread(ap, state.tmp.buffer, 0L, n, 0) > 0);
487                         bflushin(ap);
488                         break;
489                 }
490                 ap->format = IN_DEFAULT;
491         }
492 }
493
494 /*
495  * write archive epilogue after files have been copied
496  */
497
498 void
499 putepilogue __PARAM__((Archive_t* ap), (ap)) __OTORP__(Archive_t* ap;){
500         long            n;
501         unsigned long   boundary;
502
503         static int              selected;
504
505         if (ap->selected > selected)
506         {
507                 if (ap->delta && (ap->delta->format == COMPRESS || ap->delta->format == DELTA)) switch (ap->format)
508                 {
509                 case BINARY:
510                 case CPIO:
511                 case ASC:
512                 case ASCHK:
513                         break;
514                 default:
515                         putinfo(ap, NiL, ap->delta->index + 1, 0);
516                         break;
517                 }
518                 selected = ap->selected;
519                 boundary = ap->io.count;
520                 switch (ap->format)
521                 {
522                 case ALAR:
523                 case IBMAR:
524                         bwrite(ap, alar_header, 0);
525                         bwrite(ap, alar_header, 0);
526                         break;
527                 case BINARY:
528                 case CPIO:
529                 case ASC:
530                 case ASCHK:
531                         putinfo(ap, CPIO_TRAILER, ap->delta && (ap->delta->format == COMPRESS || ap->delta->format == DELTA) ? ap->delta->index + 1 : 0, 0);
532                         boundary = ap->io.unblocked ? BLOCKSIZE : state.blocksize;
533                         break;
534                 case PAX:
535                 case TAR:
536                 case USTAR:
537                         memzero(tar_block, TAR_HEADER);
538                         bwrite(ap, tar_block, TAR_HEADER);
539                         bwrite(ap, tar_block, TAR_HEADER);
540                         boundary = ap->io.unblocked ? BLOCKSIZE : state.blocksize;
541                         break;
542                 case VDB:
543                         if (state.record.header)
544                                 bwrite(ap, state.record.header, state.record.headerlen);
545                         sfprintf(state.vdb.directory, "%c%s%c%0*lu%c%0*lu\n", VDB_DELIMITER, VDB_DIRECTORY, VDB_DELIMITER, VDB_FIXED, ap->io.offset + ap->io.count + sizeof(VDB_DIRECTORY), VDB_DELIMITER, VDB_FIXED, sftell(state.vdb.directory) - sizeof(VDB_DIRECTORY) + VDB_LENGTH + 1);
546                         bwrite(ap, sfstrbase(state.vdb.directory), sfstrtell(state.vdb.directory));
547                         sfstrclose(state.vdb.directory);
548                         boundary = ap->io.count;
549                         break;
550                 }
551                 if ((n = boundary - ap->io.count) < 0)
552                         n = roundof(ap->io.count, boundary) - ap->io.count;
553                 if (n)
554                 {
555                         memzero(state.tmp.buffer, n);
556                         bwrite(ap, state.tmp.buffer, n);
557                 }
558                 bflushout(ap);
559                 ap->volume++;
560         }
561         else
562         {
563                 ap->io.count = ap->io.offset = 0;
564                 ap->io.next = ap->io.buffer;
565         }
566 }
567
568 #if CPIO_EXTENDED
569
570 static char     opsbuf[PATH_MAX];       /* extended ops buffer          */
571
572 static char*    ops = opsbuf;           /* opsbuf output pointer        */
573
574 /*
575  * get and execute extended ops from input
576  */
577
578 static void
579 getxops __PARAM__((Archive_t* ap, File_t* f), (ap, f)) __OTORP__(Archive_t* ap; File_t* f;){
580         char*   p;
581         char*   s;
582         int     c;
583         long            n;
584
585         if (f->namesize > (n = strlen(f->name) + 1)) for (p = f->name + n; c = *p++;)
586         {
587                 for (s = p; *p; p++);
588                 p++;
589                 n = strtol(s, NiL, 16);
590                 message((-2, "%s: %s: entry %d.%d op = %c%s", ap->name, f->name, ap->volume, ap->entry, c, s));
591                 switch (c)
592                 {
593                 case 'd':
594                         IDEVICE(f->st, n);
595                         break;
596                 case 'g':
597                         f->st->st_gid = n;
598                         break;
599                 case 'u':
600                         f->st->st_uid = n;
601                         break;
602                 case 'G':
603                         f->gidname = s;
604                         break;
605                 case 'U':
606                         f->uidname = s;
607                         break;
608
609                         /*
610                          * NOTE: ignore unknown ops for future extensions
611                          */
612                 }
613         }
614 }
615
616 /*
617  * set end of extended ops
618  */
619
620 static void
621 setxops __PARAM__((Archive_t* ap, File_t* f), (ap, f)) __OTORP__(Archive_t* ap; File_t* f;){
622         int     n;
623
624         NoP(ap);
625         if (n = ops - opsbuf)
626         {
627                 n++;
628                 *ops++ = 0;
629                 if ((f->namesize += n) > CPIO_NAMESIZE) error(1, "%s: extended ops may crash older cpio programs", f->name);
630         }
631 }
632
633 /*
634  * output filename and extended ops
635  */
636
637 static void
638 putxops __PARAM__((Archive_t* ap, File_t* f), (ap, f)) __OTORP__(Archive_t* ap; File_t* f;){
639         int     n;
640
641         n = ops - opsbuf;
642         bwrite(ap, f->name, f->namesize -= n);
643         if (n) bwrite(ap, ops = opsbuf, n);
644 }
645
646
647 /*
648  * add extended op string
649  */
650
651 static void
652 addxopstr __PARAM__((Archive_t* ap, int op, char* s), (ap, op, s)) __OTORP__(Archive_t* ap; int op; char* s;){
653         char*   p = ops;
654         char*   e = opsbuf + sizeof(opsbuf) - 3;
655
656         NoP(ap);
657         if (p < e)
658         {
659                 *p++ = op;
660                 while (*s && p < e) *p++ = *s++;
661                 *p++ = 0;
662                 ops = p;
663         }
664 #if DEBUG
665         if (*s) error(PANIC, "addxopstr('%c',\"%s\") overflow", op, s);
666 #endif
667 }
668
669 /*
670  * add extended op number
671  */
672
673 static void
674 addxopnum __PARAM__((Archive_t* ap, int op, long n), (ap, op, n)) __OTORP__(Archive_t* ap; int op; long n;){
675         char    buf[17];
676
677         sfsprintf(buf, sizeof(buf), "%x", n);
678         addxopstr(ap, op, buf);
679 }
680
681 #endif
682
683 /*
684  * get key name value
685  */
686
687 static void
688 getkeyname __PARAM__((Archive_t* ap, File_t* f, int index, char** nm), (ap, f, index, nm)) __OTORP__(Archive_t* ap; File_t* f; int index; char** nm;){
689         Option_t*       op;
690
691         static int              uinit;
692         static int              ginit;
693         static uid_t            euid;
694         static gid_t            egid;
695
696         op = &options[index];
697         if (op->level >= 6) switch (index)
698         {
699         case OPT_gname:
700                 *nm = 0;
701                 if (!uinit)
702                 {
703                         uinit = 1;
704                         euid = geteuid();
705                 }
706                 f->st->st_uid = euid;
707                 break;
708         case OPT_uname:
709                 *nm = 0;
710                 if (!ginit)
711                 {
712                         ginit = 1;
713                         egid = getegid();
714                 }
715                 f->st->st_gid = egid;
716                 break;
717         }
718         else if (op->level < 5)
719         {
720                 if (op->entry == ap->entry || op->level > 3)
721                         *nm = op->temp.string;
722                 else if (op->level >= 1 && op->level < 3)
723                         *nm = op->perm.string;
724         }
725 }
726
727 /*
728  * get key time value
729  */
730
731 static void
732 getkeytime __PARAM__((Archive_t* ap, File_t* f, int index, time_t* tm), (ap, f, index, tm)) __OTORP__(Archive_t* ap; File_t* f; int index; time_t* tm;){
733         Option_t*       op;
734
735         NoP(f);
736         op = &options[index];
737         if (op->level >= 6)
738                 *tm = time((time_t*)0);
739         else if (op->level < 5)
740         {
741                 if (op->entry == ap->entry || op->level >= 3)
742                         *tm = op->temp.number;
743                 else if (op->level >= 1)
744                         *tm = op->perm.number;
745         }
746 }
747
748 /*
749  * read next archive entry header
750  */
751
752 int
753 getheader __PARAM__((Archive_t* ap, File_t* f), (ap, f)) __OTORP__(Archive_t* ap; File_t* f;){
754         char*   s;
755         int     i;
756         long    n;
757         char*           t;
758         long            num;
759         int             warned;
760         int             checkdelta;
761         int             lab;
762         int             type;
763         int_2           magic;
764
765         struct
766         {
767                 long    dev;
768                 long    ino;
769                 long    mode;
770                 long    uid;
771                 long    gid;
772                 long    nlink;
773                 long    rdev;
774                 long    mtime;
775                 long    size;
776                 long    dev_major;
777                 long    dev_minor;
778                 long    rdev_major;
779                 long    rdev_minor;
780                 long    checksum;
781         }               lst;
782
783         static char     idbuffer[ALAR_NAMESIZE + 1];
784         static char     uidname[9];
785         static char     gidname[9];
786
787         static struct tar_header_info   tar_last[16];
788         static int                      tar_last_index;
789
790         ap->sum++;
791  volume:
792         warned = 0;
793         checkdelta = !ap->entry++ && (!ap->delta || ap->delta->format != DELTA_IGNORE && ap->delta->format != DELTA_PATCH);
794         type = 0;
795         if (ap->io.mode) bsave(ap);
796  again:
797         ap->memsum = 0;
798         for (;;)
799         {
800                 f->record.format = 0;
801                 f->skip = 0;
802                 message((-2, "%s:", format[ap->format].name));
803                 switch (ap->format)
804                 {
805                 case ALAR:
806                 case IBMAR:
807                         if (!(lab = getlabel(ap, f))) return(0);
808                         f->name = ap->path.header;
809                         f->st->st_dev = 0;
810                         f->st->st_ino = 0;
811                         f->st->st_mode = X_IFREG|X_IRUSR|X_IWUSR|X_IRGRP|X_IROTH;
812                         f->st->st_uid = state.uid;
813                         f->st->st_gid = state.gid;
814                         f->st->st_nlink = 1;
815                         IDEVICE(f->st, 0);
816                         f->st->st_size = 0;
817                         f->linktype = NOLINK;
818                         f->linkname = 0;
819                         f->uidname = 0;
820                         f->gidname = 0;
821                         type = 0;
822                         do
823                         {
824                                 if (ap->format == IBMAR) memetoa(alar_header, alar_header, ALAR_HEADER);
825                                 if (checkdelta && strneq(alar_header, "UVL1", 4) && strneq(alar_header + 5, ID, IDLEN))
826                                 {
827                                         checkdelta = 0;
828                                         s = alar_header + 10;
829                                         f->st->st_mtime = getlabnum(alar_header, 14, 10, 10);
830                                         n = getlabnum(alar_header, 24, 10, 10);
831                                         f->st->st_uid = DELTA_LO(n);
832                                         f->st->st_gid = DELTA_HI(n);
833                                         if (t = strchr(s, ' ')) *t = 0;
834                                         goto deltaverify;
835                                 }
836                                 else if (strneq(alar_header, "HDR", 3))
837                                 {
838                                         if (getlabnum(alar_header, 4, 1, 10) != ++type) error(3, "%s format HDR label out of sequence", format[ap->format].name);
839                                         if (type == 1)
840                                         {
841                                                 s = ap->path.header;
842                                                 for (i = 4; i <= ALAR_NAMESIZE + 3; i++)
843                                                 {
844                                                         if (alar_header[i] == ' ')
845                                                         {
846                                                                 if (i >= ALAR_NAMESIZE + 3 || alar_header[i + 1] == ' ') break;
847                                                                 *s++ = '.';
848                                                         }
849                                                         else *s++ = isupper(alar_header[i]) ? tolower(alar_header[i]) : alar_header[i];
850                                                 }
851                                                 if ((n = getlabnum(alar_header, 40, 2, 10)) > 0 && n < 99) sfsprintf(s, 3, ".%02d", n);
852                                                 else *s = 0;
853                                                 f->record.section = getlabnum(alar_header, 28, 4, 10);
854                                                 getlabstr(alar_header, 5, ALAR_NAMESIZE, f->id = idbuffer);
855                                                 getlabstr(alar_header, 61, 6, state.id.format);
856                                                 getlabstr(alar_header, 67, 7, state.id.implementation);
857 #if SAVESET
858                                                 if (streq(state.id.format, SAVESET_ID) && streq(state.id.implementation, SAVESET_IMPL))
859                                                         ap->format = SAVESET;
860 #endif
861                                                 f->st->st_mtime = 0;
862                                                 if (n = getlabnum(alar_header, 43, 2, 10))
863                                                 {
864                                                         if (alar_header[41] == '0') n += 100;
865                                                         if ((i = getlabnum(alar_header, 45, 3, 10)) >= 0 && i <= 365)
866                                                         {
867                                                                 f->st->st_mtime = i;
868                                                                 while (n-- > 70) f->st->st_mtime += ((n % 4) || n == 100) ? 365 : 366;
869                                                                 f->st->st_mtime *= 24L * 60L * 60L;
870                                                                 f->st->st_mtime += 12L * 60L * 60L;
871                                                         }
872                                                 }
873                                                 if (!f->st->st_mtime)
874                                                         f->st->st_mtime = time((time_t*)0);
875                                         }
876                                         else if (type == 2)
877                                         {
878                                                 switch (f->record.format = alar_header[4])
879                                                 {
880                                                 case 'D': /* decimal variable   */
881                                                 case 'F': /* fixed length       */
882                                                 case 'S': /* spanned            */
883                                                 case 'U': /* input block size   */
884                                                 case 'V': /* binary variable    */
885                                                         break;
886                                                 default:
887                                                         error(2, "%s record format %c not supported", format[ap->format].name, f->record.format);
888                                                         f->skip = 1;
889                                                 }
890                                                 state.blocksize = getlabnum(alar_header, 6, 5, 10);
891                                                 state.record.size = getlabnum(alar_header, 11, 5, 10);
892                                                 if (!ap->io.blocked) f->st->st_size = getlabnum(alar_header, 16, 10, 10);
893                                                 state.record.offset = getlabnum(alar_header, 51, 2, 10);
894                                         }
895                                 }
896                                 else if (!ap->io.blocked && strneq(alar_header, "VOL1", 4))
897                                 {
898                                         bunread(ap, alar_header, lab);
899                                         if (!(getprologue(ap))) return(0);
900                                         goto volume;
901                                 }
902                         } while ((lab = getlabel(ap, f)));
903 #if SAVESET
904                         if (ap->format != SAVESET) goto found;
905                         state.saveset.time = f->st->st_mtime;
906                         if (state.blocksize > state.saveset.blocksize)
907                         {
908                                 state.saveset.blocksize = state.blocksize;
909                                 if (state.saveset.block) free(state.saveset.block);
910                                 if (!(state.saveset.block = newof(0, char, state.saveset.blocksize, 0)))
911                                         error(3, "cannot allocate %s format buffer", format[ap->format].name);
912                         }
913                         state.saveset.bp = state.saveset.block + state.blocksize;
914                         /*FALLTHROUGH*/
915                 case SAVESET:
916                         f->name = ap->path.header;
917                         if (!getsaveset(ap, f, 1)) goto again;
918 #endif
919                         goto found;
920                 case BINARY:
921                         if (bread(ap, &binary_header, (long)BINARY_HEADER, (long)BINARY_HEADER, 0) <= 0) break;
922                         if (ap->swap)
923                         {
924                                 memcpy(state.tmp.buffer, &binary_header, BINARY_HEADER);
925                                 swapmem(ap->swap, &binary_header, &binary_header, BINARY_HEADER);
926                         }
927                         f->magic = binary_header.magic;
928                         if (f->magic == CPIO_MAGIC)
929                         {
930                                 f->namesize = binary_header.namesize;
931                                 f->st->st_dev = binary_header.dev;
932                                 f->st->st_ino = binary_header.ino;
933                                 f->st->st_mode = binary_header.mode;
934                                 f->st->st_uid = binary_header.uid;
935                                 f->st->st_gid = binary_header.gid;
936                                 f->st->st_nlink = binary_header.links;
937                                 IDEVICE(f->st, binary_header.rdev);
938                                 f->st->st_mtime = cpio_long(binary_header.mtime);
939                                 f->st->st_size = cpio_long(binary_header.size);
940                         cpio_common:
941                                 f->linktype = NOLINK;
942                                 f->linkname = 0;
943                                 f->uidname = 0;
944                                 f->gidname = 0;
945                                 f->name = ap->path.header;
946                                 switch (ap->format)
947                                 {
948                                 case BINARY:
949                                         i = BINARY_ALIGN;
950                                         n = BINARY_HEADER;
951                                         break;
952                                 case ASC:
953                                 case ASCHK:
954                                         i = ASC_ALIGN;
955                                         n = ASC_HEADER;
956                                         break;
957                                 default:
958                                         i = 0;
959                                         break;
960                                 }
961                                 if (i)
962                                 {
963                                         if (n = (n + f->namesize) % i) i -= n;
964                                         else i = 0;
965                                 }
966                                 if (f->namesize >= sizeof(ap->path.header))
967                                 {
968                                         error(2, "%s: entry %d.%d file name too long", ap->name, ap->volume, ap->entry);
969                                         for (n = f->namesize + i; n > 0; n -= sizeof(ap->path.header))
970                                                 bread(ap, ap->path.header, 0L, n > sizeof(ap->path.header) ? (long)sizeof(ap->path.header) : n, 1);
971                                         f->skip = 1;
972                                 }
973                                 else
974                                 {
975                                         bread(ap, ap->path.header, 0, (long)(f->namesize + i), 1);
976                                         if (ap->path.header[f->namesize - 1])
977                                         {
978                                                 bunread(ap, &ap->path.header[f->namesize - 1], 1);
979                                                 ap->path.header[f->namesize - 1] = 0;
980                                                 error(state.keepgoing ? 1 : 3, "%s: entry %d.%d file name terminating null missing", ap->name, ap->volume, ap->entry);
981                                         }
982 #if CPIO_EXTENDED
983                                         getxops(ap, f);
984 #endif
985                                 }
986                                 if (streq(f->name, CPIO_TRAILER))
987                                 {
988                                         getdeltaheader(ap, f);
989                                         if (ap->delta)
990                                                 setinfo(ap, f);
991                                         return(0);
992                                 }
993                                 switch (f->type = X_ITYPE(f->st->st_mode))
994                                 {
995                                 case X_IFBLK:
996                                 case X_IFCHR:
997                                 case X_IFDIR:
998                                 case X_IFIFO:
999                                 case X_IFLNK:
1000                                 case X_IFREG:
1001                                 case X_IFSOCK:
1002                                         break;
1003                                 default:
1004                                         error(1, "%s: unknown file type %07o -- regular file assumed", f->name, f->type);
1005                                         f->type = X_IFREG;
1006                                         break;
1007                                 }
1008                                 f->st->st_mode &= X_IPERM;
1009                                 f->st->st_mode |= f->type;
1010                                 switch (f->type)
1011                                 {
1012                                 case X_IFLNK:
1013                                         if (f->st->st_size > sizeof(ap->path.link) - 1)
1014                                         {
1015                                                 error(2, "%s: entry %d.%d symbolic link text too long", ap->name, ap->volume, ap->entry);
1016                                                 f->skip = 1;
1017                                         }
1018                                         else
1019                                         {
1020                                                 f->linktype = SOFTLINK;
1021                                                 s = f->linkname = ap->path.link;
1022                                                 while (bread(ap, s, 1, 1, 1) > 0)
1023                                                 {
1024                                                         f->st->st_size--;
1025                                                         if (!*s++) break;
1026                                                 }
1027                                         }
1028                                         break;
1029                                 default:
1030                                         f->linktype = NOLINK;
1031                                         break;
1032                                 }
1033                                 goto found;
1034                         }
1035                         bunread(ap, ap->swap ? state.tmp.buffer : (char*)&binary_header, BINARY_HEADER);
1036                         break;
1037                 case CPIO:
1038                         if (bread(ap, state.tmp.buffer, 0L, (long)CPIO_HEADER, 0) <= 0) break;
1039                         state.tmp.buffer[CPIO_HEADER] = 0;
1040                         if (state.tmp.buffer[0] == '0' && sscanf(state.tmp.buffer, "%6o%6lo%6lo%6lo%6lo%6lo%6lo%6lo%11lo%6o%11lo",
1041                                 &f->magic,
1042                                 &lst.dev,
1043                                 &lst.ino,
1044                                 &lst.mode,
1045                                 &lst.uid,
1046                                 &lst.gid,
1047                                 &lst.nlink,
1048                                 &lst.rdev,
1049                                 &lst.mtime,
1050                                 &f->namesize,
1051                                 &lst.size) == 11 && f->magic == CPIO_MAGIC)
1052                         {
1053                                 f->st->st_dev = lst.dev;
1054                                 f->st->st_ino = lst.ino;
1055                                 f->st->st_mode = lst.mode;
1056                                 f->st->st_uid = lst.uid;
1057                                 f->st->st_gid = lst.gid;
1058                                 f->st->st_nlink = lst.nlink;
1059                                 IDEVICE(f->st, lst.rdev);
1060                                 f->st->st_mtime = lst.mtime;
1061                                 f->st->st_size = lst.size;
1062                                 goto cpio_common;
1063                         }
1064                         bunread(ap, state.tmp.buffer, CPIO_HEADER);
1065                         break;
1066                 case PAX:
1067                 case TAR:
1068                 case USTAR:
1069                         if (bread(ap, tar_block, 0L, (long)TAR_HEADER, 0) <= 0) break;
1070                         if (!*tar_header.name)
1071                         {
1072                                 if (ap->entry == 1) goto notar;
1073                                 return(0);
1074                         }
1075                         if (sscanf(tar_header.mode, "%11lo", &num) != 1) goto notar;
1076                         f->st->st_mode = num;
1077                         if (sscanf(tar_header.uid, "%11lo", &num) != 1) goto notar;
1078                         f->st->st_uid = num;
1079                         if (sscanf(tar_header.gid, "%11lo", &num) != 1) goto notar;
1080                         f->st->st_gid = num;
1081                         if (sscanf(tar_header.size, "%11lo", &num) != 1) goto notar;
1082                         f->st->st_size = num;
1083                         if (sscanf(tar_header.mtime, "%11lo", &num) != 1) goto notar;
1084                         f->st->st_mtime = num;
1085                         if (sscanf(tar_header.chksum, "%11lo", &num) != 1) goto notar;
1086                         if ((n = num) != (i = tar_checksum()))
1087                         {
1088                                 if (ap->entry == 1) goto notar;
1089                                 error(state.keepgoing ? 1 : 3, "%s format checksum error (%d != %d)", format[ap->format].name, n, i);
1090                         }
1091                         if (ap->format != TAR)
1092                         {
1093                                 if (!streq(tar_header.magic, TMAGIC))
1094                                 {
1095                                         if (strneq(tar_header.magic, TMAGIC, TMAGLEN - 1))
1096                                                 error(1, "%s: %s format botched -- %s format assumed", ap->name, format[ap->format].name, format[TAR].name);
1097                                         else if (ap->entry > 1) goto notar;
1098                                         ap->format = TAR;
1099                                 }
1100                                 else if (!strneq(tar_header.version, TVERSION, sizeof(tar_header.version)))
1101                                 {
1102                                         error(1, "%s: %s format version %-.*s incompatible with implementation version %-.*s -- assuming %s", ap->name, format[ap->format].name, sizeof(tar_header.version), tar_header.version, sizeof(tar_header.version), TVERSION, format[TAR].name);
1103                                         ap->format = TAR;
1104                                 }
1105                         }
1106                         *(tar_header.name + sizeof(tar_header.name)) = 0;
1107                         if (ap->format != TAR && *tar_header.prefix)
1108                                 sfsprintf(f->name = ap->path.header, sizeof(ap->path.header), "%-.*s/%s", sizeof(tar_header.prefix), tar_header.prefix, tar_header.name);
1109                         else f->name = tar_header.name;
1110                         *(tar_header.linkname + sizeof(tar_header.name)) = 0;
1111                         f->linkname = tar_header.linkname;
1112                         f->linktype = NOLINK;
1113                         f->st->st_nlink = 1;
1114                         switch (tar_header.typeflag)
1115                         {
1116                         case LNKTYPE:
1117                                 f->linktype = HARDLINK;
1118                                 f->st->st_mode |= X_IFREG;
1119                                 f->st->st_nlink = 2;
1120                                 f->st->st_size = 0;     /* lest they forget */
1121                                 break;
1122                         case SYMTYPE:
1123                                 f->linktype = SOFTLINK;
1124                                 f->st->st_mode |= X_IFLNK;
1125                                 break;
1126                         case CHRTYPE:
1127                                 f->st->st_mode |= X_IFCHR;
1128                         device:
1129                                 if (sscanf(tar_header.devmajor, "%11o", &num) != 1) goto notar;
1130                                 i = num;
1131                                 if (sscanf(tar_header.devminor, "%11o", &num) != 1) goto notar;
1132                                 IDEVICE(f->st, makedev(i, num));
1133                                 break;
1134                         case BLKTYPE:
1135                                 f->st->st_mode |= X_IFBLK;
1136                                 goto device;
1137                         case DIRTYPE:
1138                                 f->st->st_mode |= X_IFDIR;
1139                                 break;
1140                         case FIFOTYPE:
1141                                 f->st->st_mode |= X_IFIFO;
1142                                 break;
1143 #ifdef SOKTYPE
1144                         case SOKTYPE:
1145                                 f->st->st_mode |= X_IFSOCK;
1146                                 break;
1147 #endif
1148                         case EXTTYPE:
1149                                 ap->format = PAX;
1150                                 if (f->st->st_size > 0)
1151                                 {
1152                                         if (s = bget(ap, f->st->st_size))
1153                                         {
1154                                                 s[f->st->st_size - 1] = 0;
1155                                                 stropt(s, state.options, 0, setoption, ap);
1156                                         }
1157                                         else error(3, "invalid %s format extended header", format[ap->format].name);
1158                                 }
1159                                 gettrailer(ap, f);
1160                                 goto again;
1161                         default:
1162                                 error(1, "unknown file type `%c' -- regular file assumed", tar_header.typeflag);
1163                                 /*FALLTHROUGH*/
1164                         case REGTYPE:
1165                         case AREGTYPE:
1166                                 f->namesize = strlen(f->name) + 1;
1167                                 if (f->name[f->namesize - 2] == '/')
1168                                 {
1169                                         f->st->st_mode |= X_IFDIR;
1170                                         if (f->namesize > 2) f->name[--f->namesize - 1] = 0;
1171                                 }
1172                                 else f->st->st_mode |= X_IFREG;
1173                                 break;
1174                         }
1175                         f->uidname = 0;
1176                         f->gidname = 0;
1177                         if (ap->format != TAR)
1178                         {
1179                                 if (*tar_header.uname) f->uidname = tar_header.uname;
1180                                 if (*tar_header.gname) f->gidname = tar_header.gname;
1181                         }
1182                         goto found;
1183                 notar:
1184                         bunread(ap, tar_block, TAR_HEADER);
1185                         break;
1186                 case ASC:
1187                 case ASCHK:
1188                         if (bread(ap, state.tmp.buffer, 0L, (long)ASC_HEADER, 0) <= 0) break;
1189                         state.tmp.buffer[ASC_HEADER] = 0;
1190                         if (state.tmp.buffer[0] == '0' && sscanf(state.tmp.buffer, "%6o%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8x%8lx",
1191                                 &f->magic,
1192                                 &lst.ino,
1193                                 &lst.mode,
1194                                 &lst.uid,
1195                                 &lst.gid,
1196                                 &lst.nlink,
1197                                 &lst.mtime,
1198                                 &lst.size,
1199                                 &lst.dev_major,
1200                                 &lst.dev_minor,
1201                                 &lst.rdev_major,
1202                                 &lst.rdev_minor,
1203                                 &f->namesize,
1204                                 &lst.checksum) == 14 && (f->magic == ASC_MAGIC || f->magic == ASCHK_MAGIC))
1205                         {
1206                                 if (f->magic == ASCHK_MAGIC) ap->format = ASCHK;
1207                                 f->checksum = lst.checksum;
1208                                 f->st->st_dev = makedev(lst.dev_major, lst.dev_minor);
1209                                 f->st->st_ino = lst.ino;
1210                                 f->st->st_mode = lst.mode;
1211                                 f->st->st_uid = lst.uid;
1212                                 f->st->st_gid = lst.gid;
1213                                 f->st->st_nlink = lst.nlink;
1214                                 IDEVICE(f->st, makedev(lst.rdev_major, lst.rdev_minor));
1215                                 f->st->st_mtime = lst.mtime;
1216                                 f->st->st_size = lst.size;
1217                                 goto cpio_common;
1218                         }
1219                         bunread(ap, state.tmp.buffer, ASC_HEADER);
1220                         break;
1221                 case PORTAR:
1222                 case RANDAR:
1223                         if (bread(ap, &portar_header, 0L, (long)PORTAR_HEADER, 0) <= 0) break;
1224                         if (strneq(portar_header.ar_fmag, PORTAR_END, PORTAR_ENDSIZ) && sscanf(portar_header.ar_date, "%12ld%6ld%6ld%8lo%10ld",
1225                                 &lst.mtime,
1226                                 &lst.uid,
1227                                 &lst.gid,
1228                                 &lst.mode,
1229                                 &lst.size) == 5)
1230                         {
1231                                 f->name = (ap->names && portar_header.ar_name[0] == PORTAR_TERM) ? (ap->names + strtol(portar_header.ar_name + 1, NiL, 10)) : portar_header.ar_name;
1232                                 portar_header.ar_date[0] = 0;
1233                                 if ((s = strchr(f->name, PORTAR_TERM)) || (s = strchr(f->name, RANDAR_TERM))) *s = 0;
1234                                 f->st->st_dev = 0;
1235                                 f->st->st_ino = 0;
1236                                 f->st->st_mode = X_IFREG|(lst.mode&X_IPERM);
1237                                 f->st->st_uid = lst.uid;
1238                                 f->st->st_gid = lst.gid;
1239                                 f->st->st_nlink = 1;
1240                                 IDEVICE(f->st, 0);
1241                                 f->st->st_mtime = lst.mtime;
1242                                 f->st->st_size = lst.size;
1243                                 f->linktype = NOLINK;
1244                                 f->linkname = 0;
1245                                 f->uidname = 0;
1246                                 f->gidname = 0;
1247                                 goto found;
1248                         }
1249                         bunread(ap, &portar_header, PORTAR_HEADER);
1250                         return(0);
1251                 case VDB:
1252                         if (!state.vdb.header.base)
1253                         {
1254                                 if (fstat(ap->io.fd, &state.vdb.st)) break;
1255                                 state.vdb.st.st_mode = modex(state.vdb.st.st_mode);
1256                                 s = tar_block;
1257                                 n = sizeof(VDB_MAGIC) + sizeof(state.id.volume) + 1;
1258                                 if (bread(ap, s, 0L, n, 0) <= 0) break;
1259                                 bunread(ap, s, n);
1260                                 if (s[0] != VDB_DELIMITER || !strneq(s + 1, VDB_MAGIC, sizeof(VDB_MAGIC) - 1) || s[sizeof(VDB_MAGIC)] != VDB_DELIMITER) break;
1261                                 if (s[sizeof(VDB_MAGIC) + 1] != '\n')
1262                                 {
1263                                         s[n] = 0;
1264                                         if (t = strchr(s, '\n')) *t = 0;
1265                                         strncpy(state.id.volume, s + sizeof(VDB_MAGIC) + 1, sizeof(state.id.volume) - 2);
1266                                 }
1267                                 if (lseek(ap->io.fd, -(VDB_LENGTH + 1), SEEK_END) <= 0) break;
1268                                 if (read(ap->io.fd, s, VDB_LENGTH + 1) != (VDB_LENGTH + 1)) break;
1269                                 state.vdb.variant = *s++ != '\n';
1270                                 if (!strneq(s, VDB_DIRECTORY, sizeof(VDB_DIRECTORY) - 1)) break;
1271                                 state.vdb.delimiter = s[VDB_OFFSET - 1];
1272                                 n = strtol(s + VDB_OFFSET, NiL, 10) - sizeof(VDB_DIRECTORY);
1273                                 i = lseek(ap->io.fd, 0L, SEEK_CUR) - n - VDB_LENGTH - state.vdb.variant;
1274                                 if (!(state.vdb.header.base = newof(0, char, i, 0))) break;
1275                                 if (lseek(ap->io.fd, n, SEEK_SET) != n) break;
1276                                 if (read(ap->io.fd, state.vdb.header.base, i) != i) break;
1277                                 *(state.vdb.header.base + i) = 0;
1278                                 if (!strneq(state.vdb.header.base, VDB_DIRECTORY, sizeof(VDB_DIRECTORY) - 1)) break;
1279                                 if (!(state.vdb.header.next = strchr(state.vdb.header.base, '\n'))) break;
1280                                 state.vdb.header.next++;
1281                         }
1282                         t = state.vdb.header.next;
1283                         if (!(state.vdb.header.next = strchr(t, '\n'))) goto vdb_eof;
1284                         *state.vdb.header.next++ = 0;
1285                         message((-1, "VDB: next=`%s'", t));
1286                         if (state.vdb.variant) state.vdb.delimiter = *t++;
1287                         f->name = t;
1288                         if (!(t = strchr(t, state.vdb.delimiter))) goto vdb_eof;
1289                         *t++ = 0;
1290                         n = strtol(t, &t, 10);
1291                         if (*t++ != state.vdb.delimiter) goto vdb_eof;
1292                         if (lseek(ap->io.fd, n, SEEK_SET) != n) goto vdb_eof;
1293                         *f->st = state.vdb.st;
1294                         f->st->st_size = strtol(t, &t, 10);
1295                         if (*t++ == state.vdb.delimiter) do
1296                         {
1297                                 if (s = strchr(t, state.vdb.delimiter))
1298                                         *s++ = 0;
1299                                 if (strneq(t, VDB_DATE, sizeof(VDB_DATE) - 1))
1300                                         f->st->st_mtime = strtol(t + sizeof(VDB_DATE), NiL, 10);
1301                                 else if (strneq(t, VDB_MODE, sizeof(VDB_MODE) - 1))
1302                                         f->st->st_mode = (strtol(t + sizeof(VDB_MODE), NiL, 8) & X_IPERM) | X_IFREG;
1303                         } while (t = s);
1304                         f->st->st_dev = 0;
1305                         f->st->st_ino = 0;
1306                         f->st->st_nlink = 1;
1307                         IDEVICE(f->st, 0);
1308                         f->linktype = NOLINK;
1309                         f->linkname = 0;
1310                         f->uidname = 0;
1311                         f->gidname = 0;
1312                         ap->io.eof = 1;
1313                         bflushin(ap);
1314                         ap->io.eof = 0;
1315                         goto found;
1316                 vdb_eof:
1317                         ap->io.eof = 0;
1318                         lseek(ap->io.fd, 0L, SEEK_END);
1319                         bflushin(ap);
1320                         return(0);
1321                 default:
1322                         error(PANIC, "%s: incomplete input format implementation", format[ap->format].name);
1323                         break;
1324                 }
1325                 if (ap->entry == 1) for (;;) switch (ap->format)
1326                 {
1327                 case BINARY:
1328                         ap->format = USTAR;
1329                         goto again;
1330                 case CPIO:
1331                         ap->format = BINARY;
1332                         ap->swap = 0;
1333                         if (bread(ap, &binary_header.magic, 0L, (long)sizeof(binary_header.magic), 0) <= 0) break;
1334                         bunread(ap, &binary_header.magic, sizeof(binary_header.magic));
1335                         if (binary_header.magic == CPIO_MAGIC) goto again;
1336                         ap->swap++;
1337                         magic = binary_header.magic;
1338                         swapmem(ap->swap, &magic, &magic, sizeof(magic));
1339                         message((-1, "binary_header.magic=0%05o swap(BYTE)=0%05o", (unsigned short)binary_header.magic, (unsigned short)magic));
1340                         if (magic == CPIO_MAGIC)
1341                         {
1342                                 message((-1, "swapping %s header bytes", format[ap->format].name));
1343                                 goto again;
1344                         }
1345                         break;
1346                 case PAX:
1347                 case TAR:
1348                 case USTAR:
1349                         ap->format = ASC;
1350                         goto again;
1351                 case ASC:
1352                 case ASCHK:
1353                         ap->format = VDB;
1354                         goto again;
1355                 case VDB:
1356                         if (ap->entries > 0 && ap->volume > 1)
1357                         {
1358                                 if (--ap->volume > 1) error(1, "junk data after volume %d", ap->volume);
1359                                 finish(0);
1360                         }
1361                         if (!state.keepgoing) error(3, "%s: unknown input format", ap->name);
1362                         ap->format = IN_DEFAULT;
1363                         goto skip;
1364                 }
1365         skip:
1366                 if (ap->io.eof) return(0);
1367                 i = 3;
1368                 if (state.keepgoing && bread(ap, ap->path.header, 0L, 1L, 0) > 0)
1369                 {
1370                         if (warned) continue;
1371                         warned = 1;
1372                         i = 1;
1373                 }
1374                 error(i, "%s: entry %d.%d is out of phase", ap->name, ap->volume, ap->entry);
1375                 if (ap->entry > 1) ap->entry++;
1376         }
1377  found:
1378         if (checkdelta || ap->delta)
1379         {
1380                 if (!f->st->st_size && !f->st->st_dev && !f->st->st_ino && !(f->st->st_mode & (X_IRWXU|X_IRWXG|X_IRWXO)) && strmatch(f->name, INFO_MATCH))
1381                 {
1382                         s = f->name;
1383                         if (checkdelta)
1384                         {
1385                                 Archive_t*      bp;
1386                                 int             ordered = 0;
1387
1388                                 checkdelta = 0;
1389                                 i = 0;
1390                                 n = 0;
1391                                 if (*s++ == INFO_SEP)
1392                                 {
1393                                         if (strneq(s, ID, IDLEN) && (s = strchr(s, INFO_SEP)))
1394                                         {
1395                                         deltaverify:
1396                                                 switch (*++s)
1397                                                 {
1398                                                 case TYPE_COMPRESS:
1399                                                         n = COMPRESS;
1400                                                         break;
1401                                                 case TYPE_DELTA:
1402                                                         n = DELTA;
1403                                                         break;
1404                                                 default:
1405                                                         error(3, "type %c encoding not supported", *s);
1406                                                 }
1407                                                 if (*++s == INFO_SEP)
1408                                                 {
1409                                                         if (t = strchr(++s, INFO_SEP)) *t++ = 0;
1410                                                         for (i = DELTA; format[i].algorithm; i++)
1411                                                                 if (streq(s, format[i].algorithm))
1412                                                                         break;
1413                                                         if (!format[i].algorithm)
1414                                                                 error(3, "delta version %s not supported", s);
1415
1416                                                         /*
1417                                                          * [<INFO_SEP>[<OP>]<VAL>]* may appear here
1418                                                          */
1419
1420                                                         while ((s = t) && *s != INFO_SEP)
1421                                                         {
1422                                                                 if (t = strchr(s, INFO_SEP)) *t++ = 0;
1423                                                                 switch (*s++)
1424                                                                 {
1425                                                                 case INFO_ORDERED:
1426                                                                         ordered = 1;
1427                                                                         break;
1428                                                                 }
1429                                                         }
1430                                                 }
1431                                         }
1432                                         else
1433                                         {
1434                                                 if (s = strchr(f->name + 3, INFO_SEP)) *s = 0;
1435                                                 error(1, "unknown %s header ignored", f->name + 3);
1436                                                 goto again;
1437                                         }
1438                                 }
1439                                 else if (streq(f->name, "DELTA!!!"))
1440                                 {
1441                                         n = DELTA;
1442                                         i = DELTA_88;
1443                                 }
1444                                 if (n)
1445                                 {
1446                                         if (n == DELTA && ap->parent)
1447                                                 error(3, "%s: %s: base archive cannot be a delta", ap->parent->name, ap->name);
1448                                         initdelta(ap);
1449                                         ap->delta->format = n;
1450                                         ap->delta->version = i;
1451                                         if (bp = ap->delta->base)
1452                                         {
1453                                                 if (i == DELTA_88)
1454                                                         bp->checksum = bp->old.checksum;
1455                                                 message((-5, "checkdelta: %s size=%ld:%ld LO=%d:%d HI=%d:%d", format[ap->delta->version].name, f->st->st_mtime, bp->size, DELTA_LO(f->st->st_uid), DELTA_LO(bp->checksum), DELTA_LO(f->st->st_gid), DELTA_HI(bp->checksum)));
1456                                                 if (n == DELTA)
1457                                                 {
1458                                                         if (!ordered)
1459                                                         {
1460                                                                 if (state.ordered)
1461                                                                         error(3, "%s: delta archive not ordered", ap->name);
1462                                                                 if (f->st->st_mtime != bp->size)
1463                                                                         error(3, "%s: %s: base archive size mismatch", ap->name, bp->name);
1464                                                         }
1465                                                         if (DELTA_LO(f->st->st_uid) != DELTA_LO(bp->checksum) || DELTA_LO(f->st->st_gid) != DELTA_HI(bp->checksum))
1466                                                                 error(1, "%s: %s: base archive checksum mismatch", ap->name, bp->name);
1467                                                 }
1468                                         }
1469                                         else if (n == DELTA)
1470                                         {
1471                                                 error(state.list ? 1 : 3, "%s: base archive must be specified", ap->name);
1472                                                 deltabase(ap);
1473                                                 ap->delta->format = COMPRESS;
1474                                         }
1475                                         if (ap->sum <= 0)
1476                                                 ap->sum++;
1477                                         goto again;
1478                                 }
1479                                 else error(1, "%s: %s: unknown control header treated as regular file", ap->name, f->name);
1480                         }
1481                         else if (*s++ == INFO_SEP && strneq(s, ID, IDLEN) && *(s + IDLEN) == INFO_SEP)
1482                         {
1483                                 setinfo(ap, f);
1484                                 goto again;
1485                         }
1486                 }
1487                 if (checkdelta && ap->delta)
1488                         ap->delta->format = DELTA_PATCH;
1489         }
1490         ap->entries++;
1491         getkeytime(ap, f, OPT_atime, &f->st->st_atime);
1492         getkeytime(ap, f, OPT_ctime, &f->st->st_ctime);
1493         getkeytime(ap, f, OPT_mtime, &f->st->st_mtime);
1494         getkeyname(ap, f, OPT_gname, &f->gidname);
1495         getkeyname(ap, f, OPT_path, &f->name);
1496         getkeyname(ap, f, OPT_linkpath, &f->linkname);
1497         getkeyname(ap, f, OPT_uname, &f->uidname);
1498         if (f->name != ap->path.header)
1499                 f->name = strcpy(ap->path.header, f->name);
1500         for (i = strlen(f->name); i > 2 && *(f->name + i - 1) == '/'; i--);
1501         *(f->name + i) = 0;
1502         f->path = strcpy(ap->path.name, f->name);
1503         pathcanon(f->name, 0);
1504         f->name = map(f->name);
1505         f->namesize = strlen(f->name) + 1;
1506         if (f->linkname)
1507         {
1508                 pathcanon(f->linkname, 0);
1509                 if (!(state.ftwflags & FTW_PHYSICAL))
1510                         f->linkname = map(f->linkname);
1511                 f->linknamesize = strlen(f->linkname) + 1;
1512         }
1513         else f->linknamesize = 0;
1514         if (f->uidname || f->gidname) setidnames(f);
1515         f->type = X_ITYPE(f->st->st_mode);
1516         f->perm = modei(f->st->st_mode);
1517         getdeltaheader(ap, f);
1518 #if DEBUG
1519         if (error_info.trace)
1520         {
1521                 s = &state.tmp.buffer[0];
1522                 if (f->record.format) sfsprintf(s, state.tmp.buffersize, " [%c,%d,%d]", f->record.format, state.blocksize, state.record.size);
1523                 else *s = 0;
1524                 message((-1, "archive=%s path=%s name=%s entry=%d.%d size=%ld delta=%c%s", ap->name, f->path, f->name, ap->volume, ap->entry, f->st->st_size, f->delta.op ? f->delta.op : DELTA_nop, s));
1525         }
1526 #endif
1527         if (ap->entry == 1)
1528         {
1529                 /*
1530                  * some tar implementations write garbage after
1531                  * the 2 null blocks that sometimes contain
1532                  * valid headers that were previously output
1533                  * but are still in the output buffer
1534                  */
1535
1536                 if ((ap->format == PAX || ap->format == TAR || ap->format == USTAR) && ap->volume > 1)
1537                         for (i = 0; i < elementsof(tar_last); i++)
1538                                 if (!memcmp((char*)&tar_last[i], (char*)&tar_header, sizeof(tar_header)))
1539                                 {
1540                                         if (--ap->volume == 1) error(1, "junk data after volume %d", ap->volume);
1541                                         return(0);
1542                                 }
1543                 if (ap->parent)
1544                 {
1545                         if (ap->io.blocked)
1546                                 error(3, "%s: blocked base archives are not supported", ap->delta->base);
1547                         switch (ap->format)
1548                         {
1549                         case ALAR:
1550                         case IBMAR:
1551 #if SAVESET
1552                         case SAVESET:
1553 #endif
1554                                 error(3, "%s: %s format base archives not supported", ap->delta->base, format[ap->format].name);
1555                         }
1556                 }
1557                 if (state.summary && state.verbose)
1558                 {
1559                         if (ap->io.blok) sfprintf(sfstderr, "BLOK ");
1560                         if (ap->parent) sfprintf(sfstderr, "%s base %s", ap->parent->name, ap->name);
1561                         else sfprintf(sfstderr, "%s volume %d", ap->name, ap->volume);
1562                         if (state.id.volume[0])
1563                                 sfprintf(sfstderr, " label %s", state.id.volume);
1564                         sfprintf(sfstderr, " in");
1565                         if (ap->compress)
1566                                 sfprintf(sfstderr, " %s", format[ap->compress].name);
1567                         if (ap->delta && ap->delta->version)
1568                                 sfprintf(sfstderr, " %s", format[ap->delta->version].name);
1569                         sfprintf(sfstderr, " %s format", format[ap->format].name);
1570                         if (error_info.trace)
1571                         {
1572                                 if (*state.id.format) sfprintf(sfstderr, " %s", state.id.format);
1573                                 if (*state.id.implementation) sfprintf(sfstderr, " implementation %s", state.id.implementation);
1574                         }
1575                         sfprintf(sfstderr, "\n");
1576                 }
1577         }
1578         if (ap->format == PAX || ap->format == TAR || ap->format == USTAR)
1579         {
1580                 if (++tar_last_index >= elementsof(tar_last)) tar_last_index = 0;
1581                 tar_last[tar_last_index] = tar_header;
1582         }
1583         if (!ap->delta || !ap->delta->trailer)
1584                 ap->memsum = 0;
1585         ap->old.memsum = 0;
1586         return(1);
1587 }
1588
1589 /*
1590  * output extended header keyword assignment
1591  */
1592
1593 static void
1594 putkey __PARAM__((Sfio_t* sp, Sfio_t* tp, const char* name, int op, const char* value), (sp, tp, name, op, value)) __OTORP__(Sfio_t* sp; Sfio_t* tp; const char* name; int op; const char* value;){
1595         const char*     s;
1596         int             c;
1597         int             n;
1598
1599         sfprintf(tp, " %s", name);
1600         if (op) sfputc(tp, op);
1601         sfputc(tp, '=');
1602         n = 0;
1603         s = value;
1604         for (;;)
1605         {
1606                 switch (*s++)
1607                 {
1608                 case 0:
1609                         break;
1610                 case '"':
1611                         n |= 04;
1612                         continue;
1613                 case '\'':
1614                         n |= 02;
1615                         continue;
1616                 case '\\':
1617                 case ' ':
1618                 case '\t':
1619                 case '\n':
1620                         n |= 01;
1621                         continue;
1622                 default:
1623                         continue;
1624                 }
1625                 break;
1626         }
1627         s = value;
1628         if (n)
1629         {
1630                 n = (n & 06) == 04 ? '\'' : '"';
1631                 sfputc(tp, n);
1632                 while (c = *s++)
1633                 {
1634                         if (c == n || c == '\\')
1635                                 sfputc(tp, '\\');
1636                         sfputc(tp, c);
1637                 }
1638                 sfputc(tp, n);
1639                 sfputc(tp, '\n');
1640         }
1641         else sfputr(tp, s, '\n');
1642         n = sfstrtell(tp) + 1;
1643         if (n >= 10000)
1644                 n += 4;
1645         else if (n >= 1000)
1646                 n += 3;
1647         else if (n >= 100)
1648                 n += 2;
1649         else if (n >= 10)
1650                 n += 1;
1651         sfprintf(sp, "%d%s", n, sfstruse(tp));
1652 }
1653
1654 /*
1655  * write next archive entry header
1656  */
1657
1658 void
1659 putheader __PARAM__((Archive_t* ap, File_t* f), (ap, f)) __OTORP__(Archive_t* ap; File_t* f;){
1660         char*   s;
1661         int     n;
1662         int             c;
1663
1664         setdeltaheader(ap, f);
1665         if (!f->extended)
1666         {
1667                 ap->entry++;
1668                 if (ap->format == PAX)
1669                 {
1670                         unsigned long           t;
1671                         char*                   base;
1672                         char*                   next;
1673                         Buffer_t*               bp;
1674                         File_t                  h;
1675                         Hash_position_t*        pos;
1676                         Option_t*               op;
1677                         Sfio_t*                 hp;
1678                         Sfio_t*                 tp;
1679                         Value_t*                vp;
1680                         char                    num[32];
1681
1682                         if (!(hp = sfstropen()) || !(tp = sfstropen()))
1683                                 error(3, "out of space [extended]");
1684                         if (pos = hashscan(state.options, 0))
1685                         {
1686                                 while (hashnext(pos))
1687                                 {
1688                                         op = (Option_t*)pos->bucket->value;
1689                                         if ((op->flags & (OPT_HEADER|OPT_READONLY)) == OPT_HEADER && op->name == pos->bucket->name && (!op->level || op->level >= (ap->entry == 1 ? 1 : 3) && op->level < 5))
1690                                         {
1691                                                 vp = (op->level >= 3) ? &op->temp : &op->perm;
1692                                                 s = vp->string;
1693                                                 switch (op->index)
1694                                                 {
1695                                                 case OPT_atime:
1696                                                 case OPT_ctime:
1697                                                 case OPT_mtime:
1698                                                         if (op->flags & OPT_SET) t = vp->number;
1699                                                         else switch (op->index)
1700                                                         {
1701                                                         case OPT_atime:
1702                                                                 t = f->st->st_atime;
1703                                                                 break;
1704                                                         case OPT_ctime:
1705                                                                 t = f->st->st_ctime;
1706                                                                 break;
1707                                                         case OPT_mtime:
1708                                                                 /* already in tar_header */
1709                                                                 continue;
1710                                                         }
1711                                                         sfsprintf(s = num, sizeof(num), "%lu.0", t);
1712                                                         break;
1713                                                 case OPT_gname:
1714                                                         if (op->flags & OPT_SET)
1715                                                         {
1716                                                                 f->gidname = s;
1717                                                                 s = 0;
1718                                                         }
1719                                                         getidnames(f);
1720                                                         if (strlen(f->gidname) >= sizeof(tar_header.gname) || !portable(f->gidname))
1721                                                                 s = f->gidname;
1722                                                         break;
1723                                                 case OPT_uname:
1724                                                         if (op->flags & OPT_SET)
1725                                                         {
1726                                                                 f->uidname = s;
1727                                                                 s = 0;
1728                                                         }
1729                                                         getidnames(f);
1730                                                         if (strlen(f->uidname) >= sizeof(tar_header.uname) || !portable(f->uidname))
1731                                                                 s = f->uidname;
1732                                                         break;
1733                                                 default:
1734                                                         if (!s && (op->flags & OPT_SET))
1735                                                                 sfsprintf(s = num, sizeof(num), "%ld", vp->number);
1736                                                         break;
1737                                                 }
1738                                                 if (s) putkey(hp, tp, op->name, !op->level || op->level >= 3 ? ':' : 0, s);
1739                                         }
1740                                 }
1741                                 hashdone(pos);
1742                         }
1743                         s = f->name;
1744                         if (f->namesize > sizeof(tar_header.name) - (f->type == X_IFDIR))
1745                                 for (; s = strchr(s, '/'); s++)
1746                                 {
1747                                         if ((n = s - f->name) >= sizeof(tar_header.prefix))
1748                                         {
1749                                                 s = 0;
1750                                                 break;
1751                                         }
1752                                         if (f->namesize <= sizeof(tar_header.name) + n)
1753                                                 break;
1754                                 }
1755                         if (!s || !portable(f->name))
1756                                 putkey(hp, tp, options[OPT_path].name, ':', f->name);
1757                         if (f->linktype != NOLINK && (f->linknamesize > sizeof(tar_header.linkname) || !portable(f->linkname)))
1758                                 putkey(hp, tp, options[OPT_linkpath].name, ':', f->linkname);
1759                         if (n = sfstrtell(hp))
1760                         {
1761                                 s = sfstruse(hp);
1762                                 listprintf(tp, ap, f, state.header.name);
1763                                 initfile(ap, &h, sfstruse(tp), X_IFREG|X_IRUSR|X_IWUSR|X_IRGRP|X_IROTH);
1764                                 h.extended = 1;
1765                                 h.st->st_gid = f->st->st_gid;
1766                                 h.st->st_uid = f->st->st_uid;
1767                                 h.st->st_mtime = time((time_t*)0);
1768                                 h.st->st_size = n;
1769                                 h.fd = setbuffer(0);
1770                                 bp = getbuffer(h.fd);
1771                                 base = bp->base;
1772                                 next = bp->next;
1773                                 bp->base = bp->next = s;
1774                                 fileout(ap, &h);
1775                                 bp->base = base;
1776                                 bp->next = next;
1777                         }
1778                         sfstrclose(hp);
1779                         sfstrclose(tp);
1780                 }
1781         }
1782         if (state.complete)
1783         {
1784                 unsigned long   c = f->st->st_size;
1785
1786                 switch (ap->format)
1787                 {
1788                 case ALAR:
1789                 case IBMAR:
1790                         c += 4 * ALAR_HEADER;
1791                         break;
1792                 case ASC:
1793                 case ASCHK:
1794                         c += ASC_HEADER + f->namesize;
1795                         break;
1796                 case BINARY:
1797                         c += BINARY_HEADER + f->namesize;
1798                         c = roundof(c, 2);
1799                         break;
1800                 case CPIO:
1801                         c += CPIO_HEADER + f->namesize;
1802                         break;
1803                 case PAX:
1804                 case TAR:
1805                 case USTAR:
1806                         c += TAR_HEADER;
1807                         c = roundof(c, BLOCKSIZE);
1808                         break;
1809                 case VDB:
1810                         c += state.record.header ? state.record.headerlen : f->namesize;
1811                         break;
1812                 }
1813                 if (ap->io.count + c > state.maxout)
1814                 {
1815                         if (c > state.maxout) error(1, "%s: too large to fit in one volume", f->name);
1816                         else
1817                         {
1818                                 state.complete = 0;
1819                                 putepilogue(ap);
1820                                 newio(ap, 0, 0);
1821                                 putprologue(ap);
1822                                 state.complete = 1;
1823                         }
1824                 }
1825         }
1826         switch (ap->format)
1827         {
1828         case ALAR:
1829         case IBMAR:
1830                 putlabels(ap, f, "HDR");
1831                 break;
1832         case BINARY:
1833                 binary_header.magic = CPIO_MAGIC;
1834                 binary_header.namesize = f->namesize;
1835                 cpio_short(binary_header.size, f->st->st_size + f->linknamesize);
1836                 binary_header.dev = f->st->st_dev;
1837                 binary_header.ino = f->st->st_ino;
1838                 binary_header.mode = f->st->st_mode;
1839                 binary_header.uid = f->st->st_uid;
1840                 binary_header.gid = f->st->st_gid;
1841                 binary_header.links = f->st->st_nlink;
1842                 binary_header.rdev = idevice(f->st);
1843                 if (binary_header.rdev != idevice(f->st)) error(1, "%s: special device numbers truncated", f->name);
1844                 cpio_short(binary_header.mtime, (long)f->st->st_mtime);
1845                 bwrite(ap, &binary_header, BINARY_HEADER);
1846                 bwrite(ap, f->name, f->namesize);
1847                 if (n = (BINARY_HEADER + f->namesize) % BINARY_ALIGN)
1848                         while (n++ < BINARY_ALIGN) bwrite(ap, "", 1);
1849                 if (f->type == X_IFLNK)
1850                 {
1851                 cpio_link:
1852                         if (streq(f->name, f->linkname))
1853                                 error(1, "%s: symbolic link loops to self", f->name);
1854                         bwrite(ap, f->linkname, f->linknamesize);
1855                         putdeltaheader(ap, f);
1856                 }
1857                 break;
1858         case CPIO:
1859 #if CPIO_EXTENDED
1860                 if (!f->skip)
1861                 {
1862                         getidnames(f);
1863                         addxopstr(ap, 'U', f->uidname);
1864                         addxopstr(ap, 'G', f->gidname);
1865                         if (CPIO_TRUNCATE(idevice(f->st)) != idevice(f->st)) addxopnum(ap, 'd', idevice(f->st));
1866 #if NUMBER_EVEN_THOUGH_NAME
1867                         if (CPIO_TRUNCATE(f->st->st_gid) != f->st->st_gid) addxopnum(ap, 'g', f->st->st_gid);
1868                         if (CPIO_TRUNCATE(f->st->st_uid) != f->st->st_uid) addxopnum(ap, 'u', f->st->st_uid);
1869 #endif
1870                         setxops(ap, f);
1871                 }
1872 #else
1873                 if (CPIO_TRUNCATE(idevice(f->st)) != idevice(f->st)) error(1, "%s: special device number truncated", f->name);
1874                 if (CPIO_TRUNCATE(f->st->st_gid) != f->st->st_gid) error(1, "%s: gid number truncated", f->name);
1875                 if (CPIO_TRUNCATE(f->st->st_uid) != f->st->st_uid) error(1, "%s: uid number truncated", f->name);
1876 #endif
1877                 sfsprintf(state.tmp.buffer, state.tmp.buffersize, "%0.6o%0.6o%0.6o%0.6o%0.6o%0.6o%0.6o%0.6o%0.11lo%0.6o%0.11lo",
1878                         CPIO_TRUNCATE(CPIO_MAGIC),
1879                         CPIO_TRUNCATE(f->st->st_dev),
1880                         CPIO_TRUNCATE(f->st->st_ino),
1881                         CPIO_TRUNCATE(f->st->st_mode),
1882                         CPIO_TRUNCATE(f->st->st_uid),
1883                         CPIO_TRUNCATE(f->st->st_gid),
1884                         CPIO_TRUNCATE(f->st->st_nlink),
1885                         CPIO_TRUNCATE(idevice(f->st)),
1886                         f->st->st_mtime,
1887                         f->namesize,
1888                         f->st->st_size + f->linknamesize);
1889                 bwrite(ap, state.tmp.buffer, CPIO_HEADER);
1890 #if CPIO_EXTENDED
1891                 putxops(ap, f);
1892 #else
1893                 bwrite(ap, f->name, f->namesize);
1894 #endif
1895                 if (f->type == X_IFLNK) goto cpio_link;
1896                 break;
1897         case ASC:
1898                 f->checksum = 0;
1899                 /*FALLTHROUGH*/
1900         case ASCHK:
1901                 sfsprintf(state.tmp.buffer, state.tmp.buffersize, "%0.6o%0.8lx%0.8lx%0.8lx%0.8lx%0.8lx%0.8lx%0.8lx%0.8lx%0.8lx%0.8lx%0.8lx%0.8lx%0.8lx%0.8lx%0.8lx",
1902                         ap->format == ASC ? ASC_MAGIC : ASCHK_MAGIC,
1903                         (long)f->st->st_ino,
1904                         (long)f->st->st_mode,
1905                         (long)f->st->st_uid,
1906                         (long)f->st->st_gid,
1907                         (long)f->st->st_nlink,
1908                         (long)f->st->st_mtime,
1909                         (long)f->st->st_size + (long)f->linknamesize,
1910                         (long)major(f->st->st_dev),
1911                         (long)minor(f->st->st_dev),
1912                         (long)major(idevice(f->st)),
1913                         (long)minor(idevice(f->st)),
1914                         (long)f->namesize,
1915                         f->checksum);
1916                 bwrite(ap, state.tmp.buffer, ASC_HEADER);
1917                 bwrite(ap, f->name, f->namesize);
1918                 if (n = (ASC_HEADER + f->namesize) % ASC_ALIGN)
1919                         while (n++ < ASC_ALIGN) bwrite(ap, "", 1);
1920                 if (f->type == X_IFLNK) goto cpio_link;
1921                 break;
1922         case PAX:
1923         case TAR:
1924         case USTAR:
1925                 memzero(tar_block, TAR_HEADER);
1926                 s = f->name;
1927                 if (f->namesize > sizeof(tar_header.name) - (f->type == X_IFDIR))
1928                         for (;; s++)
1929                         {
1930                                 if (!(s = strchr(s, '/')))
1931                                 {
1932                                         s = f->name;
1933                                         break;
1934                                 }
1935                                 if ((f->namesize - (s - f->name)) <= sizeof(tar_header.name))
1936                                 {
1937                                         *s = 0;
1938                                         sfsprintf(tar_header.prefix, sizeof(tar_header.prefix), "%-.*s", sizeof(tar_header.prefix), f->name);
1939                                         *s++ = '/';
1940                                         break;
1941                                 }
1942                         }
1943                 sfsprintf(tar_header.name, sizeof(tar_header.name), "%s%s", s, f->type == X_IFDIR ? "/" : "");
1944                 if (f->extended) tar_header.typeflag = EXTTYPE;
1945                 else switch (f->linktype)
1946                 {
1947                 case HARDLINK:
1948                         tar_header.typeflag = LNKTYPE;
1949                 linked:
1950                         sfsprintf(tar_header.linkname, sizeof(tar_header.linkname), "%s", f->linkname);
1951                         break;
1952                 case SOFTLINK:
1953                         tar_header.typeflag = SYMTYPE;
1954                         goto linked;
1955                 default:
1956                         switch (ap->format == TAR ? X_IFREG : f->type)
1957                         {
1958                         case X_IFCHR:
1959                                 tar_header.typeflag = CHRTYPE;
1960                         special:
1961                                 sfsprintf(tar_header.devmajor, sizeof(tar_header.devmajor), "%*o ", sizeof(tar_header.devmajor) - 2, major(idevice(f->st)));
1962                                 sfsprintf(tar_header.devminor, sizeof(tar_header.devminor), "%*o ", sizeof(tar_header.devminor) - 2, minor(idevice(f->st)));
1963                                 break;
1964                         case X_IFBLK:
1965                                 tar_header.typeflag = BLKTYPE;
1966                                 goto special;
1967                         case X_IFDIR:
1968                                 tar_header.typeflag = DIRTYPE;
1969                                 break;
1970                         case X_IFIFO:
1971                                 tar_header.typeflag = FIFOTYPE;
1972                                 break;
1973                         case X_IFSOCK:
1974                                 tar_header.typeflag = SOKTYPE;
1975                                 goto special;
1976                         default:
1977                                 if (!f->skip)
1978                                         error(1, "%s: unknown file type 0%03o -- assuming regular file", f->name, f->type >> 12);
1979                                 /*FALLTHROUGH*/
1980                         case X_IFREG:
1981                                 tar_header.typeflag = REGTYPE;
1982                                 break;
1983                         }
1984                         break;
1985                 }
1986                 sfsprintf(tar_header.mode, sizeof(tar_header.mode), "%*o ", sizeof(tar_header.mode) - 2, f->st->st_mode & X_IPERM);
1987                 sfsprintf(tar_header.uid, sizeof(tar_header.uid), "%*o ", sizeof(tar_header.uid) - 2, f->st->st_uid);
1988                 sfsprintf(tar_header.gid, sizeof(tar_header.gid), "%*o ", sizeof(tar_header.gid) - 2, f->st->st_gid);
1989                 sfsprintf(tar_header.size, sizeof(tar_header.size), "%*lo ", sizeof(tar_header.size) - 1, f->st->st_size);
1990                 sfsprintf(tar_header.mtime, sizeof(tar_header.mtime), "%*lo ", sizeof(tar_header.mtime) - 2, f->st->st_mtime);
1991                 if (ap->format != TAR)
1992                 {
1993                         strncpy(tar_header.magic, TMAGIC, sizeof(tar_header.magic));
1994                         strncpy(tar_header.version, TVERSION, sizeof(tar_header.version));
1995                         getidnames(f);
1996                         strcpy(tar_header.uname, f->uidname);
1997                         strcpy(tar_header.gname, f->gidname);
1998                 }
1999                 sfsprintf(tar_header.chksum, sizeof(tar_header.chksum), "%*o ", sizeof(tar_header.chksum) - 2, tar_checksum());
2000                 bwrite(ap, tar_block, TAR_HEADER);
2001                 break;
2002         case VDB:
2003                 if (state.record.header) bwrite(ap, state.record.header, state.record.headerlen);
2004                 else
2005                 {
2006                         f->name[f->namesize - 1] = '\n';
2007                         bwrite(ap, f->name, f->namesize);
2008                         f->name[f->namesize - 1] = 0;
2009                 }
2010                 if (!(c = state.record.delimiter))
2011                 {
2012                         c = VDB_DELIMITER;
2013                         if (f->fd >= 0)
2014                         {
2015                                 n = read(f->fd, tar_block, TAR_HEADER);
2016                                 if (n > 0) lseek(f->fd, -n, SEEK_CUR);
2017                         }
2018                         else if ((n = bread(ap, tar_block, 0L, (long)TAR_HEADER, 1)) > 0)
2019                                 bunread(ap, tar_block, n);
2020                         if (n > 0)
2021                         {
2022                                 int             dp;
2023                                 int             ds;
2024                                 int             mp = 0;
2025                                 int             ms = 0;
2026                                 unsigned char   hit[UCHAR_MAX + 1];
2027
2028                                 /*
2029                                  * to determine the delimiter, if any
2030                                  */
2031
2032                                 memzero(hit, sizeof(hit));
2033                                 while (--n > 0)
2034                                         hit[*((unsigned char*)tar_block + n)]++;
2035                                 for (n = 0; n <= UCHAR_MAX; n++)
2036                                         if (n == '_' || n == '/' || n == '.' || n == '\n' || n == '\\')
2037                                                 /* nop */;
2038                                         else if (isspace(n))
2039                                         {
2040                                                 if ((int)hit[n] > ms)
2041                                                 {
2042                                                         ms = hit[n];
2043                                                         ds = n;
2044                                                 }
2045                                         }
2046                                         else if ((int)hit[n] > mp && isprint(n) && !isalnum(n))
2047                                         {
2048                                                 mp = hit[n];
2049                                                 dp = n;
2050                                         }
2051                                 if (mp) c = dp;
2052                                 else if (ms) c = ds;
2053                         }
2054                 }
2055                 n = (c == '=') ? ':' : '=';
2056                 sfprintf(state.vdb.directory, "%c%s%c%lu%c%lu%c%s%c%lu%c%s%c0%o\n", c, f->name, c, ap->io.offset + ap->io.count, c, f->st->st_size, c, VDB_DATE, n, f->st->st_mtime, c, VDB_MODE, n, modex(f->st->st_mode & X_IPERM));
2057                 break;
2058         }
2059         putdeltaheader(ap, f);
2060 }
2061
2062 /*
2063  * read entry trailer
2064  */
2065
2066 void
2067 gettrailer __PARAM__((Archive_t* ap, File_t* f), (ap, f)) __OTORP__(Archive_t* ap; File_t* f;){
2068         long    n;
2069
2070         NoP(f);
2071         if (ap->sum-- > 0)
2072         {
2073                 ap->checksum ^= ap->memsum;
2074                 ap->old.checksum ^= ap->old.memsum;
2075         }
2076         getdeltatrailer(ap, f);
2077         if ((n = format[ap->format].align) && (n = roundof(ap->io.count, n) - ap->io.count))
2078                 bread(ap, state.tmp.buffer, 0L, n, 1);
2079         ap->memsum = 0;
2080         ap->old.memsum = 0;
2081 }
2082
2083 /*
2084  * write entry trailer
2085  */
2086
2087 void
2088 puttrailer __PARAM__((Archive_t* ap, File_t* f), (ap, f)) __OTORP__(Archive_t* ap; File_t* f;){
2089         int     n;
2090
2091         putdeltatrailer(ap, f);
2092         switch (ap->format)
2093         {
2094         case ALAR:
2095         case IBMAR:
2096                 putlabels(ap, f, "EOF");
2097                 break;
2098         case VDB:
2099                 if (state.record.trailer)
2100                         bwrite(ap, state.record.trailer, state.record.trailerlen);
2101                 break;
2102         }
2103         if ((n = format[ap->format].align) && (n = roundof(ap->io.count, n) - ap->io.count))
2104         {
2105                 memzero(state.tmp.buffer, n);
2106                 bwrite(ap, state.tmp.buffer, n);
2107         }
2108         listentry(f);
2109 }
2110
2111 /*
2112  * return length of next label
2113  * variable length labels have label number > 3 and Vnnnn at position 5
2114  * where nnnn is the decimal length of the entire label
2115  * nnnn may be < ALAR_HEADER but label block must be >= ALAR_HEADER
2116  * 0 returned at end of label group
2117  */
2118
2119 int
2120 getlabel __PARAM__((Archive_t* ap, File_t* f), (ap, f)) __OTORP__(Archive_t* ap; File_t* f;){
2121         int     c;
2122         int     n;
2123
2124         static char     last[5];
2125         static int      done;
2126
2127         if (done || (c = bread(ap, alar_header, (long)ALAR_HEADER, (long)ALAR_LABEL, 0)) < ALAR_HEADER) return(*last = done = c = 0);
2128         if (ap->format == IBMAR) memetoa(alar_header, alar_header, ALAR_HEADER);
2129         if (alar_header[4] == 'V' && ((n = getlabnum(alar_header, 4, 1, 10)) < 1 || n > 3) && (n = getlabnum(alar_header, 6, 4, 10)) != c)
2130         {
2131                 if ((c = n - c) > 0)
2132                 {
2133                         if (ap->io.blocked || bread(ap, alar_header + ALAR_HEADER, 0L, (long)c, 1) != c)
2134                         {
2135                                 c = ALAR_HEADER;
2136                                 error(2, "%s: %-*.*s: variable length label record too short", f->name, c, c, alar_header);
2137                         }
2138                         else
2139                         {
2140                                 if (ap->format == IBMAR) memetoa(alar_header + ALAR_HEADER, alar_header + ALAR_HEADER, c);
2141                                 c = n;
2142                         }
2143                 }
2144                 else if (n <= ALAR_VARHDR) c = ALAR_VARHDR;
2145                 else c = n;
2146         }
2147         if (!ap->io.blocked && !*last && alar_header[3] == '2' && (strneq(alar_header, "HDR", 3) || strneq(alar_header, "EOF", 3) || strneq(alar_header, "EOV", 3)))
2148                 getlabstr(alar_header, 26, 4, last);
2149         if (*last && strneq(alar_header, last, 4)) done = 1;
2150         message((-4, "label: %-*.*s", c, c, alar_header));
2151         return(c);
2152 }
2153
2154 /*
2155  * output file HDR/EOF/EOV labels
2156  */
2157
2158 void
2159 putlabels __PARAM__((Archive_t* ap, File_t* f, char* type), (ap, f, type)) __OTORP__(Archive_t* ap; File_t* f; char* type;){
2160         struct tm*      tm;
2161
2162         static int      section = 1;
2163         static int      sequence;
2164
2165         switch (*type)
2166         {
2167         case 'E':
2168                 bwrite(ap, alar_header, 0);
2169                 break;
2170         case 'H':
2171                 sequence++;
2172                 break;
2173         }
2174         tm = gmtime(&f->st->st_mtime);
2175         sfsprintf(alar_header, sizeof(alar_header), "%s1%-17.17s000001%04d%04d000100 %02d%03d 00000 %06d%-6.6sD%-7.7s       ", type, f->id, section, sequence, tm->tm_year, tm->tm_yday, f->record.blocks, state.id.format, state.id.implementation);
2176         if (ap->format == IBMAR) mematoe(alar_header, alar_header, ALAR_HEADER);
2177         bwrite(ap, alar_header, ALAR_HEADER);
2178         sfsprintf(alar_header, sizeof(alar_header), "%s2%c%05d%05d%010d%s%c                     00                            ", type, state.record.format, state.blocksize, state.record.size, f->st->st_size, type, '2');
2179         if (ap->format == IBMAR) mematoe(alar_header, alar_header, ALAR_HEADER);
2180         bwrite(ap, alar_header, ALAR_HEADER);
2181         bwrite(ap, alar_header, 0);
2182         if (streq(type, "EOV"))
2183         {
2184                 section++;
2185                 sequence = 0;
2186         }
2187         else section = 1;
2188 }
2189
2190 #ifdef SAVESET
2191
2192 /*
2193  * get next saveset record
2194  * if header!=0 then all records skipped until REC_file found
2195  * otherwise REC_vbn cause non-zero return
2196  * 0 returned for no record match
2197  */
2198
2199 int
2200 getsaveset __PARAM__((Archive_t* ap, File_t* f, int header), (ap, f, header)) __OTORP__(Archive_t* ap; File_t* f; int header;){
2201         char*   p;
2202         char*   s;
2203         char*           t;
2204         int             i;
2205         long            n;
2206
2207         for (;;)
2208         {
2209                 state.saveset.bp += state.saveset.lastsize;
2210                 while (state.saveset.bp >= state.saveset.block + state.blocksize)
2211                 {
2212                         state.saveset.bp = state.saveset.block;
2213                         state.saveset.lastsize = 0;
2214                         if (bread(ap, state.saveset.bp, 0L, (long)state.blocksize, 0) <= 0)
2215                         {
2216                                 ap->format = ALAR;
2217                                 if (header) gettrailer(ap, f);
2218                                 return(0);
2219                         }
2220                         if (swapget(1, state.saveset.bp + BLKHDR_hdrsiz, 2) != BLKHDR_SIZE)
2221                                 error(3, "invalid %s format block header", format[ap->format].name);
2222                         if (!(n = swapget(3, state.saveset.bp + BLKHDR_blksiz, 4)))
2223                                 state.saveset.bp += state.blocksize;
2224                         else if (n != state.blocksize)
2225                                 error(3, "invalid %s format blocksize=%ld", format[ap->format].name, n);
2226                         state.saveset.bp += BLKHDR_SIZE;
2227                 }
2228                 state.saveset.lastsize = swapget(1, state.saveset.bp + RECHDR_size, 2);
2229                 i = swapget(1, state.saveset.bp + RECHDR_type, 2);
2230                 state.saveset.bp += RECHDR_SIZE;
2231                 message((-2, "record: type=%d size=%d", i, state.saveset.lastsize));
2232                 if (i == REC_file)
2233                 {
2234                         if (header)
2235                         {
2236                                 p = state.saveset.bp;
2237                                 if (swapget(1, p, 2) != FILHDR_MAGIC)
2238                                         error(3, "invalid %s format file header", format[ap->format].name);
2239                                 p += 2;
2240                                 i = swapget(1, p + FILHDR_size, 2);
2241                                 if (p + FILHDR_data + i > state.saveset.block + state.blocksize)
2242                                         error(3, "invalid %s format file attribute", format[ap->format].name);
2243                                 t = f->name;
2244                                 n = 0;
2245                                 for (s = p + FILHDR_data + 1; s < p + FILHDR_data + i; s++)
2246                                 {
2247                                         if (isupper(*s)) *t++ = tolower(*s);
2248                                         else if (n)
2249                                         {
2250                                                 if (*s == ';') break;
2251                                                 *t++ = *s;
2252                                         }
2253                                         else if (*s == ']')
2254                                         {
2255                                                 n = 1;
2256                                                 *t++ = '/';
2257                                         }
2258                                         else if (*s == '.') *t++ = '/';
2259                                         else *t++ = *s;
2260                                 }
2261                                 *t = 0;
2262                                 for (i = 0; i < 5; i++)
2263                                 {
2264                                         s = p + FILHDR_size;
2265                                         if ((p += FILHDR_SIZE + (long)swapget(1, s, 2)) > state.saveset.block + state.blocksize)
2266                                                 error(3, "invalid %s format file attribute", format[ap->format].name);
2267                                 }
2268                                 state.saveset.recatt = *(p + FILHDR_data + FILATT_recfmt);
2269                                 state.saveset.recfmt = *(p + FILHDR_data + FILATT_recfmt);
2270                                 state.saveset.reclen = swapget(1, p + FILHDR_data + FILATT_reclen, 2);
2271                                 state.saveset.recvfc = swapget(1, p + FILHDR_data + FILATT_recvfc, 2);
2272                                 f->st->st_size = (long)(swapget(1, p + FILHDR_data + FILATT_blocks, 2) - 1) * BLOCKSIZE + (long)swapget(1, p + FILHDR_data + FILATT_frag, 2);
2273                                 for (; i < 15; i++)
2274                                 {
2275                                         s = p + FILHDR_size;
2276                                         if ((p += FILHDR_SIZE + (long)swapget(1, s, 2)) > state.saveset.block + state.blocksize)
2277                                                 error(3, "invalid %s format file attribute", format[ap->format].name);
2278                                 }
2279
2280                                 /*
2281                                  * pure guesswork based on 100 nsec epoch
2282                                  * 17-NOV-1858 00:00:00 GMT
2283                                  */
2284
2285                                 if ((n = swapget(3, p + FILHDR_data + 4, 4) - 7355000) < 0) n = 1;
2286                                 else n = (n << 8) + *(p + FILHDR_data + 3);
2287                                 f->st->st_mtime = (time_t)n;
2288                                 return(1);
2289                         }
2290                         state.saveset.bp -= RECHDR_SIZE;
2291                         state.saveset.lastsize = 0;
2292                         return(0);
2293                 }
2294                 else if (i == REC_vbn && !header) return(1);
2295         }
2296 }
2297
2298 #endif