source: freewrt/tools/paxmirabilis/src/tar.c@ 9b4fa61

freewrt_2_0
Last change on this file since 9b4fa61 was 9b4fa61, checked in by Waldemar Brodkorb <wbx@…>, 4 months ago

include missing sysmacros.h

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