More work on ACLs: fix error in archive_entry's ACL parsing code,

try to set ACLs even if fflag restore fails, first cut at reading
  Solaris tar ACLs

Code improvement: merge gnu tar read support into main tar reader;
  this eliminates a lot of duplicate code and generalizes the tar
  reader to handle formats with GNU-like extensions.

Style: Makefile cleanup, eliminate 'dmalloc' references, remove 'tartype'
  from archive_entry (this makes archive_entry more format-agnostic)

Thanks to: David Magda for providing Solaris tar test files
This commit is contained in:
Tim Kientzle 2004-04-12 01:16:16 +00:00
parent 4cbbc3a35e
commit aee47dd7c8
36 changed files with 396 additions and 933 deletions

View File

@ -1,14 +1,16 @@
# Makefile for libarchive.
#
# $FreeBSD$
DEBUG_FLAGS=-g
LIB= archive
SHLIB_MAJOR= 1
WARNS?= 6
# I'm not yet ready for a shared version of this library, as
# there are a couple of API changes still in the works.
NOPIC= 1
INCS= archive.h archive_entry.h
SRCS= archive_check_magic.c \
archive_entry.c \
archive_read.c \
@ -23,7 +25,6 @@ SRCS= archive_check_magic.c \
archive_read_support_compression_none.c \
archive_read_support_format_all.c \
archive_read_support_format_cpio.c \
archive_read_support_format_gnutar.c \
archive_read_support_format_tar.c \
archive_string.c \
archive_string_sprintf.c \
@ -41,90 +42,78 @@ SRCS= archive_check_magic.c \
archive_write_set_format_shar.c \
archive_write_set_format_ustar.c
MAN = archive_entry.3 \
MAN= archive_entry.3 \
archive_read.3 \
archive_util.3 \
archive_write.3 \
libarchive.3 \
tar.5
MLINKS += archive_entry.3 archive_entry_clear.3
MLINKS += archive_entry.3 archive_entry_clone.3
MLINKS += archive_entry.3 archive_entry_copy_stat.3
MLINKS += archive_entry.3 archive_entry_dup.3
MLINKS += archive_entry.3 archive_entry_free.3
MLINKS += archive_entry.3 archive_entry_gname.3
MLINKS += archive_entry.3 archive_entry_hardlink.3
MLINKS += archive_entry.3 archive_entry_new.3
MLINKS += archive_entry.3 archive_entry_pathname.3
MLINKS += archive_entry.3 archive_entry_set_devmajor.3
MLINKS += archive_entry.3 archive_entry_set_devminor.3
MLINKS += archive_entry.3 archive_entry_set_gid.3
MLINKS += archive_entry.3 archive_entry_set_gname.3
MLINKS += archive_entry.3 archive_entry_set_hardlink.3
MLINKS += archive_entry.3 archive_entry_set_mode.3
MLINKS += archive_entry.3 archive_entry_set_pathname.3
MLINKS += archive_entry.3 archive_entry_set_symlink.3
MLINKS += archive_entry.3 archive_entry_set_tartype.3
MLINKS += archive_entry.3 archive_entry_set_uid.3
MLINKS += archive_entry.3 archive_entry_set_uname.3
MLINKS += archive_entry.3 archive_entry_size.3
MLINKS += archive_entry.3 archive_entry_stat.3
MLINKS += archive_entry.3 archive_entry_symlink.3
MLINKS += archive_entry.3 archive_entry_tartype.3
MLINKS += archive_entry.3 archive_entry_uname.3
MLINKS += archive_read.3 archive_read_data.3
MLINKS += archive_read.3 archive_read_data_into_buffer.3
MLINKS += archive_read.3 archive_read_data_into_file.3
MLINKS += archive_read.3 archive_read_data_skip.3
MLINKS += archive_read.3 archive_read_extract.3
MLINKS += archive_read.3 archive_read_finish.3
MLINKS += archive_read.3 archive_read_new.3
MLINKS += archive_read.3 archive_read_next_header.3
MLINKS += archive_read.3 archive_read_open.3
MLINKS += archive_read.3 archive_read_open_fd.3
MLINKS += archive_read.3 archive_read_open_file.3
MLINKS += archive_read.3 archive_read_set_bytes_per_block.3
MLINKS += archive_read.3 archive_read_support_compression_all.3
MLINKS += archive_read.3 archive_read_support_compression_bzip2.3
MLINKS += archive_read.3 archive_read_support_compression_gzip.3
MLINKS += archive_read.3 archive_read_support_compression_none.3
MLINKS += archive_read.3 archive_read_support_format_all.3
MLINKS += archive_read.3 archive_read_support_format_cpio.3
MLINKS += archive_read.3 archive_read_support_format_gnutar.3
MLINKS += archive_read.3 archive_read_support_format_tar.3
MLINKS += archive_util.3 archive_compression.3
MLINKS += archive_util.3 archive_compression_name.3
MLINKS += archive_util.3 archive_errno.3
MLINKS += archive_util.3 archive_error_string.3
MLINKS += archive_util.3 archive_format.3
MLINKS += archive_util.3 archive_format_name.3
MLINKS += archive_write.3 archive_write_data.3
MLINKS += archive_write.3 archive_write_finish.3
MLINKS += archive_write.3 archive_write_header.3
MLINKS += archive_write.3 archive_write_new.3
MLINKS += archive_write.3 archive_write_open.3
MLINKS += archive_write.3 archive_write_open_fd.3
MLINKS += archive_write.3 archive_write_open_file.3
MLINKS += archive_write.3 archive_write_prepare.3
MLINKS += archive_write.3 archive_write_set_bytes_per_block.3
MLINKS += archive_write.3 archive_write_set_bytes_in_last_block.3
MLINKS += archive_write.3 archive_write_set_callbacks.3
MLINKS += archive_write.3 archive_write_set_compression_bzip2.3
MLINKS += archive_write.3 archive_write_set_compression_gzip.3
MLINKS += archive_write.3 archive_write_set_format_pax.3
MLINKS += archive_write.3 archive_write_set_format_ustar.3
MLINKS += libarchive.3 archive.3
INCS = archive.h archive_entry.h
.if defined(DMALLOC)
DEBUG_FLAGS+= -DDEBUG -g
CFLAGS+= -DHAVE_DMALLOC -I/usr/local/include
LDFLAGS+= -L/usr/local/lib -ldmalloc
.endif
#CFLAGS+= -O3
WARNS?= 6
MLINKS+= archive_entry.3 archive_entry_clear.3
MLINKS+= archive_entry.3 archive_entry_clone.3
MLINKS+= archive_entry.3 archive_entry_copy_stat.3
MLINKS+= archive_entry.3 archive_entry_dup.3
MLINKS+= archive_entry.3 archive_entry_free.3
MLINKS+= archive_entry.3 archive_entry_gname.3
MLINKS+= archive_entry.3 archive_entry_hardlink.3
MLINKS+= archive_entry.3 archive_entry_new.3
MLINKS+= archive_entry.3 archive_entry_pathname.3
MLINKS+= archive_entry.3 archive_entry_set_devmajor.3
MLINKS+= archive_entry.3 archive_entry_set_devminor.3
MLINKS+= archive_entry.3 archive_entry_set_gid.3
MLINKS+= archive_entry.3 archive_entry_set_gname.3
MLINKS+= archive_entry.3 archive_entry_set_hardlink.3
MLINKS+= archive_entry.3 archive_entry_set_link.3
MLINKS+= archive_entry.3 archive_entry_set_mode.3
MLINKS+= archive_entry.3 archive_entry_set_pathname.3
MLINKS+= archive_entry.3 archive_entry_set_symlink.3
MLINKS+= archive_entry.3 archive_entry_set_uid.3
MLINKS+= archive_entry.3 archive_entry_set_uname.3
MLINKS+= archive_entry.3 archive_entry_size.3
MLINKS+= archive_entry.3 archive_entry_stat.3
MLINKS+= archive_entry.3 archive_entry_symlink.3
MLINKS+= archive_entry.3 archive_entry_uname.3
MLINKS+= archive_read.3 archive_read_data.3
MLINKS+= archive_read.3 archive_read_data_into_buffer.3
MLINKS+= archive_read.3 archive_read_data_into_file.3
MLINKS+= archive_read.3 archive_read_data_skip.3
MLINKS+= archive_read.3 archive_read_extract.3
MLINKS+= archive_read.3 archive_read_finish.3
MLINKS+= archive_read.3 archive_read_new.3
MLINKS+= archive_read.3 archive_read_next_header.3
MLINKS+= archive_read.3 archive_read_open.3
MLINKS+= archive_read.3 archive_read_open_fd.3
MLINKS+= archive_read.3 archive_read_open_file.3
MLINKS+= archive_read.3 archive_read_set_bytes_per_block.3
MLINKS+= archive_read.3 archive_read_support_compression_all.3
MLINKS+= archive_read.3 archive_read_support_compression_bzip2.3
MLINKS+= archive_read.3 archive_read_support_compression_gzip.3
MLINKS+= archive_read.3 archive_read_support_compression_none.3
MLINKS+= archive_read.3 archive_read_support_format_all.3
MLINKS+= archive_read.3 archive_read_support_format_cpio.3
MLINKS+= archive_read.3 archive_read_support_format_gnutar.3
MLINKS+= archive_read.3 archive_read_support_format_tar.3
MLINKS+= archive_util.3 archive_compression.3
MLINKS+= archive_util.3 archive_compression_name.3
MLINKS+= archive_util.3 archive_errno.3
MLINKS+= archive_util.3 archive_error_string.3
MLINKS+= archive_util.3 archive_format.3
MLINKS+= archive_util.3 archive_format_name.3
MLINKS+= archive_write.3 archive_write_data.3
MLINKS+= archive_write.3 archive_write_finish.3
MLINKS+= archive_write.3 archive_write_header.3
MLINKS+= archive_write.3 archive_write_new.3
MLINKS+= archive_write.3 archive_write_open.3
MLINKS+= archive_write.3 archive_write_open_fd.3
MLINKS+= archive_write.3 archive_write_open_file.3
MLINKS+= archive_write.3 archive_write_prepare.3
MLINKS+= archive_write.3 archive_write_set_bytes_per_block.3
MLINKS+= archive_write.3 archive_write_set_bytes_in_last_block.3
MLINKS+= archive_write.3 archive_write_set_callbacks.3
MLINKS+= archive_write.3 archive_write_set_compression_bzip2.3
MLINKS+= archive_write.3 archive_write_set_compression_gzip.3
MLINKS+= archive_write.3 archive_write_set_format_pax.3
MLINKS+= archive_write.3 archive_write_set_format_ustar.3
MLINKS+= libarchive.3 archive.3
.include <bsd.lib.mk>

