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