tar.c revision 1.10 1 /* $NetBSD: tar.c,v 1.10 1998/07/28 17:44:24 mycroft 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.10 1998/07/28 17:44:24 mycroft 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
54 #include <ctype.h>
55 #include <grp.h>
56 #include <pwd.h>
57 #include <stdio.h>
58 #include <stdlib.h>
59 #include <string.h>
60 #include <unistd.h>
61
62 #include "pax.h"
63 #include "extern.h"
64 #include "tar.h"
65
66 /*
67 * Routines for reading, writing and header identify of various versions of tar
68 */
69
70 static u_long tar_chksm __P((char *, int));
71 static char *name_split __P((char *, int));
72 static int ul_oct __P((u_long, char *, int, int));
73 #ifndef NET2_STAT
74 static int uqd_oct __P((u_quad_t, char *, int, int));
75 #endif
76
77 /*
78 * Routines common to all versions of tar
79 */
80
81 static int tar_nodir; /* do not write dirs under old tar */
82
83 /*
84 * tar_endwr()
85 * add the tar trailer of two null blocks
86 * Return:
87 * 0 if ok, -1 otherwise (what wr_skip returns)
88 */
89
90 #if __STDC__
91 int
92 tar_endwr(void)
93 #else
94 int
95 tar_endwr()
96 #endif
97 {
98 return(wr_skip((off_t)(NULLCNT*BLKMULT)));
99 }
100
101 /*
102 * tar_endrd()
103 * no cleanup needed here, just return size of trailer (for append)
104 * Return:
105 * size of trailer (2 * BLKMULT)
106 */
107
108 #if __STDC__
109 off_t
110 tar_endrd(void)
111 #else
112 off_t
113 tar_endrd()
114 #endif
115 {
116 return((off_t)(NULLCNT*BLKMULT));
117 }
118
119 /*
120 * tar_trail()
121 * Called to determine if a header block is a valid trailer. We are passed
122 * the block, the in_sync flag (which tells us we are in resync mode;
123 * looking for a valid header), and cnt (which starts at zero) which is
124 * used to count the number of empty blocks we have seen so far.
125 * Return:
126 * 0 if a valid trailer, -1 if not a valid trailer, or 1 if the block
127 * could never contain a header.
128 */
129
130 #if __STDC__
131 int
132 tar_trail(char *buf, int in_resync, int *cnt)
133 #else
134 int
135 tar_trail(buf, in_resync, cnt)
136 char *buf;
137 int in_resync;
138 int *cnt;
139 #endif
140 {
141 int i;
142
143 /*
144 * look for all zero, trailer is two consecutive blocks of zero
145 */
146 for (i = 0; i < BLKMULT; ++i) {
147 if (buf[i] != '\0')
148 break;
149 }
150
151 /*
152 * if not all zero it is not a trailer, but MIGHT be a header.
153 */
154 if (i != BLKMULT)
155 return(-1);
156
157 /*
158 * When given a zero block, we must be careful!
159 * If we are not in resync mode, check for the trailer. Have to watch
160 * out that we do not mis-identify file data as the trailer, so we do
161 * NOT try to id a trailer during resync mode. During resync mode we
162 * might as well throw this block out since a valid header can NEVER be
163 * a block of all 0 (we must have a valid file name).
164 */
165 if (!in_resync && (++*cnt >= NULLCNT))
166 return(0);
167 return(1);
168 }
169
170 /*
171 * ul_oct()
172 * convert an unsigned long to an octal string. many oddball field
173 * termination characters are used by the various versions of tar in the
174 * different fields. term selects which kind to use. str is '0' padded
175 * at the front to len. we are unable to use only one format as many old
176 * tar readers are very cranky about this.
177 * Return:
178 * 0 if the number fit into the string, -1 otherwise
179 */
180
181 #if __STDC__
182 static int
183 ul_oct(u_long val, char *str, int len, int term)
184 #else
185 static int
186 ul_oct(val, str, len, term)
187 u_long val;
188 char *str;
189 int len;
190 int term;
191 #endif
192 {
193 char *pt;
194
195 /*
196 * term selects the appropriate character(s) for the end of the string
197 */
198 pt = str + len - 1;
199 switch(term) {
200 case 3:
201 *pt-- = '\0';
202 break;
203 case 2:
204 *pt-- = ' ';
205 *pt-- = '\0';
206 break;
207 case 1:
208 *pt-- = ' ';
209 break;
210 case 0:
211 default:
212 *pt-- = '\0';
213 *pt-- = ' ';
214 break;
215 }
216
217 /*
218 * convert and blank pad if there is space
219 */
220 while (pt >= str) {
221 *pt-- = '0' + (char)(val & 0x7);
222 if ((val = val >> 3) == (u_long)0)
223 break;
224 }
225
226 while (pt >= str)
227 *pt-- = '0';
228 if (val != (u_long)0)
229 return(-1);
230 return(0);
231 }
232
233 #ifndef NET2_STAT
234 /*
235 * uqd_oct()
236 * convert an u_quad_t to an octal string. one of many oddball field
237 * termination characters are used by the various versions of tar in the
238 * different fields. term selects which kind to use. str is '0' padded
239 * at the front to len. we are unable to use only one format as many old
240 * tar readers are very cranky about this.
241 * Return:
242 * 0 if the number fit into the string, -1 otherwise
243 */
244
245 #if __STDC__
246 static int
247 uqd_oct(u_quad_t val, char *str, int len, int term)
248 #else
249 static int
250 uqd_oct(val, str, len, term)
251 u_quad_t val;
252 char *str;
253 int len;
254 int term;
255 #endif
256 {
257 char *pt;
258
259 /*
260 * term selects the appropriate character(s) for the end of the string
261 */
262 pt = str + len - 1;
263 switch(term) {
264 case 3:
265 *pt-- = '\0';
266 break;
267 case 2:
268 *pt-- = ' ';
269 *pt-- = '\0';
270 break;
271 case 1:
272 *pt-- = ' ';
273 break;
274 case 0:
275 default:
276 *pt-- = '\0';
277 *pt-- = ' ';
278 break;
279 }
280
281 /*
282 * convert and blank pad if there is space
283 */
284 while (pt >= str) {
285 *pt-- = '0' + (char)(val & 0x7);
286 if ((val = val >> 3) == 0)
287 break;
288 }
289
290 while (pt >= str)
291 *pt-- = '0';
292 if (val != (u_quad_t)0)
293 return(-1);
294 return(0);
295 }
296 #endif
297
298 /*
299 * tar_chksm()
300 * calculate the checksum for a tar block counting the checksum field as
301 * all blanks (BLNKSUM is that value pre-calculated, the sume of 8 blanks).
302 * NOTE: we use len to short circuit summing 0's on write since we ALWAYS
303 * pad headers with 0.
304 * Return:
305 * unsigned long checksum
306 */
307
308 #if __STDC__
309 static u_long
310 tar_chksm(char *blk, int len)
311 #else
312 static u_long
313 tar_chksm(blk, len)
314 char *blk;
315 int len;
316 #endif
317 {
318 char *stop;
319 char *pt;
320 u_long chksm = BLNKSUM; /* inital value is checksum field sum */
321
322 /*
323 * add the part of the block before the checksum field
324 */
325 pt = blk;
326 stop = blk + CHK_OFFSET;
327 while (pt < stop)
328 chksm += (u_long)(*pt++ & 0xff);
329 /*
330 * move past the checksum field and keep going, spec counts the
331 * checksum field as the sum of 8 blanks (which is pre-computed as
332 * BLNKSUM).
333 * ASSUMED: len is greater than CHK_OFFSET. (len is where our 0 padding
334 * starts, no point in summing zero's)
335 */
336 pt += CHK_LEN;
337 stop = blk + len;
338 while (pt < stop)
339 chksm += (u_long)(*pt++ & 0xff);
340 return(chksm);
341 }
342
343 /*
344 * Routines for old BSD style tar (also made portable to sysV tar)
345 */
346
347 /*
348 * tar_id()
349 * determine if a block given to us is a valid tar header (and not a USTAR
350 * header). We have to be on the lookout for those pesky blocks of all
351 * zero's.
352 * Return:
353 * 0 if a tar header, -1 otherwise
354 */
355
356 #if __STDC__
357 int
358 tar_id(char *blk, int size)
359 #else
360 int
361 tar_id(blk, size)
362 char *blk;
363 int size;
364 #endif
365 {
366 HD_TAR *hd;
367 HD_USTAR *uhd;
368
369 if (size < BLKMULT)
370 return(-1);
371 hd = (HD_TAR *)blk;
372 uhd = (HD_USTAR *)blk;
373
374 /*
375 * check for block of zero's first, a simple and fast test, then make
376 * sure this is not a ustar header by looking for the ustar magic
377 * cookie. We should use TMAGLEN, but some USTAR archive programs are
378 * wrong and create archives missing the \0. Last we check the
379 * checksum. If this is ok we have to assume it is a valid header.
380 */
381 if (hd->name[0] == '\0')
382 return(-1);
383 if (strncmp(uhd->magic, TMAGIC, TMAGLEN - 1) == 0)
384 return(-1);
385 if (asc_ul(hd->chksum,sizeof(hd->chksum),OCT) != tar_chksm(blk,BLKMULT))
386 return(-1);
387 return(0);
388 }
389
390 /*
391 * tar_opt()
392 * handle tar format specific -o options
393 * Return:
394 * 0 if ok -1 otherwise
395 */
396
397 #if __STDC__
398 int
399 tar_opt(void)
400 #else
401 int
402 tar_opt()
403 #endif
404 {
405 OPLIST *opt;
406
407 while ((opt = opt_next()) != NULL) {
408 if (strcmp(opt->name, TAR_OPTION) ||
409 strcmp(opt->value, TAR_NODIR)) {
410 tty_warn(1,
411 "Unknown tar format -o option/value pair %s=%s",
412 opt->name, opt->value);
413 tty_warn(1,
414 "%s=%s is the only supported tar format option",
415 TAR_OPTION, TAR_NODIR);
416 return(-1);
417 }
418
419 /*
420 * we only support one option, and only when writing
421 */
422 if ((act != APPND) && (act != ARCHIVE)) {
423 tty_warn(1, "%s=%s is only supported when writing.",
424 opt->name, opt->value);
425 return(-1);
426 }
427 tar_nodir = 1;
428 }
429 return(0);
430 }
431
432
433 /*
434 * tar_rd()
435 * extract the values out of block already determined to be a tar header.
436 * store the values in the ARCHD parameter.
437 * Return:
438 * 0
439 */
440
441 #if __STDC__
442 int
443 tar_rd(ARCHD *arcn, char *buf)
444 #else
445 int
446 tar_rd(arcn, buf)
447 ARCHD *arcn;
448 char *buf;
449 #endif
450 {
451 HD_TAR *hd;
452 char *pt;
453
454 /*
455 * we only get proper sized buffers passed to us
456 */
457 if (tar_id(buf, BLKMULT) < 0)
458 return(-1);
459 arcn->org_name = arcn->name;
460 arcn->sb.st_nlink = 1;
461 arcn->pat = NULL;
462
463 /*
464 * copy out the name and values in the stat buffer
465 */
466 hd = (HD_TAR *)buf;
467 arcn->nlen = l_strncpy(arcn->name, hd->name, sizeof(hd->name));
468 arcn->name[arcn->nlen] = '\0';
469 arcn->sb.st_mode = (mode_t)(asc_ul(hd->mode,sizeof(hd->mode),OCT) &
470 0xfff);
471 arcn->sb.st_uid = (uid_t)asc_ul(hd->uid, sizeof(hd->uid), OCT);
472 arcn->sb.st_gid = (gid_t)asc_ul(hd->gid, sizeof(hd->gid), OCT);
473 arcn->sb.st_size = (size_t)asc_ul(hd->size, sizeof(hd->size), OCT);
474 arcn->sb.st_mtime = (time_t)asc_ul(hd->mtime, sizeof(hd->mtime), OCT);
475 arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
476
477 /*
478 * have to look at the last character, it may be a '/' and that is used
479 * to encode this as a directory
480 */
481 pt = &(arcn->name[arcn->nlen - 1]);
482 arcn->pad = 0;
483 arcn->skip = 0;
484 switch(hd->linkflag) {
485 case SYMTYPE:
486 /*
487 * symbolic link, need to get the link name and set the type in
488 * the st_mode so -v printing will look correct.
489 */
490 arcn->type = PAX_SLK;
491 arcn->ln_nlen = l_strncpy(arcn->ln_name, hd->linkname,
492 sizeof(hd->linkname));
493 arcn->ln_name[arcn->ln_nlen] = '\0';
494 arcn->sb.st_mode |= S_IFLNK;
495 break;
496 case LNKTYPE:
497 /*
498 * hard link, need to get the link name, set the type in the
499 * st_mode and st_nlink so -v printing will look better.
500 */
501 arcn->type = PAX_HLK;
502 arcn->sb.st_nlink = 2;
503 arcn->ln_nlen = l_strncpy(arcn->ln_name, hd->linkname,
504 sizeof(hd->linkname));
505 arcn->ln_name[arcn->ln_nlen] = '\0';
506
507 /*
508 * no idea of what type this thing really points at, but
509 * we set something for printing only.
510 */
511 arcn->sb.st_mode |= S_IFREG;
512 break;
513 case AREGTYPE:
514 case REGTYPE:
515 default:
516 /*
517 * If we have a trailing / this is a directory and NOT a file.
518 */
519 arcn->ln_name[0] = '\0';
520 arcn->ln_nlen = 0;
521 if (*pt == '/') {
522 /*
523 * it is a directory, set the mode for -v printing
524 */
525 arcn->type = PAX_DIR;
526 arcn->sb.st_mode |= S_IFDIR;
527 arcn->sb.st_nlink = 2;
528 } else {
529 /*
530 * have a file that will be followed by data. Set the
531 * skip value to the size field and caluculate the size
532 * of the padding.
533 */
534 arcn->type = PAX_REG;
535 arcn->sb.st_mode |= S_IFREG;
536 arcn->pad = TAR_PAD(arcn->sb.st_size);
537 arcn->skip = arcn->sb.st_size;
538 }
539 break;
540 }
541
542 /*
543 * strip off any trailing slash.
544 */
545 if (*pt == '/') {
546 *pt = '\0';
547 --arcn->nlen;
548 }
549 return(0);
550 }
551
552 /*
553 * tar_wr()
554 * write a tar header for the file specified in the ARCHD to the archive.
555 * Have to check for file types that cannot be stored and file names that
556 * are too long. Be careful of the term (last arg) to ul_oct, each field
557 * of tar has it own spec for the termination character(s).
558 * ASSUMED: space after header in header block is zero filled
559 * Return:
560 * 0 if file has data to be written after the header, 1 if file has NO
561 * data to write after the header, -1 if archive write failed
562 */
563
564 #if __STDC__
565 int
566 tar_wr(ARCHD *arcn)
567 #else
568 int
569 tar_wr(arcn)
570 ARCHD *arcn;
571 #endif
572 {
573 HD_TAR *hd;
574 int len;
575 char hdblk[sizeof(HD_TAR)];
576
577 /*
578 * check for those file system types which tar cannot store
579 */
580 switch(arcn->type) {
581 case PAX_DIR:
582 /*
583 * user asked that dirs not be written to the archive
584 */
585 if (tar_nodir)
586 return(1);
587 break;
588 case PAX_CHR:
589 tty_warn(1, "Tar cannot archive a character device %s",
590 arcn->org_name);
591 return(1);
592 case PAX_BLK:
593 tty_warn(1,
594 "Tar cannot archive a block device %s", arcn->org_name);
595 return(1);
596 case PAX_SCK:
597 tty_warn(1, "Tar cannot archive a socket %s", arcn->org_name);
598 return(1);
599 case PAX_FIF:
600 tty_warn(1, "Tar cannot archive a fifo %s", arcn->org_name);
601 return(1);
602 case PAX_SLK:
603 case PAX_HLK:
604 case PAX_HRG:
605 if (arcn->ln_nlen > sizeof(hd->linkname)) {
606 tty_warn(1,"Link name too long for tar %s",
607 arcn->ln_name);
608 return(1);
609 }
610 break;
611 case PAX_REG:
612 case PAX_CTG:
613 default:
614 break;
615 }
616
617 /*
618 * check file name len, remember extra char for dirs (the / at the end)
619 */
620 len = arcn->nlen;
621 if (arcn->type == PAX_DIR)
622 ++len;
623 if (len > sizeof(hd->name)) {
624 tty_warn(1, "File name too long for tar %s", arcn->name);
625 return(1);
626 }
627
628 /*
629 * copy the data out of the ARCHD into the tar header based on the type
630 * of the file. Remember many tar readers want the unused fields to be
631 * padded with zero. We set the linkflag field (type), the linkname
632 * (or zero if not used),the size, and set the padding (if any) to be
633 * added after the file data (0 for all other types, as they only have
634 * a header)
635 */
636 hd = (HD_TAR *)hdblk;
637 zf_strncpy(hd->name, arcn->name, sizeof(hd->name));
638 arcn->pad = 0;
639
640 if (arcn->type == PAX_DIR) {
641 /*
642 * directories are the same as files, except have a filename
643 * that ends with a /, we add the slash here. No data follows,
644 * dirs, so no pad.
645 */
646 hd->linkflag = AREGTYPE;
647 memset(hd->linkname, 0, sizeof(hd->linkname));
648 hd->name[len-1] = '/';
649 if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1))
650 goto out;
651 } else if (arcn->type == PAX_SLK) {
652 /*
653 * no data follows this file, so no pad
654 */
655 hd->linkflag = SYMTYPE;
656 zf_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname));
657 if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1))
658 goto out;
659 } else if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG)) {
660 /*
661 * no data follows this file, so no pad
662 */
663 hd->linkflag = LNKTYPE;
664 zf_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname));
665 if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1))
666 goto out;
667 } else {
668 /*
669 * data follows this file, so set the pad
670 */
671 hd->linkflag = AREGTYPE;
672 memset(hd->linkname, 0, sizeof(hd->linkname));
673 # ifdef NET2_STAT
674 if (ul_oct((u_long)arcn->sb.st_size, hd->size,
675 sizeof(hd->size), 1)) {
676 # else
677 if (uqd_oct((u_quad_t)arcn->sb.st_size, hd->size,
678 sizeof(hd->size), 1)) {
679 # endif
680 tty_warn(1,"File is too large for tar %s",
681 arcn->org_name);
682 return(1);
683 }
684 arcn->pad = TAR_PAD(arcn->sb.st_size);
685 }
686
687 /*
688 * copy those fields that are independent of the type
689 */
690 if (ul_oct((u_long)arcn->sb.st_mode, hd->mode, sizeof(hd->mode), 0) ||
691 ul_oct((u_long)arcn->sb.st_uid, hd->uid, sizeof(hd->uid), 0) ||
692 ul_oct((u_long)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), 0) ||
693 ul_oct((u_long)arcn->sb.st_mtime, hd->mtime, sizeof(hd->mtime), 1))
694 goto out;
695
696 /*
697 * calculate and add the checksum, then write the header. A return of
698 * 0 tells the caller to now write the file data, 1 says no data needs
699 * to be written
700 */
701 if (ul_oct(tar_chksm(hdblk, sizeof(HD_TAR)), hd->chksum,
702 sizeof(hd->chksum), 2))
703 goto out;
704 if (wr_rdbuf(hdblk, sizeof(HD_TAR)) < 0)
705 return(-1);
706 if (wr_skip((off_t)(BLKMULT - sizeof(HD_TAR))) < 0)
707 return(-1);
708 if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG))
709 return(0);
710 return(1);
711
712 out:
713 /*
714 * header field is out of range
715 */
716 tty_warn(1, "Tar header field is too small for %s", arcn->org_name);
717 return(1);
718 }
719
720 /*
721 * Routines for POSIX ustar
722 */
723
724 /*
725 * ustar_strd()
726 * initialization for ustar read
727 * Return:
728 * 0 if ok, -1 otherwise
729 */
730
731 #if __STDC__
732 int
733 ustar_strd(void)
734 #else
735 int
736 ustar_strd()
737 #endif
738 {
739 return(0);
740 }
741
742 /*
743 * ustar_stwr()
744 * initialization for ustar write
745 * Return:
746 * 0 if ok, -1 otherwise
747 */
748
749 #if __STDC__
750 int
751 ustar_stwr(void)
752 #else
753 int
754 ustar_stwr()
755 #endif
756 {
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_from_group(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_from_user(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 const char *user, *group;
979
980 /*
981 * check for those file system types ustar cannot store
982 */
983 if (arcn->type == PAX_SCK) {
984 tty_warn(1, "Ustar cannot archive a socket %s", arcn->org_name);
985 return(1);
986 }
987
988 /*
989 * check the length of the linkname
990 */
991 if (((arcn->type == PAX_SLK) || (arcn->type == PAX_HLK) ||
992 (arcn->type == PAX_HRG)) && (arcn->ln_nlen > sizeof(hd->linkname))){
993 tty_warn(1, "Link name too long for ustar %s", arcn->ln_name);
994 return(1);
995 }
996
997 /*
998 * split the path name into prefix and name fields (if needed). if
999 * pt != arcn->name, the name has to be split
1000 */
1001 if ((pt = name_split(arcn->name, arcn->nlen)) == NULL) {
1002 tty_warn(1, "File name too long for ustar %s", arcn->name);
1003 return(1);
1004 }
1005 hd = (HD_USTAR *)hdblk;
1006 arcn->pad = 0L;
1007
1008 /*
1009 * split the name, or zero out the prefix
1010 */
1011 if (pt != arcn->name) {
1012 /*
1013 * name was split, pt points at the / where the split is to
1014 * occur, we remove the / and copy the first part to the prefix
1015 */
1016 *pt = '\0';
1017 zf_strncpy(hd->prefix, arcn->name, sizeof(hd->prefix));
1018 *pt++ = '/';
1019 } else
1020 memset(hd->prefix, 0, sizeof(hd->prefix));
1021
1022 /*
1023 * copy the name part. this may be the whole path or the part after
1024 * the prefix
1025 */
1026 zf_strncpy(hd->name, pt, sizeof(hd->name));
1027
1028 /*
1029 * set the fields in the header that are type dependent
1030 */
1031 switch(arcn->type) {
1032 case PAX_DIR:
1033 hd->typeflag = DIRTYPE;
1034 memset(hd->linkname, 0, sizeof(hd->linkname));
1035 memset(hd->devmajor, 0, sizeof(hd->devmajor));
1036 memset(hd->devminor, 0, sizeof(hd->devminor));
1037 if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3))
1038 goto out;
1039 break;
1040 case PAX_CHR:
1041 case PAX_BLK:
1042 if (arcn->type == PAX_CHR)
1043 hd->typeflag = CHRTYPE;
1044 else
1045 hd->typeflag = BLKTYPE;
1046 memset(hd->linkname, 0, sizeof(hd->linkname));
1047 if (ul_oct((u_long)MAJOR(arcn->sb.st_rdev), hd->devmajor,
1048 sizeof(hd->devmajor), 3) ||
1049 ul_oct((u_long)MINOR(arcn->sb.st_rdev), hd->devminor,
1050 sizeof(hd->devminor), 3) ||
1051 ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3))
1052 goto out;
1053 break;
1054 case PAX_FIF:
1055 hd->typeflag = FIFOTYPE;
1056 memset(hd->linkname, 0, sizeof(hd->linkname));
1057 memset(hd->devmajor, 0, sizeof(hd->devmajor));
1058 memset(hd->devminor, 0, sizeof(hd->devminor));
1059 if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3))
1060 goto out;
1061 break;
1062 case PAX_SLK:
1063 case PAX_HLK:
1064 case PAX_HRG:
1065 if (arcn->type == PAX_SLK)
1066 hd->typeflag = SYMTYPE;
1067 else
1068 hd->typeflag = LNKTYPE;
1069 zf_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname));
1070 memset(hd->devmajor, 0, sizeof(hd->devmajor));
1071 memset(hd->devminor, 0, sizeof(hd->devminor));
1072 if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3))
1073 goto out;
1074 break;
1075 case PAX_REG:
1076 case PAX_CTG:
1077 default:
1078 /*
1079 * file data with this type, set the padding
1080 */
1081 if (arcn->type == PAX_CTG)
1082 hd->typeflag = CONTTYPE;
1083 else
1084 hd->typeflag = REGTYPE;
1085 memset(hd->linkname, 0, sizeof(hd->linkname));
1086 memset(hd->devmajor, 0, sizeof(hd->devmajor));
1087 memset(hd->devminor, 0, sizeof(hd->devminor));
1088 arcn->pad = TAR_PAD(arcn->sb.st_size);
1089 # ifdef NET2_STAT
1090 if (ul_oct((u_long)arcn->sb.st_size, hd->size,
1091 sizeof(hd->size), 3)) {
1092 # else
1093 if (uqd_oct((u_quad_t)arcn->sb.st_size, hd->size,
1094 sizeof(hd->size), 3)) {
1095 # endif
1096 tty_warn(1,"File is too long for ustar %s",
1097 arcn->org_name);
1098 return(1);
1099 }
1100 break;
1101 }
1102
1103 zf_strncpy(hd->magic, TMAGIC, TMAGLEN);
1104 zf_strncpy(hd->version, TVERSION, TVERSLEN);
1105
1106 /*
1107 * set the remaining fields. Some versions want all 16 bits of mode
1108 * we better humor them (they really do not meet spec though)....
1109 */
1110 if (ul_oct((u_long)arcn->sb.st_mode, hd->mode, sizeof(hd->mode), 3) ||
1111 ul_oct((u_long)arcn->sb.st_uid, hd->uid, sizeof(hd->uid), 3) ||
1112 ul_oct((u_long)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), 3) ||
1113 ul_oct((u_long)arcn->sb.st_mtime,hd->mtime,sizeof(hd->mtime),3))
1114 goto out;
1115 user = user_from_uid(arcn->sb.st_uid, 1);
1116 group = group_from_gid(arcn->sb.st_gid, 1);
1117 zf_strncpy(hd->uname, user ? user : "", sizeof(hd->uname));
1118 zf_strncpy(hd->gname, group ? group : "", sizeof(hd->gname));
1119
1120 /*
1121 * calculate and store the checksum write the header to the archive
1122 * return 0 tells the caller to now write the file data, 1 says no data
1123 * needs to be written
1124 */
1125 if (ul_oct(tar_chksm(hdblk, sizeof(HD_USTAR)), hd->chksum,
1126 sizeof(hd->chksum), 3))
1127 goto out;
1128 if (wr_rdbuf(hdblk, sizeof(HD_USTAR)) < 0)
1129 return(-1);
1130 if (wr_skip((off_t)(BLKMULT - sizeof(HD_USTAR))) < 0)
1131 return(-1);
1132 if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG))
1133 return(0);
1134 return(1);
1135
1136 out:
1137 /*
1138 * header field is out of range
1139 */
1140 tty_warn(1, "Ustar header field is too small for %s", arcn->org_name);
1141 return(1);
1142 }
1143
1144 /*
1145 * name_split()
1146 * see if the name has to be split for storage in a ustar header. We try
1147 * to fit the entire name in the name field without splitting if we can.
1148 * The split point is always at a /
1149 * Return
1150 * character pointer to split point (always the / that is to be removed
1151 * if the split is not needed, the points is set to the start of the file
1152 * name (it would violate the spec to split there). A NULL is returned if
1153 * the file name is too long
1154 */
1155
1156 #if __STDC__
1157 static char *
1158 name_split(char *name, int len)
1159 #else
1160 static char *
1161 name_split(name, len)
1162 char *name;
1163 int len;
1164 #endif
1165 {
1166 char *start;
1167
1168 /*
1169 * check to see if the file name is small enough to fit in the name
1170 * field. if so just return a pointer to the name.
1171 */
1172 if (len <= TNMSZ)
1173 return(name);
1174 if (len > (TPFSZ + TNMSZ + 1))
1175 return(NULL);
1176
1177 /*
1178 * we start looking at the biggest sized piece that fits in the name
1179 * field. We walk foward looking for a slash to split at. The idea is
1180 * to find the biggest piece to fit in the name field (or the smallest
1181 * prefix we can find) (the -1 is correct the biggest piece would
1182 * include the slash between the two parts that gets thrown away)
1183 */
1184 start = name + len - TNMSZ - 1;
1185 while ((*start != '\0') && (*start != '/'))
1186 ++start;
1187
1188 /*
1189 * if we hit the end of the string, this name cannot be split, so we
1190 * cannot store this file.
1191 */
1192 if (*start == '\0')
1193 return(NULL);
1194 len = start - name;
1195
1196 /*
1197 * NOTE: /str where the length of str == TNMSZ can not be stored under
1198 * the p1003.1-1990 spec for ustar. We could force a prefix of / and
1199 * the file would then expand on extract to //str. The len == 0 below
1200 * makes this special case follow the spec to the letter.
1201 */
1202 if ((len > TPFSZ) || (len == 0))
1203 return(NULL);
1204
1205 /*
1206 * ok have a split point, return it to the caller
1207 */
1208 return(start);
1209 }
1210