View File

@ -1,14 +1,16 @@
# Makefile for libarchive.
#
# $FreeBSD$
DEBUG_FLAGS=-g
LIB= archive
SHLIB_MAJOR= 1
WARNS?= 6
# I'm not yet ready for a shared version of this library, as
# there are a couple of API changes still in the works.
NOPIC= 1
INCS= archive.h archive_entry.h
SRCS= archive_check_magic.c \
archive_entry.c \
archive_read.c \
@ -23,7 +25,6 @@ SRCS= archive_check_magic.c \
archive_read_support_compression_none.c \
archive_read_support_format_all.c \
archive_read_support_format_cpio.c \
archive_read_support_format_gnutar.c \
archive_read_support_format_tar.c \
archive_string.c \
archive_string_sprintf.c \
@ -41,90 +42,78 @@ SRCS= archive_check_magic.c \
archive_write_set_format_shar.c \
archive_write_set_format_ustar.c
MAN = archive_entry.3 \
MAN= archive_entry.3 \
archive_read.3 \
archive_util.3 \
archive_write.3 \
libarchive.3 \
tar.5
MLINKS += archive_entry.3 archive_entry_clear.3
MLINKS += archive_entry.3 archive_entry_clone.3
MLINKS += archive_entry.3 archive_entry_copy_stat.3
MLINKS += archive_entry.3 archive_entry_dup.3
MLINKS += archive_entry.3 archive_entry_free.3
MLINKS += archive_entry.3 archive_entry_gname.3
MLINKS += archive_entry.3 archive_entry_hardlink.3
MLINKS += archive_entry.3 archive_entry_new.3
MLINKS += archive_entry.3 archive_entry_pathname.3
MLINKS += archive_entry.3 archive_entry_set_devmajor.3
MLINKS += archive_entry.3 archive_entry_set_devminor.3
MLINKS += archive_entry.3 archive_entry_set_gid.3
MLINKS += archive_entry.3 archive_entry_set_gname.3
MLINKS += archive_entry.3 archive_entry_set_hardlink.3
MLINKS += archive_entry.3 archive_entry_set_mode.3
MLINKS += archive_entry.3 archive_entry_set_pathname.3
MLINKS += archive_entry.3 archive_entry_set_symlink.3
MLINKS += archive_entry.3 archive_entry_set_tartype.3
MLINKS += archive_entry.3 archive_entry_set_uid.3
MLINKS += archive_entry.3 archive_entry_set_uname.3
MLINKS += archive_entry.3 archive_entry_size.3
MLINKS += archive_entry.3 archive_entry_stat.3
MLINKS += archive_entry.3 archive_entry_symlink.3
MLINKS += archive_entry.3 archive_entry_tartype.3
MLINKS += archive_entry.3 archive_entry_uname.3
MLINKS += archive_read.3 archive_read_data.3
MLINKS += archive_read.3 archive_read_data_into_buffer.3
MLINKS += archive_read.3 archive_read_data_into_file.3
MLINKS += archive_read.3 archive_read_data_skip.3
MLINKS += archive_read.3 archive_read_extract.3
MLINKS += archive_read.3 archive_read_finish.3
MLINKS += archive_read.3 archive_read_new.3
MLINKS += archive_read.3 archive_read_next_header.3
MLINKS += archive_read.3 archive_read_open.3
MLINKS += archive_read.3 archive_read_open_fd.3
MLINKS += archive_read.3 archive_read_open_file.3
MLINKS += archive_read.3 archive_read_set_bytes_per_block.3
MLINKS += archive_read.3 archive_read_support_compression_all.3
MLINKS += archive_read.3 archive_read_support_compression_bzip2.3
MLINKS += archive_read.3 archive_read_support_compression_gzip.3
MLINKS += archive_read.3 archive_read_support_compression_none.3
MLINKS += archive_read.3 archive_read_support_format_all.3
MLINKS += archive_read.3 archive_read_support_format_cpio.3
MLINKS += archive_read.3 archive_read_support_format_gnutar.3
MLINKS += archive_read.3 archive_read_support_format_tar.3
MLINKS += archive_util.3 archive_compression.3
MLINKS += archive_util.3 archive_compression_name.3
MLINKS += archive_util.3 archive_errno.3
MLINKS += archive_util.3 archive_error_string.3
MLINKS += archive_util.3 archive_format.3
MLINKS += archive_util.3 archive_format_name.3
MLINKS += archive_write.3 archive_write_data.3
MLINKS += archive_write.3 archive_write_finish.3
MLINKS += archive_write.3 archive_write_header.3
MLINKS += archive_write.3 archive_write_new.3
MLINKS += archive_write.3 archive_write_open.3
MLINKS += archive_write.3 archive_write_open_fd.3
MLINKS += archive_write.3 archive_write_open_file.3
MLINKS += archive_write.3 archive_write_prepare.3
MLINKS += archive_write.3 archive_write_set_bytes_per_block.3
MLINKS += archive_write.3 archive_write_set_bytes_in_last_block.3
MLINKS += archive_write.3 archive_write_set_callbacks.3
MLINKS += archive_write.3 archive_write_set_compression_bzip2.3
MLINKS += archive_write.3 archive_write_set_compression_gzip.3
MLINKS += archive_write.3 archive_write_set_format_pax.3
MLINKS += archive_write.3 archive_write_set_format_ustar.3
MLINKS += libarchive.3 archive.3
INCS = archive.h archive_entry.h
.if defined(DMALLOC)
DEBUG_FLAGS+= -DDEBUG -g
CFLAGS+= -DHAVE_DMALLOC -I/usr/local/include
LDFLAGS+= -L/usr/local/lib -ldmalloc
.endif
#CFLAGS+= -O3
WARNS?= 6
MLINKS+= archive_entry.3 archive_entry_clear.3
MLINKS+= archive_entry.3 archive_entry_clone.3
MLINKS+= archive_entry.3 archive_entry_copy_stat.3
MLINKS+= archive_entry.3 archive_entry_dup.3
MLINKS+= archive_entry.3 archive_entry_free.3
MLINKS+= archive_entry.3 archive_entry_gname.3
MLINKS+= archive_entry.3 archive_entry_hardlink.3
MLINKS+= archive_entry.3 archive_entry_new.3
MLINKS+= archive_entry.3 archive_entry_pathname.3
MLINKS+= archive_entry.3 archive_entry_set_devmajor.3
MLINKS+= archive_entry.3 archive_entry_set_devminor.3
MLINKS+= archive_entry.3 archive_entry_set_gid.3
MLINKS+= archive_entry.3 archive_entry_set_gname.3
MLINKS+= archive_entry.3 archive_entry_set_hardlink.3
MLINKS+= archive_entry.3 archive_entry_set_link.3
MLINKS+= archive_entry.3 archive_entry_set_mode.3
MLINKS+= archive_entry.3 archive_entry_set_pathname.3
MLINKS+= archive_entry.3 archive_entry_set_symlink.3
MLINKS+= archive_entry.3 archive_entry_set_uid.3
MLINKS+= archive_entry.3 archive_entry_set_uname.3
MLINKS+= archive_entry.3 archive_entry_size.3
MLINKS+= archive_entry.3 archive_entry_stat.3
MLINKS+= archive_entry.3 archive_entry_symlink.3
MLINKS+= archive_entry.3 archive_entry_uname.3
MLINKS+= archive_read.3 archive_read_data.3
MLINKS+= archive_read.3 archive_read_data_into_buffer.3
MLINKS+= archive_read.3 archive_read_data_into_file.3
MLINKS+= archive_read.3 archive_read_data_skip.3
MLINKS+= archive_read.3 archive_read_extract.3
MLINKS+= archive_read.3 archive_read_finish.3
MLINKS+= archive_read.3 archive_read_new.3
MLINKS+= archive_read.3 archive_read_next_header.3
MLINKS+= archive_read.3 archive_read_open.3
MLINKS+= archive_read.3 archive_read_open_fd.3
MLINKS+= archive_read.3 archive_read_open_file.3
MLINKS+= archive_read.3 archive_read_set_bytes_per_block.3
MLINKS+= archive_read.3 archive_read_support_compression_all.3
MLINKS+= archive_read.3 archive_read_support_compression_bzip2.3
MLINKS+= archive_read.3 archive_read_support_compression_gzip.3
MLINKS+= archive_read.3 archive_read_support_compression_none.3
MLINKS+= archive_read.3 archive_read_support_format_all.3
MLINKS+= archive_read.3 archive_read_support_format_cpio.3
MLINKS+= archive_read.3 archive_read_support_format_gnutar.3
MLINKS+= archive_read.3 archive_read_support_format_tar.3
MLINKS+= archive_util.3 archive_compression.3
MLINKS+= archive_util.3 archive_compression_name.3
MLINKS+= archive_util.3 archive_errno.3
MLINKS+= archive_util.3 archive_error_string.3
MLINKS+= archive_util.3 archive_format.3
MLINKS+= archive_util.3 archive_format_name.3
MLINKS+= archive_write.3 archive_write_data.3
MLINKS+= archive_write.3 archive_write_finish.3
MLINKS+= archive_write.3 archive_write_header.3
MLINKS+= archive_write.3 archive_write_new.3
MLINKS+= archive_write.3 archive_write_open.3
MLINKS+= archive_write.3 archive_write_open_fd.3
MLINKS+= archive_write.3 archive_write_open_file.3
MLINKS+= archive_write.3 archive_write_prepare.3
MLINKS+= archive_write.3 archive_write_set_bytes_per_block.3
MLINKS+= archive_write.3 archive_write_set_bytes_in_last_block.3
MLINKS+= archive_write.3 archive_write_set_callbacks.3
MLINKS+= archive_write.3 archive_write_set_compression_bzip2.3
MLINKS+= archive_write.3 archive_write_set_compression_gzip.3
MLINKS+= archive_write.3 archive_write_set_format_pax.3
MLINKS+= archive_write.3 archive_write_set_format_ustar.3
MLINKS+= libarchive.3 archive.3
.include <bsd.lib.mk>

