tar.c revision 1.9 1 /* $NetBSD: tar.c,v 1.9 1997/07/20 20:32:47 christos Exp $ */
2
3 /*-
4 * Copyright (c) 1992 Keith Muller.
5 * Copyright (c) 1992, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * This code is derived from software contributed to Berkeley by
9 * Keith Muller of the University of California, San Diego.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the University of
22 * California, Berkeley and its contributors.
23 * 4. Neither the name of the University nor the names of its contributors
24 * may be used to endorse or promote products derived from this software
25 * without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * SUCH DAMAGE.
38 */
39
40 #include <sys/cdefs.h>
41 #ifndef lint
42 #if 0
43 static char sccsid[] = "@(#)tar.c 8.2 (Berkeley) 4/18/94";
44 #else
45 __RCSID("$NetBSD: tar.c,v 1.9 1997/07/20 20:32:47 christos Exp $");
46 #endif
47 #endif /* not lint */
48
49 #include <sys/types.h>
50 #include <sys/time.h>
51 #include <sys/stat.h>
52 #include <sys/param.h>
53 #include <string.h>
54 #include <stdio.h>
55 #include <ctype.h>
56 #include <unistd.h>
57 #include <stdlib.h>
58 #include "pax.h"
59 #include "extern.h"
60 #include "tar.h"
61
62 /*
63 * Routines for reading, writing and header identify of various versions of tar
64 */
65
66 static u_long tar_chksm __P((char *, int));
67 static char *name_split __P((char *, int));
68 static int ul_oct __P((u_long, char *, int, int));
69 #ifndef NET2_STAT
70 static int uqd_oct __P((u_quad_t, char *, int, int));
71 #endif
72
73 /*
74 * Routines common to all versions of tar
75 */
76
77 static int tar_nodir; /* do not write dirs under old tar */
78
79 /*
80 * tar_endwr()
81 * add the tar trailer of two null blocks
82 * Return:
83 * 0 if ok, -1 otherwise (what wr_skip returns)
84 */
85
86 #if __STDC__
87 int
88 tar_endwr(void)
89 #else
90 int
91 tar_endwr()
92 #endif
93 {
94 return(wr_skip((off_t)(NULLCNT*BLKMULT)));
95 }
96
97 /*
98 * tar_endrd()
99 * no cleanup needed here, just return size of trailer (for append)
100 * Return:
101 * size of trailer (2 * BLKMULT)
102 */
103
104 #if __STDC__
105 off_t
106 tar_endrd(void)
107 #else
108 off_t
109 tar_endrd()
110 #endif
111 {
112 return((off_t)(NULLCNT*BLKMULT));
113 }
114
115 /*
116 * tar_trail()
117 * Called to determine if a header block is a valid trailer. We are passed
118 * the block, the in_sync flag (which tells us we are in resync mode;
119 * looking for a valid header), and cnt (which starts at zero) which is
120 * used to count the number of empty blocks we have seen so far.
121 * Return:
122 * 0 if a valid trailer, -1 if not a valid trailer, or 1 if the block
123 * could never contain a header.
124 */
125
126 #if __STDC__
127 int
128 tar_trail(char *buf, int in_resync, int *cnt)
129 #else
130 int
131 tar_trail(buf, in_resync, cnt)
132 char *buf;
133 int in_resync;
134 int *cnt;
135 #endif
136 {
137 int i;
138
139 /*
140 * look for all zero, trailer is two consecutive blocks of zero
141 */
142 for (i = 0; i < BLKMULT; ++i) {
143 if (buf[i] != '\0')
144 break;
145 }
146
147 /*
148 * if not all zero it is not a trailer, but MIGHT be a header.
149 */
150 if (i != BLKMULT)
151 return(-1);
152
153 /*
154 * When given a zero block, we must be careful!
155 * If we are not in resync mode, check for the trailer. Have to watch
156 * out that we do not mis-identify file data as the trailer, so we do
157 * NOT try to id a trailer during resync mode. During resync mode we
158 * might as well throw this block out since a valid header can NEVER be
159 * a block of all 0 (we must have a valid file name).
160 */
161 if (!in_resync && (++*cnt >= NULLCNT))
162 return(0);
163 return(1);
164 }
165
166 /*
167 * ul_oct()
168 * convert an unsigned long to an octal string. many oddball field
169 * termination characters are used by the various versions of tar in the
170 * different fields. term selects which kind to use. str is '0' padded
171 * at the front to len. we are unable to use only one format as many old
172 * tar readers are very cranky about this.
173 * Return:
174 * 0 if the number fit into the string, -1 otherwise
175 */
176
177 #if __STDC__
178 static int
179 ul_oct(u_long val, char *str, int len, int term)
180 #else
181 static int
182 ul_oct(val, str, len, term)
183 u_long val;
184 char *str;
185 int len;
186 int term;
187 #endif
188 {
189 char *pt;
190
191 /*
192 * term selects the appropriate character(s) for the end of the string
193 */
194 pt = str + len - 1;
195 switch(term) {
196 case 3:
197 *pt-- = '\0';
198 break;
199 case 2:
200 *pt-- = ' ';
201 *pt-- = '\0';
202 break;
203 case 1:
204 *pt-- = ' ';
205 break;
206 case 0:
207 default:
208 *pt-- = '\0';
209 *pt-- = ' ';
210 break;
211 }
212
213 /*
214 * convert and blank pad if there is space
215 */
216 while (pt >= str) {
217 *pt-- = '0' + (char)(val & 0x7);
218 if ((val = val >> 3) == (u_long)0)
219 break;
220 }
221
222 while (pt >= str)
223 *pt-- = '0';
224 if (val != (u_long)0)
225 return(-1);
226 return(0);
227 }
228
229 #ifndef NET2_STAT
230 /*
231 * uqd_oct()
232 * convert an u_quad_t to an octal string. one of many oddball field
233 * termination characters are used by the various versions of tar in the
234 * different fields. term selects which kind to use. str is '0' padded
235 * at the front to len. we are unable to use only one format as many old
236 * tar readers are very cranky about this.
237 * Return:
238 * 0 if the number fit into the string, -1 otherwise
239 */
240
241 #if __STDC__
242 static int
243 uqd_oct(u_quad_t val, char *str, int len, int term)
244 #else
245 static int
246 uqd_oct(val, str, len, term)
247 u_quad_t val;
248 char *str;
249 int len;
250 int term;
251 #endif
252 {
253 char *pt;
254
255 /*
256 * term selects the appropriate character(s) for the end of the string
257 */
258 pt = str + len - 1;
259 switch(term) {
260 case 3:
261 *pt-- = '\0';
262 break;
263 case 2:
264 *pt-- = ' ';
265 *pt-- = '\0';
266 break;
267 case 1:
268 *pt-- = ' ';
269 break;
270 case 0:
271 default:
272 *pt-- = '\0';
273 *pt-- = ' ';
274 break;
275 }
276
277 /*
278 * convert and blank pad if there is space
279 */
280 while (pt >= str) {
281 *pt-- = '0' + (char)(val & 0x7);
282 if ((val = val >> 3) == 0)
283 break;
284 }
285
286 while (pt >= str)
287 *pt-- = '0';
288 if (val != (u_quad_t)0)
289 return(-1);
290 return(0);
291 }
292 #endif
293
294 /*
295 * tar_chksm()
296 * calculate the checksum for a tar block counting the checksum field as
297 * all blanks (BLNKSUM is that value pre-calculated, the sume of 8 blanks).
298 * NOTE: we use len to short circuit summing 0's on write since we ALWAYS
299 * pad headers with 0.
300 * Return:
301 * unsigned long checksum
302 */
303
304 #if __STDC__
305 static u_long
306 tar_chksm(char *blk, int len)
307 #else
308 static u_long
309 tar_chksm(blk, len)
310 char *blk;
311 int len;
312 #endif
313 {
314 char *stop;
315 char *pt;
316 u_long chksm = BLNKSUM; /* inital value is checksum field sum */
317
318 /*
319 * add the part of the block before the checksum field
320 */
321 pt = blk;
322 stop = blk + CHK_OFFSET;
323 while (pt < stop)
324 chksm += (u_long)(*pt++ & 0xff);
325 /*
326 * move past the checksum field and keep going, spec counts the
327 * checksum field as the sum of 8 blanks (which is pre-computed as
328 * BLNKSUM).
329 * ASSUMED: len is greater than CHK_OFFSET. (len is where our 0 padding
330 * starts, no point in summing zero's)
331 */
332 pt += CHK_LEN;
333 stop = blk + len;
334 while (pt < stop)
335 chksm += (u_long)(*pt++ & 0xff);
336 return(chksm);
337 }
338
339 /*
340 * Routines for old BSD style tar (also made portable to sysV tar)
341 */
342
343 /*
344 * tar_id()
345 * determine if a block given to us is a valid tar header (and not a USTAR
346 * header). We have to be on the lookout for those pesky blocks of all
347 * zero's.
348 * Return:
349 * 0 if a tar header, -1 otherwise
350 */
351
352 #if __STDC__
353 int
354 tar_id(char *blk, int size)
355 #else
356 int
357 tar_id(blk, size)
358 char *blk;
359 int size;
360 #endif
361 {
362 HD_TAR *hd;
363 HD_USTAR *uhd;
364
365 if (size < BLKMULT)
366 return(-1);
367 hd = (HD_TAR *)blk;
368 uhd = (HD_USTAR *)blk;
369
370 /*
371 * check for block of zero's first, a simple and fast test, then make
372 * sure this is not a ustar header by looking for the ustar magic
373 * cookie. We should use TMAGLEN, but some USTAR archive programs are
374 * wrong and create archives missing the \0. Last we check the
375 * checksum. If this is ok we have to assume it is a valid header.
376 */
377 if (hd->name[0] == '\0')
378 return(-1);
379 if (strncmp(uhd->magic, TMAGIC, TMAGLEN - 1) == 0)
380 return(-1);
381 if (asc_ul(hd->chksum,sizeof(hd->chksum),OCT) != tar_chksm(blk,BLKMULT))
382 return(-1);
383 return(0);
384 }
385
386 /*
387 * tar_opt()
388 * handle tar format specific -o options
389 * Return:
390 * 0 if ok -1 otherwise
391 */
392
393 #if __STDC__
394 int
395 tar_opt(void)
396 #else
397 int
398 tar_opt()
399 #endif
400 {
401 OPLIST *opt;
402
403 while ((opt = opt_next()) != NULL) {
404 if (strcmp(opt->name, TAR_OPTION) ||
405 strcmp(opt->value, TAR_NODIR)) {
406 tty_warn(1,
407 "Unknown tar format -o option/value pair %s=%s",
408 opt->name, opt->value);
409 tty_warn(1,
410 "%s=%s is the only supported tar format option",
411 TAR_OPTION, TAR_NODIR);
412 return(-1);
413 }
414
415 /*
416 * we only support one option, and only when writing
417 */
418 if ((act != APPND) && (act != ARCHIVE)) {
419 tty_warn(1, "%s=%s is only supported when writing.",
420 opt->name, opt->value);
421 return(-1);
422 }
423 tar_nodir = 1;
424 }
425 return(0);
426 }
427
428
429 /*
430 * tar_rd()
431 * extract the values out of block already determined to be a tar header.
432 * store the values in the ARCHD parameter.
433 * Return:
434 * 0
435 */
436
437 #if __STDC__
438 int
439 tar_rd(ARCHD *arcn, char *buf)
440 #else
441 int
442 tar_rd(arcn, buf)
443 ARCHD *arcn;
444 char *buf;
445 #endif
446 {
447 HD_TAR *hd;
448 char *pt;
449
450 /*
451 * we only get proper sized buffers passed to us
452 */
453 if (tar_id(buf, BLKMULT) < 0)
454 return(-1);
455 arcn->org_name = arcn->name;
456 arcn->sb.st_nlink = 1;
457 arcn->pat = NULL;
458
459 /*
460 * copy out the name and values in the stat buffer
461 */
462 hd = (HD_TAR *)buf;
463 arcn->nlen = l_strncpy(arcn->name, hd->name, sizeof(hd->name));
464 arcn->name[arcn->nlen] = '\0';
465 arcn->sb.st_mode = (mode_t)(asc_ul(hd->mode,sizeof(hd->mode),OCT) &
466 0xfff);
467 arcn->sb.st_uid = (uid_t)asc_ul(hd->uid, sizeof(hd->uid), OCT);
468 arcn->sb.st_gid = (gid_t)asc_ul(hd->gid, sizeof(hd->gid), OCT);
469 arcn->sb.st_size = (size_t)asc_ul(hd->size, sizeof(hd->size), OCT);
470 arcn->sb.st_mtime = (time_t)asc_ul(hd->mtime, sizeof(hd->mtime), OCT);
471 arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
472
473 /*
474 * have to look at the last character, it may be a '/' and that is used
475 * to encode this as a directory
476 */
477 pt = &(arcn->name[arcn->nlen - 1]);
478 arcn->pad = 0;
479 arcn->skip = 0;
480 switch(hd->linkflag) {
481 case SYMTYPE:
482 /*
483 * symbolic link, need to get the link name and set the type in
484 * the st_mode so -v printing will look correct.
485 */
486 arcn->type = PAX_SLK;
487 arcn->ln_nlen = l_strncpy(arcn->ln_name, hd->linkname,
488 sizeof(hd->linkname));
489 arcn->ln_name[arcn->ln_nlen] = '\0';
490 arcn->sb.st_mode |= S_IFLNK;
491 break;
492 case LNKTYPE:
493 /*
494 * hard link, need to get the link name, set the type in the
495 * st_mode and st_nlink so -v printing will look better.
496 */
497 arcn->type = PAX_HLK;
498 arcn->sb.st_nlink = 2;
499 arcn->ln_nlen = l_strncpy(arcn->ln_name, hd->linkname,
500 sizeof(hd->linkname));
501 arcn->ln_name[arcn->ln_nlen] = '\0';
502
503 /*
504 * no idea of what type this thing really points at, but
505 * we set something for printing only.
506 */
507 arcn->sb.st_mode |= S_IFREG;
508 break;
509 case AREGTYPE:
510 case REGTYPE:
511 default:
512 /*
513 * If we have a trailing / this is a directory and NOT a file.
514 */
515 arcn->ln_name[0] = '\0';
516 arcn->ln_nlen = 0;
517 if (*pt == '/') {
518 /*
519 * it is a directory, set the mode for -v printing
520 */
521 arcn->type = PAX_DIR;
522 arcn->sb.st_mode |= S_IFDIR;
523 arcn->sb.st_nlink = 2;
524 } else {
525 /*
526 * have a file that will be followed by data. Set the
527 * skip value to the size field and caluculate the size
528 * of the padding.
529 */
530 arcn->type = PAX_REG;
531 arcn->sb.st_mode |= S_IFREG;
532 arcn->pad = TAR_PAD(arcn->sb.st_size);
533 arcn->skip = arcn->sb.st_size;
534 }
535 break;
536 }
537
538 /*
539 * strip off any trailing slash.
540 */
541 if (*pt == '/') {
542 *pt = '\0';
543 --arcn->nlen;
544 }
545 return(0);
546 }
547
548 /*
549 * tar_wr()
550 * write a tar header for the file specified in the ARCHD to the archive.
551 * Have to check for file types that cannot be stored and file names that
552 * are too long. Be careful of the term (last arg) to ul_oct, each field
553 * of tar has it own spec for the termination character(s).
554 * ASSUMED: space after header in header block is zero filled
555 * Return:
556 * 0 if file has data to be written after the header, 1 if file has NO
557 * data to write after the header, -1 if archive write failed
558 */
559
560 #if __STDC__
561 int
562 tar_wr(ARCHD *arcn)
563 #else
564 int
565 tar_wr(arcn)
566 ARCHD *arcn;
567 #endif
568 {
569 HD_TAR *hd;
570 int len;
571 char hdblk[sizeof(HD_TAR)];
572
573 /*
574 * check for those file system types which tar cannot store
575 */
576 switch(arcn->type) {
577 case PAX_DIR:
578 /*
579 * user asked that dirs not be written to the archive
580 */
581 if (tar_nodir)
582 return(1);
583 break;
584 case PAX_CHR:
585 tty_warn(1, "Tar cannot archive a character device %s",
586 arcn->org_name);
587 return(1);
588 case PAX_BLK:
589 tty_warn(1,
590 "Tar cannot archive a block device %s", arcn->org_name);
591 return(1);
592 case PAX_SCK:
593 tty_warn(1, "Tar cannot archive a socket %s", arcn->org_name);
594 return(1);
595 case PAX_FIF:
596 tty_warn(1, "Tar cannot archive a fifo %s", arcn->org_name);
597 return(1);
598 case PAX_SLK:
599 case PAX_HLK:
600 case PAX_HRG:
601 if (arcn->ln_nlen > sizeof(hd->linkname)) {
602 tty_warn(1,"Link name too long for tar %s",
603 arcn->ln_name);
604 return(1);
605 }
606 break;
607 case PAX_REG:
608 case PAX_CTG:
609 default:
610 break;
611 }
612
613 /*
614 * check file name len, remember extra char for dirs (the / at the end)
615 */
616 len = arcn->nlen;
617 if (arcn->type == PAX_DIR)
618 ++len;
619 if (len > sizeof(hd->name)) {
620 tty_warn(1, "File name too long for tar %s", arcn->name);
621 return(1);
622 }
623
624 /*
625 * copy the data out of the ARCHD into the tar header based on the type
626 * of the file. Remember many tar readers want the unused fields to be
627 * padded with zero. We set the linkflag field (type), the linkname
628 * (or zero if not used),the size, and set the padding (if any) to be
629 * added after the file data (0 for all other types, as they only have
630 * a header)
631 */
632 hd = (HD_TAR *)hdblk;
633 zf_strncpy(hd->name, arcn->name, sizeof(hd->name));
634 arcn->pad = 0;
635
636 if (arcn->type == PAX_DIR) {
637 /*
638 * directories are the same as files, except have a filename
639 * that ends with a /, we add the slash here. No data follows,
640 * dirs, so no pad.
641 */
642 hd->linkflag = AREGTYPE;
643 memset(hd->linkname, 0, sizeof(hd->linkname));
644 hd->name[len-1] = '/';
645 if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1))
646 goto out;
647 } else if (arcn->type == PAX_SLK) {
648 /*
649 * no data follows this file, so no pad
650 */
651 hd->linkflag = SYMTYPE;
652 zf_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname));
653 if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1))
654 goto out;
655 } else if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG)) {
656 /*
657 * no data follows this file, so no pad
658 */
659 hd->linkflag = LNKTYPE;
660 zf_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname));
661 if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1))
662 goto out;
663 } else {
664 /*
665 * data follows this file, so set the pad
666 */
667 hd->linkflag = AREGTYPE;
668 memset(hd->linkname, 0, sizeof(hd->linkname));
669 # ifdef NET2_STAT
670 if (ul_oct((u_long)arcn->sb.st_size, hd->size,
671 sizeof(hd->size), 1)) {
672 # else
673 if (uqd_oct((u_quad_t)arcn->sb.st_size, hd->size,
674 sizeof(hd->size), 1)) {
675 # endif
676 tty_warn(1,"File is too large for tar %s",
677 arcn->org_name);
678 return(1);
679 }
680 arcn->pad = TAR_PAD(arcn->sb.st_size);
681 }
682
683 /*
684 * copy those fields that are independent of the type
685 */
686 if (ul_oct((u_long)arcn->sb.st_mode, hd->mode, sizeof(hd->mode), 0) ||
687 ul_oct((u_long)arcn->sb.st_uid, hd->uid, sizeof(hd->uid), 0) ||
688 ul_oct((u_long)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), 0) ||
689 ul_oct((u_long)arcn->sb.st_mtime, hd->mtime, sizeof(hd->mtime), 1))
690 goto out;
691
692 /*
693 * calculate and add the checksum, then write the header. A return of
694 * 0 tells the caller to now write the file data, 1 says no data needs
695 * to be written
696 */
697 if (ul_oct(tar_chksm(hdblk, sizeof(HD_TAR)), hd->chksum,
698 sizeof(hd->chksum), 2))
699 goto out;
700 if (wr_rdbuf(hdblk, sizeof(HD_TAR)) < 0)
701 return(-1);
702 if (wr_skip((off_t)(BLKMULT - sizeof(HD_TAR))) < 0)
703 return(-1);
704 if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG))
705 return(0);
706 return(1);
707
708 out:
709 /*
710 * header field is out of range
711 */
712 tty_warn(1, "Tar header field is too small for %s", arcn->org_name);
713 return(1);
714 }
715
716 /*
717 * Routines for POSIX ustar
718 */
719
720 /*
721 * ustar_strd()
722 * initialization for ustar read
723 * Return:
724 * 0 if ok, -1 otherwise
725 */
726
727 #if __STDC__
728 int
729 ustar_strd(void)
730 #else
731 int
732 ustar_strd()
733 #endif
734 {
735 if ((usrtb_start() < 0) || (grptb_start() < 0))
736 return(-1);
737 return(0);
738 }
739
740 /*
741 * ustar_stwr()
742 * initialization for ustar write
743 * Return:
744 * 0 if ok, -1 otherwise
745 */
746
747 #if __STDC__
748 int
749 ustar_stwr(void)
750 #else
751 int
752 ustar_stwr()
753 #endif
754 {
755 if ((uidtb_start() < 0) || (gidtb_start() < 0))
756 return(-1);
757 return(0);
758 }
759
760 /*
761 * ustar_id()
762 * determine if a block given to us is a valid ustar header. We have to
763 * be on the lookout for those pesky blocks of all zero's
764 * Return:
765 * 0 if a ustar header, -1 otherwise
766 */
767
768 #if __STDC__
769 int
770 ustar_id(char *blk, int size)
771 #else
772 int
773 ustar_id(blk, size)
774 char *blk;
775 int size;
776 #endif
777 {
778 HD_USTAR *hd;
779
780 if (size < BLKMULT)
781 return(-1);
782 hd = (HD_USTAR *)blk;
783
784 /*
785 * check for block of zero's first, a simple and fast test then check
786 * ustar magic cookie. We should use TMAGLEN, but some USTAR archive
787 * programs are fouled up and create archives missing the \0. Last we
788 * check the checksum. If ok we have to assume it is a valid header.
789 */
790 if (hd->name[0] == '\0')
791 return(-1);
792 if (strncmp(hd->magic, TMAGIC, TMAGLEN - 1) != 0)
793 return(-1);
794 if (asc_ul(hd->chksum,sizeof(hd->chksum),OCT) != tar_chksm(blk,BLKMULT))
795 return(-1);
796 return(0);
797 }
798
799 /*
800 * ustar_rd()
801 * extract the values out of block already determined to be a ustar header.
802 * store the values in the ARCHD parameter.
803 * Return:
804 * 0
805 */
806
807 #if __STDC__
808 int
809 ustar_rd(ARCHD *arcn, char *buf)
810 #else
811 int
812 ustar_rd(arcn, buf)
813 ARCHD *arcn;
814 char *buf;
815 #endif
816 {
817 HD_USTAR *hd;
818 char *dest;
819 int cnt = 0;
820 dev_t devmajor;
821 dev_t devminor;
822
823 /*
824 * we only get proper sized buffers
825 */
826 if (ustar_id(buf, BLKMULT) < 0)
827 return(-1);
828 arcn->org_name = arcn->name;
829 arcn->sb.st_nlink = 1;
830 arcn->pat = NULL;
831 hd = (HD_USTAR *)buf;
832
833 /*
834 * see if the filename is split into two parts. if, so joint the parts.
835 * we copy the prefix first and add a / between the prefix and name.
836 */
837 dest = arcn->name;
838 if (*(hd->prefix) != '\0') {
839 cnt = l_strncpy(arcn->name, hd->prefix, sizeof(hd->prefix));
840 dest = arcn->name + arcn->nlen;
841 *dest++ = '/';
842 cnt++;
843 }
844 arcn->nlen = l_strncpy(dest, hd->name, sizeof(hd->name));
845 arcn->nlen += cnt;
846 arcn->name[arcn->nlen] = '\0';
847
848 /*
849 * follow the spec to the letter. we should only have mode bits, strip
850 * off all other crud we may be passed.
851 */
852 arcn->sb.st_mode = (mode_t)(asc_ul(hd->mode, sizeof(hd->mode), OCT) &
853 0xfff);
854 arcn->sb.st_size = (size_t)asc_ul(hd->size, sizeof(hd->size), OCT);
855 arcn->sb.st_mtime = (time_t)asc_ul(hd->mtime, sizeof(hd->mtime), OCT);
856 arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
857
858 /*
859 * If we can find the ascii names for gname and uname in the password
860 * and group files we will use the uid's and gid they bind. Otherwise
861 * we use the uid and gid values stored in the header. (This is what
862 * the posix spec wants).
863 */
864 hd->gname[sizeof(hd->gname) - 1] = '\0';
865 if (gid_name(hd->gname, &(arcn->sb.st_gid)) < 0)
866 arcn->sb.st_gid = (gid_t)asc_ul(hd->gid, sizeof(hd->gid), OCT);
867 hd->uname[sizeof(hd->uname) - 1] = '\0';
868 if (uid_name(hd->uname, &(arcn->sb.st_uid)) < 0)
869 arcn->sb.st_uid = (uid_t)asc_ul(hd->uid, sizeof(hd->uid), OCT);
870
871 /*
872 * set the defaults, these may be changed depending on the file type
873 */
874 arcn->ln_name[0] = '\0';
875 arcn->ln_nlen = 0;
876 arcn->pad = 0;
877 arcn->skip = 0;
878 arcn->sb.st_rdev = (dev_t)0;
879
880 /*
881 * set the mode and PAX type according to the typeflag in the header
882 */
883 switch(hd->typeflag) {
884 case FIFOTYPE:
885 arcn->type = PAX_FIF;
886 arcn->sb.st_mode |= S_IFIFO;
887 break;
888 case DIRTYPE:
889 arcn->type = PAX_DIR;
890 arcn->sb.st_mode |= S_IFDIR;
891 arcn->sb.st_nlink = 2;
892
893 /*
894 * Some programs that create ustar archives append a '/'
895 * to the pathname for directories. This clearly violates
896 * ustar specs, but we will silently strip it off anyway.
897 */
898 if (arcn->name[arcn->nlen - 1] == '/')
899 arcn->name[--arcn->nlen] = '\0';
900 break;
901 case BLKTYPE:
902 case CHRTYPE:
903 /*
904 * this type requires the rdev field to be set.
905 */
906 if (hd->typeflag == BLKTYPE) {
907 arcn->type = PAX_BLK;
908 arcn->sb.st_mode |= S_IFBLK;
909 } else {
910 arcn->type = PAX_CHR;
911 arcn->sb.st_mode |= S_IFCHR;
912 }
913 devmajor = (dev_t)asc_ul(hd->devmajor,sizeof(hd->devmajor),OCT);
914 devminor = (dev_t)asc_ul(hd->devminor,sizeof(hd->devminor),OCT);
915 arcn->sb.st_rdev = TODEV(devmajor, devminor);
916 break;
917 case SYMTYPE:
918 case LNKTYPE:
919 if (hd->typeflag == SYMTYPE) {
920 arcn->type = PAX_SLK;
921 arcn->sb.st_mode |= S_IFLNK;
922 } else {
923 arcn->type = PAX_HLK;
924 /*
925 * so printing looks better
926 */
927 arcn->sb.st_mode |= S_IFREG;
928 arcn->sb.st_nlink = 2;
929 }
930 /*
931 * copy the link name
932 */
933 arcn->ln_nlen = l_strncpy(arcn->ln_name, hd->linkname,
934 sizeof(hd->linkname));
935 arcn->ln_name[arcn->ln_nlen] = '\0';
936 break;
937 case CONTTYPE:
938 case AREGTYPE:
939 case REGTYPE:
940 default:
941 /*
942 * these types have file data that follows. Set the skip and
943 * pad fields.
944 */
945 arcn->type = PAX_REG;
946 arcn->pad = TAR_PAD(arcn->sb.st_size);
947 arcn->skip = arcn->sb.st_size;
948 arcn->sb.st_mode |= S_IFREG;
949 break;
950 }
951 return(0);
952 }
953
954 /*
955 * ustar_wr()
956 * write a ustar header for the file specified in the ARCHD to the archive
957 * Have to check for file types that cannot be stored and file names that
958 * are too long. Be careful of the term (last arg) to ul_oct, we only use
959 * '\0' for the termination character (this is different than picky tar)
960 * ASSUMED: space after header in header block is zero filled
961 * Return:
962 * 0 if file has data to be written after the header, 1 if file has NO
963 * data to write after the header, -1 if archive write failed
964 */
965
966 #if __STDC__
967 int
968 ustar_wr(ARCHD *arcn)
969 #else
970 int
971 ustar_wr(arcn)
972 ARCHD *arcn;
973 #endif
974 {
975 HD_USTAR *hd;
976 char *pt;
977 char hdblk[sizeof(HD_USTAR)];
978
979 /*
980 * check for those file system types ustar cannot store
981 */
982 if (arcn->type == PAX_SCK) {
983 tty_warn(1, "Ustar cannot archive a socket %s", arcn->org_name);
984 return(1);
985 }
986
987 /*
988 * check the length of the linkname
989 */
990 if (((arcn->type == PAX_SLK) || (arcn->type == PAX_HLK) ||
991 (arcn->type == PAX_HRG)) && (arcn->ln_nlen > sizeof(hd->linkname))){
992 tty_warn(1, "Link name too long for ustar %s", arcn->ln_name);
993 return(1);
994 }
995
996 /*
997 * split the path name into prefix and name fields (if needed). if
998 * pt != arcn->name, the name has to be split
999 */
1000 if ((pt = name_split(arcn->name, arcn->nlen)) == NULL) {
1001 tty_warn(1, "File name too long for ustar %s", arcn->name);
1002 return(1);
1003 }
1004 hd = (HD_USTAR *)hdblk;
1005 arcn->pad = 0L;
1006
1007 /*
1008 * split the name, or zero out the prefix
1009 */
1010 if (pt != arcn->name) {
1011 /*
1012 * name was split, pt points at the / where the split is to
1013 * occur, we remove the / and copy the first part to the prefix
1014 */
1015 *pt = '\0';
1016 zf_strncpy(hd->prefix, arcn->name, sizeof(hd->prefix));
1017 *pt++ = '/';
1018 } else
1019 memset(hd->prefix, 0, sizeof(hd->prefix));
1020
1021 /*
1022 * copy the name part. this may be the whole path or the part after
1023 * the prefix
1024 */
1025 zf_strncpy(hd->name, pt, sizeof(hd->name));
1026
1027 /*
1028 * set the fields in the header that are type dependent
1029 */
1030 switch(arcn->type) {
1031 case PAX_DIR:
1032 hd->typeflag = DIRTYPE;
1033 memset(hd->linkname, 0, sizeof(hd->linkname));
1034 memset(hd->devmajor, 0, sizeof(hd->devmajor));
1035 memset(hd->devminor, 0, sizeof(hd->devminor));
1036 if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3))
1037 goto out;
1038 break;
1039 case PAX_CHR:
1040 case PAX_BLK:
1041 if (arcn->type == PAX_CHR)
1042 hd->typeflag = CHRTYPE;
1043 else
1044 hd->typeflag = BLKTYPE;
1045 memset(hd->linkname, 0, sizeof(hd->linkname));
1046 if (ul_oct((u_long)MAJOR(arcn->sb.st_rdev), hd->devmajor,
1047 sizeof(hd->devmajor), 3) ||
1048 ul_oct((u_long)MINOR(arcn->sb.st_rdev), hd->devminor,
1049 sizeof(hd->devminor), 3) ||
1050 ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3))
1051 goto out;
1052 break;
1053 case PAX_FIF:
1054 hd->typeflag = FIFOTYPE;
1055 memset(hd->linkname, 0, sizeof(hd->linkname));
1056 memset(hd->devmajor, 0, sizeof(hd->devmajor));
1057 memset(hd->devminor, 0, sizeof(hd->devminor));
1058 if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3))
1059 goto out;
1060 break;
1061 case PAX_SLK:
1062 case PAX_HLK:
1063 case PAX_HRG:
1064 if (arcn->type == PAX_SLK)
1065 hd->typeflag = SYMTYPE;
1066 else
1067 hd->typeflag = LNKTYPE;
1068 zf_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname));
1069 memset(hd->devmajor, 0, sizeof(hd->devmajor));
1070 memset(hd->devminor, 0, sizeof(hd->devminor));
1071 if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3))
1072 goto out;
1073 break;
1074 case PAX_REG:
1075 case PAX_CTG:
1076 default:
1077 /*
1078 * file data with this type, set the padding
1079 */
1080 if (arcn->type == PAX_CTG)
1081 hd->typeflag = CONTTYPE;
1082 else
1083 hd->typeflag = REGTYPE;
1084 memset(hd->linkname, 0, sizeof(hd->linkname));
1085 memset(hd->devmajor, 0, sizeof(hd->devmajor));
1086 memset(hd->devminor, 0, sizeof(hd->devminor));
1087 arcn->pad = TAR_PAD(arcn->sb.st_size);
1088 # ifdef NET2_STAT
1089 if (ul_oct((u_long)arcn->sb.st_size, hd->size,
1090 sizeof(hd->size), 3)) {
1091 # else
1092 if (uqd_oct((u_quad_t)arcn->sb.st_size, hd->size,
1093 sizeof(hd->size), 3)) {
1094 # endif
1095 tty_warn(1,"File is too long for ustar %s",
1096 arcn->org_name);
1097 return(1);
1098 }
1099 break;
1100 }
1101
1102 zf_strncpy(hd->magic, TMAGIC, TMAGLEN);
1103 zf_strncpy(hd->version, TVERSION, TVERSLEN);
1104
1105 /*
1106 * set the remaining fields. Some versions want all 16 bits of mode
1107 * we better humor them (they really do not meet spec though)....
1108 */
1109 if (ul_oct((u_long)arcn->sb.st_mode, hd->mode, sizeof(hd->mode), 3) ||
1110 ul_oct((u_long)arcn->sb.st_uid, hd->uid, sizeof(hd->uid), 3) ||
1111 ul_oct((u_long)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), 3) ||
1112 ul_oct((u_long)arcn->sb.st_mtime,hd->mtime,sizeof(hd->mtime),3))
1113 goto out;
1114 zf_strncpy(hd->uname,name_uid(arcn->sb.st_uid, 0),sizeof(hd->uname));
1115 zf_strncpy(hd->gname,name_gid(arcn->sb.st_gid, 0),sizeof(hd->gname));
1116
1117 /*
1118 * calculate and store the checksum write the header to the archive
1119 * return 0 tells the caller to now write the file data, 1 says no data
1120 * needs to be written
1121 */
1122 if (ul_oct(tar_chksm(hdblk, sizeof(HD_USTAR)), hd->chksum,
1123 sizeof(hd->chksum), 3))
1124 goto out;
1125 if (wr_rdbuf(hdblk, sizeof(HD_USTAR)) < 0)
1126 return(-1);
1127 if (wr_skip((off_t)(BLKMULT - sizeof(HD_USTAR))) < 0)
1128 return(-1);
1129 if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG))
1130 return(0);
1131 return(1);
1132
1133 out:
1134 /*
1135 * header field is out of range
1136 */
1137 tty_warn(1, "Ustar header field is too small for %s", arcn->org_name);
1138 return(1);
1139 }
1140
1141 /*
1142 * name_split()
1143 * see if the name has to be split for storage in a ustar header. We try
1144 * to fit the entire name in the name field without splitting if we can.
1145 * The split point is always at a /
1146 * Return
1147 * character pointer to split point (always the / that is to be removed
1148 * if the split is not needed, the points is set to the start of the file
1149 * name (it would violate the spec to split there). A NULL is returned if
1150 * the file name is too long
1151 */
1152
1153 #if __STDC__
1154 static char *
1155 name_split(char *name, int len)
1156 #else
1157 static char *
1158 name_split(name, len)
1159 char *name;
1160 int len;
1161 #endif
1162 {
1163 char *start;
1164
1165 /*
1166 * check to see if the file name is small enough to fit in the name
1167 * field. if so just return a pointer to the name.
1168 */
1169 if (len <= TNMSZ)
1170 return(name);
1171 if (len > (TPFSZ + TNMSZ + 1))
1172 return(NULL);
1173
1174 /*
1175 * we start looking at the biggest sized piece that fits in the name
1176 * field. We walk foward looking for a slash to split at. The idea is
1177 * to find the biggest piece to fit in the name field (or the smallest
1178 * prefix we can find) (the -1 is correct the biggest piece would
1179 * include the slash between the two parts that gets thrown away)
1180 */
1181 start = name + len - TNMSZ - 1;
1182 while ((*start != '\0') && (*start != '/'))
1183 ++start;
1184
1185 /*
1186 * if we hit the end of the string, this name cannot be split, so we
1187 * cannot store this file.
1188 */
1189 if (*start == '\0')
1190 return(NULL);
1191 len = start - name;
1192
1193 /*
1194 * NOTE: /str where the length of str == TNMSZ can not be stored under
1195 * the p1003.1-1990 spec for ustar. We could force a prefix of / and
1196 * the file would then expand on extract to //str. The len == 0 below
1197 * makes this special case follow the spec to the letter.
1198 */
1199 if ((len > TPFSZ) || (len == 0))
1200 return(NULL);
1201
1202 /*
1203 * ok have a split point, return it to the caller
1204 */
1205 return(start);
1206 }
1207