source: freewrt/tools/paxmirabilis/src/tar.c@ bceb42b

freewrt_1_0 freewrt_2_0
Last change on this file since bceb42b was bceb42b, checked in by Thorsten Glaser <tg@…>, 19 years ago

wbx@ asked me a few seconds too late to use an src/ subdirectory

git-svn-id: svn://www.freewrt.org/trunk/freewrt@204 afb5a338-a214-0410-bd46-81f09a774fd1

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