View File

@ -29,9 +29,6 @@ __FBSDID("$FreeBSD$");
#include <sys/types.h>
#ifdef HAVE_DMALLOC
#include <dmalloc.h>
#endif
#include <stdio.h>
#include <string.h>
#include <unistd.h>

View File

@ -52,14 +52,12 @@
.Nm archive_entry_set_mode
.Nm archive_entry_set_pathname
.Nm archive_entry_set_symlink
.Nm archive_entry_set_tartype
.Nm archive_entry_set_uid
.Nm archive_entry_set_uname
.Nm archive_entry_size
.Nm archive_entry_stat
.Nm archive_entry_symlink
.Nm archive_entry_symlink_w
.Nm archive_entry_tartype
.Nm archive_entry_uname
.Nm archive_entry_uname_w
.Nd functions for manipulating archive entry descriptions
@ -114,8 +112,6 @@
.Ft void
.Fn archive_entry_set_symlink "struct archive_entry *" "const char *"
.Ft void
.Fn archive_entry_set_tartype "struct archive_entry *" "int"
.Ft void
.Fn archive_entry_set_uid "struct archive_entry *" "uid_t"
.Ft void
.Fn archive_entry_set_uname "struct archive_entry *" "const char *"
@ -127,8 +123,6 @@
.Fn archive_entry_symlink "struct archive_entry *"
.Ft const wchar_t *
.Fn archive_entry_symlink_w "struct archive_entry *"
.Ft int
.Fn archive_entry_tartype "struct archive_entry *"
.Ft const char *
.Fn archive_entry_uname "struct archive_entry *"
.Ft const wchar_t *
@ -199,12 +193,6 @@ object.
Allocate and return a blank
.Tn struct archive_entry
object.
.It Fn archive_entry_set_tartype
Sets the value to be used in a tar-format header
for this entry.
Client code should generally not set this; if it
is left unset, the library will automatically determine
an appropriate value.
.El
.\" .Sh EXAMPLE
.\" .Sh RETURN VALUES

View File

