1 |
/* Create a tar archive. |
2 |
|
3 |
Copyright (C) 1985, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001, |
4 |
2003, 2004 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 |
|
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 |
/* FIXME: This is the only place where GNU_FORMAT differs from |
190 |
OLDGNU_FORMAT. Apart from this they are completely identical. */ |
191 |
uintmax_t s = (negsub &= archive_format == GNU_FORMAT) ? - sub : sub; |
192 |
char subbuf[UINTMAX_STRSIZE_BOUND + 1]; |
193 |
char *sub_string = STRINGIFY_BIGINT (s, subbuf + 1); |
194 |
if (negsub) |
195 |
*--sub_string = '-'; |
196 |
WARN ((0, 0, _("value %s out of %s range %s..%s; substituting %s"), |
197 |
value_string, type, minval_string, maxval_string, |
198 |
sub_string)); |
199 |
to_chars (negsub, s, valsize, 0, where, size, type); |
200 |
} |
201 |
else |
202 |
ERROR ((0, 0, _("value %s out of %s range %s..%s"), |
203 |
value_string, type, minval_string, maxval_string)); |
204 |
} |
205 |
} |
206 |
|
207 |
static uintmax_t |
208 |
gid_substitute (int *negative) |
209 |
{ |
210 |
gid_t r; |
211 |
#ifdef GID_NOBODY |
212 |
r = GID_NOBODY; |
213 |
#else |
214 |
static gid_t gid_nobody; |
215 |
if (!gid_nobody && !gname_to_gid ("nobody", &gid_nobody)) |
216 |
gid_nobody = -2; |
217 |
r = gid_nobody; |
218 |
#endif |
219 |
*negative = r < 0; |
220 |
return r; |
221 |
} |
222 |
|
223 |
void |
224 |
gid_to_chars (gid_t v, char *p, size_t s) |
225 |
{ |
226 |
to_chars (v < 0, (uintmax_t) v, sizeof v, gid_substitute, p, s, "gid_t"); |
227 |
} |
228 |
|
229 |
void |
230 |
major_to_chars (major_t v, char *p, size_t s) |
231 |
{ |
232 |
to_chars (v < 0, (uintmax_t) v, sizeof v, 0, p, s, "major_t"); |
233 |
} |
234 |
|
235 |
void |
236 |
minor_to_chars (minor_t v, char *p, size_t s) |
237 |
{ |
238 |
to_chars (v < 0, (uintmax_t) v, sizeof v, 0, p, s, "minor_t"); |
239 |
} |
240 |
|
241 |
void |
242 |
mode_to_chars (mode_t v, char *p, size_t s) |
243 |
{ |
244 |
/* In the common case where the internal and external mode bits are the same, |
245 |
and we are not using POSIX or GNU format, |
246 |
propagate all unknown bits to the external mode. |
247 |
This matches historical practice. |
248 |
Otherwise, just copy the bits we know about. */ |
249 |
int negative; |
250 |
uintmax_t u; |
251 |
if (S_ISUID == TSUID && S_ISGID == TSGID && S_ISVTX == TSVTX |
252 |
&& S_IRUSR == TUREAD && S_IWUSR == TUWRITE && S_IXUSR == TUEXEC |
253 |
&& S_IRGRP == TGREAD && S_IWGRP == TGWRITE && S_IXGRP == TGEXEC |
254 |
&& S_IROTH == TOREAD && S_IWOTH == TOWRITE && S_IXOTH == TOEXEC |
255 |
&& archive_format != POSIX_FORMAT |
256 |
&& archive_format != USTAR_FORMAT |
257 |
&& archive_format != GNU_FORMAT) |
258 |
{ |
259 |
negative = v < 0; |
260 |
u = v; |
261 |
} |
262 |
else |
263 |
{ |
264 |
negative = 0; |
265 |
u = ((v & S_ISUID ? TSUID : 0) |
266 |
| (v & S_ISGID ? TSGID : 0) |
267 |
| (v & S_ISVTX ? TSVTX : 0) |
268 |
| (v & S_IRUSR ? TUREAD : 0) |
269 |
| (v & S_IWUSR ? TUWRITE : 0) |
270 |
| (v & S_IXUSR ? TUEXEC : 0) |
271 |
| (v & S_IRGRP ? TGREAD : 0) |
272 |
| (v & S_IWGRP ? TGWRITE : 0) |
273 |
| (v & S_IXGRP ? TGEXEC : 0) |
274 |
| (v & S_IROTH ? TOREAD : 0) |
275 |
| (v & S_IWOTH ? TOWRITE : 0) |
276 |
| (v & S_IXOTH ? TOEXEC : 0)); |
277 |
} |
278 |
to_chars (negative, u, sizeof v, 0, p, s, "mode_t"); |
279 |
} |
280 |
|
281 |
void |
282 |
off_to_chars (off_t v, char *p, size_t s) |
283 |
{ |
284 |
to_chars (v < 0, (uintmax_t) v, sizeof v, 0, p, s, "off_t"); |
285 |
} |
286 |
|
287 |
void |
288 |
size_to_chars (size_t v, char *p, size_t s) |
289 |
{ |
290 |
to_chars (0, (uintmax_t) v, sizeof v, 0, p, s, "size_t"); |
291 |
} |
292 |
|
293 |
void |
294 |
time_to_chars (time_t v, char *p, size_t s) |
295 |
{ |
296 |
to_chars (v < 0, (uintmax_t) v, sizeof v, 0, p, s, "time_t"); |
297 |
} |
298 |
|
299 |
static uintmax_t |
300 |
uid_substitute (int *negative) |
301 |
{ |
302 |
uid_t r; |
303 |
#ifdef UID_NOBODY |
304 |
r = UID_NOBODY; |
305 |
#else |
306 |
static uid_t uid_nobody; |
307 |
if (!uid_nobody && !uname_to_uid ("nobody", &uid_nobody)) |
308 |
uid_nobody = -2; |
309 |
r = uid_nobody; |
310 |
#endif |
311 |
*negative = r < 0; |
312 |
return r; |
313 |
} |
314 |
|
315 |
void |
316 |
uid_to_chars (uid_t v, char *p, size_t s) |
317 |
{ |
318 |
to_chars (v < 0, (uintmax_t) v, sizeof v, uid_substitute, p, s, "uid_t"); |
319 |
} |
320 |
|
321 |
void |
322 |
uintmax_to_chars (uintmax_t v, char *p, size_t s) |
323 |
{ |
324 |
to_chars (0, v, sizeof v, 0, p, s, "uintmax_t"); |
325 |
} |
326 |
|
327 |
void |
328 |
string_to_chars (char *str, char *p, size_t s) |
329 |
{ |
330 |
strncpy (p, str, s); |
331 |
p[s-1] = 0; |
332 |
} |
333 |
|
334 |
|
335 |
/* A file is not dumpable if |
336 |
a) it is empty *and* world-readable, or |
337 |
b) current archive is /dev/null */ |
338 |
|
339 |
bool |
340 |
file_dumpable_p (struct tar_stat_info *st) |
341 |
{ |
342 |
return !(dev_null_output |
343 |
|| (st->archive_file_size == 0 |
344 |
&& (st->stat.st_mode & MODE_R) == MODE_R)); |
345 |
} |
346 |
|
347 |
|
348 |
/* Writing routines. */ |
349 |
|
350 |
/* Write the EOT block(s). Zero at least two blocks, through the end |
351 |
of the record. Old tar, as previous versions of GNU tar, writes |
352 |
garbage after two zeroed blocks. */ |
353 |
void |
354 |
write_eot (void) |
355 |
{ |
356 |
union block *pointer = find_next_block (); |
357 |
memset (pointer->buffer, 0, BLOCKSIZE); |
358 |
set_next_block_after (pointer); |
359 |
pointer = find_next_block (); |
360 |
memset (pointer->buffer, 0, available_space_after (pointer)); |
361 |
set_next_block_after (pointer); |
362 |
} |
363 |
|
364 |
/* Copy at most LEN bytes from SRC to DST. Terminate with NUL unless |
365 |
SRC is LEN characters long */ |
366 |
static void |
367 |
tar_copy_str (char *dst, const char *src, size_t len) |
368 |
{ |
369 |
dst[len-1] = 0; |
370 |
strncpy (dst, src, len); |
371 |
} |
372 |
|
373 |
/* Write a "private" header */ |
374 |
union block * |
375 |
start_private_header (const char *name, size_t size) |
376 |
{ |
377 |
time_t t; |
378 |
union block *header = find_next_block (); |
379 |
|
380 |
memset (header->buffer, 0, sizeof (union block)); |
381 |
|
382 |
tar_copy_str (header->header.name, name, NAME_FIELD_SIZE); |
383 |
OFF_TO_CHARS (size, header->header.size); |
384 |
|
385 |
time (&t); |
386 |
TIME_TO_CHARS (t, header->header.mtime); |
387 |
MODE_TO_CHARS (S_IFREG|S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, header->header.mode); |
388 |
UID_TO_CHARS (getuid (), header->header.uid); |
389 |
GID_TO_CHARS (getgid (), header->header.gid); |
390 |
MAJOR_TO_CHARS (0, header->header.devmajor); |
391 |
MAJOR_TO_CHARS (0, header->header.devminor); |
392 |
strncpy (header->header.magic, TMAGIC, TMAGLEN); |
393 |
strncpy (header->header.version, TVERSION, TVERSLEN); |
394 |
return header; |
395 |
} |
396 |
|
397 |
/* Create a new header and store there at most NAME_FIELD_SIZE bytes of |
398 |
the file name */ |
399 |
|
400 |
static union block * |
401 |
write_short_name (struct tar_stat_info *st) |
402 |
{ |
403 |
union block *header = find_next_block (); |
404 |
memset (header->buffer, 0, sizeof (union block)); |
405 |
tar_copy_str (header->header.name, st->file_name, NAME_FIELD_SIZE); |
406 |
return header; |
407 |
} |
408 |
|
409 |
/* Write a GNUTYPE_LONGLINK or GNUTYPE_LONGNAME block. */ |
410 |
static void |
411 |
write_gnu_long_link (struct tar_stat_info *st, const char *p, char type) |
412 |
{ |
413 |
size_t size = strlen (p) + 1; |
414 |
size_t bufsize; |
415 |
union block *header; |
416 |
|
417 |
header = start_private_header ("././@LongLink", size); |
418 |
strcpy (header->header.magic, OLDGNU_MAGIC); |
419 |
header->header.typeflag = type; |
420 |
finish_header (st, header, -1); |
421 |
|
422 |
header = find_next_block (); |
423 |
|
424 |
bufsize = available_space_after (header); |
425 |
|
426 |
while (bufsize < size) |
427 |
{ |
428 |
memcpy (header->buffer, p, bufsize); |
429 |
p += bufsize; |
430 |
size -= bufsize; |
431 |
set_next_block_after (header + (bufsize - 1) / BLOCKSIZE); |
432 |
header = find_next_block (); |
433 |
bufsize = available_space_after (header); |
434 |
} |
435 |
memcpy (header->buffer, p, size); |
436 |
memset (header->buffer + size, 0, bufsize - size); |
437 |
set_next_block_after (header + (size - 1) / BLOCKSIZE); |
438 |
} |
439 |
|
440 |
static size_t |
441 |
split_long_name (const char *name, size_t length) |
442 |
{ |
443 |
size_t i; |
444 |
|
445 |
if (length > PREFIX_FIELD_SIZE) |
446 |
length = PREFIX_FIELD_SIZE+2; |
447 |
for (i = length - 1; i > 0; i--) |
448 |
if (ISSLASH (name[i])) |
449 |
break; |
450 |
return i; |
451 |
} |
452 |
|
453 |
static union block * |
454 |
write_ustar_long_name (const char *name) |
455 |
{ |
456 |
size_t length = strlen (name); |
457 |
size_t i; |
458 |
union block *header; |
459 |
|
460 |
if (length > PREFIX_FIELD_SIZE + NAME_FIELD_SIZE + 1) |
461 |
{ |
462 |
ERROR ((0, 0, _("%s: file name is too long (max %d); not dumped"), |
463 |
quotearg_colon (name), |
464 |
PREFIX_FIELD_SIZE + NAME_FIELD_SIZE + 1)); |
465 |
return NULL; |
466 |
} |
467 |
|
468 |
i = split_long_name (name, length); |
469 |
if (i == 0 || length - i - 1 > NAME_FIELD_SIZE) |
470 |
{ |
471 |
ERROR ((0, 0, |
472 |
_("%s: file name is too long (cannot be split); not dumped"), |
473 |
quotearg_colon (name))); |
474 |
return NULL; |
475 |
} |
476 |
|
477 |
header = find_next_block (); |
478 |
memset (header->buffer, 0, sizeof (header->buffer)); |
479 |
memcpy (header->header.prefix, name, i); |
480 |
memcpy (header->header.name, name + i + 1, length - i - 1); |
481 |
|
482 |
return header; |
483 |
} |
484 |
|
485 |
/* Write a long link name, depending on the current archive format */ |
486 |
static void |
487 |
write_long_link (struct tar_stat_info *st) |
488 |
{ |
489 |
switch (archive_format) |
490 |
{ |
491 |
case POSIX_FORMAT: |
492 |
xheader_store ("linkpath", st, NULL); |
493 |
break; |
494 |
|
495 |
case V7_FORMAT: /* old V7 tar format */ |
496 |
case USTAR_FORMAT: |
497 |
case STAR_FORMAT: |
498 |
ERROR ((0, 0, |
499 |
_("%s: link name is too long; not dumped"), |
500 |
quotearg_colon (st->link_name))); |
501 |
break; |
502 |
|
503 |
case OLDGNU_FORMAT: |
504 |
case GNU_FORMAT: |
505 |
write_gnu_long_link (st, st->link_name, GNUTYPE_LONGLINK); |
506 |
break; |
507 |
|
508 |
default: |
509 |
abort(); /*FIXME*/ |
510 |
} |
511 |
} |
512 |
|
513 |
static union block * |
514 |
write_long_name (struct tar_stat_info *st) |
515 |
{ |
516 |
switch (archive_format) |
517 |
{ |
518 |
case POSIX_FORMAT: |
519 |
xheader_store ("path", st, NULL); |
520 |
break; |
521 |
|
522 |
case V7_FORMAT: |
523 |
if (strlen (st->file_name) > NAME_FIELD_SIZE-1) |
524 |
{ |
525 |
ERROR ((0, 0, _("%s: file name is too long (max %d); not dumped"), |
526 |
quotearg_colon (st->file_name), |
527 |
NAME_FIELD_SIZE - 1)); |
528 |
return NULL; |
529 |
} |
530 |
break; |
531 |
|
532 |
case USTAR_FORMAT: |
533 |
case STAR_FORMAT: |
534 |
return write_ustar_long_name (st->file_name); |
535 |
|
536 |
case OLDGNU_FORMAT: |
537 |
case GNU_FORMAT: |
538 |
write_gnu_long_link (st, st->file_name, GNUTYPE_LONGNAME); |
539 |
break; |
540 |
|
541 |
default: |
542 |
abort(); /*FIXME*/ |
543 |
} |
544 |
return write_short_name (st); |
545 |
} |
546 |
|
547 |
static union block * |
548 |
write_extended (struct tar_stat_info *st, union block *old_header) |
549 |
{ |
550 |
union block *header, hp; |
551 |
char *p; |
552 |
|
553 |
if (extended_header.buffer || extended_header.stk == NULL) |
554 |
return old_header; |
555 |
|
556 |
xheader_finish (&extended_header); |
557 |
memcpy (hp.buffer, old_header, sizeof (hp)); |
558 |
p = xheader_xhdr_name (st); |
559 |
xheader_write (XHDTYPE, p, &extended_header); |
560 |
free (p); |
561 |
header = find_next_block (); |
562 |
memcpy (header, &hp.buffer, sizeof (hp.buffer)); |
563 |
return header; |
564 |
} |
565 |
|
566 |
static union block * |
567 |
write_header_name (struct tar_stat_info *st) |
568 |
{ |
569 |
if (archive_format == POSIX_FORMAT && !string_ascii_p (st->file_name)) |
570 |
{ |
571 |
xheader_store ("path", st, NULL); |
572 |
return write_short_name (st); |
573 |
} |
574 |
else if (NAME_FIELD_SIZE < strlen (st->file_name)) |
575 |
return write_long_name (st); |
576 |
else |
577 |
return write_short_name (st); |
578 |
} |
579 |
|
580 |
|
581 |
/* Header handling. */ |
582 |
|
583 |
/* Make a header block for the file whose stat info is st, |
584 |
and return its address. */ |
585 |
|
586 |
union block * |
587 |
start_header (struct tar_stat_info *st) |
588 |
{ |
589 |
union block *header; |
590 |
|
591 |
header = write_header_name (st); |
592 |
if (!header) |
593 |
return NULL; |
594 |
|
595 |
/* Override some stat fields, if requested to do so. */ |
596 |
|
597 |
if (owner_option != (uid_t) -1) |
598 |
st->stat.st_uid = owner_option; |
599 |
if (group_option != (gid_t) -1) |
600 |
st->stat.st_gid = group_option; |
601 |
if (mode_option) |
602 |
st->stat.st_mode = ((st->stat.st_mode & ~MODE_ALL) |
603 |
| mode_adjust (st->stat.st_mode, mode_option)); |
604 |
|
605 |
/* Paul Eggert tried the trivial test ($WRITER cf a b; $READER tvf a) |
606 |
for a few tars and came up with the following interoperability |
607 |
matrix: |
608 |
|
609 |
WRITER |
610 |
1 2 3 4 5 6 7 8 9 READER |
611 |
. . . . . . . . . 1 = SunOS 4.2 tar |
612 |
# . . # # . . # # 2 = NEC SVR4.0.2 tar |
613 |
. . . # # . . # . 3 = Solaris 2.1 tar |
614 |
. . . . . . . . . 4 = GNU tar 1.11.1 |
615 |
. . . . . . . . . 5 = HP-UX 8.07 tar |
616 |
. . . . . . . . . 6 = Ultrix 4.1 |
617 |
. . . . . . . . . 7 = AIX 3.2 |
618 |
. . . . . . . . . 8 = Hitachi HI-UX 1.03 |
619 |
. . . . . . . . . 9 = Omron UNIOS-B 4.3BSD 1.60Beta |
620 |
|
621 |
. = works |
622 |
# = ``impossible file type'' |
623 |
|
624 |
The following mask for old archive removes the `#'s in column 4 |
625 |
above, thus making GNU tar both a universal donor and a universal |
626 |
acceptor for Paul's test. */ |
627 |
|
628 |
if (archive_format == V7_FORMAT || archive_format == USTAR_FORMAT) |
629 |
MODE_TO_CHARS (st->stat.st_mode & MODE_ALL, header->header.mode); |
630 |
else |
631 |
MODE_TO_CHARS (st->stat.st_mode, header->header.mode); |
632 |
|
633 |
if (st->stat.st_uid > MAXOCTAL7 && archive_format == POSIX_FORMAT) |
634 |
xheader_store ("uid", st, NULL); |
635 |
else |
636 |
UID_TO_CHARS (st->stat.st_uid, header->header.uid); |
637 |
|
638 |
if (st->stat.st_gid > MAXOCTAL7 && archive_format == POSIX_FORMAT) |
639 |
xheader_store ("gid", st, NULL); |
640 |
else |
641 |
GID_TO_CHARS (st->stat.st_gid, header->header.gid); |
642 |
|
643 |
if (st->stat.st_size > MAXOCTAL11 && archive_format == POSIX_FORMAT) |
644 |
xheader_store ("size", st, NULL); |
645 |
else |
646 |
OFF_TO_CHARS (st->stat.st_size, header->header.size); |
647 |
|
648 |
TIME_TO_CHARS (st->stat.st_mtime, header->header.mtime); |
649 |
|
650 |
/* FIXME */ |
651 |
if (S_ISCHR (st->stat.st_mode) |
652 |
|| S_ISBLK (st->stat.st_mode)) |
653 |
{ |
654 |
st->devmajor = major (st->stat.st_rdev); |
655 |
st->devminor = minor (st->stat.st_rdev); |
656 |
|
657 |
if (st->devmajor > MAXOCTAL7 && archive_format == POSIX_FORMAT) |
658 |
xheader_store ("devmajor", st, NULL); |
659 |
else |
660 |
MAJOR_TO_CHARS (st->devmajor, header->header.devmajor); |
661 |
|
662 |
if (st->devminor > MAXOCTAL7 && archive_format == POSIX_FORMAT) |
663 |
xheader_store ("devminor", st, NULL); |
664 |
else |
665 |
MAJOR_TO_CHARS (st->devminor, header->header.devminor); |
666 |
} |
667 |
else |
668 |
{ |
669 |
MAJOR_TO_CHARS (0, header->header.devmajor); |
670 |
MINOR_TO_CHARS (0, header->header.devminor); |
671 |
} |
672 |
|
673 |
if (archive_format == POSIX_FORMAT) |
674 |
{ |
675 |
xheader_store ("atime", st, NULL); |
676 |
xheader_store ("ctime", st, NULL); |
677 |
} |
678 |
else if (incremental_option) |
679 |
if (archive_format == OLDGNU_FORMAT || archive_format == GNU_FORMAT) |
680 |
{ |
681 |
TIME_TO_CHARS (st->stat.st_atime, header->oldgnu_header.atime); |
682 |
TIME_TO_CHARS (st->stat.st_ctime, header->oldgnu_header.ctime); |
683 |
} |
684 |
|
685 |
header->header.typeflag = archive_format == V7_FORMAT ? AREGTYPE : REGTYPE; |
686 |
|
687 |
switch (archive_format) |
688 |
{ |
689 |
case V7_FORMAT: |
690 |
break; |
691 |
|
692 |
case OLDGNU_FORMAT: |
693 |
case GNU_FORMAT: /*FIXME?*/ |
694 |
/* Overwrite header->header.magic and header.version in one blow. */ |
695 |
strcpy (header->header.magic, OLDGNU_MAGIC); |
696 |
break; |
697 |
|
698 |
case POSIX_FORMAT: |
699 |
case USTAR_FORMAT: |
700 |
strncpy (header->header.magic, TMAGIC, TMAGLEN); |
701 |
strncpy (header->header.version, TVERSION, TVERSLEN); |
702 |
break; |
703 |
|
704 |
default: |
705 |
abort (); |
706 |
} |
707 |
|
708 |
if (archive_format == V7_FORMAT || numeric_owner_option) |
709 |
{ |
710 |
/* header->header.[ug]name are left as the empty string. */ |
711 |
} |
712 |
else |
713 |
{ |
714 |
uid_to_uname (st->stat.st_uid, &st->uname); |
715 |
gid_to_gname (st->stat.st_gid, &st->gname); |
716 |
|
717 |
if (archive_format == POSIX_FORMAT |
718 |
&& (strlen (st->uname) > UNAME_FIELD_SIZE |
719 |
|| !string_ascii_p (st->uname))) |
720 |
xheader_store ("uname", st, NULL); |
721 |
else |
722 |
UNAME_TO_CHARS (st->uname, header->header.uname); |
723 |
|
724 |
if (archive_format == POSIX_FORMAT |
725 |
&& (strlen (st->gname) > GNAME_FIELD_SIZE |
726 |
|| !string_ascii_p (st->gname))) |
727 |
xheader_store ("gname", st, NULL); |
728 |
else |
729 |
GNAME_TO_CHARS (st->gname, header->header.gname); |
730 |
} |
731 |
|
732 |
return header; |
733 |
} |
734 |
|
735 |
void |
736 |
simple_finish_header (union block *header) |
737 |
{ |
738 |
size_t i; |
739 |
int sum; |
740 |
char *p; |
741 |
|
742 |
memcpy (header->header.chksum, CHKBLANKS, sizeof header->header.chksum); |
743 |
|
744 |
sum = 0; |
745 |
p = header->buffer; |
746 |
for (i = sizeof *header; i-- != 0; ) |
747 |
/* We can't use unsigned char here because of old compilers, e.g. V7. */ |
748 |
sum += 0xFF & *p++; |
749 |
|
750 |
/* Fill in the checksum field. It's formatted differently from the |
751 |
other fields: it has [6] digits, a null, then a space -- rather than |
752 |
digits, then a null. We use to_chars. |
753 |
The final space is already there, from |
754 |
checksumming, and to_chars doesn't modify it. |
755 |
|
756 |
This is a fast way to do: |
757 |
|
758 |
sprintf(header->header.chksum, "%6o", sum); */ |
759 |
|
760 |
uintmax_to_chars ((uintmax_t) sum, header->header.chksum, 7); |
761 |
|
762 |
set_next_block_after (header); |
763 |
} |
764 |
|
765 |
/* Finish off a filled-in header block and write it out. We also |
766 |
print the file name and/or full info if verbose is on. If BLOCK_ORDINAL |
767 |
is not negative, is the block ordinal of the first record for this |
768 |
file, which may be a preceding long name or long link record. */ |
769 |
void |
770 |
finish_header (struct tar_stat_info *st, |
771 |
union block *header, off_t block_ordinal) |
772 |
{ |
773 |
/* Note: It is important to do this before the call to write_extended(), |
774 |
so that the actual ustar header is printed */ |
775 |
if (verbose_option |
776 |
&& header->header.typeflag != GNUTYPE_LONGLINK |
777 |
&& header->header.typeflag != GNUTYPE_LONGNAME |
778 |
&& header->header.typeflag != XHDTYPE |
779 |
&& header->header.typeflag != XGLTYPE) |
780 |
{ |
781 |
/* These globals are parameters to print_header, sigh. */ |
782 |
|
783 |
current_header = header; |
784 |
current_format = archive_format; |
785 |
print_header (st, block_ordinal); |
786 |
} |
787 |
|
788 |
header = write_extended (st, header); |
789 |
simple_finish_header (header); |
790 |
} |
791 |
|
792 |
|
793 |
void |
794 |
pad_archive (off_t size_left) |
795 |
{ |
796 |
union block *blk; |
797 |
while (size_left > 0) |
798 |
{ |
799 |
save_sizeleft = size_left; |
800 |
blk = find_next_block (); |
801 |
memset (blk->buffer, 0, BLOCKSIZE); |
802 |
set_next_block_after (blk); |
803 |
size_left -= BLOCKSIZE; |
804 |
} |
805 |
} |
806 |
|
807 |
static enum dump_status |
808 |
dump_regular_file (int fd, struct tar_stat_info *st) |
809 |
{ |
810 |
off_t size_left = st->stat.st_size; |
811 |
off_t block_ordinal; |
812 |
union block *blk; |
813 |
|
814 |
block_ordinal = current_block_ordinal (); |
815 |
blk = start_header (st); |
816 |
if (!blk) |
817 |
return dump_status_fail; |
818 |
|
819 |
/* Mark contiguous files, if we support them. */ |
820 |
if (archive_format != V7_FORMAT && S_ISCTG (st->stat.st_mode)) |
821 |
blk->header.typeflag = CONTTYPE; |
822 |
|
823 |
finish_header (st, blk, block_ordinal); |
824 |
|
825 |
while (size_left > 0) |
826 |
{ |
827 |
size_t bufsize, count; |
828 |
|
829 |
if (multi_volume_option) |
830 |
{ |
831 |
assign_string (&save_name, st->file_name); |
832 |
save_sizeleft = size_left; |
833 |
save_totsize = st->stat.st_size; |
834 |
} |
835 |
blk = find_next_block (); |
836 |
|
837 |
bufsize = available_space_after (blk); |
838 |
|
839 |
if (size_left < bufsize) |
840 |
{ |
841 |
/* Last read -- zero out area beyond. */ |
842 |
bufsize = size_left; |
843 |
count = bufsize % BLOCKSIZE; |
844 |
if (count) |
845 |
memset (blk->buffer + size_left, 0, BLOCKSIZE - count); |
846 |
} |
847 |
|
848 |
count = (fd < 0) ? bufsize : safe_read (fd, blk->buffer, bufsize); |
849 |
if (count == SAFE_READ_ERROR) |
850 |
{ |
851 |
read_diag_details (st->orig_file_name, |
852 |
st->stat.st_size - size_left, bufsize); |
853 |
pad_archive (size_left); |
854 |
return dump_status_short; |
855 |
} |
856 |
size_left -= count; |
857 |
|
858 |
set_next_block_after (blk + (bufsize - 1) / BLOCKSIZE); |
859 |
|
860 |
if (count != bufsize) |
861 |
{ |
862 |
char buf[UINTMAX_STRSIZE_BOUND]; |
863 |
memset (blk->buffer + count, 0, bufsize - count); |
864 |
WARN ((0, 0, |
865 |
ngettext ("%s: File shrank by %s byte; padding with zeros", |
866 |
"%s: File shrank by %s bytes; padding with zeros", |
867 |
size_left), |
868 |
quotearg_colon (st->orig_file_name), |
869 |
STRINGIFY_BIGINT (size_left, buf))); |
870 |
if (! ignore_failed_read_option) |
871 |
exit_status = TAREXIT_FAILURE; |
872 |
pad_archive (size_left); |
873 |
return dump_status_short; |
874 |
} |
875 |
} |
876 |
return dump_status_ok; |
877 |
} |
878 |
|
879 |
static void |
880 |
dump_regular_finish (int fd, struct tar_stat_info *st, time_t original_ctime) |
881 |
{ |
882 |
if (fd >= 0) |
883 |
{ |
884 |
struct stat final_stat; |
885 |
if (fstat (fd, &final_stat) != 0) |
886 |
{ |
887 |
stat_diag (st->orig_file_name); |
888 |
} |
889 |
else if (final_stat.st_ctime != original_ctime) |
890 |
{ |
891 |
WARN ((0, 0, _("%s: file changed as we read it"), |
892 |
quotearg_colon (st->orig_file_name))); |
893 |
} |
894 |
if (close (fd) != 0) |
895 |
{ |
896 |
close_diag (st->orig_file_name); |
897 |
} |
898 |
} |
899 |
if (remove_files_option) |
900 |
{ |
901 |
if (unlink (st->orig_file_name) == -1) |
902 |
unlink_error (st->orig_file_name); |
903 |
} |
904 |
} |
905 |
|
906 |
static void |
907 |
dump_dir0 (char *directory, |
908 |
struct tar_stat_info *st, int top_level, dev_t parent_device) |
909 |
{ |
910 |
dev_t our_device = st->stat.st_dev; |
911 |
|
912 |
if (!is_avoided_name (st->orig_file_name)) |
913 |
{ |
914 |
union block *blk = NULL; |
915 |
off_t block_ordinal = current_block_ordinal (); |
916 |
st->stat.st_size = 0; /* force 0 size on dir */ |
917 |
|
918 |
blk = start_header (st); |
919 |
if (!blk) |
920 |
return; |
921 |
|
922 |
if (incremental_option) |
923 |
blk->header.typeflag = GNUTYPE_DUMPDIR; |
924 |
else /* if (standard_option) */ |
925 |
blk->header.typeflag = DIRTYPE; |
926 |
|
927 |
/* If we're gnudumping, we aren't done yet so don't close it. */ |
928 |
|
929 |
if (!incremental_option) |
930 |
finish_header (st, blk, block_ordinal); |
931 |
else if (gnu_list_name->dir_contents) |
932 |
{ |
933 |
off_t size_left; |
934 |
off_t totsize; |
935 |
size_t bufsize; |
936 |
ssize_t count; |
937 |
const char *buffer, *p_buffer; |
938 |
|
939 |
block_ordinal = current_block_ordinal (); |
940 |
buffer = gnu_list_name->dir_contents; /* FOO */ |
941 |
totsize = 0; |
942 |
if (buffer) |
943 |
for (p_buffer = buffer; *p_buffer; ) |
944 |
{ |
945 |
size_t size = strlen (p_buffer) + 1; |
946 |
totsize += size; |
947 |
p_buffer += size; |
948 |
} |
949 |
totsize++; |
950 |
OFF_TO_CHARS (totsize, blk->header.size); |
951 |
finish_header (st, blk, block_ordinal); |
952 |
p_buffer = buffer; |
953 |
size_left = totsize; |
954 |
while (size_left > 0) |
955 |
{ |
956 |
if (multi_volume_option) |
957 |
{ |
958 |
assign_string (&save_name, st->orig_file_name); |
959 |
save_sizeleft = size_left; |
960 |
save_totsize = totsize; |
961 |
} |
962 |
blk = find_next_block (); |
963 |
bufsize = available_space_after (blk); |
964 |
if (size_left < bufsize) |
965 |
{ |
966 |
bufsize = size_left; |
967 |
count = bufsize % BLOCKSIZE; |
968 |
if (count) |
969 |
memset (blk->buffer + size_left, 0, BLOCKSIZE - count); |
970 |
} |
971 |
memcpy (blk->buffer, p_buffer, bufsize); |
972 |
size_left -= bufsize; |
973 |
p_buffer += bufsize; |
974 |
set_next_block_after (blk + (bufsize - 1) / BLOCKSIZE); |
975 |
} |
976 |
if (multi_volume_option) |
977 |
assign_string (&save_name, 0); |
978 |
return; |
979 |
} |
980 |
} |
981 |
|
982 |
if (!recursion_option) |
983 |
return; |
984 |
|
985 |
if (one_file_system_option |
986 |
&& !top_level |
987 |
&& parent_device != st->stat.st_dev) |
988 |
{ |
989 |
if (verbose_option) |
990 |
WARN ((0, 0, |
991 |
_("%s: file is on a different filesystem; not dumped"), |
992 |
quotearg_colon (st->orig_file_name))); |
993 |
return; |
994 |
} |
995 |
|
996 |
{ |
997 |
char const *entry; |
998 |
size_t entry_len; |
999 |
char *name_buf = strdup (st->orig_file_name); |
1000 |
size_t name_size = strlen (name_buf); |
1001 |
size_t name_len = name_size; |
1002 |
|
1003 |
/* Now output all the files in the directory. */ |
1004 |
/* FIXME: Should speed this up by cd-ing into the dir. */ |
1005 |
|
1006 |
for (entry = directory; (entry_len = strlen (entry)) != 0; |
1007 |
entry += entry_len + 1) |
1008 |
{ |
1009 |
if (name_size < name_len + entry_len) |
1010 |
{ |
1011 |
name_size = name_len + entry_len; |
1012 |
name_buf = xrealloc (name_buf, name_size + 1); |
1013 |
} |
1014 |
strcpy (name_buf + name_len, entry); |
1015 |
if (!excluded_name (name_buf)) |
1016 |
dump_file (name_buf, 0, our_device); |
1017 |
} |
1018 |
|
1019 |
free (name_buf); |
1020 |
} |
1021 |
} |
1022 |
|
1023 |
/* Ensure exactly one trailing slash. */ |
1024 |
static void |
1025 |
ensure_slash (char **pstr) |
1026 |
{ |
1027 |
size_t len = strlen (*pstr); |
1028 |
while (len >= 1 && ISSLASH ((*pstr)[len - 1])) |
1029 |
len--; |
1030 |
if (!ISSLASH ((*pstr)[len])) |
1031 |
*pstr = xrealloc (*pstr, len + 2); |
1032 |
(*pstr)[len++] = '/'; |
1033 |
(*pstr)[len] = '\0'; |
1034 |
} |
1035 |
|
1036 |
static bool |
1037 |
dump_dir (struct tar_stat_info *st, int top_level, dev_t parent_device) |
1038 |
{ |
1039 |
char *directory; |
1040 |
|
1041 |
directory = savedir (st->orig_file_name); |
1042 |
if (!directory) |
1043 |
{ |
1044 |
savedir_diag (st->orig_file_name); |
1045 |
return false; |
1046 |
} |
1047 |
|
1048 |
ensure_slash (&st->orig_file_name); |
1049 |
ensure_slash (&st->file_name); |
1050 |
|
1051 |
dump_dir0 (directory, st, top_level, parent_device); |
1052 |
|
1053 |
free (directory); |
1054 |
return true; |
1055 |
} |
1056 |
|
1057 |
|
1058 |
/* Main functions of this module. */ |
1059 |
|
1060 |
void |
1061 |
create_archive (void) |
1062 |
{ |
1063 |
char *p; |
1064 |
|
1065 |
open_archive (ACCESS_WRITE); |
1066 |
xheader_write_global (); |
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 *l = entry; |
1135 |
uintmax_t num = l->dev ^ l->ino; |
1136 |
return num % n_buckets; |
1137 |
} |
1138 |
|
1139 |
/* Compare two links for equality. */ |
1140 |
static bool |
1141 |
compare_links (void const *entry1, void const *entry2) |
1142 |
{ |
1143 |
struct link const *link1 = entry1; |
1144 |
struct link const *link2 = entry2; |
1145 |
return ((link1->dev ^ link2->dev) | (link1->ino ^ link2->ino)) == 0; |
1146 |
} |
1147 |
|
1148 |
static void |
1149 |
unknown_file_error (char *p) |
1150 |
{ |
1151 |
WARN ((0, 0, _("%s: Unknown file type; file ignored"), |
1152 |
quotearg_colon (p))); |
1153 |
if (!ignore_failed_read_option) |
1154 |
exit_status = TAREXIT_FAILURE; |
1155 |
} |
1156 |
|
1157 |
|
1158 |
/* Handling of hard links */ |
1159 |
|
1160 |
/* Table of all non-directories that we've written so far. Any time |
1161 |
we see another, we check the table and avoid dumping the data |
1162 |
again if we've done it once already. */ |
1163 |
static Hash_table *link_table; |
1164 |
|
1165 |
/* Try to dump stat as a hard link to another file in the archive. If |
1166 |
succeeded returns true */ |
1167 |
static bool |
1168 |
dump_hard_link (struct tar_stat_info *st) |
1169 |
{ |
1170 |
if (link_table && st->stat.st_nlink > 1) |
1171 |
{ |
1172 |
struct link lp; |
1173 |
struct link *duplicate; |
1174 |
off_t block_ordinal; |
1175 |
union block *blk; |
1176 |
|
1177 |
lp.ino = st->stat.st_ino; |
1178 |
lp.dev = st->stat.st_dev; |
1179 |
|
1180 |
if ((duplicate = hash_lookup (link_table, &lp))) |
1181 |
{ |
1182 |
/* We found a link. */ |
1183 |
char const *link_name = safer_name_suffix (duplicate->name, true); |
1184 |
|
1185 |
duplicate->nlink--; |
1186 |
|
1187 |
block_ordinal = current_block_ordinal (); |
1188 |
assign_string (&st->link_name, link_name); |
1189 |
if (NAME_FIELD_SIZE < strlen (link_name)) |
1190 |
write_long_link (st); |
1191 |
|
1192 |
st->stat.st_size = 0; |
1193 |
blk = start_header (st); |
1194 |
if (!blk) |
1195 |
return true; |
1196 |
tar_copy_str (blk->header.linkname, link_name, NAME_FIELD_SIZE); |
1197 |
|
1198 |
blk->header.typeflag = LNKTYPE; |
1199 |
finish_header (st, blk, block_ordinal); |
1200 |
|
1201 |
if (remove_files_option && unlink (st->orig_file_name) != 0) |
1202 |
unlink_error (st->orig_file_name); |
1203 |
|
1204 |
return true; |
1205 |
} |
1206 |
} |
1207 |
return false; |
1208 |
} |
1209 |
|
1210 |
static void |
1211 |
file_count_links (struct tar_stat_info *st) |
1212 |
{ |
1213 |
if (st->stat.st_nlink > 1) |
1214 |
{ |
1215 |
struct link *duplicate; |
1216 |
struct link *lp = xmalloc (offsetof (struct link, name) |
1217 |
+ strlen (st->orig_file_name) + 1); |
1218 |
lp->ino = st->stat.st_ino; |
1219 |
lp->dev = st->stat.st_dev; |
1220 |
lp->nlink = st->stat.st_nlink; |
1221 |
strcpy (lp->name, st->orig_file_name); |
1222 |
|
1223 |
if (! ((link_table |
1224 |
|| (link_table = hash_initialize (0, 0, hash_link, |
1225 |
compare_links, 0))) |
1226 |
&& (duplicate = hash_insert (link_table, lp)))) |
1227 |
xalloc_die (); |
1228 |
|
1229 |
if (duplicate != lp) |
1230 |
abort (); |
1231 |
lp->nlink--; |
1232 |
} |
1233 |
} |
1234 |
|
1235 |
/* For each dumped file, check if all its links were dumped. Emit |
1236 |
warnings if it is not so. */ |
1237 |
void |
1238 |
check_links (void) |
1239 |
{ |
1240 |
struct link *lp; |
1241 |
|
1242 |
if (!link_table) |
1243 |
return; |
1244 |
|
1245 |
for (lp = hash_get_first (link_table); lp; |
1246 |
lp = hash_get_next (link_table, lp)) |
1247 |
{ |
1248 |
if (lp->nlink) |
1249 |
{ |
1250 |
WARN ((0, 0, _("Missing links to '%s'.\n"), lp->name)); |
1251 |
} |
1252 |
} |
1253 |
} |
1254 |
|
1255 |
|
1256 |
/* Dump a single file, recursing on directories. P is the file name |
1257 |
to dump. TOP_LEVEL tells whether this is a top-level call; zero |
1258 |
means no, positive means yes, and negative means the top level |
1259 |
of an incremental dump. PARENT_DEVICE is the device of P's |
1260 |
parent directory; it is examined only if TOP_LEVEL is zero. */ |
1261 |
|
1262 |
/* FIXME: One should make sure that for *every* path leading to setting |
1263 |
exit_status to failure, a clear diagnostic has been issued. */ |
1264 |
|
1265 |
static void |
1266 |
dump_file0 (struct tar_stat_info *st, char *p, |
1267 |
int top_level, dev_t parent_device) |
1268 |
{ |
1269 |
union block *header; |
1270 |
char type; |
1271 |
time_t original_ctime; |
1272 |
struct utimbuf restore_times; |
1273 |
off_t block_ordinal = -1; |
1274 |
|
1275 |
if (interactive_option && !confirm ("add", p)) |
1276 |
return; |
1277 |
|
1278 |
assign_string (&st->orig_file_name, p); |
1279 |
assign_string (&st->file_name, safer_name_suffix (p, false)); |
1280 |
|
1281 |
if (deref_stat (dereference_option, p, &st->stat) != 0) |
1282 |
{ |
1283 |
stat_diag (p); |
1284 |
return; |
1285 |
} |
1286 |
st->archive_file_size = st->stat.st_size; |
1287 |
sys_stat_nanoseconds (st); |
1288 |
original_ctime = st->stat.st_ctime; |
1289 |
restore_times.actime = st->stat.st_atime; |
1290 |
restore_times.modtime = st->stat.st_mtime; |
1291 |
|
1292 |
#ifdef S_ISHIDDEN |
1293 |
if (S_ISHIDDEN (st->stat.st_mode)) |
1294 |
{ |
1295 |
char *new = (char *) alloca (strlen (p) + 2); |
1296 |
if (new) |
1297 |
{ |
1298 |
strcpy (new, p); |
1299 |
strcat (new, "@"); |
1300 |
p = new; |
1301 |
} |
1302 |
} |
1303 |
#endif |
1304 |
|
1305 |
/* See if we want only new files, and check if this one is too old to |
1306 |
put in the archive. */ |
1307 |
|
1308 |
if (!S_ISDIR (st->stat.st_mode) |
1309 |
&& OLDER_STAT_TIME (st->stat, m) |
1310 |
&& (!after_date_option || OLDER_STAT_TIME (st->stat, c))) |
1311 |
{ |
1312 |
if (0 < top_level) /* equivalent to !incremental_option */ |
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 (st)) |
1321 |
{ |
1322 |
WARN ((0, 0, _("%s: file is the archive; not dumped"), |
1323 |
quotearg_colon (p))); |
1324 |
return; |
1325 |
} |
1326 |
|
1327 |
if (S_ISDIR (st->stat.st_mode)) |
1328 |
{ |
1329 |
dump_dir (st, 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 (st)) |
1340 |
return; |
1341 |
|
1342 |
/* This is not a link to a previously dumped file, so dump it. */ |
1343 |
|
1344 |
if (S_ISREG (st->stat.st_mode) |
1345 |
|| S_ISCTG (st->stat.st_mode)) |
1346 |
{ |
1347 |
int fd; |
1348 |
enum dump_status status; |
1349 |
|
1350 |
if (file_dumpable_p (st)) |
1351 |
{ |
1352 |
fd = open (st->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 (st->orig_file_name))); |
1359 |
else |
1360 |
open_diag (st->orig_file_name); |
1361 |
return; |
1362 |
} |
1363 |
} |
1364 |
else |
1365 |
fd = -1; |
1366 |
|
1367 |
if (sparse_option && sparse_file_p (st)) |
1368 |
{ |
1369 |
status = sparse_dump_file (fd, st); |
1370 |
if (status == dump_status_not_implemented) |
1371 |
status = dump_regular_file (fd, st); |
1372 |
} |
1373 |
else |
1374 |
status = dump_regular_file (fd, st); |
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, st, 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 (st->orig_file_name, &restore_times); |
1400 |
file_count_links (st); |
1401 |
return; |
1402 |
} |
1403 |
#ifdef HAVE_READLINK |
1404 |
else if (S_ISLNK (st->stat.st_mode)) |
1405 |
{ |
1406 |
char *buffer; |
1407 |
int size; |
1408 |
size_t linklen = st->stat.st_size; |
1409 |
if (linklen != st->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 (&st->link_name, buffer); |
1420 |
if (size > NAME_FIELD_SIZE) |
1421 |
write_long_link (st); |
1422 |
|
1423 |
block_ordinal = current_block_ordinal (); |
1424 |
st->stat.st_size = 0; /* force 0 size on symlink */ |
1425 |
header = start_header (st); |
1426 |
if (!header) |
1427 |
return; |
1428 |
tar_copy_str (header->header.linkname, buffer, NAME_FIELD_SIZE); |
1429 |
header->header.typeflag = SYMTYPE; |
1430 |
finish_header (st, 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 (st); |
1439 |
return; |
1440 |
} |
1441 |
#endif |
1442 |
else if (S_ISCHR (st->stat.st_mode)) |
1443 |
type = CHRTYPE; |
1444 |
else if (S_ISBLK (st->stat.st_mode)) |
1445 |
type = BLKTYPE; |
1446 |
else if (S_ISFIFO (st->stat.st_mode)) |
1447 |
type = FIFOTYPE; |
1448 |
else if (S_ISSOCK (st->stat.st_mode)) |
1449 |
{ |
1450 |
WARN ((0, 0, _("%s: socket ignored"), quotearg_colon (p))); |
1451 |
return; |
1452 |
} |
1453 |
else if (S_ISDOOR (st->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 |
st->stat.st_size = 0; /* force 0 size */ |
1473 |
header = start_header (st); |
1474 |
if (!header) |
1475 |
return; |
1476 |
header->header.typeflag = type; |
1477 |
|
1478 |
if (type != FIFOTYPE) |
1479 |
{ |
1480 |
MAJOR_TO_CHARS (major (st->stat.st_rdev), |
1481 |
header->header.devmajor); |
1482 |
MINOR_TO_CHARS (minor (st->stat.st_rdev), |
1483 |
header->header.devminor); |
1484 |
} |
1485 |
|
1486 |
finish_header (st, 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 st; |
1498 |
tar_stat_init (&st); |
1499 |
dump_file0 (&st, p, top_level, parent_device); |
1500 |
tar_stat_destroy (&st); |
1501 |
} |