English Language flag
// Log In
// CVSweb
Project: FreeWRT
// Summary // Activity // Search // Tracker // Lists // News // SCM // Wiki

SCM Repository

ViewVC logotype

Contents of /branches/freewrt_1_0/tools/paxmirabilis/src/tar.c

Parent Directory Parent Directory | Revision Log Revision Log


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

root@freewrt.org:443
ViewVC Help
Powered by ViewVC 1.1.20