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