30 |
#define max(a, b) ((a) < (b) ? (b) : (a)) |
#define max(a, b) ((a) < (b) ? (b) : (a)) |
31 |
|
|
32 |
union block *current_header; /* points to current archive header */ |
union block *current_header; /* points to current archive header */ |
|
struct stat current_stat; /* stat struct corresponding */ |
|
33 |
enum archive_format current_format; /* recognized format */ |
enum archive_format current_format; /* recognized format */ |
34 |
union block *recent_long_name; /* recent long name header and contents */ |
union block *recent_long_name; /* recent long name header and contents */ |
35 |
union block *recent_long_link; /* likewise, for long link */ |
union block *recent_long_link; /* likewise, for long link */ |
87 |
/* Valid header. We should decode next field (mode) first. |
/* Valid header. We should decode next field (mode) first. |
88 |
Ensure incoming names are null terminated. */ |
Ensure incoming names are null terminated. */ |
89 |
|
|
90 |
if (! name_match (current_file_name) |
if (! name_match (current_stat_info.file_name) |
91 |
|| (newer_mtime_option != TYPE_MINIMUM (time_t) |
|| (newer_mtime_option != TYPE_MINIMUM (time_t) |
92 |
/* FIXME: We get mtime now, and again later; this causes |
/* FIXME: We get mtime now, and again later; this causes |
93 |
duplicate diagnostics if header.mtime is bogus. */ |
duplicate diagnostics if header.mtime is bogus. */ |
94 |
&& ((current_stat.st_mtime |
&& ((current_stat_info.stat.st_mtime |
95 |
= TIME_FROM_HEADER (current_header->header.mtime)) |
= TIME_FROM_HEADER (current_header->header.mtime)) |
96 |
< newer_mtime_option)) |
< newer_mtime_option)) |
97 |
|| excluded_name (current_file_name)) |
|| excluded_name (current_stat_info.file_name)) |
98 |
{ |
{ |
99 |
switch (current_header->header.typeflag) |
switch (current_header->header.typeflag) |
100 |
{ |
{ |
106 |
case DIRTYPE: |
case DIRTYPE: |
107 |
if (show_omitted_dirs_option) |
if (show_omitted_dirs_option) |
108 |
WARN ((0, 0, _("%s: Omitting"), |
WARN ((0, 0, _("%s: Omitting"), |
109 |
quotearg_colon (current_file_name))); |
quotearg_colon (current_stat_info.file_name))); |
110 |
/* Fall through. */ |
/* Fall through. */ |
111 |
default: |
default: |
112 |
skip_member (); |
skip_member (); |
178 |
if (verbose_option) |
if (verbose_option) |
179 |
{ |
{ |
180 |
if (verbose_option > 1) |
if (verbose_option > 1) |
181 |
decode_header (current_header, ¤t_stat, ¤t_format, 0); |
decode_header (current_header, ¤t_stat_info, ¤t_format, 0); |
182 |
print_header (-1); |
print_header (-1); |
183 |
} |
} |
184 |
|
|
191 |
set_next_block_after (current_header); |
set_next_block_after (current_header); |
192 |
if (multi_volume_option) |
if (multi_volume_option) |
193 |
{ |
{ |
194 |
assign_string (&save_name, current_file_name); |
assign_string (&save_name, current_stat_info.file_name); |
195 |
save_totsize = current_stat.st_size; |
save_totsize = current_stat_info.stat.st_size; |
196 |
} |
} |
197 |
for (size = current_stat.st_size; size > 0; size -= written) |
for (size = current_stat_info.stat.st_size; size > 0; size -= written) |
198 |
{ |
{ |
199 |
if (multi_volume_option) |
if (multi_volume_option) |
200 |
save_sizeleft = size; |
save_sizeleft = size; |
213 |
(data_block->buffer + written - 1)); |
(data_block->buffer + written - 1)); |
214 |
if (check != written) |
if (check != written) |
215 |
{ |
{ |
216 |
write_error_details (current_file_name, check, written); |
write_error_details (current_stat_info.file_name, check, written); |
217 |
skip_file (size - written); |
skip_file (size - written); |
218 |
break; |
break; |
219 |
} |
} |
227 |
} |
} |
228 |
|
|
229 |
if (multi_volume_option) |
if (multi_volume_option) |
230 |
assign_string (&save_name, current_file_name); |
assign_string (&save_name, current_stat_info.file_name); |
231 |
|
|
232 |
skip_member (); |
skip_member (); |
233 |
|
|
237 |
|
|
238 |
/* Read a block that's supposed to be a header block. Return its |
/* Read a block that's supposed to be a header block. Return its |
239 |
address in "current_header", and if it is good, the file's size in |
address in "current_header", and if it is good, the file's size in |
240 |
current_stat.st_size. |
current_stat_info.stat.st_size. |
241 |
|
|
242 |
Return 1 for success, 0 if the checksum is bad, EOF on eof, 2 for a |
Return 1 for success, 0 if the checksum is bad, EOF on eof, 2 for a |
243 |
block full of zeros (EOF marker). |
block full of zeros (EOF marker). |
319 |
|
|
320 |
/* Good block. Decode file size and return. */ |
/* Good block. Decode file size and return. */ |
321 |
|
|
322 |
|
if (header->header.typeflag == XHDTYPE |
323 |
|
|| header->header.typeflag == XGLTYPE) |
324 |
|
{ |
325 |
|
xheader_read (header, OFF_FROM_HEADER (header->header.size)); |
326 |
|
continue; |
327 |
|
} |
328 |
|
|
329 |
if (header->header.typeflag == LNKTYPE) |
if (header->header.typeflag == LNKTYPE) |
330 |
current_stat.st_size = 0; /* links 0 size on tape */ |
current_stat_info.stat.st_size = 0; /* links 0 size on tape */ |
331 |
else |
else |
332 |
current_stat.st_size = OFF_FROM_HEADER (header->header.size); |
current_stat_info.stat.st_size = OFF_FROM_HEADER (header->header.size); |
333 |
|
|
334 |
if (header->header.typeflag == GNUTYPE_LONGNAME |
if (header->header.typeflag == GNUTYPE_LONGNAME |
335 |
|| header->header.typeflag == GNUTYPE_LONGLINK) |
|| header->header.typeflag == GNUTYPE_LONGLINK) |
338 |
return HEADER_SUCCESS_EXTENDED; |
return HEADER_SUCCESS_EXTENDED; |
339 |
else |
else |
340 |
{ |
{ |
341 |
size_t name_size = current_stat.st_size; |
size_t name_size = current_stat_info.stat.st_size; |
342 |
size = name_size - name_size % BLOCKSIZE + 2 * BLOCKSIZE; |
size = name_size - name_size % BLOCKSIZE + 2 * BLOCKSIZE; |
343 |
if (name_size != current_stat.st_size || size < name_size) |
if (name_size != current_stat_info.stat.st_size || size < name_size) |
344 |
xalloc_die (); |
xalloc_die (); |
345 |
} |
} |
346 |
|
|
427 |
recent_long_name = 0; |
recent_long_name = 0; |
428 |
recent_long_name_blocks = 0; |
recent_long_name_blocks = 0; |
429 |
} |
} |
430 |
assign_string (&orig_file_name, name); |
assign_string (¤t_stat_info.orig_file_name, name); |
431 |
assign_string (¤t_file_name, name); |
assign_string (¤t_stat_info.file_name, name); |
432 |
current_trailing_slash = strip_trailing_slashes (current_file_name); |
current_stat_info.had_trailing_slash = strip_trailing_slashes (current_stat_info.file_name); |
433 |
|
|
434 |
if (recent_long_link) |
if (recent_long_link) |
435 |
free (recent_long_link); |
free (recent_long_link); |
448 |
recent_long_link = 0; |
recent_long_link = 0; |
449 |
recent_long_link_blocks = 0; |
recent_long_link_blocks = 0; |
450 |
} |
} |
451 |
assign_string (¤t_link_name, name); |
assign_string (¤t_stat_info.link_name, name); |
452 |
|
|
453 |
return HEADER_SUCCESS; |
return HEADER_SUCCESS; |
454 |
} |
} |
455 |
} |
} |
456 |
} |
} |
457 |
|
|
458 |
|
#define ISOCTAL(c) ((c)>='0'&&(c)<='7') |
459 |
|
|
460 |
/* Decode things from a file HEADER block into STAT_INFO, also setting |
/* Decode things from a file HEADER block into STAT_INFO, also setting |
461 |
*FORMAT_POINTER depending on the header block format. If |
*FORMAT_POINTER depending on the header block format. If |
462 |
DO_USER_GROUP, decode the user/group information (this is useful |
DO_USER_GROUP, decode the user/group information (this is useful |
471 |
should decode it without uid/gid before calling a routine, |
should decode it without uid/gid before calling a routine, |
472 |
e.g. print_header, that assumes decoded data. */ |
e.g. print_header, that assumes decoded data. */ |
473 |
void |
void |
474 |
decode_header (union block *header, struct stat *stat_info, |
decode_header (union block *header, struct tar_stat_info *stat_info, |
475 |
enum archive_format *format_pointer, int do_user_group) |
enum archive_format *format_pointer, int do_user_group) |
476 |
{ |
{ |
477 |
enum archive_format format; |
enum archive_format format; |
478 |
|
|
479 |
if (strcmp (header->header.magic, TMAGIC) == 0) |
if (strcmp (header->header.magic, TMAGIC) == 0) |
480 |
format = POSIX_FORMAT; |
{ |
481 |
|
if (header->star_header.prefix[130] == 0 |
482 |
|
&& ISOCTAL (header->star_header.atime[0]) |
483 |
|
&& header->star_header.atime[11] == ' ' |
484 |
|
&& ISOCTAL (header->star_header.ctime[0]) |
485 |
|
&& header->star_header.ctime[11] == ' ') |
486 |
|
format = STAR_FORMAT; |
487 |
|
else |
488 |
|
format = POSIX_FORMAT; |
489 |
|
} |
490 |
else if (strcmp (header->header.magic, OLDGNU_MAGIC) == 0) |
else if (strcmp (header->header.magic, OLDGNU_MAGIC) == 0) |
491 |
format = OLDGNU_FORMAT; |
format = OLDGNU_FORMAT; |
492 |
else |
else |
493 |
format = V7_FORMAT; |
format = V7_FORMAT; |
494 |
*format_pointer = format; |
*format_pointer = format; |
495 |
|
|
496 |
stat_info->st_mode = MODE_FROM_HEADER (header->header.mode); |
stat_info->stat.st_mode = MODE_FROM_HEADER (header->header.mode); |
497 |
stat_info->st_mtime = TIME_FROM_HEADER (header->header.mtime); |
stat_info->stat.st_mtime = TIME_FROM_HEADER (header->header.mtime); |
498 |
|
assign_string (&stat_info->uname, header->header.uname); |
499 |
|
assign_string (&stat_info->gname, header->header.gname); |
500 |
|
stat_info->devmajor = MAJOR_FROM_HEADER (header->header.devmajor); |
501 |
|
stat_info->devminor = MINOR_FROM_HEADER (header->header.devminor); |
502 |
|
|
503 |
if (format == OLDGNU_FORMAT && incremental_option) |
if (format == OLDGNU_FORMAT && incremental_option) |
504 |
{ |
{ |
505 |
stat_info->st_atime = TIME_FROM_HEADER (header->oldgnu_header.atime); |
stat_info->stat.st_atime = TIME_FROM_HEADER (header->oldgnu_header.atime); |
506 |
stat_info->st_ctime = TIME_FROM_HEADER (header->oldgnu_header.ctime); |
stat_info->stat.st_ctime = TIME_FROM_HEADER (header->oldgnu_header.ctime); |
507 |
} |
} |
508 |
|
|
509 |
if (format == V7_FORMAT) |
if (format == V7_FORMAT) |
510 |
{ |
{ |
511 |
stat_info->st_uid = UID_FROM_HEADER (header->header.uid); |
stat_info->stat.st_uid = UID_FROM_HEADER (header->header.uid); |
512 |
stat_info->st_gid = GID_FROM_HEADER (header->header.gid); |
stat_info->stat.st_gid = GID_FROM_HEADER (header->header.gid); |
513 |
stat_info->st_rdev = 0; |
stat_info->stat.st_rdev = 0; |
514 |
} |
} |
515 |
else |
else |
516 |
{ |
{ |
517 |
|
|
518 |
|
if (format == STAR_FORMAT) |
519 |
|
{ |
520 |
|
stat_info->stat.st_atime = TIME_FROM_HEADER (header->star_header.atime); |
521 |
|
stat_info->stat.st_ctime = TIME_FROM_HEADER (header->star_header.ctime); |
522 |
|
} |
523 |
|
|
524 |
if (do_user_group) |
if (do_user_group) |
525 |
{ |
{ |
526 |
/* FIXME: Decide if this should somewhat depend on -p. */ |
/* FIXME: Decide if this should somewhat depend on -p. */ |
527 |
|
|
528 |
if (numeric_owner_option |
if (numeric_owner_option |
529 |
|| !*header->header.uname |
|| !*header->header.uname |
530 |
|| !uname_to_uid (header->header.uname, &stat_info->st_uid)) |
|| !uname_to_uid (header->header.uname, &stat_info->stat.st_uid)) |
531 |
stat_info->st_uid = UID_FROM_HEADER (header->header.uid); |
stat_info->stat.st_uid = UID_FROM_HEADER (header->header.uid); |
532 |
|
|
533 |
if (numeric_owner_option |
if (numeric_owner_option |
534 |
|| !*header->header.gname |
|| !*header->header.gname |
535 |
|| !gname_to_gid (header->header.gname, &stat_info->st_gid)) |
|| !gname_to_gid (header->header.gname, &stat_info->stat.st_gid)) |
536 |
stat_info->st_gid = GID_FROM_HEADER (header->header.gid); |
stat_info->stat.st_gid = GID_FROM_HEADER (header->header.gid); |
537 |
} |
} |
538 |
|
|
539 |
switch (header->header.typeflag) |
switch (header->header.typeflag) |
540 |
{ |
{ |
541 |
case BLKTYPE: |
case BLKTYPE: |
|
stat_info->st_rdev |
|
|
= makedev (MAJOR_FROM_HEADER (header->header.devmajor), |
|
|
MINOR_FROM_HEADER (header->header.devminor)); |
|
|
break; |
|
|
|
|
542 |
case CHRTYPE: |
case CHRTYPE: |
543 |
stat_info->st_rdev |
stat_info->stat.st_rdev = makedev (stat_info->devmajor, stat_info->devminor); |
|
= makedev (MAJOR_FROM_HEADER (header->header.devmajor), |
|
|
MINOR_FROM_HEADER (header->header.devminor)); |
|
544 |
break; |
break; |
545 |
|
|
546 |
default: |
default: |
547 |
stat_info->st_rdev = 0; |
stat_info->stat.st_rdev = 0; |
548 |
} |
} |
549 |
} |
} |
550 |
|
|
551 |
|
if (extended_header.nblocks) |
552 |
|
xheader_decode (stat_info); |
553 |
} |
} |
554 |
|
|
555 |
/* Convert buffer at WHERE0 of size DIGS from external format to |
/* Convert buffer at WHERE0 of size DIGS from external format to |
748 |
*--value_string = '-'; |
*--value_string = '-'; |
749 |
if (minus_minval) |
if (minus_minval) |
750 |
*--minval_string = '-'; |
*--minval_string = '-'; |
751 |
ERROR ((0, 0, _("Archive value %s is out of %s range %s..%s"), |
ERROR ((0, 0, _("Archive value %s is out of %s range %s.%s"), |
752 |
value_string, type, |
value_string, type, |
753 |
minval_string, STRINGIFY_BIGINT (maxval, maxval_buf))); |
minval_string, STRINGIFY_BIGINT (maxval, maxval_buf))); |
754 |
} |
} |
910 |
|
|
911 |
|
|
912 |
/* FIXME: Note that print_header uses the globals HEAD, HSTAT, and |
/* FIXME: Note that print_header uses the globals HEAD, HSTAT, and |
913 |
HEAD_STANDARD, which must be set up in advance. Not very clean... */ |
HEAD_STANDARD, which must be set up in advance. Not very clean.. */ |
914 |
|
|
915 |
/* UGSWIDTH starts with 18, so with user and group names <= 8 chars, the |
/* UGSWIDTH starts with 18, so with user and group names <= 8 chars, the |
916 |
columns never shift during the listing. */ |
columns never shift during the listing. */ |
929 |
{ |
{ |
930 |
char modes[11]; |
char modes[11]; |
931 |
char const *time_stamp; |
char const *time_stamp; |
932 |
char *temp_name = orig_file_name ? orig_file_name : current_file_name; |
char *temp_name = current_stat_info.orig_file_name ? current_stat_info.orig_file_name : current_stat_info.file_name; |
933 |
|
|
934 |
/* These hold formatted ints. */ |
/* These hold formatted ints. */ |
935 |
char uform[UINTMAX_STRSIZE_BOUND], gform[UINTMAX_STRSIZE_BOUND]; |
char uform[UINTMAX_STRSIZE_BOUND], gform[UINTMAX_STRSIZE_BOUND]; |
1013 |
break; |
break; |
1014 |
} |
} |
1015 |
|
|
1016 |
decode_mode (current_stat.st_mode, modes + 1); |
decode_mode (current_stat_info.stat.st_mode, modes + 1); |
1017 |
|
|
1018 |
/* Time stamp. */ |
/* Time stamp. */ |
1019 |
|
|
1020 |
time_stamp = tartime (current_stat.st_mtime); |
time_stamp = tartime (current_stat_info.stat.st_mtime); |
1021 |
|
|
1022 |
/* User and group names. */ |
/* User and group names. */ |
1023 |
|
|
1072 |
case CHRTYPE: |
case CHRTYPE: |
1073 |
case BLKTYPE: |
case BLKTYPE: |
1074 |
strcpy (size, |
strcpy (size, |
1075 |
STRINGIFY_BIGINT (major (current_stat.st_rdev), uintbuf)); |
STRINGIFY_BIGINT (major (current_stat_info.stat.st_rdev), uintbuf)); |
1076 |
strcat (size, ","); |
strcat (size, ","); |
1077 |
strcat (size, |
strcat (size, |
1078 |
STRINGIFY_BIGINT (minor (current_stat.st_rdev), uintbuf)); |
STRINGIFY_BIGINT (minor (current_stat_info.stat.st_rdev), uintbuf)); |
1079 |
break; |
break; |
1080 |
case GNUTYPE_SPARSE: |
case GNUTYPE_SPARSE: |
1081 |
strcpy (size, |
strcpy (size, |
1085 |
uintbuf)); |
uintbuf)); |
1086 |
break; |
break; |
1087 |
default: |
default: |
1088 |
strcpy (size, STRINGIFY_BIGINT (current_stat.st_size, uintbuf)); |
strcpy (size, STRINGIFY_BIGINT (current_stat_info.stat.st_size, uintbuf)); |
1089 |
break; |
break; |
1090 |
} |
} |
1091 |
|
|
1103 |
switch (current_header->header.typeflag) |
switch (current_header->header.typeflag) |
1104 |
{ |
{ |
1105 |
case SYMTYPE: |
case SYMTYPE: |
1106 |
fprintf (stdlis, " -> %s\n", quotearg (current_link_name)); |
fprintf (stdlis, " -> %s\n", quotearg (current_stat_info.link_name)); |
1107 |
break; |
break; |
1108 |
|
|
1109 |
case LNKTYPE: |
case LNKTYPE: |
1110 |
fprintf (stdlis, _(" link to %s\n"), quotearg (current_link_name)); |
fprintf (stdlis, _(" link to %s\n"), quotearg (current_stat_info.link_name)); |
1111 |
break; |
break; |
1112 |
|
|
1113 |
default: |
default: |
1217 |
char save_typeflag = current_header->header.typeflag; |
char save_typeflag = current_header->header.typeflag; |
1218 |
set_next_block_after (current_header); |
set_next_block_after (current_header); |
1219 |
|
|
1220 |
if (current_header->oldgnu_header.isextended) |
if (current_format == OLDGNU_FORMAT |
1221 |
|
&& current_header->oldgnu_header.isextended) |
1222 |
{ |
{ |
1223 |
union block *exhdr; |
union block *exhdr; |
1224 |
do |
do |
1232 |
} |
} |
1233 |
|
|
1234 |
if (save_typeflag != DIRTYPE) |
if (save_typeflag != DIRTYPE) |
1235 |
skip_file (current_stat.st_size); |
skip_file (current_stat_info.stat.st_size); |
1236 |
} |
} |