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