@ -29,9 +29,6 @@ __FBSDID("$FreeBSD$");
#include <sys/stat.h>
#include <sys/types.h>
#ifdef HAVE_DMALLOC
#include <dmalloc.h>
#endif
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
@ -119,9 +116,6 @@ struct archive_entry {
*/
struct stat ae_stat;
/* I'm not happy with having this format-particular data here. */
int ae_tartype;
/*
* Use aes here so that we get transparent mbs<->wcs conversions.
*/
@ -283,7 +277,6 @@ archive_entry_clear(struct archive_entry *entry)
aes_clean(&entry->ae_uname);
archive_entry_acl_clear(entry);
memset(entry, 0, sizeof(*entry));
entry->ae_tartype = -1;
return entry;
}
@ -298,7 +291,6 @@ archive_entry_clone(struct archive_entry *entry)
return (NULL);
memset(entry2, 0, sizeof(*entry2));
entry2->ae_stat = entry->ae_stat;
entry2->ae_tartype = entry->ae_tartype;
aes_copy(&entry2->ae_fflags ,&entry->ae_fflags);
aes_copy(&entry2->ae_gname ,&entry->ae_gname);
@ -326,7 +318,6 @@ archive_entry_new(void)
if(entry == NULL)
return (NULL);
memset(entry, 0, sizeof(*entry));
entry->ae_tartype = -1;
return (entry);
}
@ -415,12 +406,6 @@ archive_entry_symlink(struct archive_entry *entry)
return (aes_get_mbs(&entry->ae_symlink));
}
int
archive_entry_tartype(struct archive_entry *entry)
{
return (entry->ae_tartype);
}
const char *
archive_entry_uname(struct archive_entry *entry)
{
@ -501,6 +486,16 @@ archive_entry_copy_hardlink_w(struct archive_entry *entry, const wchar_t *target
aes_copy_wcs(&entry->ae_hardlink, target);
}
/* Set symlink if symlink is already set, else set hardlink. */
void
archive_entry_set_link(struct archive_entry *entry, const char *target)
{
if (entry->ae_symlink.aes_mbs != NULL ||
entry->ae_symlink.aes_wcs != NULL)
aes_set_mbs(&entry->ae_symlink, target);
aes_set_mbs(&entry->ae_hardlink, target);
}
void
archive_entry_set_mode(struct archive_entry *entry, mode_t m)
{
@ -537,12 +532,6 @@ archive_entry_copy_symlink_w(struct archive_entry *entry, const wchar_t *linknam
aes_copy_wcs(&entry->ae_symlink, linkname);
}
void
archive_entry_set_tartype(struct archive_entry *entry, char t)
{
entry->ae_tartype = t;
}
void
archive_entry_set_uid(struct archive_entry *entry, uid_t u)
{
@ -1121,15 +1110,16 @@ __archive_entry_acl_parse_w(struct archive_entry *entry,
namebuff =
malloc(namebuff_length * sizeof(wchar_t));
}
wmemcpy(namebuff, start, end-start);
wmemcpy(namebuff, name_start, name_end - name_start);
archive_entry_acl_add_entry_w(entry, type,
permset, tag, id, namebuff);
}
}
if (namebuff != NULL)
free(namebuff);
return (ARCHIVE_OK);
fail:
fprintf(stderr, "ACL error\n");
if (namebuff != NULL)
free(namebuff);
return (ARCHIVE_WARN);

View File

@ -79,7 +79,6 @@ const wchar_t *archive_entry_pathname_w(struct archive_entry *);
int64_t archive_entry_size(struct archive_entry *);
const struct stat *archive_entry_stat(struct archive_entry *);
const char *archive_entry_symlink(struct archive_entry *);
int archive_entry_tartype(struct archive_entry *);
const char *archive_entry_uname(struct archive_entry *);
/*
@ -99,23 +98,24 @@ void archive_entry_set_gname(struct archive_entry *, const char *);
void archive_entry_copy_gname_w(struct archive_entry *, const wchar_t *);
void archive_entry_set_hardlink(struct archive_entry *, const char *);
void archive_entry_copy_hardlink_w(struct archive_entry *, const wchar_t *);
void archive_entry_set_link(struct archive_entry *, const char *);
void archive_entry_set_mode(struct archive_entry *, mode_t);
void archive_entry_set_pathname(struct archive_entry *, const char *);
void archive_entry_copy_pathname_w(struct archive_entry *, const wchar_t *);
void archive_entry_set_size(struct archive_entry *, int64_t);
void archive_entry_set_symlink(struct archive_entry *, const char *);
void archive_entry_copy_symlink_w(struct archive_entry *, const wchar_t *);
void archive_entry_set_tartype(struct archive_entry *, char);
void archive_entry_set_uid(struct archive_entry *, uid_t);
void archive_entry_set_uname(struct archive_entry *, const char *);
void archive_entry_copy_uname_w(struct archive_entry *, const wchar_t *);
/*
* ACL routines. This used to simply store and return text-format ACL
* strings, but that proved insufficient. The intent here is to allow
* libarchive internals to fetch/store text-format strings, but
* clients use the more involved interface that allows them control
* over uid/uname/gid/gname lookups.
* strings, but that proved insufficient for a number of reasons:
* = clients need control over uname/uid and gname/gid mappings
* = there are many different ACL text formats
* = would like to be able to read/convert archives containing ACLs
* on platforms that lack ACL libraries
*/
/*
@ -139,7 +139,6 @@ void archive_entry_copy_uname_w(struct archive_entry *, const wchar_t *);
#define ARCHIVE_ENTRY_ACL_MASK 10005 /* Modify group access. */
#define ARCHIVE_ENTRY_ACL_OTHER 10006 /* Public. */
/*
* Set the ACL by clearing it and adding entries one at a time.
* Unlike the POSIX.1e ACL routines, you must specify the type
@ -185,6 +184,17 @@ const wchar_t *archive_entry_acl_text_w(struct archive_entry *, int flags);
/* Return a count of entries matching 'want_type' */
int archive_entry_acl_count(struct archive_entry *, int want_type);
/*
* Private ACL parser. This is private because it handles some
* very weird formats that clients should not be messing with.
* Clients should only deal with their platform-native formats.
* Because of the need to support many formats cleanly, new arguments
* are likely to get added on a regular basis. Clients who try to use
* this interface are likely to be surprised when it changes.
*
* You were warned!
*/
int __archive_entry_acl_parse_w(struct archive_entry *,
const wchar_t *, int type);
#endif /* !ARCHIVE_ENTRY_H_INCLUDED */

View File

@ -201,7 +201,7 @@ struct archive {
/* Utility function to format a USTAR header into a buffer. */
int
__archive_write_format_header_ustar(struct archive *, char buff[512],
struct archive_entry *);
struct archive_entry *, int tartype);
#define ARCHIVE_STATE_ANY 0xFFFFU
#define ARCHIVE_STATE_NEW 1U
@ -231,17 +231,4 @@ int __archive_read_register_compression(struct archive *a,
#define err_combine(a,b) ((a) < (b) ? (a) : (b))
/*
* Private ACL handling: parse and generate ACL strings.
* These are private because they handle a lot of very weird formats
* that clients should not be messing with. Clients should only
* deal with their platform-native formats. Because of the need to
* support many formats cleanly, new arguments are likely to get added
* on a regular basis. Clients who try to use this interface are
* likely to be surprised when it changes.
*/
int __archive_entry_acl_parse_w(struct archive_entry *,
const wchar_t *, int type);
#endif

View File

@ -35,9 +35,6 @@
#include "archive_platform.h"
__FBSDID("$FreeBSD$");
#ifdef HAVE_DMALLOC
#include <dmalloc.h>
#endif
#include <err.h>
#include <errno.h>
#include <stdio.h>

View File

@ -27,9 +27,6 @@
#include "archive_platform.h"
__FBSDID("$FreeBSD$");
#ifdef HAVE_DMALLOC
#include <dmalloc.h>
#endif
#include <string.h>
#include "archive.h"

View File

@ -28,10 +28,6 @@
__FBSDID("$FreeBSD$");
#include <sys/types.h>
#ifdef HAVE_DMALLOC
#include <dmalloc.h>
#endif
#include <unistd.h>
#include "archive.h"

View File

@ -34,9 +34,6 @@ __FBSDID("$FreeBSD$");
#endif
#include <sys/time.h>
#ifdef HAVE_DMALLOC
#include <dmalloc.h>
#endif
#include <errno.h>
#include <fcntl.h>
#include <grp.h>
@ -773,15 +770,15 @@ set_perm(struct archive *a, struct archive_entry *entry, int mode, int flags)
static int
set_extended_perm(struct archive *a, struct archive_entry *entry, int flags)
{
int ret;
int ret, ret2;
if ((flags & ARCHIVE_EXTRACT_PERM) == 0)
return (ARCHIVE_OK);
ret = set_fflags(a, entry);
if (ret == ARCHIVE_OK)
ret = set_acls(a, entry);
return (ret);
ret2 = set_acls(a, entry);
return (err_combine(ret,ret2));
}
static int
@ -831,6 +828,7 @@ set_acls(struct archive *a, struct archive_entry *entry)
{
(void)a;
(void)entry;
return (ARCHIVE_OK);
}
@ -878,22 +876,33 @@ set_acl(struct archive *a, struct archive_entry *entry, acl_type_t acl_type,
&ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) {
acl_create_entry(&acl, &acl_entry);
if (ae_tag == ARCHIVE_ENTRY_ACL_USER) {
switch (ae_tag) {
case ARCHIVE_ENTRY_ACL_USER:
acl_set_tag_type(acl_entry, ACL_USER);
ae_uid = lookup_uid(a, ae_name, ae_id);
acl_set_qualifier(acl_entry, &ae_uid);
} else if (ae_tag == ARCHIVE_ENTRY_ACL_GROUP) {
break;
case ARCHIVE_ENTRY_ACL_GROUP:
acl_set_tag_type(acl_entry, ACL_GROUP);
ae_gid = lookup_gid(a, ae_name, ae_id);
acl_set_qualifier(acl_entry, &ae_gid);
} else if (ae_tag == ARCHIVE_ENTRY_ACL_USER_OBJ)
break;
case ARCHIVE_ENTRY_ACL_USER_OBJ:
acl_set_tag_type(acl_entry, ACL_USER_OBJ);
else if (ae_tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ)
break;
case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
acl_set_tag_type(acl_entry, ACL_GROUP_OBJ);
else if (ae_tag == ARCHIVE_ENTRY_ACL_MASK)
break;
case ARCHIVE_ENTRY_ACL_MASK:
acl_set_tag_type(acl_entry, ACL_MASK);
else if (ae_tag == ARCHIVE_ENTRY_ACL_OTHER)
break;
case ARCHIVE_ENTRY_ACL_OTHER:
acl_set_tag_type(acl_entry, ACL_OTHER);
break;
default:
/* XXX */
break;
}
acl_get_permset(acl_entry, &acl_permset);
acl_clear_perms(acl_permset);
@ -906,6 +915,7 @@ set_acl(struct archive *a, struct archive_entry *entry, acl_type_t acl_type,
}
name = archive_entry_pathname(entry);
if (acl_set_file(name, acl_type, acl) != 0) {
archive_set_error(a, errno, "Failed to set %s acl", typename);
ret = ARCHIVE_WARN;

View File

@ -27,9 +27,6 @@
#include "archive_platform.h"
__FBSDID("$FreeBSD$");
#ifdef HAVE_DMALLOC
#include <dmalloc.h>
#endif
#include <errno.h>
#include <stdlib.h>
#include <string.h>

View File

@ -27,9 +27,6 @@
#include "archive_platform.h"
__FBSDID("$FreeBSD$");
#ifdef HAVE_DMALLOC
#include <dmalloc.h>
#endif
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>

View File

@ -27,9 +27,6 @@
#include "archive_platform.h"
__FBSDID("$FreeBSD$");
#ifdef HAVE_DMALLOC
#include <dmalloc.h>
#endif
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>

View File

@ -27,10 +27,6 @@
#include "archive_platform.h"
__FBSDID("$FreeBSD$");
#ifdef HAVE_DMALLOC
#include <dmalloc.h>
#endif
#include "archive.h"
int

View File

@ -27,9 +27,6 @@
#include "archive_platform.h"
__FBSDID("$FreeBSD$");
#ifdef HAVE_DMALLOC
#include <dmalloc.h>
#endif
#include <err.h>
#include <errno.h>
#include <stdlib.h>

View File

@ -27,9 +27,6 @@
#include "archive_platform.h"
__FBSDID("$FreeBSD$");
#ifdef HAVE_DMALLOC
#include <dmalloc.h>
#endif
#include <errno.h>
#include <stdlib.h>
#include <string.h>

View File

@ -27,9 +27,6 @@
#include "archive_platform.h"
__FBSDID("$FreeBSD$");
#ifdef HAVE_DMALLOC
#include <dmalloc.h>
#endif
#include <errno.h>
#include <stdlib.h>
#include <string.h>

View File

@ -27,10 +27,6 @@
#include "archive_platform.h"
__FBSDID("$FreeBSD$");
#ifdef HAVE_DMALLOC
#include <dmalloc.h>
#endif
#include "archive.h"
int

View File

@ -29,9 +29,6 @@ __FBSDID("$FreeBSD$");
#include <sys/stat.h>
#ifdef HAVE_DMALLOC
#include <dmalloc.h>
#endif
#include <err.h>
#include <errno.h>
/* #include <stdint.h> */ /* See archive_platform.h */

View File

@ -1,574 +0,0 @@
/*-
* Copyright (c) 2003-2004 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer
* in this position and unchanged.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "archive_platform.h"
__FBSDID("$FreeBSD$");
#include <sys/stat.h>
#ifdef HAVE_DMALLOC
#include <dmalloc.h>
#endif
#include <err.h>
#include <errno.h>
/* #include <stdint.h> */ /* See archive_platform.h */
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "archive.h"
#include "archive_entry.h"
#include "archive_private.h"
/*
* Structure of GNU tar header
*/
struct archive_entry_header_gnutar {
char name[100];
char mode[8];
char uid[8];
char gid[8];
char size[12];
char mtime[12];
char checksum[8];
char typeflag[1];
char linkname[100];
char magic[8]; /* "ustar \0" (note blank/blank/null at end) */
char uname[32];
char gname[32];
char devmajor[8];
char devminor[8];
char atime[12];
char ctime[12];
char offset[12];
char longnames[4];
char unused[1];
struct {
char offset[12];
char numbytes[12];
} sparse[4];
char isextended[1];
char realsize[12];
/*
* GNU doesn't use POSIX 'prefix' field; they use the 'L' (longname)
* entry instead.
*/
};
struct gnutar {
struct archive_string entry_name;
struct archive_string entry_linkname;
struct archive_string entry_uname;
struct archive_string entry_gname;
struct archive_string gnu_name;
struct archive_string gnu_linkname;
int gnu_header_recursion_depth;
};
static int archive_block_is_null(const unsigned char *p);
static int archive_header_gnu(struct archive *, struct archive_entry *,
const void *);
static int archive_read_format_gnutar_bid(struct archive *a);
static int archive_read_format_gnutar_cleanup(struct archive *);
static int archive_read_format_gnutar_read_header(struct archive *a,
struct archive_entry *);
static int checksum(struct archive *a, const void *h);
static int64_t tar_atol(const char *, unsigned);
static int64_t tar_atol8(const char *, unsigned);
static int64_t tar_atol256(const char *, unsigned);
/*
* The ONLY publicly visible function in this file.
*/
int
archive_read_support_format_gnutar(struct archive *a)
{
struct gnutar *gnutar;
gnutar = malloc(sizeof(*gnutar));
memset(gnutar, 0, sizeof(*gnutar));
return (__archive_read_register_format(a,
gnutar,
archive_read_format_gnutar_bid,
archive_read_format_gnutar_read_header,
archive_read_format_gnutar_cleanup));
}
static int
archive_read_format_gnutar_cleanup(struct archive *a)
{
struct gnutar *gnutar;
gnutar = *(a->pformat_data);
if (gnutar->entry_name.s != NULL)
free(gnutar->entry_name.s);
if (gnutar->entry_linkname.s != NULL)
free(gnutar->entry_linkname.s);
if (gnutar->entry_uname.s != NULL)
free(gnutar->entry_uname.s);
if (gnutar->entry_gname.s != NULL)
free(gnutar->entry_gname.s);
if (gnutar->gnu_name.s != NULL)
free(gnutar->gnu_name.s);
if (gnutar->gnu_linkname.s != NULL)
free(gnutar->gnu_linkname.s);
free(gnutar);
*(a->pformat_data) = NULL;
return (ARCHIVE_OK);
}
static int
archive_read_format_gnutar_bid(struct archive *a)
{
int bid;
size_t bytes_read;
const void *h;
const struct archive_entry_header_gnutar *header;
/*
* If we're already reading a non-tar file, don't
* bother to bid.
*/
if (a->archive_format != 0 &&
(a->archive_format & ARCHIVE_FORMAT_BASE_MASK) !=
ARCHIVE_FORMAT_TAR)
return (0);
bid = 0;
/* If last header was my preferred format, bid a bit more. */
if (a->archive_format == ARCHIVE_FORMAT_TAR_GNUTAR)
bid += 10;
bytes_read = (a->compression_read_ahead)(a, &h, 512);
if (bytes_read < 512)
return (-1);
/*
* TODO: if checksum or header fail, scan ahead for
* next valid header.
*/
/* Checksum field is eight 8-bit values: 64 bits of validation. */
if (!checksum(a, h))
return (0);
bid += 64;
header = (const struct archive_entry_header_gnutar *)h;
/* This distinguishes GNU tar formats from POSIX formats */
if (memcmp(header->magic, "ustar \0", 8) != 0)
return (0);
bid += 64;
return (bid);
}
static int
archive_read_format_gnutar_read_header(struct archive *a,
struct archive_entry *entry)
{
const void *h;
ssize_t bytes;
int oldstate;
struct gnutar *gnutar;
gnutar = *(a->pformat_data);
a->archive_format = ARCHIVE_FORMAT_TAR_GNUTAR;
a->archive_format_name = "GNU tar";
/* Skip remains of previous entry. */
oldstate = a->state;
a->state = ARCHIVE_STATE_DATA;
archive_read_data_skip(a);
a->state = oldstate;
/* Read 512-byte header record */
bytes = (a->compression_read_ahead)(a, &h, 512);
if (bytes < 512)
return (ARCHIVE_FATAL);
(a->compression_read_consume)(a, 512);
/*
* If this is a block of nulls, return 0 (no more entries).
* Note the initial (*h)==0 test short-circuits the function call
* in the most common case.
*/
if (((*(const char *)h)==0) && archive_block_is_null(h)) {
/* TODO: Store file location of start of block in public area */
archive_set_error(a, 0, NULL);
return (ARCHIVE_EOF);
}
/* TODO: add support for scanning for next valid header */
if (!checksum(a, h)) {
archive_set_error(a, EINVAL, "Damaged GNU tar archive");
return (ARCHIVE_FATAL); /* Not a valid header. */
}
/* This function gets called recursively for long name headers, etc. */
if (++gnutar->gnu_header_recursion_depth > 32)
errx(EINVAL,
"*** Too many special headers for one entry; giving up. "
"(%s:%s@%d)\n",
__FUNCTION__, __FILE__, __LINE__);
archive_header_gnu(a, entry, h);
gnutar->gnu_header_recursion_depth--;
return (0);
}
/*
* Return true if block checksum is correct.
*/
static int
checksum(struct archive *a, const void *h)
{
const unsigned char *bytes;
const struct archive_entry_header_gnutar *header;
int i, sum, signed_sum, unsigned_sum;
(void)a; /* UNUSED */
bytes = h;
header = h;
/* Test checksum: POSIX specifies UNSIGNED for this calculation. */
sum = tar_atol(header->checksum, sizeof(header->checksum));
unsigned_sum = 0;
for (i = 0; i < 148; i++)
unsigned_sum += (unsigned char)bytes[i];
for (; i < 156; i++)
unsigned_sum += 32;
for (; i < 512; i++)
unsigned_sum += (unsigned char)bytes[i];
if (sum == unsigned_sum)
return (1);
/*
* Repeat test with SIGNED bytes, just in case this archive
* was created by an old BSD, Solaris, or HP-UX tar with a broken
* checksum calculation.
*/
signed_sum = 0;
for (i = 0; i < 148; i++)
signed_sum += (signed char)bytes[i];
for (; i < 156; i++)
signed_sum += 32;
for (; i < 512; i++)
signed_sum += (signed char)bytes[i];
if (sum == signed_sum)
return (1);
return (0);
}
/*
* Return true if this block contains only nulls.
*/
static int
archive_block_is_null(const unsigned char *p)
{
unsigned i;
for (i = 0; i < ARCHIVE_BYTES_PER_RECORD / sizeof(*p); i++) {
if (*p++)
return (0);
}
return (1);
}
/*
* Parse GNU tar header
*/
static int
archive_header_gnu(struct archive *a, struct archive_entry *entry,
const void *h)
{
struct stat st;
const struct archive_entry_header_gnutar *header;
struct gnutar *gnutar;
char tartype;
unsigned oldstate;
/* Clear out entry structure */
memset(&st, 0, sizeof(st));
gnutar = *(a->pformat_data);
/*
* GNU header is like POSIX, except 'prefix' is
* replaced with some other fields. This also means the
* filename is stored as in old-style archives.
*/
/* Copy filename over (to ensure null termination). */
header = h;
archive_strncpy(&(gnutar->entry_name), header->name,
sizeof(header->name));
archive_entry_set_pathname(entry, gnutar->entry_name.s);
/* Copy linkname over */
if (header->linkname[0])
archive_strncpy(&(gnutar->entry_linkname), header->linkname,
sizeof(header->linkname));
/* Parse out the numeric fields (all are octal) */
st.st_mode = tar_atol(header->mode, sizeof(header->mode));
st.st_uid = tar_atol(header->uid, sizeof(header->uid));
st.st_gid = tar_atol(header->gid, sizeof(header->gid));
st.st_size = tar_atol(header->size, sizeof(header->size));
st.st_mtime = tar_atol(header->mtime, sizeof(header->mtime));
/* Handle the tar type flag appropriately. */
tartype = header->typeflag[0];
archive_entry_set_tartype(entry, tartype);
st.st_mode &= ~S_IFMT;
/* Fields common to ustar and GNU */
archive_strncpy(&(gnutar->entry_uname),
header->uname, sizeof(header->uname));
archive_entry_set_uname(entry, gnutar->entry_uname.s);
archive_strncpy(&(gnutar->entry_gname),
header->gname, sizeof(header->gname));
archive_entry_set_gname(entry, gnutar->entry_gname.s);
/* Parse out device numbers only for char and block specials */
if (header->typeflag[0] == '3' || header->typeflag[0] == '4')
st.st_rdev = makedev (
tar_atol(header->devmajor, sizeof(header->devmajor)),
tar_atol(header->devminor, sizeof(header->devminor)));
else
st.st_rdev = 0;
/* Grab additional GNU fields. */
/* TODO: FILL THIS IN!!! */
st.st_atime = tar_atol(header->atime, sizeof(header->atime));
st.st_ctime = tar_atol(header->atime, sizeof(header->ctime));
/* Set internal counter for locating next header */
a->entry_bytes_remaining = st.st_size;
a->entry_padding = 0x1ff & (-a->entry_bytes_remaining);
/* Interpret entry type */
switch (tartype) {
case '1': /* Hard link */
archive_entry_set_hardlink(entry, gnutar->entry_linkname.s);
/*
* Note: Technically, tar does not store the file type
* for a "hard link" entry, only the fact that it is a
* hard link. So, I leave the file type in st_mode
* zero here.
*/
archive_entry_copy_stat(entry, &st);
break;
case '2': /* Symlink */
st.st_mode |= S_IFLNK;
st.st_size = 0;
archive_entry_set_symlink(entry, gnutar->entry_linkname.s);
archive_entry_copy_stat(entry, &st);
break;
case '3': /* Character device */
st.st_mode |= S_IFCHR;
st.st_size = 0;
archive_entry_copy_stat(entry, &st);
break;
case '4': /* Block device */
st.st_mode |= S_IFBLK;
st.st_size = 0;
archive_entry_copy_stat(entry, &st);
break;
case '5': /* POSIX Dir */
st.st_mode |= S_IFDIR;
st.st_size = 0;
archive_entry_copy_stat(entry, &st);
break;
case '6': /* FIFO device */
st.st_mode |= S_IFIFO;
st.st_size = 0;
archive_entry_copy_stat(entry, &st);
break;
case 'D': /* GNU incremental directory type */
/*
* No special handling is actually required here.
* It might be nice someday to preprocess the file list and
* provide it to the client, though.
*/
st.st_mode &= ~ S_IFMT;
st.st_mode |= S_IFDIR;
archive_entry_copy_stat(entry, &st);
break;
case 'K': /* GNU long linkname */
/* Entry body is full name of link for next header. */
archive_string_ensure(&(gnutar->gnu_linkname), st.st_size+1);
/* Temporarily fudge internal state for read_data call. */
oldstate = a->state;
a->state = ARCHIVE_STATE_DATA;
archive_read_data_into_buffer(a, gnutar->gnu_linkname.s,
st.st_size);
a->state = oldstate;
gnutar->gnu_linkname.s[st.st_size] = 0; /* Null term name! */
/*
* This next call will usually overwrite
* gnutar->entry_linkname, which is why we _must_ have
* a separate gnu_linkname field.
*/
archive_read_format_gnutar_read_header(a, entry);
if (archive_entry_tartype(entry) == '1')
archive_entry_set_hardlink(entry, gnutar->gnu_linkname.s);
else if (archive_entry_tartype(entry) == '2')
archive_entry_set_symlink(entry, gnutar->gnu_linkname.s);
/* TODO: else { ... } */
break;
case 'L': /* GNU long filename */
/* Entry body is full pathname for next header. */
archive_string_ensure(&(gnutar->gnu_name), st.st_size+1);
/* Temporarily fudge internal state for read_data call. */
oldstate = a->state;
a->state = ARCHIVE_STATE_DATA;
archive_read_data_into_buffer(a, gnutar->gnu_name.s,
st.st_size);
a->state = oldstate;
gnutar->gnu_name.s[st.st_size] = 0; /* Null terminate name! */
/*
* This next call will typically overwrite
* gnutar->entry_name, which is why we _must_ have a
* separate gnu_name field.
*/
archive_read_format_gnutar_read_header(a, entry);
archive_entry_set_pathname(entry, gnutar->gnu_name.s);
break;
case 'M': /* GNU Multi-volume (remainder of file from last archive) */
/*
* As far as I can tell, this is just like a regular file
* entry, except that the contents should be _appended_ to
* the indicated file at the indicated offset. This may
* require some API work to fully support.
*/
break;
case 'N': /* Old GNU long filename; this will never be supported */
/* Essentially, body of this entry is a script for
* renaming previously-extracted entries. Ugh. */
break;
case 'S': /* GNU Sparse files: These are really ugly, and unlikely
* to be supported anytime soon. */
break;
case 'V': /* GNU volume header */
/* Just skip it */
return (archive_read_format_gnutar_read_header(a, entry));
default: /* Regular file and non-standard types */
/* Per POSIX: non-recognized types should always be
* treated as regular files. Of course, GNU
* extensions aren't compatible with this dictum.
* <sigh> */
st.st_mode |= S_IFREG;
archive_entry_copy_stat(entry, &st);
break;
}
return (0);
}
/*
* Convert text->integer.
*
* Traditional tar formats (including POSIX) specify base-8 for
* all of the standard numeric fields. GNU tar supports base-256
* as well in many of the numeric fields. There is also an old
* and short-lived base-64 format, but I doubt I'll ever see
* an archive that uses it. (According to the changelog for GNU tar,
* that format was only implemented for a couple of weeks!)
*/
static int64_t
tar_atol(const char *p, unsigned char_cnt)
{
if (*p & 0x80)
return (tar_atol256(p, char_cnt));
return (tar_atol8(p, char_cnt));
}
/*
* Note that this implementation does not (and should not!) obey
* locale settings; you cannot simply substitute strtol here, since
* it does obey locale.
*/
static int64_t
tar_atol8(const char *p, unsigned char_cnt)
{
int64_t l;
int digit, sign;
static const int64_t limit = INT64_MAX / 8;
static const int base = 8;
static const char last_digit_limit = INT64_MAX % 8;
while (*p == ' ' || *p == '\t')
p++;
if (*p == '-') {
sign = -1;
p++;
} else
sign = 1;
l = 0;
digit = *p - '0';
while (digit >= 0 && digit < base && char_cnt-- > 0) {
if (l>limit || (l == limit && digit > last_digit_limit)) {
l = INT64_MAX; /* Truncate on overflow */
break;
}
l = ( l * base ) + digit;
digit = *++p - '0';
}
return (sign < 0) ? -l : l;
}
/*
* Parse a base-256 integer.
*
* TODO: This overflows very quickly for negative values; fix this.
*/
static int64_t
tar_atol256(const char *p, unsigned char_cnt)
{
int64_t l;
int digit;
const int64_t limit = INT64_MAX / 256;
/* Ignore high bit of first byte (that's the base-256 flag). */
l = 0;
digit = 0x7f & *(const unsigned char *)p;
while (char_cnt-- > 0) {
if (l > limit) {
l = INT64_MAX; /* Truncate on overflow */
break;
}
l = (l << 8) + digit;
digit = *(const unsigned char *)++p;
}
return (l);
}

View File

@ -28,9 +28,6 @@
__FBSDID("$FreeBSD$");
#include <sys/stat.h>
#ifdef HAVE_DMALLOC
#include <dmalloc.h>
#endif
#include <errno.h>
/* #include <stdint.h> */ /* See archive_platform.h */
#include <stdlib.h>
@ -97,8 +94,12 @@ static int header_longlink(struct archive *, struct tar *,
struct archive_entry *, struct stat *, const void *h);
static int header_longname(struct archive *, struct tar *,
struct archive_entry *, struct stat *, const void *h);
static int header_volume(struct archive *, struct tar *,
struct archive_entry *, struct stat *, const void *h);
static int header_ustar(struct archive *, struct tar *,
struct archive_entry *, struct stat *, const void *h);
static int header_gnutar(struct archive *, struct tar *,
struct archive_entry *, struct stat *, const void *h);
static int archive_read_format_tar_bid(struct archive *);
static int archive_read_format_tar_cleanup(struct archive *);
static int archive_read_format_tar_read_header(struct archive *,
@ -119,6 +120,13 @@ static int tar_read_header(struct archive *, struct tar *,
struct archive_entry *, struct stat *);
static int utf8_decode(wchar_t *, const char *, size_t length);
int
archive_read_support_format_gnutar(struct archive *a)
{
return (archive_read_support_format_tar(a));
}
int
archive_read_support_format_tar(struct archive *a)
{
@ -185,11 +193,6 @@ archive_read_format_tar_bid(struct archive *a)
ARCHIVE_FORMAT_TAR)
bid++;
/* If last header was my preferred format, bid a bit more. */
if (a->archive_format == ARCHIVE_FORMAT_TAR_USTAR ||
a->archive_format == ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE)
bid++;
/* Now let's look at the actual header and see if it matches. */
bytes_read = (a->compression_read_ahead)(a, &h, 512);
if (bytes_read < 512)
@ -211,6 +214,11 @@ archive_read_format_tar_bid(struct archive *a)
&&(memcmp(header->version, "00", 2)==0))
bid += 56;
/* Recognize GNU tar format as well. */
if ((memcmp(header->magic, "ustar ", 6) == 0)
&&(memcmp(header->version, " \0", 2)==0))
bid += 56;
/* Type flag must be null, digit or A-Z, a-z. */
if (header->typeflag[0] != 0 &&
!( header->typeflag[0] >= '0' && header->typeflag[0] <= '9') &&
@ -280,7 +288,6 @@ tar_read_header(struct archive *a, struct tar *tar,
/* Check for end-of-archive mark. */
if (((*(const char *)h)==0) && archive_block_is_null(h)) {
/* TODO: Store file location of start of block */
archive_set_error(a, 0, NULL);
return (ARCHIVE_EOF);
}
@ -304,11 +311,7 @@ tar_read_header(struct archive *a, struct tar *tar,
/* Determine the format variant. */
header = h;
if (memcmp(header->magic, "ustar", 5) != 0) {
a->archive_format = ARCHIVE_FORMAT_TAR;
a->archive_format_name = "tar (non-POSIX)";
err = header_old_tar(a, tar, entry, st, h);
} else switch(header->typeflag[0]) {
switch(header->typeflag[0]) {
case 'A': /* Solaris tar ACL */
a->archive_format = ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE;
a->archive_format_name = "Solaris tar";
@ -319,12 +322,15 @@ tar_read_header(struct archive *a, struct tar *tar,
a->archive_format_name = "POSIX pax interchange format";
err = header_pax_global(a, tar, entry, st, h);
break;
case 'K': /* Long link name (non-POSIX, but fairly common). */
case 'K': /* Long link name (GNU tar, others) */
err = header_longlink(a, tar, entry, st, h);
break;
case 'L': /* Long filename (non-POSIX, but fairly common). */
case 'L': /* Long filename (GNU tar, others) */
err = header_longname(a, tar, entry, st, h);
break;
case 'V': /* GNU volume header */
err = header_volume(a, tar, entry, st, h);
break;
case 'X': /* Used by SUN tar; same as 'x'. */
a->archive_format = ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE;
a->archive_format_name =
@ -337,12 +343,21 @@ tar_read_header(struct archive *a, struct tar *tar,
err = header_pax_extensions(a, tar, entry, st, h);
break;
default:
if (a->archive_format != ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE
&& a->archive_format != ARCHIVE_FORMAT_TAR_USTAR) {
a->archive_format = ARCHIVE_FORMAT_TAR_USTAR;
a->archive_format_name = "POSIX ustar format";
if (memcmp(header->magic, "ustar \0", 8) == 0) {
a->archive_format = ARCHIVE_FORMAT_TAR_GNUTAR;
a->archive_format_name = "GNU tar format";
err = header_gnutar(a, tar, entry, st, h);
} else if (memcmp(header->magic, "ustar", 5) == 0) {
if (a->archive_format != ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE) {
a->archive_format = ARCHIVE_FORMAT_TAR_USTAR;
a->archive_format_name = "POSIX ustar format";
}
err = header_ustar(a, tar, entry, st, h);
} else {
a->archive_format = ARCHIVE_FORMAT_TAR;
a->archive_format_name = "tar (non-POSIX)";
err = header_old_tar(a, tar, entry, st, h);
}
err = header_ustar(a, tar, entry, st, h);
}
archive_entry_copy_stat(entry, st);
--tar->header_recursion_depth;
@ -418,17 +433,32 @@ header_Solaris_ACL(struct archive *a, struct tar *tar,
struct archive_entry *entry, struct stat *st, const void *h)
{
int err, err2;
char *p;
wchar_t *wp;
err = read_body_to_string(a, &(tar->acl_text), h);
err2 = tar_read_header(a, tar, entry, st);
err = err_combine(err, err2);
/* XXX DO SOMETHING WITH THE ACL!!! XXX */
{
const char *msg = "\nXXX Solaris ACL entries recognized but not yet handled!!\n";
write(2, msg, strlen(msg));
/* XXX Ensure p doesn't overrun acl_text */
/* Skip leading octal number. */
/* XXX TODO: Parse the octal number and sanity-check it. */
p = tar->acl_text.s;
while (*p != '\0')
p++;
p++;
wp = malloc((strlen(p) + 1) * sizeof(wchar_t));
if (wp != NULL) {
utf8_decode(wp, p, strlen(p));
err2 = __archive_entry_acl_parse_w(entry, wp,
ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
err = err_combine(err, err2);
free(wp);
}
return (err_combine(err, err2));
return (err);
}
/*
@ -443,10 +473,8 @@ header_longlink(struct archive *a, struct tar *tar,
err = read_body_to_string(a, &(tar->longlink), h);
err2 = tar_read_header(a, tar, entry, st);
if (err == ARCHIVE_OK && err2 == ARCHIVE_OK) {
if (archive_entry_tartype(entry) == '1')
archive_entry_set_hardlink(entry, tar->longlink.s);
else if (archive_entry_tartype(entry) == '2')
archive_entry_set_symlink(entry, tar->longlink.s);
/* Set symlink if symlink already set, else hardlink. */
archive_entry_set_link(entry, tar->longlink.s);
}
return (err_combine(err, err2));
}
@ -468,6 +496,20 @@ header_longname(struct archive *a, struct tar *tar,
return (err_combine(err, err2));
}
/*
* Interpret 'V' GNU tar volume header.
*/
static int
header_volume(struct archive *a, struct tar *tar,
struct archive_entry *entry, struct stat *st, const void *h)
{
(void)h;
/* Just skip this and read the next header. */
return (tar_read_header(a, tar, entry, st));
}
/*
* Read body of an archive entry into an archive_string object.
*/
@ -535,7 +577,6 @@ header_common(struct archive *a, struct tar *tar, struct archive_entry *entry,
/* Handle the tar type flag appropriately. */
tartype = header->typeflag[0];
archive_entry_set_tartype(entry, tartype);
st->st_mode &= ~S_IFMT;
switch (tartype) {
@ -574,6 +615,31 @@ header_common(struct archive *a, struct tar *tar, struct archive_entry *entry,
st->st_mode |= S_IFIFO;
st->st_size = 0;
break;
case 'D': /* GNU incremental directory type */
/*
* No special handling is actually required here.
* It might be nice someday to preprocess the file list and
* provide it to the client, though.
*/
st->st_mode |= S_IFDIR;
break;
case 'M': /* GNU "Multi-volume" (remainder of file from last archive)*/
/*
* As far as I can tell, this is just like a regular file
* entry, except that the contents should be _appended_ to
* the indicated file at the indicated offset. This may
* require some API work to fully support.
*/
break;
case 'N': /* Old GNU "long filename" entry. */
/* The body of this entry is a script for renaming
* previously-extracted entries. Ugh. It will never
* be supported by libarchive. */
st->st_mode |= S_IFREG;
break;
case 'S': /* GNU sparse files */
/* I would like to support these someday... */
break;
default: /* Regular file and non-standard types */
/*
* Per POSIX: non-recognized types should always be
@ -612,7 +678,6 @@ header_old_tar(struct archive *a, struct tar *tar, struct archive_entry *entry,
'/' == tar->entry_name.s[strlen(tar->entry_name.s) - 1]) {
st->st_mode &= ~S_IFMT;
st->st_mode |= S_IFDIR;
archive_entry_set_tartype(entry, '5');
}
a->entry_bytes_remaining = st->st_size;
@ -953,6 +1018,100 @@ pax_time(const wchar_t *p, struct timespec *t)
} while (l /= 10);
}
/*
* Structure of GNU tar header
*/
struct archive_entry_header_gnutar {
char name[100];
char mode[8];
char uid[8];
char gid[8];
char size[12];
char mtime[12];
char checksum[8];
char typeflag[1];
char linkname[100];
char magic[8]; /* "ustar \0" (note blank/blank/null at end) */
char uname[32];
char gname[32];
char devmajor[8];
char devminor[8];
char atime[12];
char ctime[12];
char offset[12];
char longnames[4];
char unused[1];
struct {
char offset[12];
char numbytes[12];
} sparse[4];
char isextended[1];
char realsize[12];
/*
* GNU doesn't use POSIX 'prefix' field; they use the 'L' (longname)
* entry instead.
*/
};
/*
* Parse GNU tar header
*/
static int
header_gnutar(struct archive *a, struct tar *tar, struct archive_entry *entry,
struct stat *st, const void *h)
{
const struct archive_entry_header_gnutar *header;
(void)a;
/*
* GNU header is like POSIX ustar, except 'prefix' is
* replaced with some other fields. This also means the
* filename is stored as in old-style archives.
*/
/* Grab fields common to all tar variants. */
header_common(a, tar, entry, st, h);
/* Copy filename over (to ensure null termination). */
header = h;
archive_strncpy(&(tar->entry_name), header->name,
sizeof(header->name));
archive_entry_set_pathname(entry, tar->entry_name.s);
/* Fields common to ustar and GNU */
/* XXX Can the following be factored out since it's common
* to ustar and gnu tar? Is it okay to move it down into
* header_common, perhaps? */
archive_strncpy(&(tar->entry_uname),
header->uname, sizeof(header->uname));
archive_entry_set_uname(entry, tar->entry_uname.s);
archive_strncpy(&(tar->entry_gname),
header->gname, sizeof(header->gname));
archive_entry_set_gname(entry, tar->entry_gname.s);
/* Parse out device numbers only for char and block specials */
if (header->typeflag[0] == '3' || header->typeflag[0] == '4')
st->st_rdev = makedev (
tar_atol(header->devmajor, sizeof(header->devmajor)),
tar_atol(header->devminor, sizeof(header->devminor)));
else
st->st_rdev = 0;
/* Grab GNU-specific fields. */
/* TODO: FILL THIS IN!!! */
st->st_atime = tar_atol(header->atime, sizeof(header->atime));
st->st_ctime = tar_atol(header->atime, sizeof(header->ctime));
/* XXX TODO: Recognize and skip extra GNU header blocks. */
a->entry_bytes_remaining = st->st_size;
a->entry_padding = 0x1ff & (-a->entry_bytes_remaining);
return (0);
}
/*-
* Convert text->integer.
*

View File

@ -32,9 +32,6 @@ __FBSDID("$FreeBSD$");
* strings while minimizing heap activity.
*/
#ifdef HAVE_DMALLOC
#include <dmalloc.h>
#endif
#include <err.h>
#include <stdlib.h>
#include <string.h>

View File

@ -34,9 +34,6 @@ __FBSDID("$FreeBSD$");
* the core code, so it cannot easily be omitted.)
*/
#ifdef HAVE_DMALLOC
#include <dmalloc.h>
#endif
#include <err.h>
#include <stdio.h>

View File

@ -29,9 +29,6 @@ __FBSDID("$FreeBSD$");
#include <sys/types.h>
#ifdef HAVE_DMALLOC
#include <dmalloc.h>
#endif
#include <string.h>
#include "archive.h"

View File

@ -36,9 +36,6 @@ __FBSDID("$FreeBSD$");
*/
#include <sys/wait.h>
#ifdef HAVE_DMALLOC
#include <dmalloc.h>
#endif
#include <limits.h>
#include <paths.h>
#include <stdio.h>

View File

@ -28,9 +28,6 @@
__FBSDID("$FreeBSD$");
#include <sys/stat.h>
#ifdef HAVE_DMALLOC
#include <dmalloc.h>
#endif
#include <errno.h>
#include <stdlib.h>
#include <string.h>

View File

@ -28,9 +28,6 @@
__FBSDID("$FreeBSD$");
#include <sys/stat.h>
#ifdef HAVE_DMALLOC
#include <dmalloc.h>
#endif
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>

View File

@ -28,9 +28,6 @@
__FBSDID("$FreeBSD$");
#include <sys/stat.h>
#ifdef HAVE_DMALLOC
#include <dmalloc.h>
#endif
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>

View File

@ -27,9 +27,6 @@
#include "archive_platform.h"
__FBSDID("$FreeBSD$");
#ifdef HAVE_DMALLOC
#include <dmalloc.h>
#endif
#include <errno.h>
#include <stdlib.h>
#include <string.h>

View File

@ -27,9 +27,6 @@
#include "archive_platform.h"
__FBSDID("$FreeBSD$");
#ifdef HAVE_DMALLOC
#include <dmalloc.h>
#endif
#include <errno.h>
#include <stdlib.h>
#include <string.h>

View File

@ -27,9 +27,6 @@
#include "archive_platform.h"
__FBSDID("$FreeBSD$");
#ifdef HAVE_DMALLOC
#include <dmalloc.h>
#endif
#include <errno.h>
#include <stdlib.h>
#include <string.h>

View File

@ -28,9 +28,6 @@
__FBSDID("$FreeBSD$");
#include <sys/stat.h>
#ifdef HAVE_DMALLOC
#include <dmalloc.h>
#endif
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>

View File

@ -29,9 +29,6 @@ __FBSDID("$FreeBSD$");
#include <sys/stat.h>
#include <errno.h>
#ifdef HAVE_DMALLOC
#include <dmalloc.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
@ -584,7 +581,7 @@ archive_write_pax_header(struct archive *a,
/* Format 'ustar' header for main entry. */
/* We don't care if this returns an error. */
__archive_write_format_header_ustar(a, ustarbuff, entry_main);
__archive_write_format_header_ustar(a, ustarbuff, entry_main, -1);
/* If we built any extended attributes, write that entry first. */
ret = 0;
@ -598,7 +595,6 @@ archive_write_pax_header(struct archive *a,
p = archive_entry_pathname(entry_main);
pax_attr_name = build_pax_attribute_name(p, &pax_entry_name);
archive_entry_set_tartype(pax_attr_entry, 'x');
archive_entry_set_pathname(pax_attr_entry, pax_attr_name);
st.st_size = archive_strlen(&(pax->pax_header));
st.st_uid = st_main->st_uid;
@ -612,7 +608,7 @@ archive_write_pax_header(struct archive *a,
archive_entry_gname(entry_main));
ret = __archive_write_format_header_ustar(a, paxbuff,
pax_attr_entry);
pax_attr_entry, 'x');
archive_entry_free(pax_attr_entry);
free(pax_entry_name.s);

View File

@ -28,9 +28,6 @@
__FBSDID("$FreeBSD$");
#include <sys/stat.h>
#ifdef HAVE_DMALLOC
#include <dmalloc.h>
#endif
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>

View File

@ -28,9 +28,6 @@
__FBSDID("$FreeBSD$");
#include <sys/stat.h>
#ifdef HAVE_DMALLOC
#include <dmalloc.h>
#endif
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
@ -132,7 +129,7 @@ archive_write_ustar_header(struct archive *a, struct archive_entry *entry)
!S_ISREG(archive_entry_mode(entry)))
archive_entry_set_size(entry, 0);
ret = __archive_write_format_header_ustar(a, buff, entry);
ret = __archive_write_format_header_ustar(a, buff, entry, -1);
if (ret != ARCHIVE_OK)
return (ret);
ret = (a->compression_write)(a, buff, 512);
@ -154,7 +151,7 @@ archive_write_ustar_header(struct archive *a, struct archive_entry *entry)
*/
int
__archive_write_format_header_ustar(struct archive *a, char buff[512],
struct archive_entry *entry)
struct archive_entry *entry, int tartype)
{
unsigned int checksum;
struct archive_entry_header_ustar *h;
@ -283,8 +280,8 @@ __archive_write_format_header_ustar(struct archive *a, char buff[512],
OCTAL_TERM_SPACE_NULL);
}
if (archive_entry_tartype(entry) >= 0) {
h->typeflag[0] = archive_entry_tartype(entry);
if (tartype >= 0) {
h->typeflag[0] = tartype;
} else if (archive_entry_hardlink(entry) != NULL) {
h->typeflag[0] = '1';
} else {