tar.c revision 1.9.2.1
1/*	$NetBSD: tar.c,v 1.9.2.1 1998/10/15 01:52:12 cgd 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
43static char sccsid[] = "@(#)tar.c	8.2 (Berkeley) 4/18/94";
44#else
45__RCSID("$NetBSD: tar.c,v 1.9.2.1 1998/10/15 01:52:12 cgd 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
66static u_long tar_chksm __P((char *, int));
67static char *name_split __P((char *, int));
68static int ul_oct __P((u_long, char *, int, int));
69#ifndef NET2_STAT
70static int uqd_oct __P((u_quad_t, char *, int, int));
71#endif
72
73/*
74 * Routines common to all versions of tar
75 */
76
77static 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__
87int
88tar_endwr(void)
89#else
90int
91tar_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__
105off_t
106tar_endrd(void)
107#else
108off_t
109tar_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__
127int
128tar_trail(char *buf, int in_resync, int *cnt)
129#else
130int
131tar_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__
178static int
179ul_oct(u_long val, char *str, int len, int term)
180#else
181static int
182ul_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__
242static int
243uqd_oct(u_quad_t val, char *str, int len, int term)
244#else
245static int
246uqd_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__
305static u_long
306tar_chksm(char *blk, int len)
307#else
308static u_long
309tar_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__
353int
354tar_id(char *blk, int size)
355#else
356int
357tar_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__
394int
395tar_opt(void)
396#else
397int
398tar_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__
438int
439tar_rd(ARCHD *arcn, char *buf)
440#else
441int
442tar_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__
561int
562tar_wr(ARCHD *arcn)
563#else
564int
565tar_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__
728int
729ustar_strd(void)
730#else
731int
732ustar_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__
748int
749ustar_stwr(void)
750#else
751int
752ustar_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__
769int
770ustar_id(char *blk, int size)
771#else
772int
773ustar_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__
808int
809ustar_rd(ARCHD *arcn, char *buf)
810#else
811int
812ustar_rd(arcn, buf)
813	ARCHD *arcn;
814	char *buf;
815#endif
816{
817	HD_USTAR *hd;
818	char *dest;
819	int cnt;
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 += cnt;
841		*dest++ = '/';
842	}
843	cnt = l_strncpy(dest, hd->name, sizeof(hd->name));
844	dest += cnt;
845	*dest = '\0';
846	arcn->nlen = dest - arcn->name;
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__
967int
968ustar_wr(ARCHD *arcn)
969#else
970int
971ustar_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__
1154static char *
1155name_split(char *name, int len)
1156#else
1157static char *
1158name_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