tar.c revision 8855
1279377Simp/*-
2279377Simp * Copyright (c) 1992 Keith Muller.
3279377Simp * Copyright (c) 1992, 1993
4279377Simp *	The Regents of the University of California.  All rights reserved.
5279377Simp *
6279377Simp * This code is derived from software contributed to Berkeley by
7279377Simp * Keith Muller of the University of California, San Diego.
8279377Simp *
9279377Simp * Redistribution and use in source and binary forms, with or without
10279377Simp * modification, are permitted provided that the following conditions
11279377Simp * are met:
12279377Simp * 1. Redistributions of source code must retain the above copyright
13279377Simp *    notice, this list of conditions and the following disclaimer.
14279377Simp * 2. Redistributions in binary form must reproduce the above copyright
15279377Simp *    notice, this list of conditions and the following disclaimer in the
16279377Simp *    documentation and/or other materials provided with the distribution.
17279377Simp * 3. All advertising materials mentioning features or use of this software
18279377Simp *    must display the following acknowledgement:
19279377Simp *	This product includes software developed by the University of
20279377Simp *	California, Berkeley and its contributors.
21279377Simp * 4. Neither the name of the University nor the names of its contributors
22279377Simp *    may be used to endorse or promote products derived from this software
23279377Simp *    without specific prior written permission.
24279377Simp *
25279377Simp * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26279377Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27279377Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28279377Simp * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29279377Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30279377Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31279377Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32279377Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33279377Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34279377Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35279377Simp * SUCH DAMAGE.
36279377Simp *
37279377Simp *	$Id: tar.c,v 1.2 1994/09/24 02:56:37 davidg Exp $
38279377Simp */
39279377Simp
40279377Simp#ifndef lint
41279377Simpstatic char sccsid[] = "@(#)tar.c	8.2 (Berkeley) 4/18/94";
42279377Simp#endif /* not lint */
43279377Simp
44279377Simp#include <sys/types.h>
45279377Simp#include <sys/time.h>
46279377Simp#include <sys/stat.h>
47279377Simp#include <sys/param.h>
48279377Simp#include <string.h>
49279377Simp#include <stdio.h>
50279377Simp#include <ctype.h>
51279377Simp#include <unistd.h>
52279377Simp#include <stdlib.h>
53279377Simp#include "pax.h"
54279377Simp#include "extern.h"
55279377Simp#include "tar.h"
56279377Simp
57279377Simp/*
58279377Simp * Routines for reading, writing and header identify of various versions of tar
59279377Simp */
60279377Simp
61279377Simpstatic u_long tar_chksm __P((register char *, register int));
62279377Simpstatic char *name_split __P((register char *, register int));
63279377Simpstatic int ul_oct __P((u_long, register char *, register int, int));
64279377Simp#ifndef NET2_STAT
65279377Simpstatic int uqd_oct __P((u_quad_t, register char *, register int, int));
66279377Simp#endif
67279377Simp
68279377Simp/*
69279377Simp * Routines common to all versions of tar
70279377Simp */
71279377Simp
72279377Simpstatic int tar_nodir;			/* do not write dirs under old tar */
73279377Simp
74279377Simp/*
75279377Simp * tar_endwr()
76279377Simp *	add the tar trailer of two null blocks
77279377Simp * Return:
78279377Simp *	0 if ok, -1 otherwise (what wr_skip returns)
79279377Simp */
80279377Simp
81279377Simp#if __STDC__
82279377Simpint
83279377Simptar_endwr(void)
84279377Simp#else
85279377Simpint
86279377Simptar_endwr()
87279377Simp#endif
88279377Simp{
89279377Simp	return(wr_skip((off_t)(NULLCNT*BLKMULT)));
90279377Simp}
91279377Simp
92279377Simp/*
93279377Simp * tar_endrd()
94279377Simp *	no cleanup needed here, just return size of trailer (for append)
95279377Simp * Return:
96279377Simp *	size of trailer (2 * BLKMULT)
97279377Simp */
98279377Simp
99279377Simp#if __STDC__
100279377Simpoff_t
101279377Simptar_endrd(void)
102279377Simp#else
103279377Simpoff_t
104279377Simptar_endrd()
105279377Simp#endif
106279377Simp{
107279377Simp	return((off_t)(NULLCNT*BLKMULT));
108279377Simp}
109279377Simp
110279377Simp/*
111279377Simp * tar_trail()
112279377Simp *	Called to determine if a header block is a valid trailer. We are passed
113279377Simp *	the block, the in_sync flag (which tells us we are in resync mode;
114279377Simp *	looking for a valid header), and cnt (which starts at zero) which is
115279377Simp *	used to count the number of empty blocks we have seen so far.
116279377Simp * Return:
117279377Simp *	0 if a valid trailer, -1 if not a valid trailer, or 1 if the block
118279377Simp *	could never contain a header.
119279377Simp */
120279377Simp
121279377Simp#if __STDC__
122279377Simpint
123279377Simptar_trail(register char *buf, register int in_resync, register int *cnt)
124279377Simp#else
125279377Simpint
126279377Simptar_trail(buf, in_resync, cnt)
127279377Simp	register char *buf;
128279377Simp	register int in_resync;
129279377Simp	register int *cnt;
130279377Simp#endif
131279377Simp{
132279377Simp	register int i;
133279377Simp
134279377Simp	/*
135279377Simp	 * look for all zero, trailer is two consecutive blocks of zero
136279377Simp	 */
137279377Simp	for (i = 0; i < BLKMULT; ++i) {
138279377Simp		if (buf[i] != '\0')
139279377Simp			break;
140279377Simp	}
141279377Simp
142279377Simp	/*
143279377Simp	 * if not all zero it is not a trailer, but MIGHT be a header.
144279377Simp	 */
145279377Simp	if (i != BLKMULT)
146279377Simp		return(-1);
147279377Simp
148279377Simp	/*
149279377Simp	 * When given a zero block, we must be careful!
150279377Simp	 * If we are not in resync mode, check for the trailer. Have to watch
151279377Simp	 * out that we do not mis-identify file data as the trailer, so we do
152279377Simp	 * NOT try to id a trailer during resync mode. During resync mode we
153279377Simp	 * might as well throw this block out since a valid header can NEVER be
154279377Simp	 * a block of all 0 (we must have a valid file name).
155279377Simp	 */
156279377Simp	if (!in_resync && (++*cnt >= NULLCNT))
157279377Simp		return(0);
158279377Simp	return(1);
159279377Simp}
160279377Simp
161279377Simp/*
162279377Simp * ul_oct()
163279377Simp *	convert an unsigned long to an octal string. many oddball field
164279377Simp *	termination characters are used by the various versions of tar in the
165279377Simp *	different fields. term selects which kind to use. str is BLANK padded
166279377Simp *	at the front to len. we are unable to use only one format as many old
167279377Simp *	tar readers are very cranky about this.
168279377Simp * Return:
169279377Simp *	0 if the number fit into the string, -1 otherwise
170279377Simp */
171279377Simp
172279377Simp#if __STDC__
173279377Simpstatic int
174279377Simpul_oct(u_long val, register char *str, register int len, int term)
175279377Simp#else
176279377Simpstatic int
177279377Simpul_oct(val, str, len, term)
178279377Simp	u_long val;
179279377Simp	register char *str;
180279377Simp	register int len;
181279377Simp	int term;
182279377Simp#endif
183279377Simp{
184279377Simp	register char *pt;
185279377Simp
186279377Simp	/*
187279377Simp	 * term selects the appropriate character(s) for the end of the string
188279377Simp	 */
189279377Simp	pt = str + len - 1;
190279377Simp	switch(term) {
191279377Simp	case 3:
192279377Simp		*pt-- = '\0';
193279377Simp		break;
194279377Simp	case 2:
195279377Simp		*pt-- = ' ';
196279377Simp		*pt-- = '\0';
197279377Simp		break;
198279377Simp	case 1:
199279377Simp		*pt-- = ' ';
200279377Simp		break;
201279377Simp	case 0:
202279377Simp	default:
203279377Simp		*pt-- = '\0';
204279377Simp		*pt-- = ' ';
205279377Simp		break;
206279377Simp	}
207279377Simp
208279377Simp	/*
209279377Simp	 * convert and blank pad if there is space
210279377Simp	 */
211279377Simp	while (pt >= str) {
212279377Simp		*pt-- = '0' + (char)(val & 0x7);
213279377Simp		if ((val = val >> 3) == (u_long)0)
214279377Simp			break;
215279377Simp	}
216279377Simp
217279377Simp	while (pt >= str)
218279377Simp		*pt-- = ' ';
219279377Simp	if (val != (u_long)0)
220279377Simp		return(-1);
221279377Simp	return(0);
222279377Simp}
223279377Simp
224279377Simp#ifndef NET2_STAT
225279377Simp/*
226279377Simp * uqd_oct()
227279377Simp *	convert an u_quad_t to an octal string. one of many oddball field
228279377Simp *	termination characters are used by the various versions of tar in the
229279377Simp *	different fields. term selects which kind to use. str is BLANK padded
230279377Simp *	at the front to len. we are unable to use only one format as many old
231279377Simp *	tar readers are very cranky about this.
232279377Simp * Return:
233279377Simp *	0 if the number fit into the string, -1 otherwise
234279377Simp */
235279377Simp
236279377Simp#if __STDC__
237279377Simpstatic int
238279377Simpuqd_oct(u_quad_t val, register char *str, register int len, int term)
239279377Simp#else
240279377Simpstatic int
241279377Simpuqd_oct(val, str, len, term)
242279377Simp	u_quad_t val;
243279377Simp	register char *str;
244279377Simp	register int len;
245279377Simp	int term;
246279377Simp#endif
247279377Simp{
248279377Simp	register char *pt;
249279377Simp
250279377Simp	/*
251279377Simp	 * term selects the appropriate character(s) for the end of the string
252279377Simp	 */
253279377Simp	pt = str + len - 1;
254279377Simp	switch(term) {
255279377Simp	case 3:
256279377Simp		*pt-- = '\0';
257279377Simp		break;
258279377Simp	case 2:
259279377Simp		*pt-- = ' ';
260279377Simp		*pt-- = '\0';
261279377Simp		break;
262279377Simp	case 1:
263279377Simp		*pt-- = ' ';
264279377Simp		break;
265279377Simp	case 0:
266279377Simp	default:
267279377Simp		*pt-- = '\0';
268279377Simp		*pt-- = ' ';
269279377Simp		break;
270279377Simp	}
271279377Simp
272279377Simp	/*
273279377Simp	 * convert and blank pad if there is space
274279377Simp	 */
275279377Simp	while (pt >= str) {
276279377Simp		*pt-- = '0' + (char)(val & 0x7);
277279377Simp		if ((val = val >> 3) == 0)
278279377Simp			break;
279279377Simp	}
280279377Simp
281279377Simp	while (pt >= str)
282279377Simp		*pt-- = ' ';
283279377Simp	if (val != (u_quad_t)0)
284279377Simp		return(-1);
285279377Simp	return(0);
286279377Simp}
287279377Simp#endif
288279377Simp
289279377Simp/*
290279377Simp * tar_chksm()
291279377Simp *	calculate the checksum for a tar block counting the checksum field as
292279377Simp *	all blanks (BLNKSUM is that value pre-calculated, the sume of 8 blanks).
293279377Simp *	NOTE: we use len to short circuit summing 0's on write since we ALWAYS
294279377Simp *	pad headers with 0.
295279377Simp * Return:
296279377Simp *	unsigned long checksum
297279377Simp */
298279377Simp
299279377Simp#if __STDC__
300279377Simpstatic u_long
301279377Simptar_chksm(register char *blk, register int len)
302279377Simp#else
303279377Simpstatic u_long
304279377Simptar_chksm(blk, len)
305279377Simp	register char *blk;
306279377Simp	register int len;
307279377Simp#endif
308279377Simp{
309279377Simp	register char *stop;
310279377Simp	register char *pt;
311279377Simp	u_long chksm = BLNKSUM;	/* inital value is checksum field sum */
312279377Simp
313279377Simp	/*
314279377Simp	 * add the part of the block before the checksum field
315279377Simp	 */
316279377Simp	pt = blk;
317279377Simp	stop = blk + CHK_OFFSET;
318279377Simp	while (pt < stop)
319279377Simp		chksm += (u_long)(*pt++ & 0xff);
320279377Simp	/*
321279377Simp	 * move past the checksum field and keep going, spec counts the
322279377Simp	 * checksum field as the sum of 8 blanks (which is pre-computed as
323279377Simp	 * BLNKSUM).
324279377Simp	 * ASSUMED: len is greater than CHK_OFFSET. (len is where our 0 padding
325279377Simp	 * starts, no point in summing zero's)
326279377Simp	 */
327279377Simp	pt += CHK_LEN;
328279377Simp	stop = blk + len;
329279377Simp	while (pt < stop)
330279377Simp		chksm += (u_long)(*pt++ & 0xff);
331279377Simp	return(chksm);
332279377Simp}
333279377Simp
334279377Simp/*
335279377Simp * Routines for old BSD style tar (also made portable to sysV tar)
336279377Simp */
337279377Simp
338279377Simp/*
339279377Simp * tar_id()
340279377Simp *	determine if a block given to us is a valid tar header (and not a USTAR
341279377Simp *	header). We have to be on the lookout for those pesky blocks of	all
342279377Simp *	zero's.
343279377Simp * Return:
344279377Simp *	0 if a tar header, -1 otherwise
345279377Simp */
346279377Simp
347279377Simp#if __STDC__
348279377Simpint
349279377Simptar_id(register char *blk, int size)
350279377Simp#else
351279377Simpint
352279377Simptar_id(blk, size)
353279377Simp	register char *blk;
354279377Simp	int size;
355279377Simp#endif
356279377Simp{
357279377Simp	register HD_TAR *hd;
358279377Simp	register HD_USTAR *uhd;
359279377Simp
360279377Simp	if (size < BLKMULT)
361279377Simp		return(-1);
362279377Simp	hd = (HD_TAR *)blk;
363279377Simp	uhd = (HD_USTAR *)blk;
364279377Simp
365279377Simp	/*
366279377Simp	 * check for block of zero's first, a simple and fast test, then make
367279377Simp	 * sure this is not a ustar header by looking for the ustar magic
368279377Simp	 * cookie. We should use TMAGLEN, but some USTAR archive programs are
369279377Simp	 * wrong and create archives missing the \0. Last we check the
370279377Simp	 * checksum. If this is ok we have to assume it is a valid header.
371279377Simp	 */
372279377Simp	if (hd->name[0] == '\0')
373279377Simp		return(-1);
374279377Simp	if (strncmp(uhd->magic, TMAGIC, TMAGLEN - 1) == 0)
375279377Simp		return(-1);
376279377Simp	if (asc_ul(hd->chksum,sizeof(hd->chksum),OCT) != tar_chksm(blk,BLKMULT))
377279377Simp		return(-1);
378279377Simp	return(0);
379279377Simp}
380279377Simp
381279377Simp/*
382279377Simp * tar_opt()
383279377Simp *	handle tar format specific -o options
384279377Simp * Return:
385279377Simp *	0 if ok -1 otherwise
386279377Simp */
387279377Simp
388279377Simp#if __STDC__
389279377Simpint
390279377Simptar_opt(void)
391279377Simp#else
392279377Simpint
393279377Simptar_opt()
394279377Simp#endif
395279377Simp{
396279377Simp	OPLIST *opt;
397279377Simp
398279377Simp	while ((opt = opt_next()) != NULL) {
399279377Simp		if (strcmp(opt->name, TAR_OPTION) ||
400279377Simp		    strcmp(opt->value, TAR_NODIR)) {
401279377Simp			warn(1, "Unknown tar format -o option/value pair %s=%s",
402279377Simp			    opt->name, opt->value);
403279377Simp			warn(1,"%s=%s is the only supported tar format option",
404279377Simp			    TAR_OPTION, TAR_NODIR);
405279377Simp			return(-1);
406279377Simp		}
407279377Simp
408279377Simp		/*
409279377Simp		 * we only support one option, and only when writing
410279377Simp		 */
411279377Simp		if ((act != APPND) && (act != ARCHIVE)) {
412279377Simp			warn(1, "%s=%s is only supported when writing.",
413279377Simp			    opt->name, opt->value);
414279377Simp			return(-1);
415279377Simp		}
416279377Simp		tar_nodir = 1;
417279377Simp	}
418279377Simp	return(0);
419279377Simp}
420279377Simp
421279377Simp
422279377Simp/*
423279377Simp * tar_rd()
424279377Simp *	extract the values out of block already determined to be a tar header.
425279377Simp *	store the values in the ARCHD parameter.
426279377Simp * Return:
427279377Simp *	0
428279377Simp */
429279377Simp
430279377Simp#if __STDC__
431279377Simpint
432279377Simptar_rd(register ARCHD *arcn, register char *buf)
433279377Simp#else
434279377Simpint
435279377Simptar_rd(arcn, buf)
436279377Simp	register ARCHD *arcn;
437279377Simp	register char *buf;
438279377Simp#endif
439279377Simp{
440279377Simp	register HD_TAR *hd;
441279377Simp	register char *pt;
442279377Simp
443279377Simp	/*
444279377Simp	 * we only get proper sized buffers passed to us
445279377Simp	 */
446279377Simp	if (tar_id(buf, BLKMULT) < 0)
447279377Simp		return(-1);
448279377Simp	arcn->org_name = arcn->name;
449279377Simp	arcn->sb.st_nlink = 1;
450279377Simp	arcn->pat = NULL;
451279377Simp
452279377Simp	/*
453279377Simp	 * copy out the name and values in the stat buffer
454279377Simp	 */
455279377Simp	hd = (HD_TAR *)buf;
456279377Simp	arcn->nlen = l_strncpy(arcn->name, hd->name, sizeof(hd->name));
457279377Simp	arcn->name[arcn->nlen] = '\0';
458279377Simp	arcn->sb.st_mode = (mode_t)(asc_ul(hd->mode,sizeof(hd->mode),OCT) &
459279377Simp	    0xfff);
460279377Simp	arcn->sb.st_uid = (uid_t)asc_ul(hd->uid, sizeof(hd->uid), OCT);
461279377Simp	arcn->sb.st_gid = (gid_t)asc_ul(hd->gid, sizeof(hd->gid), OCT);
462279377Simp	arcn->sb.st_size = (size_t)asc_ul(hd->size, sizeof(hd->size), OCT);
463279377Simp	arcn->sb.st_mtime = (time_t)asc_ul(hd->mtime, sizeof(hd->mtime), OCT);
464279377Simp	arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
465279377Simp
466279377Simp	/*
467279377Simp	 * have to look at the last character, it may be a '/' and that is used
468279377Simp	 * to encode this as a directory
469279377Simp	 */
470279377Simp	pt = &(arcn->name[arcn->nlen - 1]);
471279377Simp	arcn->pad = 0;
472279377Simp	arcn->skip = 0;
473279377Simp	switch(hd->linkflag) {
474279377Simp	case SYMTYPE:
475279377Simp		/*
476279377Simp		 * symbolic link, need to get the link name and set the type in
477279377Simp		 * the st_mode so -v printing will look correct.
478279377Simp		 */
479279377Simp		arcn->type = PAX_SLK;
480279377Simp		arcn->ln_nlen = l_strncpy(arcn->ln_name, hd->linkname,
481279377Simp			sizeof(hd->linkname));
482279377Simp		arcn->ln_name[arcn->ln_nlen] = '\0';
483279377Simp		arcn->sb.st_mode |= S_IFLNK;
484279377Simp		break;
485279377Simp	case LNKTYPE:
486279377Simp		/*
487279377Simp		 * hard link, need to get the link name, set the type in the
488279377Simp		 * st_mode and st_nlink so -v printing will look better.
489279377Simp		 */
490279377Simp		arcn->type = PAX_HLK;
491279377Simp		arcn->sb.st_nlink = 2;
492279377Simp		arcn->ln_nlen = l_strncpy(arcn->ln_name, hd->linkname,
493279377Simp			sizeof(hd->linkname));
494279377Simp		arcn->ln_name[arcn->ln_nlen] = '\0';
495279377Simp
496279377Simp		/*
497279377Simp		 * no idea of what type this thing really points at, but
498279377Simp		 * we set something for printing only.
499279377Simp		 */
500279377Simp		arcn->sb.st_mode |= S_IFREG;
501279377Simp		break;
502279377Simp	case AREGTYPE:
503279377Simp	case REGTYPE:
504279377Simp	default:
505279377Simp		/*
506279377Simp		 * If we have a trailing / this is a directory and NOT a file.
507279377Simp		 */
508279377Simp		arcn->ln_name[0] = '\0';
509279377Simp		arcn->ln_nlen = 0;
510279377Simp		if (*pt == '/') {
511279377Simp			/*
512279377Simp			 * it is a directory, set the mode for -v printing
513279377Simp			 */
514279377Simp			arcn->type = PAX_DIR;
515279377Simp			arcn->sb.st_mode |= S_IFDIR;
516279377Simp			arcn->sb.st_nlink = 2;
517279377Simp		} else {
518279377Simp			/*
519279377Simp			 * have a file that will be followed by data. Set the
520279377Simp			 * skip value to the size field and caluculate the size
521279377Simp			 * of the padding.
522279377Simp			 */
523279377Simp			arcn->type = PAX_REG;
524279377Simp			arcn->sb.st_mode |= S_IFREG;
525279377Simp			arcn->pad = TAR_PAD(arcn->sb.st_size);
526279377Simp			arcn->skip = arcn->sb.st_size;
527279377Simp		}
528279377Simp		break;
529279377Simp	}
530279377Simp
531279377Simp	/*
532279377Simp	 * strip off any trailing slash.
533279377Simp	 */
534279377Simp	if (*pt == '/') {
535279377Simp		*pt = '\0';
536279377Simp		--arcn->nlen;
537279377Simp	}
538279377Simp	return(0);
539279377Simp}
540279377Simp
541279377Simp/*
542279377Simp * tar_wr()
543279377Simp *	write a tar header for the file specified in the ARCHD to the archive.
544279377Simp *	Have to check for file types that cannot be stored and file names that
545279377Simp *	are too long. Be careful of the term (last arg) to ul_oct, each field
546279377Simp *	of tar has it own spec for the termination character(s).
547279377Simp *	ASSUMED: space after header in header block is zero filled
548279377Simp * Return:
549279377Simp *	0 if file has data to be written after the header, 1 if file has NO
550279377Simp *	data to write after the header, -1 if archive write failed
551279377Simp */
552279377Simp
553279377Simp#if __STDC__
554279377Simpint
555279377Simptar_wr(register ARCHD *arcn)
556279377Simp#else
557279377Simpint
558279377Simptar_wr(arcn)
559279377Simp	register ARCHD *arcn;
560279377Simp#endif
561279377Simp{
562279377Simp	register HD_TAR *hd;
563279377Simp	int len;
564279377Simp	char hdblk[sizeof(HD_TAR)];
565279377Simp
566279377Simp	/*
567279377Simp	 * check for those file system types which tar cannot store
568279377Simp	 */
569279377Simp	switch(arcn->type) {
570279377Simp	case PAX_DIR:
571279377Simp		/*
572279377Simp		 * user asked that dirs not be written to the archive
573279377Simp		 */
574279377Simp		if (tar_nodir)
575279377Simp			return(1);
576279377Simp		break;
577279377Simp	case PAX_CHR:
578279377Simp		warn(1, "Tar cannot archive a character device %s",
579279377Simp		    arcn->org_name);
580279377Simp		return(1);
581279377Simp	case PAX_BLK:
582279377Simp		warn(1, "Tar cannot archive a block device %s", arcn->org_name);
583279377Simp		return(1);
584279377Simp	case PAX_SCK:
585279377Simp		warn(1, "Tar cannot archive a socket %s", arcn->org_name);
586279377Simp		return(1);
587279377Simp	case PAX_FIF:
588279377Simp		warn(1, "Tar cannot archive a fifo %s", arcn->org_name);
589279377Simp		return(1);
590279377Simp	case PAX_SLK:
591279377Simp	case PAX_HLK:
592279377Simp	case PAX_HRG:
593279377Simp		if (arcn->ln_nlen > sizeof(hd->linkname)) {
594279377Simp			warn(1,"Link name too long for tar %s", arcn->ln_name);
595279377Simp			return(1);
596279377Simp		}
597279377Simp		break;
598279377Simp	case PAX_REG:
599279377Simp	case PAX_CTG:
600279377Simp	default:
601279377Simp		break;
602279377Simp	}
603279377Simp
604279377Simp	/*
605279377Simp	 * check file name len, remember extra char for dirs (the / at the end)
606279377Simp	 */
607279377Simp	len = arcn->nlen;
608279377Simp	if (arcn->type == PAX_DIR)
609279377Simp		++len;
610279377Simp	if (len > sizeof(hd->name)) {
611279377Simp		warn(1, "File name too long for tar %s", arcn->name);
612279377Simp		return(1);
613279377Simp	}
614279377Simp
615279377Simp	/*
616279377Simp	 * copy the data out of the ARCHD into the tar header based on the type
617279377Simp	 * of the file. Remember many tar readers want the unused fields to be
618279377Simp	 * padded with zero. We set the linkflag field (type), the linkname
619279377Simp	 * (or zero if not used),the size, and set the padding (if any) to be
620279377Simp	 * added after the file data (0 for all other types, as they only have
621279377Simp	 * a header)
622279377Simp	 */
623279377Simp	hd = (HD_TAR *)hdblk;
624279377Simp	zf_strncpy(hd->name, arcn->name, sizeof(hd->name));
625279377Simp	arcn->pad = 0;
626279377Simp
627279377Simp	if (arcn->type == PAX_DIR) {
628279377Simp		/*
629279377Simp		 * directories are the same as files, except have a filename
630279377Simp		 * that ends with a /, we add the slash here. No data follows,
631279377Simp		 * dirs, so no pad.
632279377Simp		 */
633279377Simp		hd->linkflag = AREGTYPE;
634279377Simp		bzero(hd->linkname, sizeof(hd->linkname));
635279377Simp		hd->name[len-1] = '/';
636279377Simp		if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1))
637279377Simp			goto out;
638279377Simp	} else if (arcn->type == PAX_SLK) {
639279377Simp		/*
640279377Simp		 * no data follows this file, so no pad
641279377Simp		 */
642279377Simp		hd->linkflag = SYMTYPE;
643279377Simp		zf_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname));
644279377Simp		if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1))
645279377Simp			goto out;
646279377Simp	} else if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG)) {
647279377Simp		/*
648279377Simp		 * no data follows this file, so no pad
649279377Simp		 */
650279377Simp		hd->linkflag = LNKTYPE;
651279377Simp		zf_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname));
652279377Simp		if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1))
653279377Simp			goto out;
654279377Simp	} else {
655279377Simp		/*
656279377Simp		 * data follows this file, so set the pad
657279377Simp		 */
658279377Simp		hd->linkflag = AREGTYPE;
659279377Simp		bzero(hd->linkname, sizeof(hd->linkname));
660279377Simp#		ifdef NET2_STAT
661279377Simp		if (ul_oct((u_long)arcn->sb.st_size, hd->size,
662279377Simp		    sizeof(hd->size), 1)) {
663279377Simp#		else
664279377Simp		if (uqd_oct((u_quad_t)arcn->sb.st_size, hd->size,
665279377Simp		    sizeof(hd->size), 1)) {
666279377Simp#		endif
667279377Simp			warn(1,"File is too large for tar %s", arcn->org_name);
668279377Simp			return(1);
669279377Simp		}
670279377Simp		arcn->pad = TAR_PAD(arcn->sb.st_size);
671279377Simp	}
672279377Simp
673279377Simp	/*
674279377Simp	 * copy those fields that are independent of the type
675279377Simp	 */
676279377Simp	if (ul_oct((u_long)arcn->sb.st_mode, hd->mode, sizeof(hd->mode), 0) ||
677279377Simp	    ul_oct((u_long)arcn->sb.st_uid, hd->uid, sizeof(hd->uid), 0) ||
678279377Simp	    ul_oct((u_long)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), 0) ||
679279377Simp	    ul_oct((u_long)arcn->sb.st_mtime, hd->mtime, sizeof(hd->mtime), 1))
680279377Simp		goto out;
681
682	/*
683	 * calculate and add the checksum, then write the header. A return of
684	 * 0 tells the caller to now write the file data, 1 says no data needs
685	 * to be written
686	 */
687	if (ul_oct(tar_chksm(hdblk, sizeof(HD_TAR)), hd->chksum,
688	    sizeof(hd->chksum), 2))
689		goto out;
690	if (wr_rdbuf(hdblk, sizeof(HD_TAR)) < 0)
691		return(-1);
692	if (wr_skip((off_t)(BLKMULT - sizeof(HD_TAR))) < 0)
693		return(-1);
694	if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG))
695		return(0);
696	return(1);
697
698    out:
699	/*
700	 * header field is out of range
701	 */
702	warn(1, "Tar header field is too small for %s", arcn->org_name);
703	return(1);
704}
705
706/*
707 * Routines for POSIX ustar
708 */
709
710/*
711 * ustar_strd()
712 *	initialization for ustar read
713 * Return:
714 *	0 if ok, -1 otherwise
715 */
716
717#if __STDC__
718int
719ustar_strd(void)
720#else
721int
722ustar_strd()
723#endif
724{
725	if ((usrtb_start() < 0) || (grptb_start() < 0))
726		return(-1);
727	return(0);
728}
729
730/*
731 * ustar_stwr()
732 *	initialization for ustar write
733 * Return:
734 *	0 if ok, -1 otherwise
735 */
736
737#if __STDC__
738int
739ustar_stwr(void)
740#else
741int
742ustar_stwr()
743#endif
744{
745	if ((uidtb_start() < 0) || (gidtb_start() < 0))
746		return(-1);
747	return(0);
748}
749
750/*
751 * ustar_id()
752 *	determine if a block given to us is a valid ustar header. We have to
753 *	be on the lookout for those pesky blocks of all zero's
754 * Return:
755 *	0 if a ustar header, -1 otherwise
756 */
757
758#if __STDC__
759int
760ustar_id(char *blk, int size)
761#else
762int
763ustar_id(blk, size)
764	char *blk;
765	int size;
766#endif
767{
768	register HD_USTAR *hd;
769
770	if (size < BLKMULT)
771		return(-1);
772	hd = (HD_USTAR *)blk;
773
774	/*
775	 * check for block of zero's first, a simple and fast test then check
776	 * ustar magic cookie. We should use TMAGLEN, but some USTAR archive
777	 * programs are fouled up and create archives missing the \0. Last we
778	 * check the checksum. If ok we have to assume it is a valid header.
779	 */
780	if (hd->name[0] == '\0')
781		return(-1);
782	if (strncmp(hd->magic, TMAGIC, TMAGLEN - 1) != 0)
783		return(-1);
784	if (asc_ul(hd->chksum,sizeof(hd->chksum),OCT) != tar_chksm(blk,BLKMULT))
785		return(-1);
786	return(0);
787}
788
789/*
790 * ustar_rd()
791 *	extract the values out of block already determined to be a ustar header.
792 *	store the values in the ARCHD parameter.
793 * Return:
794 *	0
795 */
796
797#if __STDC__
798int
799ustar_rd(register ARCHD *arcn, register char *buf)
800#else
801int
802ustar_rd(arcn, buf)
803	register ARCHD *arcn;
804	register char *buf;
805#endif
806{
807	register HD_USTAR *hd;
808	register char *dest;
809	register int cnt = 0;
810	dev_t devmajor;
811	dev_t devminor;
812
813	/*
814	 * we only get proper sized buffers
815	 */
816	if (ustar_id(buf, BLKMULT) < 0)
817		return(-1);
818	arcn->org_name = arcn->name;
819	arcn->sb.st_nlink = 1;
820	arcn->pat = NULL;
821	hd = (HD_USTAR *)buf;
822
823	/*
824	 * see if the filename is split into two parts. if, so joint the parts.
825	 * we copy the prefix first and add a / between the prefix and name.
826	 */
827	dest = arcn->name;
828	if (*(hd->prefix) != '\0') {
829		cnt = l_strncpy(arcn->name, hd->prefix, sizeof(hd->prefix));
830		dest = arcn->name + arcn->nlen;
831		*dest++ = '/';
832	}
833	arcn->nlen = l_strncpy(dest, hd->name, sizeof(hd->name));
834	arcn->nlen += cnt;
835	arcn->name[arcn->nlen] = '\0';
836
837	/*
838	 * follow the spec to the letter. we should only have mode bits, strip
839	 * off all other crud we may be passed.
840	 */
841	arcn->sb.st_mode = (mode_t)(asc_ul(hd->mode, sizeof(hd->mode), OCT) &
842	    0xfff);
843	arcn->sb.st_size = (size_t)asc_ul(hd->size, sizeof(hd->size), OCT);
844	arcn->sb.st_mtime = (time_t)asc_ul(hd->mtime, sizeof(hd->mtime), OCT);
845	arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
846
847	/*
848	 * If we can find the ascii names for gname and uname in the password
849	 * and group files we will use the uid's and gid they bind. Otherwise
850	 * we use the uid and gid values stored in the header. (This is what
851	 * the posix spec wants).
852	 */
853	hd->gname[sizeof(hd->gname) - 1] = '\0';
854	if (gid_name(hd->gname, &(arcn->sb.st_gid)) < 0)
855		arcn->sb.st_gid = (gid_t)asc_ul(hd->gid, sizeof(hd->gid), OCT);
856	hd->uname[sizeof(hd->uname) - 1] = '\0';
857	if (uid_name(hd->uname, &(arcn->sb.st_uid)) < 0)
858		arcn->sb.st_uid = (uid_t)asc_ul(hd->uid, sizeof(hd->uid), OCT);
859
860	/*
861	 * set the defaults, these may be changed depending on the file type
862	 */
863	arcn->ln_name[0] = '\0';
864	arcn->ln_nlen = 0;
865	arcn->pad = 0;
866	arcn->skip = 0;
867	arcn->sb.st_rdev = (dev_t)0;
868
869	/*
870	 * set the mode and PAX type according to the typeflag in the header
871	 */
872	switch(hd->typeflag) {
873	case FIFOTYPE:
874		arcn->type = PAX_FIF;
875		arcn->sb.st_mode |= S_IFIFO;
876		break;
877	case DIRTYPE:
878		arcn->type = PAX_DIR;
879		arcn->sb.st_mode |= S_IFDIR;
880		arcn->sb.st_nlink = 2;
881
882		/*
883		 * Some programs that create ustar archives append a '/'
884		 * to the pathname for directories. This clearly violates
885		 * ustar specs, but we will silently strip it off anyway.
886		 */
887		if (arcn->name[arcn->nlen - 1] == '/')
888			arcn->name[--arcn->nlen] = '\0';
889		break;
890	case BLKTYPE:
891	case CHRTYPE:
892		/*
893		 * this type requires the rdev field to be set.
894		 */
895		if (hd->typeflag == BLKTYPE) {
896			arcn->type = PAX_BLK;
897			arcn->sb.st_mode |= S_IFBLK;
898		} else {
899			arcn->type = PAX_CHR;
900			arcn->sb.st_mode |= S_IFCHR;
901		}
902		devmajor = (dev_t)asc_ul(hd->devmajor,sizeof(hd->devmajor),OCT);
903		devminor = (dev_t)asc_ul(hd->devminor,sizeof(hd->devminor),OCT);
904		arcn->sb.st_rdev = TODEV(devmajor, devminor);
905		break;
906	case SYMTYPE:
907	case LNKTYPE:
908		if (hd->typeflag == SYMTYPE) {
909			arcn->type = PAX_SLK;
910			arcn->sb.st_mode |= S_IFLNK;
911		} else {
912			arcn->type = PAX_HLK;
913			/*
914			 * so printing looks better
915			 */
916			arcn->sb.st_mode |= S_IFREG;
917			arcn->sb.st_nlink = 2;
918		}
919		/*
920		 * copy the link name
921		 */
922		arcn->ln_nlen = l_strncpy(arcn->ln_name, hd->linkname,
923			sizeof(hd->linkname));
924		arcn->ln_name[arcn->ln_nlen] = '\0';
925		break;
926	case CONTTYPE:
927	case AREGTYPE:
928	case REGTYPE:
929	default:
930		/*
931		 * these types have file data that follows. Set the skip and
932		 * pad fields.
933		 */
934		arcn->type = PAX_REG;
935		arcn->pad = TAR_PAD(arcn->sb.st_size);
936		arcn->skip = arcn->sb.st_size;
937		arcn->sb.st_mode |= S_IFREG;
938		break;
939	}
940	return(0);
941}
942
943/*
944 * ustar_wr()
945 *	write a ustar header for the file specified in the ARCHD to the archive
946 *	Have to check for file types that cannot be stored and file names that
947 *	are too long. Be careful of the term (last arg) to ul_oct, we only use
948 *	'\0' for the termination character (this is different than picky tar)
949 *	ASSUMED: space after header in header block is zero filled
950 * Return:
951 *	0 if file has data to be written after the header, 1 if file has NO
952 *	data to write after the header, -1 if archive write failed
953 */
954
955#if __STDC__
956int
957ustar_wr(register ARCHD *arcn)
958#else
959int
960ustar_wr(arcn)
961	register ARCHD *arcn;
962#endif
963{
964	register HD_USTAR *hd;
965	register char *pt;
966	char hdblk[sizeof(HD_USTAR)];
967
968	/*
969	 * check for those file system types ustar cannot store
970	 */
971	if (arcn->type == PAX_SCK) {
972		warn(1, "Ustar cannot archive a socket %s", arcn->org_name);
973		return(1);
974	}
975
976	/*
977	 * check the length of the linkname
978	 */
979	if (((arcn->type == PAX_SLK) || (arcn->type == PAX_HLK) ||
980	    (arcn->type == PAX_HRG)) && (arcn->ln_nlen > sizeof(hd->linkname))){
981		warn(1, "Link name too long for ustar %s", arcn->ln_name);
982		return(1);
983	}
984
985	/*
986	 * split the path name into prefix and name fields (if needed). if
987	 * pt != arcn->name, the name has to be split
988	 */
989	if ((pt = name_split(arcn->name, arcn->nlen)) == NULL) {
990		warn(1, "File name too long for ustar %s", arcn->name);
991		return(1);
992	}
993	hd = (HD_USTAR *)hdblk;
994	arcn->pad = 0L;
995
996	/*
997	 * split the name, or zero out the prefix
998	 */
999	if (pt != arcn->name) {
1000		/*
1001		 * name was split, pt points at the / where the split is to
1002		 * occur, we remove the / and copy the first part to the prefix
1003		 */
1004		*pt = '\0';
1005		zf_strncpy(hd->prefix, arcn->name, sizeof(hd->prefix));
1006		*pt++ = '/';
1007	} else
1008		bzero(hd->prefix, sizeof(hd->prefix));
1009
1010	/*
1011	 * copy the name part. this may be the whole path or the part after
1012	 * the prefix
1013	 */
1014	zf_strncpy(hd->name, pt, sizeof(hd->name));
1015
1016	/*
1017	 * set the fields in the header that are type dependent
1018	 */
1019	switch(arcn->type) {
1020	case PAX_DIR:
1021		hd->typeflag = DIRTYPE;
1022		bzero(hd->linkname, sizeof(hd->linkname));
1023		bzero(hd->devmajor, sizeof(hd->devmajor));
1024		bzero(hd->devminor, sizeof(hd->devminor));
1025		if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3))
1026			goto out;
1027		break;
1028	case PAX_CHR:
1029	case PAX_BLK:
1030		if (arcn->type == PAX_CHR)
1031			hd->typeflag = CHRTYPE;
1032		else
1033			hd->typeflag = BLKTYPE;
1034		bzero(hd->linkname, sizeof(hd->linkname));
1035		if (ul_oct((u_long)MAJOR(arcn->sb.st_rdev), hd->devmajor,
1036		   sizeof(hd->devmajor), 3) ||
1037		   ul_oct((u_long)MINOR(arcn->sb.st_rdev), hd->devminor,
1038		   sizeof(hd->devminor), 3) ||
1039		   ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3))
1040			goto out;
1041		break;
1042	case PAX_FIF:
1043		hd->typeflag = FIFOTYPE;
1044		bzero(hd->linkname, sizeof(hd->linkname));
1045		bzero(hd->devmajor, sizeof(hd->devmajor));
1046		bzero(hd->devminor, sizeof(hd->devminor));
1047		if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3))
1048			goto out;
1049		break;
1050	case PAX_SLK:
1051	case PAX_HLK:
1052	case PAX_HRG:
1053		if (arcn->type == PAX_SLK)
1054			hd->typeflag = SYMTYPE;
1055		else
1056			hd->typeflag = LNKTYPE;
1057		zf_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname));
1058		bzero(hd->devmajor, sizeof(hd->devmajor));
1059		bzero(hd->devminor, sizeof(hd->devminor));
1060		if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3))
1061			goto out;
1062		break;
1063	case PAX_REG:
1064	case PAX_CTG:
1065	default:
1066		/*
1067		 * file data with this type, set the padding
1068		 */
1069		if (arcn->type == PAX_CTG)
1070			hd->typeflag = CONTTYPE;
1071		else
1072			hd->typeflag = REGTYPE;
1073		bzero(hd->linkname, sizeof(hd->linkname));
1074		bzero(hd->devmajor, sizeof(hd->devmajor));
1075		bzero(hd->devminor, sizeof(hd->devminor));
1076		arcn->pad = TAR_PAD(arcn->sb.st_size);
1077#		ifdef NET2_STAT
1078		if (ul_oct((u_long)arcn->sb.st_size, hd->size,
1079		    sizeof(hd->size), 3)) {
1080#		else
1081		if (uqd_oct((u_quad_t)arcn->sb.st_size, hd->size,
1082		    sizeof(hd->size), 3)) {
1083#		endif
1084			warn(1,"File is too long for ustar %s",arcn->org_name);
1085			return(1);
1086		}
1087		break;
1088	}
1089
1090	zf_strncpy(hd->magic, TMAGIC, TMAGLEN);
1091	zf_strncpy(hd->version, TVERSION, TVERSLEN);
1092
1093	/*
1094	 * set the remaining fields. Some versions want all 16 bits of mode
1095	 * we better humor them (they really do not meet spec though)....
1096	 */
1097	if (ul_oct((u_long)arcn->sb.st_mode, hd->mode, sizeof(hd->mode), 3) ||
1098	    ul_oct((u_long)arcn->sb.st_uid, hd->uid, sizeof(hd->uid), 3)  ||
1099	    ul_oct((u_long)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), 3) ||
1100	    ul_oct((u_long)arcn->sb.st_mtime,hd->mtime,sizeof(hd->mtime),3))
1101		goto out;
1102	zf_strncpy(hd->uname,name_uid(arcn->sb.st_uid, 0),sizeof(hd->uname));
1103	zf_strncpy(hd->gname,name_gid(arcn->sb.st_gid, 0),sizeof(hd->gname));
1104
1105	/*
1106	 * calculate and store the checksum write the header to the archive
1107	 * return 0 tells the caller to now write the file data, 1 says no data
1108	 * needs to be written
1109	 */
1110	if (ul_oct(tar_chksm(hdblk, sizeof(HD_USTAR)), hd->chksum,
1111	   sizeof(hd->chksum), 3))
1112		goto out;
1113	if (wr_rdbuf(hdblk, sizeof(HD_USTAR)) < 0)
1114		return(-1);
1115	if (wr_skip((off_t)(BLKMULT - sizeof(HD_USTAR))) < 0)
1116		return(-1);
1117	if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG))
1118		return(0);
1119	return(1);
1120
1121    out:
1122    	/*
1123	 * header field is out of range
1124	 */
1125	warn(1, "Ustar header field is too small for %s", arcn->org_name);
1126	return(1);
1127}
1128
1129/*
1130 * name_split()
1131 *	see if the name has to be split for storage in a ustar header. We try
1132 *	to fit the entire name in the name field without splitting if we can.
1133 *	The split point is always at a /
1134 * Return
1135 *	character pointer to split point (always the / that is to be removed
1136 *	if the split is not needed, the points is set to the start of the file
1137 *	name (it would violate the spec to split there). A NULL is returned if
1138 *	the file name is too long
1139 */
1140
1141#if __STDC__
1142static char *
1143name_split(register char *name, register int len)
1144#else
1145static char *
1146name_split(name, len)
1147	register char *name;
1148	register int len;
1149#endif
1150{
1151	register char *start;
1152
1153	/*
1154	 * check to see if the file name is small enough to fit in the name
1155	 * field. if so just return a pointer to the name.
1156	 */
1157	if (len <= TNMSZ)
1158		return(name);
1159	if (len > (TPFSZ + TNMSZ + 1))
1160		return(NULL);
1161
1162	/*
1163	 * we start looking at the biggest sized piece that fits in the name
1164	 * field. We walk foward looking for a slash to split at. The idea is
1165	 * to find the biggest piece to fit in the name field (or the smallest
1166	 * prefix we can find) (the -1 is correct the biggest piece would
1167	 * include the slash between the two parts that gets thrown away)
1168	 */
1169	start = name + len - TNMSZ - 1;
1170	while ((*start != '\0') && (*start != '/'))
1171		++start;
1172
1173	/*
1174	 * if we hit the end of the string, this name cannot be split, so we
1175	 * cannot store this file.
1176	 */
1177	if (*start == '\0')
1178		return(NULL);
1179	len = start - name;
1180
1181	/*
1182	 * NOTE: /str where the length of str == TNMSZ can not be stored under
1183	 * the p1003.1-1990 spec for ustar. We could force a prefix of / and
1184	 * the file would then expand on extract to //str. The len == 0 below
1185	 * makes this special case follow the spec to the letter.
1186	 */
1187	if ((len > TPFSZ) || (len == 0))
1188		return(NULL);
1189
1190	/*
1191	 * ok have a split point, return it to the caller
1192	 */
1193	return(start);
1194}
1195