]> Dogcows Code - chaz/tar/blob - src/create.c
(write_gnu_long_link): Use oldgnu magic with @LongLink blocks.
[chaz/tar] / src / create.c
1 /* Create a tar archive.
2
3 Copyright (C) 1985, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
4 2003 Free Software Foundation, Inc.
5
6 Written by John Gilmore, on 1985-08-25.
7
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any later
11 version.
12
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
16 Public License for more details.
17
18 You should have received a copy of the GNU General Public License along
19 with this program; if not, write to the Free Software Foundation, Inc.,
20 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
21
22 #include "system.h"
23
24 #if HAVE_UTIME_H
25 # include <utime.h>
26 #else
27 struct utimbuf
28 {
29 long actime;
30 long modtime;
31 };
32 #endif
33
34 #include <quotearg.h>
35
36 #include "common.h"
37 #include <hash.h>
38
39 struct link
40 {
41 dev_t dev;
42 ino_t ino;
43 size_t nlink;
44 char name[1];
45 };
46 \f
47 /* The maximum uintmax_t value that can be represented with DIGITS digits,
48 assuming that each digit is BITS_PER_DIGIT wide. */
49 #define MAX_VAL_WITH_DIGITS(digits, bits_per_digit) \
50 ((digits) * (bits_per_digit) < sizeof (uintmax_t) * CHAR_BIT \
51 ? ((uintmax_t) 1 << ((digits) * (bits_per_digit))) - 1 \
52 : (uintmax_t) -1)
53
54 /* Convert VALUE to an octal representation suitable for tar headers.
55 Output to buffer WHERE with size SIZE.
56 The result is undefined if SIZE is 0 or if VALUE is too large to fit. */
57
58 static void
59 to_octal (uintmax_t value, char *where, size_t size)
60 {
61 uintmax_t v = value;
62 size_t i = size;
63
64 do
65 {
66 where[--i] = '0' + (v & ((1 << LG_8) - 1));
67 v >>= LG_8;
68 }
69 while (i);
70 }
71
72 /* Convert NEGATIVE VALUE to a base-256 representation suitable for
73 tar headers. NEGATIVE is 1 if VALUE was negative before being cast
74 to uintmax_t, 0 otherwise. Output to buffer WHERE with size SIZE.
75 The result is undefined if SIZE is 0 or if VALUE is too large to
76 fit. */
77
78 static void
79 to_base256 (int negative, uintmax_t value, char *where, size_t size)
80 {
81 uintmax_t v = value;
82 uintmax_t propagated_sign_bits =
83 ((uintmax_t) - negative << (CHAR_BIT * sizeof v - LG_256));
84 size_t i = size;
85
86 do
87 {
88 where[--i] = v & ((1 << LG_256) - 1);
89 v = propagated_sign_bits | (v >> LG_256);
90 }
91 while (i);
92 }
93
94 /* Convert NEGATIVE VALUE (which was originally of size VALSIZE) to
95 external form, using SUBSTITUTE (...) if VALUE won't fit. Output
96 to buffer WHERE with size SIZE. NEGATIVE is 1 iff VALUE was
97 negative before being cast to uintmax_t; its original bitpattern
98 can be deduced from VALSIZE, its original size before casting.
99 TYPE is the kind of value being output (useful for diagnostics).
100 Prefer the POSIX format of SIZE - 1 octal digits (with leading zero
101 digits), followed by '\0'. If this won't work, and if GNU or
102 OLDGNU format is allowed, use '\200' followed by base-256, or (if
103 NEGATIVE is nonzero) '\377' followed by two's complement base-256.
104 If neither format works, use SUBSTITUTE (...) instead. Pass to
105 SUBSTITUTE the address of an 0-or-1 flag recording whether the
106 substitute value is negative. */
107
108 static void
109 to_chars (int negative, uintmax_t value, size_t valsize,
110 uintmax_t (*substitute) (int *),
111 char *where, size_t size, const char *type)
112 {
113 int base256_allowed = (archive_format == GNU_FORMAT
114 || archive_format == OLDGNU_FORMAT);
115
116 /* Generate the POSIX octal representation if the number fits. */
117 if (! negative && value <= MAX_VAL_WITH_DIGITS (size - 1, LG_8))
118 {
119 where[size - 1] = '\0';
120 to_octal (value, where, size - 1);
121 }
122
123 /* Otherwise, generate the base-256 representation if we are
124 generating an old or new GNU format and if the number fits. */
125 else if (((negative ? -1 - value : value)
126 <= MAX_VAL_WITH_DIGITS (size - 1, LG_256))
127 && base256_allowed)
128 {
129 where[0] = negative ? -1 : 1 << (LG_256 - 1);
130 to_base256 (negative, value, where + 1, size - 1);
131 }
132
133 /* Otherwise, if the number is negative, and if it would not cause
134 ambiguity on this host by confusing positive with negative
135 values, then generate the POSIX octal representation of the value
136 modulo 2**(field bits). The resulting tar file is
137 machine-dependent, since it depends on the host word size. Yuck!
138 But this is the traditional behavior. */
139 else if (negative && valsize * CHAR_BIT <= (size - 1) * LG_8)
140 {
141 static int warned_once;
142 if (! warned_once)
143 {
144 warned_once = 1;
145 WARN ((0, 0, _("Generating negative octal headers")));
146 }
147 where[size - 1] = '\0';
148 to_octal (value & MAX_VAL_WITH_DIGITS (valsize * CHAR_BIT, 1),
149 where, size - 1);
150 }
151
152 /* Otherwise, output a substitute value if possible (with a
153 warning), and an error message if not. */
154 else
155 {
156 uintmax_t maxval = (base256_allowed
157 ? MAX_VAL_WITH_DIGITS (size - 1, LG_256)
158 : MAX_VAL_WITH_DIGITS (size - 1, LG_8));
159 char valbuf[UINTMAX_STRSIZE_BOUND + 1];
160 char maxbuf[UINTMAX_STRSIZE_BOUND];
161 char minbuf[UINTMAX_STRSIZE_BOUND + 1];
162 char const *minval_string;
163 char const *maxval_string = STRINGIFY_BIGINT (maxval, maxbuf);
164 char const *value_string;
165
166 if (base256_allowed)
167 {
168 uintmax_t m = maxval + 1 ? maxval + 1 : maxval / 2 + 1;
169 char *p = STRINGIFY_BIGINT (m, minbuf + 1);
170 *--p = '-';
171 minval_string = p;
172 }
173 else
174 minval_string = "0";
175
176 if (negative)
177 {
178 char *p = STRINGIFY_BIGINT (- value, valbuf + 1);
179 *--p = '-';
180 value_string = p;
181 }
182 else
183 value_string = STRINGIFY_BIGINT (value, valbuf);
184
185 if (substitute)
186 {
187 int negsub;
188 uintmax_t sub = substitute (&negsub) & maxval;
189 uintmax_t s = (negsub &= archive_format == GNU_FORMAT) ? - sub : sub;
190 char subbuf[UINTMAX_STRSIZE_BOUND + 1];
191 char *sub_string = STRINGIFY_BIGINT (s, subbuf + 1);
192 if (negsub)
193 *--sub_string = '-';
194 WARN ((0, 0, _("value %s out of %s range %s..%s; substituting %s"),
195 value_string, type, minval_string, maxval_string,
196 sub_string));
197 to_chars (negsub, s, valsize, 0, where, size, type);
198 }
199 else
200 ERROR ((0, 0, _("value %s out of %s range %s..%s"),
201 value_string, type, minval_string, maxval_string));
202 }
203 }
204
205 static uintmax_t
206 gid_substitute (int *negative)
207 {
208 gid_t r;
209 #ifdef GID_NOBODY
210 r = GID_NOBODY;
211 #else
212 static gid_t gid_nobody;
213 if (!gid_nobody && !gname_to_gid ("nobody", &gid_nobody))
214 gid_nobody = -2;
215 r = gid_nobody;
216 #endif
217 *negative = r < 0;
218 return r;
219 }
220
221 void
222 gid_to_chars (gid_t v, char *p, size_t s)
223 {
224 to_chars (v < 0, (uintmax_t) v, sizeof v, gid_substitute, p, s, "gid_t");
225 }
226
227 void
228 major_to_chars (major_t v, char *p, size_t s)
229 {
230 to_chars (v < 0, (uintmax_t) v, sizeof v, 0, p, s, "major_t");
231 }
232
233 void
234 minor_to_chars (minor_t v, char *p, size_t s)
235 {
236 to_chars (v < 0, (uintmax_t) v, sizeof v, 0, p, s, "minor_t");
237 }
238
239 void
240 mode_to_chars (mode_t v, char *p, size_t s)
241 {
242 /* In the common case where the internal and external mode bits are the same,
243 and we are not using POSIX or GNU format,
244 propagate all unknown bits to the external mode.
245 This matches historical practice.
246 Otherwise, just copy the bits we know about. */
247 int negative;
248 uintmax_t u;
249 if (S_ISUID == TSUID && S_ISGID == TSGID && S_ISVTX == TSVTX
250 && S_IRUSR == TUREAD && S_IWUSR == TUWRITE && S_IXUSR == TUEXEC
251 && S_IRGRP == TGREAD && S_IWGRP == TGWRITE && S_IXGRP == TGEXEC
252 && S_IROTH == TOREAD && S_IWOTH == TOWRITE && S_IXOTH == TOEXEC
253 && archive_format != POSIX_FORMAT
254 && archive_format != USTAR_FORMAT
255 && archive_format != GNU_FORMAT)
256 {
257 negative = v < 0;
258 u = v;
259 }
260 else
261 {
262 negative = 0;
263 u = ((v & S_ISUID ? TSUID : 0)
264 | (v & S_ISGID ? TSGID : 0)
265 | (v & S_ISVTX ? TSVTX : 0)
266 | (v & S_IRUSR ? TUREAD : 0)
267 | (v & S_IWUSR ? TUWRITE : 0)
268 | (v & S_IXUSR ? TUEXEC : 0)
269 | (v & S_IRGRP ? TGREAD : 0)
270 | (v & S_IWGRP ? TGWRITE : 0)
271 | (v & S_IXGRP ? TGEXEC : 0)
272 | (v & S_IROTH ? TOREAD : 0)
273 | (v & S_IWOTH ? TOWRITE : 0)
274 | (v & S_IXOTH ? TOEXEC : 0));
275 }
276 to_chars (negative, u, sizeof v, 0, p, s, "mode_t");
277 }
278
279 void
280 off_to_chars (off_t v, char *p, size_t s)
281 {
282 to_chars (v < 0, (uintmax_t) v, sizeof v, 0, p, s, "off_t");
283 }
284
285 void
286 size_to_chars (size_t v, char *p, size_t s)
287 {
288 to_chars (0, (uintmax_t) v, sizeof v, 0, p, s, "size_t");
289 }
290
291 void
292 time_to_chars (time_t v, char *p, size_t s)
293 {
294 to_chars (v < 0, (uintmax_t) v, sizeof v, 0, p, s, "time_t");
295 }
296
297 static uintmax_t
298 uid_substitute (int *negative)
299 {
300 uid_t r;
301 #ifdef UID_NOBODY
302 r = UID_NOBODY;
303 #else
304 static uid_t uid_nobody;
305 if (!uid_nobody && !uname_to_uid ("nobody", &uid_nobody))
306 uid_nobody = -2;
307 r = uid_nobody;
308 #endif
309 *negative = r < 0;
310 return r;
311 }
312
313 void
314 uid_to_chars (uid_t v, char *p, size_t s)
315 {
316 to_chars (v < 0, (uintmax_t) v, sizeof v, uid_substitute, p, s, "uid_t");
317 }
318
319 void
320 uintmax_to_chars (uintmax_t v, char *p, size_t s)
321 {
322 to_chars (0, v, sizeof v, 0, p, s, "uintmax_t");
323 }
324
325 void
326 string_to_chars (char *str, char *p, size_t s)
327 {
328 strncpy (p, str, s);
329 p[s-1] = 0;
330 }
331
332 \f
333 /* A file is not dumpable if
334 a) it is empty *and* world-readable, or
335 b) current archive is /dev/null */
336
337 bool
338 file_dumpable_p (struct tar_stat_info *stat)
339 {
340 return !(dev_null_output
341 || (stat->archive_file_size == 0
342 && (stat->stat.st_mode & MODE_R) == MODE_R));
343 }
344
345 \f
346 /* Writing routines. */
347
348 /* Write the EOT block(s). Zero at least two blocks, through the end
349 of the record. Old tar, as previous versions of GNU tar, writes
350 garbage after two zeroed blocks. */
351 void
352 write_eot (void)
353 {
354 union block *pointer = find_next_block ();
355 memset (pointer->buffer, 0, BLOCKSIZE);
356 set_next_block_after (pointer);
357 pointer = find_next_block ();
358 memset (pointer->buffer, 0, available_space_after (pointer));
359 set_next_block_after (pointer);
360 }
361
362 /* Copy at most LEN bytes from SRC to DST. Terminate with NUL unless
363 SRC is LEN characters long */
364 static void
365 tar_copy_str (char *dst, const char *src, size_t len)
366 {
367 dst[len-1] = 0;
368 strncpy (dst, src, len);
369 }
370
371 /* Write a "private" header */
372 static union block *
373 start_private_header (const char *name, size_t size)
374 {
375 time_t t;
376 union block *header = find_next_block ();
377
378 memset (header->buffer, 0, sizeof (union block));
379
380 tar_copy_str (header->header.name, name, NAME_FIELD_SIZE);
381 OFF_TO_CHARS (size, header->header.size);
382
383 time (&t);
384 TIME_TO_CHARS (t, header->header.mtime);
385 MODE_TO_CHARS (S_IFREG|S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, header->header.mode);
386 UID_TO_CHARS (getuid (), header->header.uid);
387 GID_TO_CHARS (getgid (), header->header.gid);
388 MAJOR_TO_CHARS (0, header->header.devmajor);
389 MAJOR_TO_CHARS (0, header->header.devminor);
390 strncpy (header->header.magic, TMAGIC, TMAGLEN);
391 strncpy (header->header.version, TVERSION, TVERSLEN);
392 return header;
393 }
394
395 /* Create a new header and store there at most NAME_FIELD_SIZE bytes of
396 the file name */
397
398 static union block *
399 write_short_name (struct tar_stat_info *st)
400 {
401 union block *header = find_next_block ();
402 memset (header->buffer, 0, sizeof (union block));
403 tar_copy_str (header->header.name, st->file_name, NAME_FIELD_SIZE);
404 return header;
405 }
406
407 /* Write a GNUTYPE_LONGLINK or GNUTYPE_LONGNAME block. */
408 static void
409 write_gnu_long_link (struct tar_stat_info *st, const char *p, char type)
410 {
411 size_t size = strlen (p) + 1;
412 size_t bufsize;
413 union block *header;
414
415 header = start_private_header ("././@LongLink", size);
416 strcpy (header->header.magic, OLDGNU_MAGIC);
417 header->header.typeflag = type;
418 finish_header (st, header, -1);
419
420 header = find_next_block ();
421
422 bufsize = available_space_after (header);
423
424 while (bufsize < size)
425 {
426 memcpy (header->buffer, p, bufsize);
427 p += bufsize;
428 size -= bufsize;
429 set_next_block_after (header + (bufsize - 1) / BLOCKSIZE);
430 header = find_next_block ();
431 bufsize = available_space_after (header);
432 }
433 memcpy (header->buffer, p, size);
434 memset (header->buffer + size, 0, bufsize - size);
435 set_next_block_after (header + (size - 1) / BLOCKSIZE);
436 }
437
438 static size_t
439 split_long_name (const char *name, size_t length)
440 {
441 size_t i;
442
443 if (length > PREFIX_FIELD_SIZE)
444 length = PREFIX_FIELD_SIZE+2;
445 for (i = length - 1; i > 0; i--)
446 if (ISSLASH (name[i]))
447 break;
448 return i;
449 }
450
451 static union block *
452 write_ustar_long_name (const char *name)
453 {
454 size_t length = strlen (name);
455 size_t i;
456 union block *header;
457
458 if (length > PREFIX_FIELD_SIZE + NAME_FIELD_SIZE + 1)
459 {
460 WARN ((0, 0, _("%s: file name is too long (max %d); not dumped"),
461 quotearg_colon (name),
462 PREFIX_FIELD_SIZE + NAME_FIELD_SIZE + 1));
463 return NULL;
464 }
465
466 i = split_long_name (name, length);
467 if (i == 0 || length - i - 1 > NAME_FIELD_SIZE)
468 {
469 WARN ((0, 0,
470 _("%s: file name is too long (cannot be split); not dumped"),
471 quotearg_colon (name)));
472 return NULL;
473 }
474
475 header = find_next_block ();
476 memset (header->buffer, 0, sizeof (header->buffer));
477 memcpy (header->header.prefix, name, i);
478 memcpy (header->header.name, name + i + 1, length - i - 1);
479
480 return header;
481 }
482
483 /* Write a long link name, depending on the current archive format */
484 static void
485 write_long_link (struct tar_stat_info *st)
486 {
487 switch (archive_format)
488 {
489 case POSIX_FORMAT:
490 xheader_store ("linkpath", st);
491 break;
492
493 case V7_FORMAT: /* old V7 tar format */
494 case USTAR_FORMAT:
495 case STAR_FORMAT:
496 WARN ((0, 0,
497 _("%s: link name is too long; not dumped"),
498 quotearg_colon (st->link_name)));
499 break;
500
501 case OLDGNU_FORMAT:
502 case GNU_FORMAT:
503 write_gnu_long_link (st, st->link_name, GNUTYPE_LONGLINK);
504 break;
505
506 default:
507 abort(); /*FIXME*/
508 }
509 }
510
511 static union block *
512 write_long_name (struct tar_stat_info *st)
513 {
514 switch (archive_format)
515 {
516 case POSIX_FORMAT:
517 xheader_store ("path", st);
518 break;
519
520 case V7_FORMAT:
521 case USTAR_FORMAT:
522 case STAR_FORMAT:
523 return write_ustar_long_name (st->file_name);
524
525 case OLDGNU_FORMAT:
526 case GNU_FORMAT:
527 write_gnu_long_link (st, st->file_name, GNUTYPE_LONGNAME);
528 break;
529
530 default:
531 abort(); /*FIXME*/
532 }
533 return write_short_name (st);
534 }
535
536 static union block *
537 write_extended (struct tar_stat_info *st, union block *old_header, char type)
538 {
539 union block *header, hp;
540 size_t size;
541 char *p;
542
543 if (extended_header.buffer || extended_header.stk == NULL)
544 return old_header;
545
546 xheader_finish (&extended_header);
547 size = extended_header.size;
548
549 memcpy (hp.buffer, old_header, sizeof (hp));
550
551 header = start_private_header ("././@PaxHeader", size);
552 header->header.typeflag = type;
553
554 finish_header (st, header, -1);
555
556 p = extended_header.buffer;
557
558 do
559 {
560 size_t len;
561
562 header = find_next_block ();
563 len = BLOCKSIZE;
564 if (len > size)
565 len = size;
566 memcpy (header->buffer, p, len);
567 if (len < BLOCKSIZE)
568 memset (header->buffer + len, 0, BLOCKSIZE - len);
569 p += len;
570 size -= len;
571 set_next_block_after (header);
572 }
573 while (size > 0);
574
575 xheader_destroy (&extended_header);
576 header = find_next_block ();
577 memcpy (header, &hp.buffer, sizeof (hp.buffer));
578 return header;
579 }
580
581 static union block *
582 write_header_name (struct tar_stat_info *st)
583 {
584 if (NAME_FIELD_SIZE < strlen (st->file_name))
585 return write_long_name (st);
586 else
587 return write_short_name (st);
588 }
589
590 \f
591 /* Header handling. */
592
593 /* Make a header block for the file whose stat info is st,
594 and return its address. */
595
596 union block *
597 start_header (struct tar_stat_info *st)
598 {
599 union block *header;
600
601 header = write_header_name (st);
602 if (!header)
603 return NULL;
604
605 /* Override some stat fields, if requested to do so. */
606
607 if (owner_option != (uid_t) -1)
608 st->stat.st_uid = owner_option;
609 if (group_option != (gid_t) -1)
610 st->stat.st_gid = group_option;
611 if (mode_option)
612 st->stat.st_mode = ((st->stat.st_mode & ~MODE_ALL)
613 | mode_adjust (st->stat.st_mode, mode_option));
614
615 /* Paul Eggert tried the trivial test ($WRITER cf a b; $READER tvf a)
616 for a few tars and came up with the following interoperability
617 matrix:
618
619 WRITER
620 1 2 3 4 5 6 7 8 9 READER
621 . . . . . . . . . 1 = SunOS 4.2 tar
622 # . . # # . . # # 2 = NEC SVR4.0.2 tar
623 . . . # # . . # . 3 = Solaris 2.1 tar
624 . . . . . . . . . 4 = GNU tar 1.11.1
625 . . . . . . . . . 5 = HP-UX 8.07 tar
626 . . . . . . . . . 6 = Ultrix 4.1
627 . . . . . . . . . 7 = AIX 3.2
628 . . . . . . . . . 8 = Hitachi HI-UX 1.03
629 . . . . . . . . . 9 = Omron UNIOS-B 4.3BSD 1.60Beta
630
631 . = works
632 # = ``impossible file type''
633
634 The following mask for old archive removes the `#'s in column 4
635 above, thus making GNU tar both a universal donor and a universal
636 acceptor for Paul's test. */
637
638 if (archive_format == V7_FORMAT || archive_format == USTAR_FORMAT)
639 MODE_TO_CHARS (st->stat.st_mode & MODE_ALL, header->header.mode);
640 else
641 MODE_TO_CHARS (st->stat.st_mode, header->header.mode);
642
643 if (st->stat.st_uid > MAXOCTAL7 && archive_format == POSIX_FORMAT)
644 xheader_store ("uid", st);
645 else
646 UID_TO_CHARS (st->stat.st_uid, header->header.uid);
647
648 if (st->stat.st_gid > MAXOCTAL7 && archive_format == POSIX_FORMAT)
649 xheader_store ("gid", st);
650 else
651 GID_TO_CHARS (st->stat.st_gid, header->header.gid);
652
653 if (st->stat.st_size > MAXOCTAL11 && archive_format == POSIX_FORMAT)
654 xheader_store ("size", st);
655 else
656 OFF_TO_CHARS (st->stat.st_size, header->header.size);
657
658 TIME_TO_CHARS (st->stat.st_mtime, header->header.mtime);
659
660 /* FIXME */
661 if (S_ISCHR (st->stat.st_mode)
662 || S_ISBLK (st->stat.st_mode))
663 {
664 st->devmajor = major (st->stat.st_rdev);
665 st->devminor = minor (st->stat.st_rdev);
666
667 if (st->devmajor > MAXOCTAL7 && archive_format == POSIX_FORMAT)
668 xheader_store ("devmajor", st);
669 else
670 MAJOR_TO_CHARS (st->devmajor, header->header.devmajor);
671
672 if (st->devminor > MAXOCTAL7 && archive_format == POSIX_FORMAT)
673 xheader_store ("devminor", st);
674 else
675 MAJOR_TO_CHARS (st->devminor, header->header.devminor);
676 }
677 else
678 {
679 MAJOR_TO_CHARS (0, header->header.devmajor);
680 MINOR_TO_CHARS (0, header->header.devminor);
681 }
682
683 if (archive_format == POSIX_FORMAT)
684 {
685 xheader_store ("atime", st);
686 xheader_store ("ctime", st);
687 }
688 else if (incremental_option)
689 if (archive_format == OLDGNU_FORMAT)
690 {
691 TIME_TO_CHARS (st->stat.st_atime, header->oldgnu_header.atime);
692 TIME_TO_CHARS (st->stat.st_ctime, header->oldgnu_header.ctime);
693 }
694
695 header->header.typeflag = archive_format == V7_FORMAT ? AREGTYPE : REGTYPE;
696
697 switch (archive_format)
698 {
699 case V7_FORMAT:
700 break;
701
702 case OLDGNU_FORMAT:
703 case GNU_FORMAT: /*FIXME?*/
704 /* Overwrite header->header.magic and header.version in one blow. */
705 strcpy (header->header.magic, OLDGNU_MAGIC);
706 break;
707
708 case POSIX_FORMAT:
709 case USTAR_FORMAT:
710 strncpy (header->header.magic, TMAGIC, TMAGLEN);
711 strncpy (header->header.version, TVERSION, TVERSLEN);
712 break;
713
714 default:
715 abort ();
716 }
717
718 if (archive_format == V7_FORMAT || numeric_owner_option)
719 {
720 /* header->header.[ug]name are left as the empty string. */
721 }
722 else
723 {
724 uid_to_uname (st->stat.st_uid, &st->uname);
725 gid_to_gname (st->stat.st_gid, &st->gname);
726
727 if (archive_format == POSIX_FORMAT
728 && strlen (st->uname) > UNAME_FIELD_SIZE)
729 xheader_store ("uname", st);
730 else
731 UNAME_TO_CHARS (st->uname, header->header.uname);
732
733 if (archive_format == POSIX_FORMAT
734 && strlen (st->gname) > GNAME_FIELD_SIZE)
735 xheader_store ("gname", st);
736 else
737 GNAME_TO_CHARS (st->gname, header->header.gname);
738 }
739
740 return header;
741 }
742
743 /* Finish off a filled-in header block and write it out. We also
744 print the file name and/or full info if verbose is on. If BLOCK_ORDINAL
745 is not negative, is the block ordinal of the first record for this
746 file, which may be a preceding long name or long link record. */
747 void
748 finish_header (struct tar_stat_info *st,
749 union block *header, off_t block_ordinal)
750 {
751 size_t i;
752 int sum;
753 char *p;
754
755 /* Note: It is important to do this before the call to write_extended(),
756 so that the actual ustar header is printed */
757 if (verbose_option
758 && header->header.typeflag != GNUTYPE_LONGLINK
759 && header->header.typeflag != GNUTYPE_LONGNAME
760 && header->header.typeflag != XHDTYPE
761 && header->header.typeflag != XGLTYPE)
762 {
763 /* These globals are parameters to print_header, sigh. */
764
765 current_header = header;
766 current_format = archive_format;
767 print_header (st, block_ordinal);
768 }
769
770 header = write_extended (st, header, XHDTYPE);
771
772 memcpy (header->header.chksum, CHKBLANKS, sizeof header->header.chksum);
773
774 sum = 0;
775 p = header->buffer;
776 for (i = sizeof *header; i-- != 0; )
777 /* We can't use unsigned char here because of old compilers, e.g. V7. */
778 sum += 0xFF & *p++;
779
780 /* Fill in the checksum field. It's formatted differently from the
781 other fields: it has [6] digits, a null, then a space -- rather than
782 digits, then a null. We use to_chars.
783 The final space is already there, from
784 checksumming, and to_chars doesn't modify it.
785
786 This is a fast way to do:
787
788 sprintf(header->header.chksum, "%6o", sum); */
789
790 uintmax_to_chars ((uintmax_t) sum, header->header.chksum, 7);
791
792 set_next_block_after (header);
793 }
794 \f
795
796 void
797 pad_archive (off_t size_left)
798 {
799 union block *blk;
800 while (size_left > 0)
801 {
802 save_sizeleft = size_left;
803 blk = find_next_block ();
804 memset (blk->buffer, 0, BLOCKSIZE);
805 set_next_block_after (blk);
806 size_left -= BLOCKSIZE;
807 }
808 }
809
810 static enum dump_status
811 dump_regular_file (int fd, struct tar_stat_info *stat)
812 {
813 off_t size_left = stat->stat.st_size;
814 off_t block_ordinal;
815 union block *blk;
816
817 block_ordinal = current_block_ordinal ();
818 blk = start_header (stat);
819 if (!blk)
820 return dump_status_fail;
821
822 /* Mark contiguous files, if we support them. */
823 if (archive_format != V7_FORMAT && S_ISCTG (stat->stat.st_mode))
824 blk->header.typeflag = CONTTYPE;
825
826 finish_header (stat, blk, block_ordinal);
827
828 while (size_left > 0)
829 {
830 size_t bufsize, count;
831
832 if (multi_volume_option)
833 {
834 assign_string (&save_name, stat->file_name);
835 save_sizeleft = size_left;
836 save_totsize = stat->stat.st_size;
837 }
838 blk = find_next_block ();
839
840 bufsize = available_space_after (blk);
841
842 if (size_left < bufsize)
843 {
844 /* Last read -- zero out area beyond. */
845 bufsize = size_left;
846 count = bufsize % BLOCKSIZE;
847 if (count)
848 memset (blk->buffer + size_left, 0, BLOCKSIZE - count);
849 }
850
851 count = (fd < 0) ? bufsize : safe_read (fd, blk->buffer, bufsize);
852 if (count < 0)
853 {
854 read_diag_details (stat->orig_file_name,
855 stat->stat.st_size - size_left, bufsize);
856 pad_archive (size_left);
857 return dump_status_short;
858 }
859 size_left -= count;
860
861 set_next_block_after (blk + (bufsize - 1) / BLOCKSIZE);
862
863 if (count != bufsize)
864 {
865 char buf[UINTMAX_STRSIZE_BOUND];
866 memset (blk->buffer + count, 0, bufsize - count);
867 WARN ((0, 0,
868 ngettext ("%s: File shrank by %s byte; padding with zeros",
869 "%s: File shrank by %s bytes; padding with zeros",
870 size_left),
871 quotearg_colon (stat->orig_file_name),
872 STRINGIFY_BIGINT (size_left, buf)));
873 if (! ignore_failed_read_option)
874 exit_status = TAREXIT_FAILURE;
875 pad_archive (size_left);
876 return dump_status_short;
877 }
878 }
879 return dump_status_ok;
880 }
881
882 void
883 dump_regular_finish (int fd, struct tar_stat_info *st, time_t original_ctime)
884 {
885 if (fd >= 0)
886 {
887 struct stat final_stat;
888 if (fstat (fd, &final_stat) != 0)
889 {
890 stat_diag (st->orig_file_name);
891 }
892 else if (final_stat.st_ctime != original_ctime)
893 {
894 WARN ((0, 0, _("%s: file changed as we read it"),
895 quotearg_colon (st->orig_file_name)));
896 }
897 if (close (fd) != 0)
898 {
899 close_diag (st->orig_file_name);
900 }
901 }
902 if (remove_files_option)
903 {
904 if (unlink (st->orig_file_name) == -1)
905 unlink_error (st->orig_file_name);
906 }
907 }
908
909 void
910 dump_dir0 (char *directory,
911 struct tar_stat_info *stat, int top_level, dev_t parent_device)
912 {
913 dev_t our_device = stat->stat.st_dev;
914
915 if (!is_avoided_name (stat->orig_file_name))
916 {
917 union block *blk = NULL;
918 off_t block_ordinal = current_block_ordinal ();
919 stat->stat.st_size = 0; /* force 0 size on dir */
920
921 blk = start_header (stat);
922 if (!blk)
923 return;
924
925 if (incremental_option)
926 blk->header.typeflag = GNUTYPE_DUMPDIR;
927 else /* if (standard_option) */
928 blk->header.typeflag = DIRTYPE;
929
930 /* If we're gnudumping, we aren't done yet so don't close it. */
931
932 if (!incremental_option)
933 finish_header (stat, blk, block_ordinal);
934 else if (gnu_list_name->dir_contents)
935 {
936 off_t size_left;
937 off_t totsize;
938 size_t bufsize;
939 ssize_t count;
940 const char *buffer, *p_buffer;
941 off_t block_ordinal = current_block_ordinal ();
942
943 buffer = gnu_list_name->dir_contents; /* FOO */
944 totsize = 0;
945 if (buffer)
946 for (p_buffer = buffer; *p_buffer; )
947 {
948 size_t size = strlen (p_buffer) + 1;
949 totsize += size;
950 p_buffer += size;
951 }
952 totsize++;
953 OFF_TO_CHARS (totsize, blk->header.size);
954 finish_header (stat, blk, block_ordinal);
955 p_buffer = buffer;
956 size_left = totsize;
957 while (size_left > 0)
958 {
959 if (multi_volume_option)
960 {
961 assign_string (&save_name, stat->orig_file_name);
962 save_sizeleft = size_left;
963 save_totsize = totsize;
964 }
965 blk = find_next_block ();
966 bufsize = available_space_after (blk);
967 if (size_left < bufsize)
968 {
969 bufsize = size_left;
970 count = bufsize % BLOCKSIZE;
971 if (count)
972 memset (blk->buffer + size_left, 0, BLOCKSIZE - count);
973 }
974 memcpy (blk->buffer, p_buffer, bufsize);
975 size_left -= bufsize;
976 p_buffer += bufsize;
977 set_next_block_after (blk + (bufsize - 1) / BLOCKSIZE);
978 }
979 if (multi_volume_option)
980 assign_string (&save_name, 0);
981 return;
982 }
983 }
984 else if (!recursion_option)
985 return;
986 else if (one_file_system_option
987 && !top_level
988 && parent_device != stat->stat.st_dev)
989 {
990 if (verbose_option)
991 WARN ((0, 0,
992 _("%s: file is on a different filesystem; not dumped"),
993 quotearg_colon (stat->orig_file_name)));
994 return;
995 }
996
997 {
998 char const *entry;
999 size_t entry_len;
1000 char *name_buf = strdup (stat->orig_file_name);
1001 size_t name_size = strlen (name_buf);
1002 size_t name_len = name_size;
1003
1004 /* Now output all the files in the directory. */
1005 /* FIXME: Should speed this up by cd-ing into the dir. */
1006
1007 for (entry = directory; (entry_len = strlen (entry)) != 0;
1008 entry += entry_len + 1)
1009 {
1010 if (name_size < name_len + entry_len)
1011 {
1012 name_size = name_len + entry_len;
1013 name_buf = xrealloc (name_buf, name_size + 1);
1014 }
1015 strcpy (name_buf + name_len, entry);
1016 if (!excluded_name (name_buf))
1017 dump_file (name_buf, 0, our_device);
1018 }
1019
1020 free (name_buf);
1021 }
1022 }
1023
1024 /* Ensure exactly one trailing slash. */
1025 static void
1026 ensure_slash (char **pstr)
1027 {
1028 size_t len = strlen (*pstr);
1029 while (len >= 1 && ISSLASH ((*pstr)[len - 1]))
1030 len--;
1031 if (!ISSLASH ((*pstr)[len]))
1032 *pstr = xrealloc (*pstr, len + 2);
1033 (*pstr)[len++] = '/';
1034 (*pstr)[len] = '\0';
1035 }
1036
1037 bool
1038 dump_dir (struct tar_stat_info *stat, int top_level, dev_t parent_device)
1039 {
1040 char *directory;
1041
1042 directory = savedir (stat->orig_file_name);
1043 if (!directory)
1044 {
1045 savedir_diag (stat->orig_file_name);
1046 return false;
1047 }
1048
1049 ensure_slash (&stat->orig_file_name);
1050 ensure_slash (&stat->file_name);
1051
1052 dump_dir0 (directory, stat, top_level, parent_device);
1053
1054 free (directory);
1055 return true;
1056 }
1057
1058 \f
1059 /* Main functions of this module. */
1060
1061 void
1062 create_archive (void)
1063 {
1064 char *p;
1065
1066 open_archive (ACCESS_WRITE);
1067
1068 if (incremental_option)
1069 {
1070 size_t buffer_size = 1000;
1071 char *buffer = xmalloc (buffer_size);
1072 const char *q;
1073
1074 collect_and_sort_names ();
1075
1076 while ((p = name_from_list ()) != NULL)
1077 if (!excluded_name (p))
1078 dump_file (p, -1, (dev_t) 0);
1079
1080 blank_name_list ();
1081 while ((p = name_from_list ()) != NULL)
1082 if (!excluded_name (p))
1083 {
1084 size_t plen = strlen (p);
1085 if (buffer_size <= plen)
1086 {
1087 while ((buffer_size *= 2) <= plen)
1088 continue;
1089 buffer = xrealloc (buffer, buffer_size);
1090 }
1091 memcpy (buffer, p, plen);
1092 if (! ISSLASH (buffer[plen - 1]))
1093 buffer[plen++] = '/';
1094 q = gnu_list_name->dir_contents;
1095 if (q)
1096 while (*q)
1097 {
1098 size_t qlen = strlen (q);
1099 if (*q == 'Y')
1100 {
1101 if (buffer_size < plen + qlen)
1102 {
1103 while ((buffer_size *=2 ) < plen + qlen)
1104 continue;
1105 buffer = xrealloc (buffer, buffer_size);
1106 }
1107 strcpy (buffer + plen, q + 1);
1108 dump_file (buffer, -1, (dev_t) 0);
1109 }
1110 q += qlen + 1;
1111 }
1112 }
1113 free (buffer);
1114 }
1115 else
1116 {
1117 while ((p = name_next (1)) != NULL)
1118 if (!excluded_name (p))
1119 dump_file (p, 1, (dev_t) 0);
1120 }
1121
1122 write_eot ();
1123 close_archive ();
1124
1125 if (listed_incremental_option)
1126 write_directory_file ();
1127 }
1128
1129
1130 /* Calculate the hash of a link. */
1131 static unsigned
1132 hash_link (void const *entry, unsigned n_buckets)
1133 {
1134 struct link const *link = entry;
1135 return (uintmax_t) (link->dev ^ link->ino) % n_buckets;
1136 }
1137
1138 /* Compare two links for equality. */
1139 static bool
1140 compare_links (void const *entry1, void const *entry2)
1141 {
1142 struct link const *link1 = entry1;
1143 struct link const *link2 = entry2;
1144 return ((link1->dev ^ link2->dev) | (link1->ino ^ link2->ino)) == 0;
1145 }
1146
1147 static void
1148 unknown_file_error (char *p)
1149 {
1150 WARN ((0, 0, _("%s: Unknown file type; file ignored"),
1151 quotearg_colon (p)));
1152 if (!ignore_failed_read_option)
1153 exit_status = TAREXIT_FAILURE;
1154 }
1155
1156 \f
1157 /* Handling of hard links */
1158
1159 /* Table of all non-directories that we've written so far. Any time
1160 we see another, we check the table and avoid dumping the data
1161 again if we've done it once already. */
1162 static Hash_table *link_table;
1163
1164 /* Try to dump stat as a hard link to another file in the archive. If
1165 succeeded returns true */
1166 static bool
1167 dump_hard_link (struct tar_stat_info *stat)
1168 {
1169 if (link_table && stat->stat.st_nlink > 1)
1170 {
1171 struct link lp;
1172 struct link *dup;
1173 off_t block_ordinal;
1174 union block *blk;
1175
1176 lp.ino = stat->stat.st_ino;
1177 lp.dev = stat->stat.st_dev;
1178
1179 if ((dup = hash_lookup (link_table, &lp)))
1180 {
1181 /* We found a link. */
1182 char const *link_name = safer_name_suffix (dup->name, 1);
1183
1184 dup->nlink--;
1185
1186 block_ordinal = current_block_ordinal ();
1187 assign_string (&stat->link_name, link_name);
1188 if (NAME_FIELD_SIZE < strlen (link_name))
1189 write_long_link (stat);
1190
1191 stat->stat.st_size = 0;
1192 blk = start_header (stat);
1193 if (!blk)
1194 return true;
1195 tar_copy_str (blk->header.linkname, link_name, NAME_FIELD_SIZE);
1196
1197 blk->header.typeflag = LNKTYPE;
1198 finish_header (stat, blk, block_ordinal);
1199
1200 if (remove_files_option && unlink (stat->orig_file_name) != 0)
1201 unlink_error (stat->orig_file_name);
1202
1203 return true;
1204 }
1205 }
1206 return false;
1207 }
1208
1209 static void
1210 file_count_links (struct tar_stat_info *stat)
1211 {
1212 if (stat->stat.st_nlink > 1)
1213 {
1214 struct link *dup;
1215 struct link *lp = xmalloc (offsetof (struct link, name)
1216 + strlen (stat->orig_file_name) + 1);
1217 lp->ino = stat->stat.st_ino;
1218 lp->dev = stat->stat.st_dev;
1219 lp->nlink = stat->stat.st_nlink;
1220 strcpy (lp->name, stat->orig_file_name);
1221
1222 if (! ((link_table
1223 || (link_table = hash_initialize (0, 0, hash_link,
1224 compare_links, 0)))
1225 && (dup = hash_insert (link_table, lp))))
1226 xalloc_die ();
1227
1228 if (dup != lp)
1229 abort ();
1230 lp->nlink--;
1231 }
1232 }
1233
1234 /* For each dumped file, check if all its links were dumped. Emit
1235 warnings if it is not so. */
1236 void
1237 check_links ()
1238 {
1239 struct link *lp;
1240
1241 if (!link_table)
1242 return;
1243
1244 for (lp = hash_get_first (link_table); lp;
1245 lp = hash_get_next (link_table, lp))
1246 {
1247 if (lp->nlink)
1248 {
1249 WARN ((0, 0, _("Missing links to '%s'.\n"), lp->name));
1250 }
1251 }
1252 }
1253
1254
1255 /* Dump a single file, recursing on directories. P is the file name
1256 to dump. TOP_LEVEL tells whether this is a top-level call; zero
1257 means no, positive means yes, and negative means the top level
1258 of an incremental dump. PARENT_DEVICE is the device of P's
1259 parent directory; it is examined only if TOP_LEVEL is zero. */
1260
1261 /* FIXME: One should make sure that for *every* path leading to setting
1262 exit_status to failure, a clear diagnostic has been issued. */
1263
1264 void
1265 dump_file0 (struct tar_stat_info *stat, char *p,
1266 int top_level, dev_t parent_device)
1267 {
1268 union block *header;
1269 char type;
1270 time_t original_ctime;
1271 struct utimbuf restore_times;
1272 off_t block_ordinal = -1;
1273
1274 if (interactive_option && !confirm ("add", p))
1275 return;
1276
1277 assign_string (&stat->orig_file_name, p);
1278 assign_string (&stat->file_name, safer_name_suffix (p, 0));
1279
1280 if (deref_stat (dereference_option, p, &stat->stat) != 0)
1281 {
1282 stat_diag (p);
1283 return;
1284 }
1285 stat->archive_file_size = stat->stat.st_size;
1286
1287 original_ctime = stat->stat.st_ctime;
1288 restore_times.actime = stat->stat.st_atime;
1289 restore_times.modtime = stat->stat.st_mtime;
1290
1291 #ifdef S_ISHIDDEN
1292 if (S_ISHIDDEN (stat->stat.st_mode))
1293 {
1294 char *new = (char *) alloca (strlen (p) + 2);
1295 if (new)
1296 {
1297 strcpy (new, p);
1298 strcat (new, "@");
1299 p = new;
1300 }
1301 }
1302 #endif
1303
1304 /* See if we want only new files, and check if this one is too old to
1305 put in the archive. */
1306
1307 if ((0 < top_level || !incremental_option)
1308 && !S_ISDIR (stat->stat.st_mode)
1309 && stat->stat.st_mtime < newer_mtime_option
1310 && (!after_date_option || stat->stat.st_ctime < newer_ctime_option))
1311 {
1312 if (0 < top_level)
1313 WARN ((0, 0, _("%s: file is unchanged; not dumped"),
1314 quotearg_colon (p)));
1315 /* FIXME: recheck this return. */
1316 return;
1317 }
1318
1319 /* See if we are trying to dump the archive. */
1320 if (sys_file_is_archive (stat))
1321 {
1322 WARN ((0, 0, _("%s: file is the archive; not dumped"),
1323 quotearg_colon (p)));
1324 return;
1325 }
1326
1327 if (S_ISDIR (stat->stat.st_mode))
1328 {
1329 dump_dir (stat, top_level, parent_device);
1330 if (atime_preserve_option)
1331 utime (p, &restore_times);
1332 return;
1333 }
1334 else if (is_avoided_name (p))
1335 return;
1336 else
1337 {
1338 /* Check for multiple links. */
1339 if (dump_hard_link (stat))
1340 return;
1341
1342 /* This is not a link to a previously dumped file, so dump it. */
1343
1344 if (S_ISREG (stat->stat.st_mode)
1345 || S_ISCTG (stat->stat.st_mode))
1346 {
1347 int fd;
1348 enum dump_status status;
1349
1350 if (file_dumpable_p (stat))
1351 {
1352 fd = open (stat->orig_file_name,
1353 O_RDONLY | O_BINARY);
1354 if (fd < 0)
1355 {
1356 if (!top_level && errno == ENOENT)
1357 WARN ((0, 0, _("%s: File removed before we read it"),
1358 quotearg_colon (stat->orig_file_name)));
1359 else
1360 open_diag (stat->orig_file_name);
1361 return;
1362 }
1363 }
1364 else
1365 fd = -1;
1366
1367 if (sparse_option && sparse_file_p (stat))
1368 {
1369 status = sparse_dump_file (fd, stat);
1370 if (status == dump_status_not_implemented)
1371 status = dump_regular_file (fd, stat);
1372 }
1373 else
1374 status = dump_regular_file (fd, stat);
1375
1376 switch (status)
1377 {
1378 case dump_status_ok:
1379 if (multi_volume_option)
1380 assign_string (&save_name, 0);
1381 dump_regular_finish (fd, stat, original_ctime);
1382 break;
1383
1384 case dump_status_short:
1385 if (multi_volume_option)
1386 assign_string (&save_name, 0);
1387 close (fd);
1388 break;
1389
1390 case dump_status_fail:
1391 close (fd);
1392 return;
1393
1394 case dump_status_not_implemented:
1395 abort ();
1396 }
1397
1398 if (atime_preserve_option)
1399 utime (stat->orig_file_name, &restore_times);
1400 file_count_links (stat);
1401 return;
1402 }
1403 #ifdef HAVE_READLINK
1404 else if (S_ISLNK (stat->stat.st_mode))
1405 {
1406 char *buffer;
1407 int size;
1408 size_t linklen = stat->stat.st_size;
1409 if (linklen != stat->stat.st_size || linklen + 1 == 0)
1410 xalloc_die ();
1411 buffer = (char *) alloca (linklen + 1);
1412 size = readlink (p, buffer, linklen + 1);
1413 if (size < 0)
1414 {
1415 readlink_diag (p);
1416 return;
1417 }
1418 buffer[size] = '\0';
1419 assign_string (&stat->link_name, buffer);
1420 if (size > NAME_FIELD_SIZE)
1421 write_long_link (stat);
1422
1423 block_ordinal = current_block_ordinal ();
1424 stat->stat.st_size = 0; /* force 0 size on symlink */
1425 header = start_header (stat);
1426 if (!header)
1427 return;
1428 tar_copy_str (header->header.linkname, buffer, NAME_FIELD_SIZE);
1429 header->header.typeflag = SYMTYPE;
1430 finish_header (stat, header, block_ordinal);
1431 /* nothing more to do to it */
1432
1433 if (remove_files_option)
1434 {
1435 if (unlink (p) == -1)
1436 unlink_error (p);
1437 }
1438 file_count_links (stat);
1439 return;
1440 }
1441 #endif
1442 else if (S_ISCHR (stat->stat.st_mode))
1443 type = CHRTYPE;
1444 else if (S_ISBLK (stat->stat.st_mode))
1445 type = BLKTYPE;
1446 else if (S_ISFIFO (stat->stat.st_mode))
1447 type = FIFOTYPE;
1448 else if (S_ISSOCK (stat->stat.st_mode))
1449 {
1450 WARN ((0, 0, _("%s: socket ignored"), quotearg_colon (p)));
1451 return;
1452 }
1453 else if (S_ISDOOR (stat->stat.st_mode))
1454 {
1455 WARN ((0, 0, _("%s: door ignored"), quotearg_colon (p)));
1456 return;
1457 }
1458 else
1459 {
1460 unknown_file_error (p);
1461 return;
1462 }
1463 }
1464
1465 if (archive_format == V7_FORMAT)
1466 {
1467 unknown_file_error (p);
1468 return;
1469 }
1470
1471 block_ordinal = current_block_ordinal ();
1472 stat->stat.st_size = 0; /* force 0 size */
1473 header = start_header (stat);
1474 if (!header)
1475 return;
1476 header->header.typeflag = type;
1477
1478 if (type != FIFOTYPE)
1479 {
1480 MAJOR_TO_CHARS (major (stat->stat.st_rdev),
1481 header->header.devmajor);
1482 MINOR_TO_CHARS (minor (stat->stat.st_rdev),
1483 header->header.devminor);
1484 }
1485
1486 finish_header (stat, header, block_ordinal);
1487 if (remove_files_option)
1488 {
1489 if (unlink (p) == -1)
1490 unlink_error (p);
1491 }
1492 }
1493
1494 void
1495 dump_file (char *p, int top_level, dev_t parent_device)
1496 {
1497 struct tar_stat_info stat;
1498 tar_stat_init (&stat);
1499 dump_file0 (&stat, p, top_level, parent_device);
1500 tar_stat_destroy (&stat);
1501 }
This page took 0.098196 seconds and 5 git commands to generate.