2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
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)
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
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
23 /* $XConsortium: format.c /main/3 1995/11/01 17:00:37 rswiston $ */
24 /***************************************************************
26 * AT&T - PROPRIETARY *
28 * THIS IS PROPRIETARY SOURCE CODE LICENSED BY *
31 * Copyright (c) 1995 AT&T Corp. *
32 * All Rights Reserved *
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 *
38 * This software was created by the *
39 * Software Engineering Research Department *
40 * AT&T Bell Laboratories *
42 * For further information contact *
43 * gsf@research.att.com *
45 ***************************************************************/
47 /* : : generated by proto : : */
49 #if !defined(__PROTO__)
50 #if defined(__STDC__) || defined(__cplusplus) || defined(_proto) || defined(c_plusplus)
51 #if defined(__cplusplus)
52 #define __MANGLE__ "C"
57 #define __PROTO__(x) x
59 #define __PARAM__(n,o) n
60 #if !defined(__STDC__) && !defined(__cplusplus)
61 #if !defined(c_plusplus)
72 #define __PROTO__(x) ()
73 #define __OTORP__(x) x
74 #define __PARAM__(n,o) o
82 #if defined(__cplusplus) || defined(c_plusplus)
83 #define __VARARG__ ...
87 #if defined(__STDARG__)
88 #define __VA_START__(p,a) va_start(p,a)
90 #define __VA_START__(p,a) va_start(p)
94 #if defined(__linux__)
95 #include <sys/sysmacros.h>
101 #if __hppa__ || __hppa || hppa
104 * the inline macros are apparently too much for the hp optimizer
105 * (the calls in putprologue() make the difference)
109 delta_lo __PARAM__((long x), (x)) __OTORP__(long x;){
114 #define DELTA_LO delta_lo
117 delta_hi __PARAM__((long x), (x)) __OTORP__(long x;){
122 #define DELTA_HI delta_hi
127 * check for ASCII or EBCDIC ALAR prologue in alar_header
131 isalar __PARAM__((Archive_t* ap, char* hdr), (ap, hdr)) __OTORP__(Archive_t* ap; char* hdr;){
134 if (!strneq(hdr, "VOL1", 4))
136 memetoa(buf, hdr, 4);
137 if (!strneq(buf, "VOL1", 4)) return(0);
138 memetoa(hdr, hdr, ALAR_HEADER);
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);
151 * read archive prologue before files are copied
155 getprologue __PARAM__((Archive_t* ap), (ap)) __OTORP__(Archive_t* ap;){
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;
164 if (bread(ap, alar_header, (long)ALAR_HEADER, (long)ALAR_HEADER, 0) <= 0)
166 if (!bcount(ap)) return(0);
168 else if (!isalar(ap, alar_header))
170 if (strneq(alar_header, PORTAR_MAG, PORTAR_MAGSIZ))
172 bunread(ap, alar_header, ALAR_HEADER - 8);
173 if (bread(ap, &portar_header, 0L, (long)PORTAR_HEADER, 0) > 0)
175 if (!strneq(portar_header.ar_fmag, PORTAR_END, PORTAR_ENDSIZ) || sscanf(portar_header.ar_size, "%ld", &size) != 1)
177 bunread(ap, &portar_header, PORTAR_HEADER);
178 bunread(ap, PORTAR_MAG, PORTAR_MAGSIZ);
183 if (strmatch(portar_header.ar_name, PORTAR_SYM) && (ap->format = PORTAR) || strmatch(portar_header.ar_name, RANDAR_SYM) && (ap->format = RANDAR))
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);
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;
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)
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);
207 else bunread(ap, &portar_header, PORTAR_HEADER);
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);
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)
227 bunread(ap, alar_header, ALAR_HEADER);
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;
238 ops[0] = PROC_FD_DUP(ap->io.fd, 0, PROC_FD_CHILD);
239 if (ap->parent && !state.ordered)
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);
245 proc = procopen(*cmd, cmd, NiL, ops, 0);
250 proc = procopen(*cmd, cmd, NiL, ops, PROC_READ);
253 error(3, "%s: cannot execute %s filter", ap->name, format[ap->compress].undo);
255 if (ap->parent && !state.ordered)
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);
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;
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");
289 * no hard links between volumes
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");
301 * set pseudo file header+trailer info
305 setinfo __PARAM__((Archive_t* ap, File_t* f), (ap, f)) __OTORP__(Archive_t* ap; File_t* f;){
310 if (ap->delta->format != DELTA_IGNORE && ap->entry > 1 && f->st->st_mtime)
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");
315 error(3, "%s: corrupt archive: %d missing file%s", ap->name, n, n == 1 ? "" : "s");
317 ap->delta->epilogue = 1;
322 * output pseudo file header+trailer
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;
333 if (!ap->delta || ap->delta->version == DELTA_88) sfprintf(np, "DELTA");
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);
338 sfprintf(np, "%c%c", INFO_SEP, INFO_ORDERED);
340 sfprintf(np, "%c%c%c", INFO_SEP, INFO_SEP, INFO_SEP);
343 initfile(ap, f, file, X_IFREG);
345 f->st->st_mtime = mtime;
346 f->st->st_uid = DELTA_LO(checksum);
347 f->st->st_gid = DELTA_HI(checksum);
350 if (np) sfstrclose(np);
354 * write archive prologue before files are copied
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;
366 if (ap->io.blok) ap->io.blocked = 1;
369 ap->io.blocked = !ap->io.unblocked;
370 if (!state.id.owner[0])
372 strncpy(state.id.owner, fmtuid(getuid()), sizeof(state.id.owner) - 1);
373 state.id.owner[sizeof(state.id.owner) - 1] = 0;
375 strupper(state.id.owner);
376 if (!state.id.volume[0])
378 strncpy(state.id.volume, state.id.owner, sizeof(state.id.volume) - 1);
379 state.id.volume[sizeof(state.id.volume) - 1] = 0;
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))
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);
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);
407 if (ap->delta && (ap->delta->format == COMPRESS || ap->delta->format == DELTA))
409 if (ap->delta->base) putinfo(ap, NiL, ap->delta->base->size, ap->delta->base->checksum);
410 else putinfo(ap, NiL, 0, 0);
417 * read archive epilogue after all files have been copied
421 getepilogue __PARAM__((Archive_t* ap), (ap)) __OTORP__(Archive_t* ap;){
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);
447 if (state.vdb.header.base)
449 free(state.vdb.header.base);
450 state.vdb.header.base = 0;
455 * check for more volumes
456 * volumes begin on BLOCKSIZE boundaries
457 * separated by up to MAXBLOCKS null byte filler
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"));
470 if (!(n = roundof(ap->io.count, BLOCKSIZE) - ap->io.count) || bread(ap, state.tmp.buffer, 0L, (long)n, 0) > 0) do
472 if (*(s = state.tmp.buffer) && n == BLOCKSIZE)
474 bunread(ap, state.tmp.buffer, BLOCKSIZE);
475 ap->format = IN_DEFAULT;
476 message((-2, "go for next volume %-.32s...", state.tmp.buffer));
479 while (s < state.tmp.buffer + n && !*s++);
480 if (s < state.tmp.buffer + n)
482 if (ap->volume > 1) error(1, "junk data after volume %d", ap->volume);
486 } while (i-- > 0 && bread(ap, state.tmp.buffer, 0L, n, 0) > 0);
490 ap->format = IN_DEFAULT;
495 * write archive epilogue after files have been copied
499 putepilogue __PARAM__((Archive_t* ap), (ap)) __OTORP__(Archive_t* ap;){
501 unsigned long boundary;
505 if (ap->selected > selected)
507 if (ap->delta && (ap->delta->format == COMPRESS || ap->delta->format == DELTA)) switch (ap->format)
515 putinfo(ap, NiL, ap->delta->index + 1, 0);
518 selected = ap->selected;
519 boundary = ap->io.count;
524 bwrite(ap, alar_header, 0);
525 bwrite(ap, alar_header, 0);
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;
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;
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;
551 if ((n = boundary - ap->io.count) < 0)
552 n = roundof(ap->io.count, boundary) - ap->io.count;
555 memzero(state.tmp.buffer, n);
556 bwrite(ap, state.tmp.buffer, n);
563 ap->io.count = ap->io.offset = 0;
564 ap->io.next = ap->io.buffer;
570 static char opsbuf[PATH_MAX]; /* extended ops buffer */
572 static char* ops = opsbuf; /* opsbuf output pointer */
575 * get and execute extended ops from input
579 getxops __PARAM__((Archive_t* ap, File_t* f), (ap, f)) __OTORP__(Archive_t* ap; File_t* f;){
585 if (f->namesize > (n = strlen(f->name) + 1)) for (p = f->name + n; c = *p++;)
587 for (s = p; *p; 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));
610 * NOTE: ignore unknown ops for future extensions
617 * set end of extended ops
621 setxops __PARAM__((Archive_t* ap, File_t* f), (ap, f)) __OTORP__(Archive_t* ap; File_t* f;){
625 if (n = ops - opsbuf)
629 if ((f->namesize += n) > CPIO_NAMESIZE) error(1, "%s: extended ops may crash older cpio programs", f->name);
634 * output filename and extended ops
638 putxops __PARAM__((Archive_t* ap, File_t* f), (ap, f)) __OTORP__(Archive_t* ap; File_t* f;){
642 bwrite(ap, f->name, f->namesize -= n);
643 if (n) bwrite(ap, ops = opsbuf, n);
648 * add extended op string
652 addxopstr __PARAM__((Archive_t* ap, int op, char* s), (ap, op, s)) __OTORP__(Archive_t* ap; int op; char* s;){
654 char* e = opsbuf + sizeof(opsbuf) - 3;
660 while (*s && p < e) *p++ = *s++;
665 if (*s) error(PANIC, "addxopstr('%c',\"%s\") overflow", op, s);
670 * add extended op number
674 addxopnum __PARAM__((Archive_t* ap, int op, long n), (ap, op, n)) __OTORP__(Archive_t* ap; int op; long n;){
677 sfsprintf(buf, sizeof(buf), "%x", n);
678 addxopstr(ap, op, buf);
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;){
696 op = &options[index];
697 if (op->level >= 6) switch (index)
706 f->st->st_uid = euid;
715 f->st->st_gid = egid;
718 else if (op->level < 5)
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;
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;){
736 op = &options[index];
738 *tm = time((time_t*)0);
739 else if (op->level < 5)
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;
749 * read next archive entry header
753 getheader __PARAM__((Archive_t* ap, File_t* f), (ap, f)) __OTORP__(Archive_t* ap; File_t* f;){
783 static char idbuffer[ALAR_NAMESIZE + 1];
784 static char uidname[9];
785 static char gidname[9];
787 static struct tar_header_info tar_last[16];
788 static int tar_last_index;
793 checkdelta = !ap->entry++ && (!ap->delta || ap->delta->format != DELTA_IGNORE && ap->delta->format != DELTA_PATCH);
795 if (ap->io.mode) bsave(ap);
800 f->record.format = 0;
802 message((-2, "%s:", format[ap->format].name));
807 if (!(lab = getlabel(ap, f))) return(0);
808 f->name = ap->path.header;
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;
817 f->linktype = NOLINK;
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))
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;
836 else if (strneq(alar_header, "HDR", 3))
838 if (getlabnum(alar_header, 4, 1, 10) != ++type) error(3, "%s format HDR label out of sequence", format[ap->format].name);
842 for (i = 4; i <= ALAR_NAMESIZE + 3; i++)
844 if (alar_header[i] == ' ')
846 if (i >= ALAR_NAMESIZE + 3 || alar_header[i + 1] == ' ') break;
849 else *s++ = isupper(alar_header[i]) ? tolower(alar_header[i]) : alar_header[i];
851 if ((n = getlabnum(alar_header, 40, 2, 10)) > 0 && n < 99) sfsprintf(s, 3, ".%02d", n);
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);
858 if (streq(state.id.format, SAVESET_ID) && streq(state.id.implementation, SAVESET_IMPL))
859 ap->format = SAVESET;
862 if (n = getlabnum(alar_header, 43, 2, 10))
864 if (alar_header[41] == '0') n += 100;
865 if ((i = getlabnum(alar_header, 45, 3, 10)) >= 0 && i <= 365)
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;
873 if (!f->st->st_mtime)
874 f->st->st_mtime = time((time_t*)0);
878 switch (f->record.format = alar_header[4])
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 */
887 error(2, "%s record format %c not supported", format[ap->format].name, f->record.format);
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);
896 else if (!ap->io.blocked && strneq(alar_header, "VOL1", 4))
898 bunread(ap, alar_header, lab);
899 if (!(getprologue(ap))) return(0);
902 } while ((lab = getlabel(ap, f)));
904 if (ap->format != SAVESET) goto found;
905 state.saveset.time = f->st->st_mtime;
906 if (state.blocksize > state.saveset.blocksize)
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);
913 state.saveset.bp = state.saveset.block + state.blocksize;
916 f->name = ap->path.header;
917 if (!getsaveset(ap, f, 1)) goto again;
921 if (bread(ap, &binary_header, (long)BINARY_HEADER, (long)BINARY_HEADER, 0) <= 0) break;
924 memcpy(state.tmp.buffer, &binary_header, BINARY_HEADER);
925 swapmem(ap->swap, &binary_header, &binary_header, BINARY_HEADER);
927 f->magic = binary_header.magic;
928 if (f->magic == CPIO_MAGIC)
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);
941 f->linktype = NOLINK;
945 f->name = ap->path.header;
963 if (n = (n + f->namesize) % i) i -= n;
966 if (f->namesize >= sizeof(ap->path.header))
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);
975 bread(ap, ap->path.header, 0, (long)(f->namesize + i), 1);
976 if (ap->path.header[f->namesize - 1])
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);
986 if (streq(f->name, CPIO_TRAILER))
988 getdeltaheader(ap, f);
993 switch (f->type = X_ITYPE(f->st->st_mode))
1004 error(1, "%s: unknown file type %07o -- regular file assumed", f->name, f->type);
1008 f->st->st_mode &= X_IPERM;
1009 f->st->st_mode |= f->type;
1013 if (f->st->st_size > sizeof(ap->path.link) - 1)
1015 error(2, "%s: entry %d.%d symbolic link text too long", ap->name, ap->volume, ap->entry);
1020 f->linktype = SOFTLINK;
1021 s = f->linkname = ap->path.link;
1022 while (bread(ap, s, 1, 1, 1) > 0)
1030 f->linktype = NOLINK;
1035 bunread(ap, ap->swap ? state.tmp.buffer : (char*)&binary_header, BINARY_HEADER);
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",
1051 &lst.size) == 11 && f->magic == CPIO_MAGIC)
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;
1064 bunread(ap, state.tmp.buffer, CPIO_HEADER);
1069 if (bread(ap, tar_block, 0L, (long)TAR_HEADER, 0) <= 0) break;
1070 if (!*tar_header.name)
1072 if (ap->entry == 1) goto notar;
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()))
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);
1091 if (ap->format != TAR)
1093 if (!streq(tar_header.magic, TMAGIC))
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;
1100 else if (!strneq(tar_header.version, TVERSION, sizeof(tar_header.version)))
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);
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)
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 */
1123 f->linktype = SOFTLINK;
1124 f->st->st_mode |= X_IFLNK;
1127 f->st->st_mode |= X_IFCHR;
1129 if (sscanf(tar_header.devmajor, "%11o", &num) != 1) goto notar;
1131 if (sscanf(tar_header.devminor, "%11o", &num) != 1) goto notar;
1132 IDEVICE(f->st, makedev(i, num));
1135 f->st->st_mode |= X_IFBLK;
1138 f->st->st_mode |= X_IFDIR;
1141 f->st->st_mode |= X_IFIFO;
1145 f->st->st_mode |= X_IFSOCK;
1150 if (f->st->st_size > 0)
1152 if (s = bget(ap, f->st->st_size))
1154 s[f->st->st_size - 1] = 0;
1155 stropt(s, state.options, 0, setoption, ap);
1157 else error(3, "invalid %s format extended header", format[ap->format].name);
1162 error(1, "unknown file type `%c' -- regular file assumed", tar_header.typeflag);
1166 f->namesize = strlen(f->name) + 1;
1167 if (f->name[f->namesize - 2] == '/')
1169 f->st->st_mode |= X_IFDIR;
1170 if (f->namesize > 2) f->name[--f->namesize - 1] = 0;
1172 else f->st->st_mode |= X_IFREG;
1177 if (ap->format != TAR)
1179 if (*tar_header.uname) f->uidname = tar_header.uname;
1180 if (*tar_header.gname) f->gidname = tar_header.gname;
1184 bunread(ap, tar_block, TAR_HEADER);
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",
1204 &lst.checksum) == 14 && (f->magic == ASC_MAGIC || f->magic == ASCHK_MAGIC))
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;
1219 bunread(ap, state.tmp.buffer, ASC_HEADER);
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",
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;
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;
1241 f->st->st_mtime = lst.mtime;
1242 f->st->st_size = lst.size;
1243 f->linktype = NOLINK;
1249 bunread(ap, &portar_header, PORTAR_HEADER);
1252 if (!state.vdb.header.base)
1254 if (fstat(ap->io.fd, &state.vdb.st)) break;
1255 state.vdb.st.st_mode = modex(state.vdb.st.st_mode);
1257 n = sizeof(VDB_MAGIC) + sizeof(state.id.volume) + 1;
1258 if (bread(ap, s, 0L, n, 0) <= 0) break;
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')
1264 if (t = strchr(s, '\n')) *t = 0;
1265 strncpy(state.id.volume, s + sizeof(VDB_MAGIC) + 1, sizeof(state.id.volume) - 2);
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++;
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++;
1288 if (!(t = strchr(t, state.vdb.delimiter))) goto vdb_eof;
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
1297 if (s = strchr(t, state.vdb.delimiter))
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;
1306 f->st->st_nlink = 1;
1308 f->linktype = NOLINK;
1318 lseek(ap->io.fd, 0L, SEEK_END);
1322 error(PANIC, "%s: incomplete input format implementation", format[ap->format].name);
1325 if (ap->entry == 1) for (;;) switch (ap->format)
1331 ap->format = BINARY;
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;
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)
1342 message((-1, "swapping %s header bytes", format[ap->format].name));
1356 if (ap->entries > 0 && ap->volume > 1)
1358 if (--ap->volume > 1) error(1, "junk data after volume %d", ap->volume);
1361 if (!state.keepgoing) error(3, "%s: unknown input format", ap->name);
1362 ap->format = IN_DEFAULT;
1366 if (ap->io.eof) return(0);
1368 if (state.keepgoing && bread(ap, ap->path.header, 0L, 1L, 0) > 0)
1370 if (warned) continue;
1374 error(i, "%s: entry %d.%d is out of phase", ap->name, ap->volume, ap->entry);
1375 if (ap->entry > 1) ap->entry++;
1378 if (checkdelta || ap->delta)
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))
1391 if (*s++ == INFO_SEP)
1393 if (strneq(s, ID, IDLEN) && (s = strchr(s, INFO_SEP)))
1405 error(3, "type %c encoding not supported", *s);
1407 if (*++s == INFO_SEP)
1409 if (t = strchr(++s, INFO_SEP)) *t++ = 0;
1410 for (i = DELTA; format[i].algorithm; i++)
1411 if (streq(s, format[i].algorithm))
1413 if (!format[i].algorithm)
1414 error(3, "delta version %s not supported", s);
1417 * [<INFO_SEP>[<OP>]<VAL>]* may appear here
1420 while ((s = t) && *s != INFO_SEP)
1422 if (t = strchr(s, INFO_SEP)) *t++ = 0;
1434 if (s = strchr(f->name + 3, INFO_SEP)) *s = 0;
1435 error(1, "unknown %s header ignored", f->name + 3);
1439 else if (streq(f->name, "DELTA!!!"))
1446 if (n == DELTA && ap->parent)
1447 error(3, "%s: %s: base archive cannot be a delta", ap->parent->name, ap->name);
1449 ap->delta->format = n;
1450 ap->delta->version = i;
1451 if (bp = ap->delta->base)
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)));
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);
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);
1469 else if (n == DELTA)
1471 error(state.list ? 1 : 3, "%s: base archive must be specified", ap->name);
1473 ap->delta->format = COMPRESS;
1479 else error(1, "%s: %s: unknown control header treated as regular file", ap->name, f->name);
1481 else if (*s++ == INFO_SEP && strneq(s, ID, IDLEN) && *(s + IDLEN) == INFO_SEP)
1487 if (checkdelta && ap->delta)
1488 ap->delta->format = DELTA_PATCH;
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--);
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;
1508 pathcanon(f->linkname, 0);
1509 if (!(state.ftwflags & FTW_PHYSICAL))
1510 f->linkname = map(f->linkname);
1511 f->linknamesize = strlen(f->linkname) + 1;
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);
1519 if (error_info.trace)
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);
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));
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
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)))
1540 if (--ap->volume == 1) error(1, "junk data after volume %d", ap->volume);
1546 error(3, "%s: blocked base archives are not supported", ap->delta->base);
1554 error(3, "%s: %s format base archives not supported", ap->delta->base, format[ap->format].name);
1557 if (state.summary && state.verbose)
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");
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)
1572 if (*state.id.format) sfprintf(sfstderr, " %s", state.id.format);
1573 if (*state.id.implementation) sfprintf(sfstderr, " implementation %s", state.id.implementation);
1575 sfprintf(sfstderr, "\n");
1578 if (ap->format == PAX || ap->format == TAR || ap->format == USTAR)
1580 if (++tar_last_index >= elementsof(tar_last)) tar_last_index = 0;
1581 tar_last[tar_last_index] = tar_header;
1583 if (!ap->delta || !ap->delta->trailer)
1590 * output extended header keyword assignment
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;){
1599 sfprintf(tp, " %s", name);
1600 if (op) sfputc(tp, op);
1630 n = (n & 06) == 04 ? '\'' : '"';
1634 if (c == n || c == '\\')
1641 else sfputr(tp, s, '\n');
1642 n = sfstrtell(tp) + 1;
1651 sfprintf(sp, "%d%s", n, sfstruse(tp));
1655 * write next archive entry header
1659 putheader __PARAM__((Archive_t* ap, File_t* f), (ap, f)) __OTORP__(Archive_t* ap; File_t* f;){
1664 setdeltaheader(ap, f);
1668 if (ap->format == PAX)
1675 Hash_position_t* pos;
1682 if (!(hp = sfstropen()) || !(tp = sfstropen()))
1683 error(3, "out of space [extended]");
1684 if (pos = hashscan(state.options, 0))
1686 while (hashnext(pos))
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))
1691 vp = (op->level >= 3) ? &op->temp : &op->perm;
1698 if (op->flags & OPT_SET) t = vp->number;
1699 else switch (op->index)
1702 t = f->st->st_atime;
1705 t = f->st->st_ctime;
1708 /* already in tar_header */
1711 sfsprintf(s = num, sizeof(num), "%lu.0", t);
1714 if (op->flags & OPT_SET)
1720 if (strlen(f->gidname) >= sizeof(tar_header.gname) || !portable(f->gidname))
1724 if (op->flags & OPT_SET)
1730 if (strlen(f->uidname) >= sizeof(tar_header.uname) || !portable(f->uidname))
1734 if (!s && (op->flags & OPT_SET))
1735 sfsprintf(s = num, sizeof(num), "%ld", vp->number);
1738 if (s) putkey(hp, tp, op->name, !op->level || op->level >= 3 ? ':' : 0, s);
1744 if (f->namesize > sizeof(tar_header.name) - (f->type == X_IFDIR))
1745 for (; s = strchr(s, '/'); s++)
1747 if ((n = s - f->name) >= sizeof(tar_header.prefix))
1752 if (f->namesize <= sizeof(tar_header.name) + n)
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))
1762 listprintf(tp, ap, f, state.header.name);
1763 initfile(ap, &h, sfstruse(tp), X_IFREG|X_IRUSR|X_IWUSR|X_IRGRP|X_IROTH);
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);
1769 h.fd = setbuffer(0);
1770 bp = getbuffer(h.fd);
1773 bp->base = bp->next = s;
1784 unsigned long c = f->st->st_size;
1790 c += 4 * ALAR_HEADER;
1794 c += ASC_HEADER + f->namesize;
1797 c += BINARY_HEADER + f->namesize;
1801 c += CPIO_HEADER + f->namesize;
1807 c = roundof(c, BLOCKSIZE);
1810 c += state.record.header ? state.record.headerlen : f->namesize;
1813 if (ap->io.count + c > state.maxout)
1815 if (c > state.maxout) error(1, "%s: too large to fit in one volume", f->name);
1830 putlabels(ap, f, "HDR");
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)
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);
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);
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);
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)),
1888 f->st->st_size + f->linknamesize);
1889 bwrite(ap, state.tmp.buffer, CPIO_HEADER);
1893 bwrite(ap, f->name, f->namesize);
1895 if (f->type == X_IFLNK) goto cpio_link;
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)),
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;
1925 memzero(tar_block, TAR_HEADER);
1927 if (f->namesize > sizeof(tar_header.name) - (f->type == X_IFDIR))
1930 if (!(s = strchr(s, '/')))
1935 if ((f->namesize - (s - f->name)) <= sizeof(tar_header.name))
1938 sfsprintf(tar_header.prefix, sizeof(tar_header.prefix), "%-.*s", sizeof(tar_header.prefix), f->name);
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)
1948 tar_header.typeflag = LNKTYPE;
1950 sfsprintf(tar_header.linkname, sizeof(tar_header.linkname), "%s", f->linkname);
1953 tar_header.typeflag = SYMTYPE;
1956 switch (ap->format == TAR ? X_IFREG : f->type)
1959 tar_header.typeflag = CHRTYPE;
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)));
1965 tar_header.typeflag = BLKTYPE;
1968 tar_header.typeflag = DIRTYPE;
1971 tar_header.typeflag = FIFOTYPE;
1974 tar_header.typeflag = SOKTYPE;
1978 error(1, "%s: unknown file type 0%03o -- assuming regular file", f->name, f->type >> 12);
1981 tar_header.typeflag = REGTYPE;
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)
1993 strncpy(tar_header.magic, TMAGIC, sizeof(tar_header.magic));
1994 strncpy(tar_header.version, TVERSION, sizeof(tar_header.version));
1996 strcpy(tar_header.uname, f->uidname);
1997 strcpy(tar_header.gname, f->gidname);
1999 sfsprintf(tar_header.chksum, sizeof(tar_header.chksum), "%*o ", sizeof(tar_header.chksum) - 2, tar_checksum());
2000 bwrite(ap, tar_block, TAR_HEADER);
2003 if (state.record.header) bwrite(ap, state.record.header, state.record.headerlen);
2006 f->name[f->namesize - 1] = '\n';
2007 bwrite(ap, f->name, f->namesize);
2008 f->name[f->namesize - 1] = 0;
2010 if (!(c = state.record.delimiter))
2015 n = read(f->fd, tar_block, TAR_HEADER);
2016 if (n > 0) lseek(f->fd, -n, SEEK_CUR);
2018 else if ((n = bread(ap, tar_block, 0L, (long)TAR_HEADER, 1)) > 0)
2019 bunread(ap, tar_block, n);
2026 unsigned char hit[UCHAR_MAX + 1];
2029 * to determine the delimiter, if any
2032 memzero(hit, sizeof(hit));
2034 hit[*((unsigned char*)tar_block + n)]++;
2035 for (n = 0; n <= UCHAR_MAX; n++)
2036 if (n == '_' || n == '/' || n == '.' || n == '\n' || n == '\\')
2038 else if (isspace(n))
2040 if ((int)hit[n] > ms)
2046 else if ((int)hit[n] > mp && isprint(n) && !isalnum(n))
2052 else if (ms) c = ds;
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));
2059 putdeltaheader(ap, f);
2063 * read entry trailer
2067 gettrailer __PARAM__((Archive_t* ap, File_t* f), (ap, f)) __OTORP__(Archive_t* ap; File_t* f;){
2073 ap->checksum ^= ap->memsum;
2074 ap->old.checksum ^= ap->old.memsum;
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);
2084 * write entry trailer
2088 puttrailer __PARAM__((Archive_t* ap, File_t* f), (ap, f)) __OTORP__(Archive_t* ap; File_t* f;){
2091 putdeltatrailer(ap, f);
2096 putlabels(ap, f, "EOF");
2099 if (state.record.trailer)
2100 bwrite(ap, state.record.trailer, state.record.trailerlen);
2103 if ((n = format[ap->format].align) && (n = roundof(ap->io.count, n) - ap->io.count))
2105 memzero(state.tmp.buffer, n);
2106 bwrite(ap, state.tmp.buffer, n);
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
2120 getlabel __PARAM__((Archive_t* ap, File_t* f), (ap, f)) __OTORP__(Archive_t* ap; File_t* f;){
2124 static char last[5];
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)
2131 if ((c = n - c) > 0)
2133 if (ap->io.blocked || bread(ap, alar_header + ALAR_HEADER, 0L, (long)c, 1) != c)
2136 error(2, "%s: %-*.*s: variable length label record too short", f->name, c, c, alar_header);
2140 if (ap->format == IBMAR) memetoa(alar_header + ALAR_HEADER, alar_header + ALAR_HEADER, c);
2144 else if (n <= ALAR_VARHDR) c = ALAR_VARHDR;
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));
2155 * output file HDR/EOF/EOV labels
2159 putlabels __PARAM__((Archive_t* ap, File_t* f, char* type), (ap, f, type)) __OTORP__(Archive_t* ap; File_t* f; char* type;){
2162 static int section = 1;
2163 static int sequence;
2168 bwrite(ap, alar_header, 0);
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"))
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
2200 getsaveset __PARAM__((Archive_t* ap, File_t* f, int header), (ap, f, header)) __OTORP__(Archive_t* ap; File_t* f; int header;){
2209 state.saveset.bp += state.saveset.lastsize;
2210 while (state.saveset.bp >= state.saveset.block + state.blocksize)
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)
2217 if (header) gettrailer(ap, f);
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;
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));
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);
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);
2245 for (s = p + FILHDR_data + 1; s < p + FILHDR_data + i; s++)
2247 if (isupper(*s)) *t++ = tolower(*s);
2250 if (*s == ';') break;
2258 else if (*s == '.') *t++ = '/';
2262 for (i = 0; i < 5; i++)
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);
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);
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);
2281 * pure guesswork based on 100 nsec epoch
2282 * 17-NOV-1858 00:00:00 GMT
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;
2290 state.saveset.bp -= RECHDR_SIZE;
2291 state.saveset.lastsize = 0;
2294 else if (i == REC_vbn && !header) return(1);