353 |
set_next_block_after (pointer); |
set_next_block_after (pointer); |
354 |
} |
} |
355 |
|
|
356 |
/* Write a GNUTYPE_LONGLINK or GNUTYPE_LONGNAME block. */ |
/* Write a "private" header */ |
357 |
|
static union block * |
358 |
|
start_private_header (const char *name, size_t size) |
359 |
|
{ |
360 |
|
time_t t; |
361 |
|
union block *header = find_next_block (); |
362 |
|
|
363 |
|
memset (header->buffer, 0, sizeof (union block)); |
364 |
|
|
365 |
|
strncpy (header->header.name, name, NAME_FIELD_SIZE); |
366 |
|
header->header.name[NAME_FIELD_SIZE - 1] = '\0'; |
367 |
|
OFF_TO_CHARS (size, header->header.size); |
368 |
|
|
369 |
|
time (&t); |
370 |
|
TIME_TO_CHARS (t, header->header.mtime); |
371 |
|
MODE_TO_CHARS (S_IFREG|S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, header->header.mode); |
372 |
|
UID_TO_CHARS (getuid (), header->header.uid); |
373 |
|
GID_TO_CHARS (getgid (), header->header.gid); |
374 |
|
MAJOR_TO_CHARS (0, header->header.devmajor); |
375 |
|
MAJOR_TO_CHARS (0, header->header.devminor); |
376 |
|
strncpy (header->header.magic, TMAGIC, TMAGLEN); |
377 |
|
strncpy (header->header.version, TVERSION, TVERSLEN); |
378 |
|
return header; |
379 |
|
} |
380 |
|
|
381 |
/* FIXME: Cross recursion between start_header and write_long! */ |
/* Create a new header and store there at most NAME_FIELD_SIZE bytes of |
382 |
|
the file name */ |
383 |
|
|
384 |
static union block *start_header (const char *, struct tar_stat_info *); |
static union block * |
385 |
|
write_short_name (struct tar_stat_info *st) |
386 |
|
{ |
387 |
|
union block *header = find_next_block (); |
388 |
|
memset (header->buffer, 0, sizeof (union block)); |
389 |
|
|
390 |
|
strncpy (header->header.name, st->file_name, NAME_FIELD_SIZE); |
391 |
|
header->header.name[NAME_FIELD_SIZE - 1] = '\0'; |
392 |
|
return header; |
393 |
|
} |
394 |
|
|
395 |
|
/* Write a GNUTYPE_LONGLINK or GNUTYPE_LONGNAME block. */ |
396 |
static void |
static void |
397 |
write_long (const char *p, char type) |
write_gnu_long_link (const char *p, char type) |
398 |
{ |
{ |
399 |
size_t size = strlen (p) + 1; |
size_t size = strlen (p) + 1; |
400 |
size_t bufsize; |
size_t bufsize; |
401 |
union block *header; |
union block *header; |
|
struct tar_stat_info foo; |
|
|
|
|
|
memset (&foo, 0, sizeof foo); |
|
|
foo.stat.st_size = size; |
|
402 |
|
|
403 |
header = start_header ("././@LongLink", &foo); |
header = start_private_header ("././@LongLink", size); |
404 |
header->header.typeflag = type; |
header->header.typeflag = type; |
405 |
finish_header (header, -1); |
finish_header (header, -1); |
406 |
|
|
422 |
set_next_block_after (header + (size - 1) / BLOCKSIZE); |
set_next_block_after (header + (size - 1) / BLOCKSIZE); |
423 |
} |
} |
424 |
|
|
425 |
|
static size_t |
426 |
|
split_long_name (const char *name, size_t length) |
427 |
|
{ |
428 |
|
size_t i; |
429 |
|
|
430 |
|
if (length > PREFIX_FIELD_SIZE) |
431 |
|
length = PREFIX_FIELD_SIZE+2; |
432 |
|
for (i = length - 1; i > 0; i--) |
433 |
|
if (ISSLASH (name[i])) |
434 |
|
break; |
435 |
|
return i; |
436 |
|
} |
437 |
|
|
438 |
|
static union block * |
439 |
|
write_ustar_long_name (const char *name) |
440 |
|
{ |
441 |
|
size_t length = strlen (name); |
442 |
|
size_t i; |
443 |
|
union block *header; |
444 |
|
|
445 |
|
if (length > PREFIX_FIELD_SIZE + NAME_FIELD_SIZE + 1) |
446 |
|
{ |
447 |
|
WARN ((0, 0, _("%s: file name is too long (max %d); not dumped"), |
448 |
|
quotearg_colon (name), |
449 |
|
PREFIX_FIELD_SIZE + NAME_FIELD_SIZE + 1)); |
450 |
|
return NULL; |
451 |
|
} |
452 |
|
|
453 |
|
i = split_long_name (name, length); |
454 |
|
if (i == 0) |
455 |
|
{ |
456 |
|
WARN ((0, 0, |
457 |
|
_("%s: file name is too long (cannot be split); not dumped"), |
458 |
|
quotearg_colon (name), |
459 |
|
PREFIX_FIELD_SIZE + NAME_FIELD_SIZE + 1)); |
460 |
|
return NULL; |
461 |
|
} |
462 |
|
|
463 |
|
header = find_next_block (); |
464 |
|
memset (header->buffer, 0, sizeof (header->buffer)); |
465 |
|
memcpy (header->header.prefix, name, i); |
466 |
|
memcpy (header->header.name, name + i + 1, length - i); |
467 |
|
|
468 |
|
return header; |
469 |
|
} |
470 |
|
|
471 |
/* Write a long link name, depending on the current archive format */ |
/* Write a long link name, depending on the current archive format */ |
472 |
static void |
static void |
473 |
write_long_link (struct tar_stat_info *st) |
write_long_link (struct tar_stat_info *st) |
474 |
{ |
{ |
475 |
if (archive_format == POSIX_FORMAT) |
switch (archive_format) |
476 |
xheader_store ("linkpath", st); |
{ |
477 |
else |
case POSIX_FORMAT: |
478 |
write_long (st->link_name, GNUTYPE_LONGNAME); |
xheader_store ("linkpath", st); |
479 |
|
break; |
480 |
|
|
481 |
|
case V7_FORMAT: /* old V7 tar format */ |
482 |
|
case USTAR_FORMAT: |
483 |
|
case STAR_FORMAT: |
484 |
|
WARN ((0, 0, |
485 |
|
_("%s: link name is too long; not dumped"), |
486 |
|
quotearg_colon (st->link_name))); |
487 |
|
break; |
488 |
|
|
489 |
|
case OLDGNU_FORMAT: |
490 |
|
case GNU_FORMAT: |
491 |
|
write_gnu_long_link (st->link_name, GNUTYPE_LONGLINK); |
492 |
|
break; |
493 |
|
|
494 |
|
default: |
495 |
|
abort(); /*FIXME*/ |
496 |
|
} |
497 |
} |
} |
498 |
|
|
499 |
/* NOTE: Cross recursion between start_header and write_extended */ |
static union block * |
500 |
|
write_long_name (struct tar_stat_info *st) |
501 |
|
{ |
502 |
|
switch (archive_format) |
503 |
|
{ |
504 |
|
case POSIX_FORMAT: |
505 |
|
xheader_store ("path", st); |
506 |
|
break; |
507 |
|
|
508 |
|
case V7_FORMAT: |
509 |
|
case USTAR_FORMAT: |
510 |
|
case STAR_FORMAT: |
511 |
|
return write_ustar_long_name (st->file_name); |
512 |
|
|
513 |
|
case OLDGNU_FORMAT: |
514 |
|
case GNU_FORMAT: |
515 |
|
write_gnu_long_link (st->file_name, GNUTYPE_LONGNAME); |
516 |
|
break; |
517 |
|
|
518 |
|
default: |
519 |
|
abort(); /*FIXME*/ |
520 |
|
} |
521 |
|
return write_short_name (st); |
522 |
|
} |
523 |
|
|
524 |
static union block * |
static union block * |
525 |
write_extended (union block *old_header, char type) |
write_extended (union block *old_header, char type) |
530 |
char *p; |
char *p; |
531 |
|
|
532 |
if (extended_header.buffer || extended_header.stk == NULL) |
if (extended_header.buffer || extended_header.stk == NULL) |
533 |
return old_header; /* Prevent recursion */ |
return old_header; |
534 |
|
|
535 |
xheader_finish (&extended_header); |
xheader_finish (&extended_header); |
536 |
size = extended_header.size; |
size = extended_header.size; |
|
memset (&foo, 0, sizeof foo); |
|
|
foo.stat.st_mode = S_IFREG|S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH; |
|
|
time (&foo.stat.st_ctime); |
|
|
foo.stat.st_atime = foo.stat.st_ctime; |
|
|
foo.stat.st_mtime = foo.stat.st_ctime; |
|
|
foo.stat.st_size = size; |
|
537 |
|
|
538 |
memcpy (hp.buffer, old_header, sizeof (hp)); |
memcpy (hp.buffer, old_header, sizeof (hp)); |
539 |
|
|
540 |
header = start_header ("././@PaxHeader", &foo); |
header = start_private_header ("././@PaxHeader", size); |
541 |
header->header.typeflag = type; |
header->header.typeflag = type; |
542 |
|
|
543 |
finish_header (header, -1); |
finish_header (header, -1); |
560 |
set_next_block_after (header); |
set_next_block_after (header); |
561 |
} |
} |
562 |
while (size > 0); |
while (size > 0); |
563 |
|
|
564 |
xheader_destroy (&extended_header); |
xheader_destroy (&extended_header); |
565 |
header = find_next_block (); |
header = find_next_block (); |
566 |
memcpy (header, &hp.buffer, sizeof (hp.buffer)); |
memcpy (header, &hp.buffer, sizeof (hp.buffer)); |
567 |
return header; |
return header; |
568 |
} |
} |
569 |
|
|
570 |
|
static union block * |
571 |
|
write_header_name (struct tar_stat_info *st) |
572 |
|
{ |
573 |
|
if (NAME_FIELD_SIZE <= strlen (st->file_name)) |
574 |
|
return write_long_name (st); |
575 |
|
else |
576 |
|
return write_short_name (st); |
577 |
|
} |
578 |
|
|
579 |
|
|
580 |
/* Header handling. */ |
/* Header handling. */ |
581 |
|
|
588 |
union block *header; |
union block *header; |
589 |
|
|
590 |
name = safer_name_suffix (name, 0); |
name = safer_name_suffix (name, 0); |
591 |
|
if (name[0] == '.' && name[1] == 0) /*FIXME!!!*/ |
592 |
|
return NULL; |
593 |
assign_string (&st->file_name, name); |
assign_string (&st->file_name, name); |
594 |
|
|
595 |
if (sizeof header->header.name <= strlen (name)) |
header = write_header_name (st); |
596 |
{ |
if (!header) |
597 |
if (archive_format == POSIX_FORMAT) |
return NULL; |
|
xheader_store ("path", st); |
|
|
else |
|
|
write_long (name, GNUTYPE_LONGNAME); |
|
|
} |
|
|
|
|
|
header = find_next_block (); |
|
|
memset (header->buffer, 0, sizeof (union block)); |
|
598 |
|
|
599 |
assign_string (¤t_stat_info.file_name, name); |
assign_string (¤t_stat_info.file_name, name); |
600 |
|
|
|
strncpy (header->header.name, name, NAME_FIELD_SIZE); |
|
|
header->header.name[NAME_FIELD_SIZE - 1] = '\0'; |
|
|
|
|
601 |
/* Override some stat fields, if requested to do so. */ |
/* Override some stat fields, if requested to do so. */ |
602 |
|
|
603 |
if (owner_option != (uid_t) -1) |
if (owner_option != (uid_t) -1) |
631 |
above, thus making GNU tar both a universal donor and a universal |
above, thus making GNU tar both a universal donor and a universal |
632 |
acceptor for Paul's test. */ |
acceptor for Paul's test. */ |
633 |
|
|
634 |
if (archive_format == V7_FORMAT) |
if (archive_format == V7_FORMAT || archive_format == USTAR_FORMAT) |
635 |
MODE_TO_CHARS (st->stat.st_mode & MODE_ALL, header->header.mode); |
MODE_TO_CHARS (st->stat.st_mode & MODE_ALL, header->header.mode); |
636 |
else |
else |
637 |
MODE_TO_CHARS (st->stat.st_mode, header->header.mode); |
MODE_TO_CHARS (st->stat.st_mode, header->header.mode); |
701 |
break; |
break; |
702 |
|
|
703 |
case POSIX_FORMAT: |
case POSIX_FORMAT: |
704 |
case GNU_FORMAT: |
case USTAR_FORMAT: |
705 |
|
case GNU_FORMAT: /*FIXME?*/ |
706 |
strncpy (header->header.magic, TMAGIC, TMAGLEN); |
strncpy (header->header.magic, TMAGIC, TMAGLEN); |
707 |
strncpy (header->header.version, TVERSION, TVERSLEN); |
strncpy (header->header.version, TVERSION, TVERSLEN); |
708 |
break; |
break; |
1227 |
files, we'd better put the / on the name. */ |
files, we'd better put the / on the name. */ |
1228 |
|
|
1229 |
header = start_header (namebuf, ¤t_stat_info); |
header = start_header (namebuf, ¤t_stat_info); |
1230 |
|
if (!header) |
1231 |
|
return; |
1232 |
|
|
1233 |
if (incremental_option) |
if (incremental_option) |
1234 |
header->header.typeflag = GNUTYPE_DUMPDIR; |
header->header.typeflag = GNUTYPE_DUMPDIR; |
1235 |
else /* if (standard_option) */ |
else /* if (standard_option) */ |
1363 |
|
|
1364 |
current_stat_info.stat.st_size = 0; |
current_stat_info.stat.st_size = 0; |
1365 |
header = start_header (p, ¤t_stat_info); |
header = start_header (p, ¤t_stat_info); |
1366 |
|
if (!header) |
1367 |
|
return; |
1368 |
strncpy (header->header.linkname, link_name, NAME_FIELD_SIZE); |
strncpy (header->header.linkname, link_name, NAME_FIELD_SIZE); |
1369 |
|
|
1370 |
/* Force null termination. */ |
/* Force null termination. */ |
1441 |
|
|
1442 |
block_ordinal = current_block_ordinal (); |
block_ordinal = current_block_ordinal (); |
1443 |
header = start_header (p, ¤t_stat_info); |
header = start_header (p, ¤t_stat_info); |
1444 |
|
if (!header) |
1445 |
|
return; |
1446 |
header->header.typeflag = GNUTYPE_SPARSE; |
header->header.typeflag = GNUTYPE_SPARSE; |
1447 |
header_moved = 1; |
header_moved = 1; |
1448 |
|
|
1514 |
{ |
{ |
1515 |
block_ordinal = current_block_ordinal (); |
block_ordinal = current_block_ordinal (); |
1516 |
header = start_header (p, ¤t_stat_info); |
header = start_header (p, ¤t_stat_info); |
1517 |
|
if (!header) |
1518 |
|
return; |
1519 |
} |
} |
1520 |
|
|
1521 |
/* Mark contiguous files, if we support them. */ |
/* Mark contiguous files, if we support them. */ |
1522 |
|
|
1523 |
if (archive_format != V7_FORMAT && S_ISCTG (current_stat_info.stat.st_mode)) |
if (archive_format != V7_FORMAT |
1524 |
|
&& S_ISCTG (current_stat_info.stat.st_mode)) |
1525 |
header->header.typeflag = CONTTYPE; |
header->header.typeflag = CONTTYPE; |
1526 |
|
|
1527 |
isextended = header->oldgnu_header.isextended; |
if (archive_format == GNU_FORMAT || archive_format == OLDGNU_FORMAT) |
1528 |
|
isextended = header->oldgnu_header.isextended; |
1529 |
|
else |
1530 |
|
isextended = 0; |
1531 |
|
if (isextended) |
1532 |
|
abort(); |
1533 |
save_typeflag = header->header.typeflag; |
save_typeflag = header->header.typeflag; |
1534 |
finish_header (header, block_ordinal); |
finish_header (header, block_ordinal); |
1535 |
if (isextended) |
if (isextended) |
1705 |
block_ordinal = current_block_ordinal (); |
block_ordinal = current_block_ordinal (); |
1706 |
current_stat_info.stat.st_size = 0; /* force 0 size on symlink */ |
current_stat_info.stat.st_size = 0; /* force 0 size on symlink */ |
1707 |
header = start_header (p, ¤t_stat_info); |
header = start_header (p, ¤t_stat_info); |
1708 |
|
if (!header) |
1709 |
|
return; |
1710 |
strncpy (header->header.linkname, buffer, NAME_FIELD_SIZE); |
strncpy (header->header.linkname, buffer, NAME_FIELD_SIZE); |
1711 |
header->header.linkname[NAME_FIELD_SIZE - 1] = '\0'; |
header->header.linkname[NAME_FIELD_SIZE - 1] = '\0'; |
1712 |
header->header.typeflag = SYMTYPE; |
header->header.typeflag = SYMTYPE; |
1747 |
block_ordinal = current_block_ordinal (); |
block_ordinal = current_block_ordinal (); |
1748 |
current_stat_info.stat.st_size = 0; /* force 0 size */ |
current_stat_info.stat.st_size = 0; /* force 0 size */ |
1749 |
header = start_header (p, ¤t_stat_info); |
header = start_header (p, ¤t_stat_info); |
1750 |
|
if (!header) |
1751 |
|
return; |
1752 |
header->header.typeflag = type; |
header->header.typeflag = type; |
1753 |
|
|
1754 |
if (type != FIFOTYPE) |
if (type != FIFOTYPE) |