Merge libarchive-3-3-2pre.

This commit is contained in:
joerg 2017-04-20 13:01:40 +00:00
parent 40b1a6e683
commit 62a2faf4ff
21 changed files with 3753 additions and 2939 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* Copyright (c) 2003-2010 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -62,7 +62,7 @@ errmsg(const char *m)
}
}
__dead static void
static __LA_DEAD void
diediedie(void)
{
#if defined(_WIN32) && !defined(__CYGWIN__) && defined(_DEBUG)
@ -86,49 +86,90 @@ state_name(unsigned s)
}
}
static const char *
archive_handle_type_name(unsigned m)
{
switch (m) {
case ARCHIVE_WRITE_MAGIC: return ("archive_write");
case ARCHIVE_READ_MAGIC: return ("archive_read");
case ARCHIVE_WRITE_DISK_MAGIC: return ("archive_write_disk");
case ARCHIVE_READ_DISK_MAGIC: return ("archive_read_disk");
case ARCHIVE_MATCH_MAGIC: return ("archive_match");
default: return NULL;
}
}
static void
write_all_states(unsigned int states)
static char *
write_all_states(char *buff, unsigned int states)
{
unsigned int lowbit;
buff[0] = '\0';
/* A trick for computing the lowest set bit. */
while ((lowbit = states & (1 + ~states)) != 0) {
states &= ~lowbit; /* Clear the low bit. */
errmsg(state_name(lowbit));
strcat(buff, state_name(lowbit));
if (states != 0)
errmsg("/");
strcat(buff, "/");
}
return buff;
}
/*
* Check magic value and current state; bail if it isn't valid.
* Check magic value and current state.
* Magic value mismatches are fatal and result in calls to abort().
* State mismatches return ARCHIVE_FATAL.
* Otherwise, returns ARCHIVE_OK.
*
* This is designed to catch serious programming errors that violate
* the libarchive API.
*/
void
int
__archive_check_magic(struct archive *a, unsigned int magic,
unsigned int state, const char *function)
{
if (a->magic != magic) {
errmsg("INTERNAL ERROR: Function ");
char states1[64];
char states2[64];
const char *handle_type;
/*
* If this isn't some form of archive handle,
* then the library user has screwed up so bad that
* we don't even have a reliable way to report an error.
*/
handle_type = archive_handle_type_name(a->magic);
if (!handle_type) {
errmsg("PROGRAMMER ERROR: Function ");
errmsg(function);
errmsg(" invoked with invalid struct archive structure.\n");
errmsg(" invoked with invalid archive handle.\n");
diediedie();
}
if (state == ARCHIVE_STATE_ANY)
return;
if (a->magic != magic) {
archive_set_error(a, -1,
"PROGRAMMER ERROR: Function '%s' invoked"
" on '%s' archive object, which is not supported.",
function,
handle_type);
a->state = ARCHIVE_STATE_FATAL;
return (ARCHIVE_FATAL);
}
if ((a->state & state) == 0) {
errmsg("INTERNAL ERROR: Function '");
errmsg(function);
errmsg("' invoked with archive structure in state '");
write_all_states(a->state);
errmsg("', should be in state '");
write_all_states(state);
errmsg("'\n");
diediedie();
/* If we're already FATAL, don't overwrite the error. */
if (a->state != ARCHIVE_STATE_FATAL)
archive_set_error(a, -1,
"INTERNAL ERROR: Function '%s' invoked with"
" archive structure in state '%s',"
" should be in state '%s'",
function,
write_all_states(states1, a->state),
write_all_states(states2, state));
a->state = ARCHIVE_STATE_FATAL;
return (ARCHIVE_FATAL);
}
return ARCHIVE_OK;
}

View File

@ -1,4 +1,5 @@
.\" Copyright (c) 2003-2007 Tim Kientzle
.\" Copyright (c) 2010 Joerg Sonnenberger
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
@ -22,269 +23,29 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD: src/lib/libarchive/archive_entry.3,v 1.18 2008/05/26 17:00:22 kientzle Exp $
.\" $FreeBSD$
.\"
.Dd May 12, 2008
.Dt archive_entry 3
.Dd February 2, 2012
.Dt ARCHIVE_ENTRY 3
.Os
.Sh NAME
.Nm archive_entry_acl_add_entry ,
.Nm archive_entry_acl_add_entry_w ,
.Nm archive_entry_acl_clear ,
.Nm archive_entry_acl_count ,
.Nm archive_entry_acl_next ,
.Nm archive_entry_acl_next_w ,
.Nm archive_entry_acl_reset ,
.Nm archive_entry_acl_text_w ,
.Nm archive_entry_atime ,
.Nm archive_entry_atime_nsec ,
.Nm archive_entry_clear ,
.Nm archive_entry_clone ,
.Nm archive_entry_copy_fflags_text ,
.Nm archive_entry_copy_fflags_text_w ,
.Nm archive_entry_copy_gname ,
.Nm archive_entry_copy_gname_w ,
.Nm archive_entry_copy_hardlink ,
.Nm archive_entry_copy_hardlink_w ,
.Nm archive_entry_copy_link ,
.Nm archive_entry_copy_link_w ,
.Nm archive_entry_copy_pathname_w ,
.Nm archive_entry_copy_sourcepath ,
.Nm archive_entry_copy_stat ,
.Nm archive_entry_copy_symlink ,
.Nm archive_entry_copy_symlink_w ,
.Nm archive_entry_copy_uname ,
.Nm archive_entry_copy_uname_w ,
.Nm archive_entry_dev ,
.Nm archive_entry_devmajor ,
.Nm archive_entry_devminor ,
.Nm archive_entry_filetype ,
.Nm archive_entry_fflags ,
.Nm archive_entry_fflags_text ,
.Nm archive_entry_free ,
.Nm archive_entry_gid ,
.Nm archive_entry_gname ,
.Nm archive_entry_hardlink ,
.Nm archive_entry_ino ,
.Nm archive_entry_mode ,
.Nm archive_entry_mtime ,
.Nm archive_entry_mtime_nsec ,
.Nm archive_entry_nlink ,
.Nm archive_entry_new ,
.Nm archive_entry_pathname ,
.Nm archive_entry_pathname_w ,
.Nm archive_entry_rdev ,
.Nm archive_entry_rdevmajor ,
.Nm archive_entry_rdevminor ,
.Nm archive_entry_set_atime ,
.Nm archive_entry_set_ctime ,
.Nm archive_entry_set_dev ,
.Nm archive_entry_set_devmajor ,
.Nm archive_entry_set_devminor ,
.Nm archive_entry_set_filetype ,
.Nm archive_entry_set_fflags ,
.Nm archive_entry_set_gid ,
.Nm archive_entry_set_gname ,
.Nm archive_entry_set_hardlink ,
.Nm archive_entry_set_link ,
.Nm archive_entry_set_mode ,
.Nm archive_entry_set_mtime ,
.Nm archive_entry_set_pathname ,
.Nm archive_entry_set_rdevmajor ,
.Nm archive_entry_set_rdevminor ,
.Nm archive_entry_set_size ,
.Nm archive_entry_set_symlink ,
.Nm archive_entry_set_uid ,
.Nm archive_entry_set_uname ,
.Nm archive_entry_size ,
.Nm archive_entry_sourcepath ,
.Nm archive_entry_stat ,
.Nm archive_entry_symlink ,
.Nm archive_entry_uid ,
.Nm archive_entry_uname
.Nd functions for manipulating archive entry descriptions
.Nd functions for managing archive entry descriptions
.Sh LIBRARY
Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive_entry.h
.Ft void
.Fo archive_entry_acl_add_entry
.Fa "struct archive_entry *"
.Fa "int type"
.Fa "int permset"
.Fa "int tag"
.Fa "int qual"
.Fa "const char *name"
.Fc
.Ft void
.Fo archive_entry_acl_add_entry_w
.Fa "struct archive_entry *"
.Fa "int type"
.Fa "int permset"
.Fa "int tag"
.Fa "int qual"
.Fa "const wchar_t *name"
.Fc
.Ft void
.Fn archive_entry_acl_clear "struct archive_entry *"
.Ft int
.Fn archive_entry_acl_count "struct archive_entry *" "int type"
.Ft int
.Fo archive_entry_acl_next
.Fa "struct archive_entry *"
.Fa "int want_type"
.Fa "int *type"
.Fa "int *permset"
.Fa "int *tag"
.Fa "int *qual"
.Fa "const char **name"
.Fc
.Ft int
.Fo archive_entry_acl_next_w
.Fa "struct archive_entry *"
.Fa "int want_type"
.Fa "int *type"
.Fa "int *permset"
.Fa "int *tag"
.Fa "int *qual"
.Fa "const wchar_t **name"
.Fc
.Ft int
.Fn archive_entry_acl_reset "struct archive_entry *" "int want_type"
.Ft const wchar_t *
.Fn archive_entry_acl_text_w "struct archive_entry *" "int flags"
.Ft time_t
.Fn archive_entry_atime "struct archive_entry *"
.Ft long
.Fn archive_entry_atime_nsec "struct archive_entry *"
.Ft "struct archive_entry *"
.Fn archive_entry_clear "struct archive_entry *"
.Ft struct archive_entry *
.Fn archive_entry_clone "struct archive_entry *"
.Ft const char *
.Fn archive_entry_copy_fflags_text "struct archive_entry *" "const char *"
.Ft const wchar_t *
.Fn archive_entry_copy_fflags_text_w "struct archive_entry *" "const wchar_t *"
.Ft void
.Fn archive_entry_copy_gname "struct archive_entry *" "const char *"
.Ft void
.Fn archive_entry_copy_gname_w "struct archive_entry *" "const wchar_t *"
.Ft void
.Fn archive_entry_copy_hardlink "struct archive_entry *" "const char *"
.Ft void
.Fn archive_entry_copy_hardlink_w "struct archive_entry *" "const wchar_t *"
.Ft void
.Fn archive_entry_copy_sourcepath "struct archive_entry *" "const char *"
.Ft void
.Fn archive_entry_copy_pathname_w "struct archive_entry *" "const wchar_t *"
.Ft void
.Fn archive_entry_copy_stat "struct archive_entry *" "const struct stat *"
.Ft void
.Fn archive_entry_copy_symlink "struct archive_entry *" "const char *"
.Ft void
.Fn archive_entry_copy_symlink_w "struct archive_entry *" "const wchar_t *"
.Ft void
.Fn archive_entry_copy_uname "struct archive_entry *" "const char *"
.Ft void
.Fn archive_entry_copy_uname_w "struct archive_entry *" "const wchar_t *"
.Ft dev_t
.Fn archive_entry_dev "struct archive_entry *"
.Ft dev_t
.Fn archive_entry_devmajor "struct archive_entry *"
.Ft dev_t
.Fn archive_entry_devminor "struct archive_entry *"
.Ft mode_t
.Fn archive_entry_filetype "struct archive_entry *"
.Ft void
.Fo archive_entry_fflags
.Fa "struct archive_entry *"
.Fa "unsigned long *set"
.Fa "unsigned long *clear"
.Fc
.Ft const char *
.Fn archive_entry_fflags_text "struct archive_entry *"
.Ft void
.Fn archive_entry_free "struct archive_entry *"
.Ft const char *
.Fn archive_entry_gname "struct archive_entry *"
.Ft const char *
.Fn archive_entry_hardlink "struct archive_entry *"
.Ft ino_t
.Fn archive_entry_ino "struct archive_entry *"
.Ft mode_t
.Fn archive_entry_mode "struct archive_entry *"
.Ft time_t
.Fn archive_entry_mtime "struct archive_entry *"
.Ft long
.Fn archive_entry_mtime_nsec "struct archive_entry *"
.Ft unsigned int
.Fn archive_entry_nlink "struct archive_entry *"
.Ft struct archive_entry *
.Fn archive_entry_new "void"
.Ft const char *
.Fn archive_entry_pathname "struct archive_entry *"
.Ft const wchar_t *
.Fn archive_entry_pathname_w "struct archive_entry *"
.Ft dev_t
.Fn archive_entry_rdev "struct archive_entry *"
.Ft dev_t
.Fn archive_entry_rdevmajor "struct archive_entry *"
.Ft dev_t
.Fn archive_entry_rdevminor "struct archive_entry *"
.Ft void
.Fn archive_entry_set_dev "struct archive_entry *" "dev_t"
.Ft void
.Fn archive_entry_set_devmajor "struct archive_entry *" "dev_t"
.Ft void
.Fn archive_entry_set_devminor "struct archive_entry *" "dev_t"
.Ft void
.Fn archive_entry_set_filetype "struct archive_entry *" "unsigned int"
.Ft void
.Fo archive_entry_set_fflags
.Fa "struct archive_entry *"
.Fa "unsigned long set"
.Fa "unsigned long clear"
.Fc
.Ft void
.Fn archive_entry_set_gid "struct archive_entry *" "gid_t"
.Ft void
.Fn archive_entry_set_gname "struct archive_entry *" "const char *"
.Ft void
.Fn archive_entry_set_hardlink "struct archive_entry *" "const char *"
.Ft void
.Fn archive_entry_set_ino "struct archive_entry *" "unsigned long"
.Ft void
.Fn archive_entry_set_link "struct archive_entry *" "const char *"
.Ft void
.Fn archive_entry_set_mode "struct archive_entry *" "mode_t"
.Ft void
.Fn archive_entry_set_mtime "struct archive_entry *" "time_t" "long nanos"
.Ft void
.Fn archive_entry_set_nlink "struct archive_entry *" "unsigned int"
.Ft void
.Fn archive_entry_set_pathname "struct archive_entry *" "const char *"
.Ft void
.Fn archive_entry_set_rdev "struct archive_entry *" "dev_t"
.Ft void
.Fn archive_entry_set_rdevmajor "struct archive_entry *" "dev_t"
.Ft void
.Fn archive_entry_set_rdevminor "struct archive_entry *" "dev_t"
.Ft void
.Fn archive_entry_set_size "struct archive_entry *" "int64_t"
.Ft void
.Fn archive_entry_set_symlink "struct archive_entry *" "const char *"
.Ft void
.Fn archive_entry_set_uid "struct archive_entry *" "uid_t"
.Ft void
.Fn archive_entry_set_uname "struct archive_entry *" "const char *"
.Ft int64_t
.Fn archive_entry_size "struct archive_entry *"
.Ft const char *
.Fn archive_entry_sourcepath "struct archive_entry *"
.Ft const struct stat *
.Fn archive_entry_stat "struct archive_entry *"
.Ft const char *
.Fn archive_entry_symlink "struct archive_entry *"
.Ft const char *
.Fn archive_entry_uname "struct archive_entry *"
.Sh DESCRIPTION
These functions create and manipulate data objects that
represent entries within an archive.
@ -320,8 +81,24 @@ Allocate and return a blank
.Tn struct archive_entry
object.
.El
.Ss Set and Get Functions
Most of the functions here set or read entries in an object.
.Ss Function groups
Due to high number of functions, the accessor functions can be found in
man pages grouped by the purpose.
.Bl -tag -width ".Xr archive_entry_perms 3"
.It Xr archive_entry_acl 3
Access Control List manipulation
.It Xr archive_entry_paths 3
Path name manipulation
.It Xr archive_entry_perms 3
User, group and mode manipulation
.It Xr archive_entry_stat 3
Functions not in the other groups and copying to/from
.Vt struct stat .
.It Xr archive_entry_time 3
Time field manipulation
.El
.Pp
Most of the functions set or read entries in an object.
Such functions have one of the following forms:
.Bl -tag -compact -width indent
.It Fn archive_entry_set_XXXX
@ -336,11 +113,11 @@ Returns the specified data.
In the case of strings, a const-qualified pointer to
the string is returned.
.El
String data can be set or accessed as wide-character strings
String data can be set or accessed as wide character strings
or normal
.Va char
strings.
The functions that use wide-character strings are suffixed with
The functions that use wide character strings are suffixed with
.Cm _w .
Note that these are different representations of the same data:
For example, if you store a narrow string and read the corresponding
@ -350,75 +127,15 @@ Similarly, if you store a wide string and then store a
narrow string for the same data, the previously-set wide string will
be discarded in favor of the new data.
.Pp
There are a few set/get functions that merit additional description:
.Bl -tag -compact -width indent
.It Fn archive_entry_set_link
This function sets the symlink field if it is already set.
Otherwise, it sets the hardlink field.
.El
.Ss File Flags
File flags are transparently converted between a bitmap
representation and a textual format.
For example, if you set the bitmap and ask for text, the library
will build a canonical text format.
However, if you set a text format and request a text format,
you will get back the same text, even if it is ill-formed.
If you need to canonicalize a textual flags string, you should first set the
text form, then request the bitmap form, then use that to set the bitmap form.
Setting the bitmap format will clear the internal text representation
and force it to be reconstructed when you next request the text form.
.Pp
The bitmap format consists of two integers, one containing bits
that should be set, the other specifying bits that should be
cleared.
Bits not mentioned in either bitmap will be ignored.
Usually, the bitmap of bits to be cleared will be set to zero.
In unusual circumstances, you can force a fully-specified set
of file flags by setting the bitmap of flags to clear to the complement
of the bitmap of flags to set.
(This differs from
.Xr fflagstostr 3 ,
which only includes names for set bits.)
Converting a bitmap to a textual string is a platform-specific
operation; bits that are not meaningful on the current platform
will be ignored.
.Pp
The canonical text format is a comma-separated list of flag names.
The
.Fn archive_entry_copy_fflags_text
and
.Fn archive_entry_copy_fflags_text_w
functions parse the provided text and sets the internal bitmap values.
This is a platform-specific operation; names that are not meaningful
on the current platform will be ignored.
The function returns a pointer to the start of the first name that was not
recognized, or NULL if every name was recognized.
Note that every name--including names that follow an unrecognized name--will
be evaluated, and the bitmaps will be set to reflect every name that is
recognized.
(In particular, this differs from
.Xr strtofflags 3 ,
which stops parsing at the first unrecognized name.)
.Ss ACL Handling
XXX This needs serious help.
XXX
.Pp
An
.Dq Access Control List
(ACL) is a list of permissions that grant access to particular users or
groups beyond what would normally be provided by standard POSIX mode bits.
The ACL handling here addresses some deficiencies in the POSIX.1e draft 17 ACL
specification.
In particular, POSIX.1e draft 17 specifies several different formats, but
none of those formats include both textual user/group names and numeric
UIDs/GIDs.
.Pp
XXX explain ACL stuff XXX
.\" .Sh EXAMPLE
.\" .Sh RETURN VALUES
.\" .Sh ERRORS
.Sh SEE ALSO
.Xr archive 3
.Xr archive_entry_acl 3 ,
.Xr archive_entry_paths 3 ,
.Xr archive_entry_perms 3 ,
.Xr archive_entry_time 3
.Xr libarchive 3 ,
.Sh HISTORY
The
.Nm libarchive
@ -429,5 +146,5 @@ library first appeared in
The
.Nm libarchive
library was written by
.An Tim Kientzle Aq Mt kientzle@acm.org .
.An Tim Kientzle Aq kientzle@acm.org .
.\" .Sh BUGS

View File

@ -1,4 +1,4 @@
/* $NetBSD: archive_pack_dev.c,v 1.1.1.1 2017/04/20 12:55:35 joerg Exp $ */
/* $NetBSD: archive_pack_dev.c,v 1.2 2017/04/20 13:01:40 joerg Exp $ */
/*-
* Copyright (c) 1998, 2001 The NetBSD Foundation, Inc.
@ -37,7 +37,7 @@
#include <sys/cdefs.h>
#endif
#if !defined(lint)
__RCSID("$NetBSD: archive_pack_dev.c,v 1.1.1.1 2017/04/20 12:55:35 joerg Exp $");
__RCSID("$NetBSD: archive_pack_dev.c,v 1.2 2017/04/20 13:01:40 joerg Exp $");
#endif /* not lint */
#ifdef HAVE_LIMITS_H

View File

@ -1,4 +1,4 @@
/* $NetBSD: archive_pack_dev.h,v 1.1.1.1 2017/04/20 12:55:33 joerg Exp $ */
/* $NetBSD: archive_pack_dev.h,v 1.2 2017/04/20 13:01:40 joerg Exp $ */
/*-
* Copyright (c) 1998, 2001 The NetBSD Foundation, Inc.

View File

@ -22,181 +22,18 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD: head/lib/libarchive/archive_read.3 191595 2009-04-27 20:13:13Z kientzle $
.\" $FreeBSD$
.\"
.Dd April 13, 2009
.Dt archive_read 3
.Dd February 2, 2012
.Dt ARCHIVE_READ 3
.Os
.Sh NAME
.Nm archive_read_new ,
.Nm archive_read_set_filter_options ,
.Nm archive_read_set_format_options ,
.Nm archive_read_set_options ,
.Nm archive_read_support_compression_all ,
.Nm archive_read_support_compression_bzip2 ,
.Nm archive_read_support_compression_compress ,
.Nm archive_read_support_compression_gzip ,
.Nm archive_read_support_compression_lzma ,
.Nm archive_read_support_compression_none ,
.Nm archive_read_support_compression_xz ,
.Nm archive_read_support_compression_program ,
.Nm archive_read_support_compression_program_signature ,
.Nm archive_read_support_format_all ,
.Nm archive_read_support_format_ar ,
.Nm archive_read_support_format_cpio ,
.Nm archive_read_support_format_empty ,
.Nm archive_read_support_format_iso9660 ,
.Nm archive_read_support_format_mtree,
.Nm archive_read_support_format_raw,
.Nm archive_read_support_format_tar ,
.Nm archive_read_support_format_zip ,
.Nm archive_read_open ,
.Nm archive_read_open2 ,
.Nm archive_read_open_fd ,
.Nm archive_read_open_FILE ,
.Nm archive_read_open_filename ,
.Nm archive_read_open_memory ,
.Nm archive_read_next_header ,
.Nm archive_read_next_header2 ,
.Nm archive_read_data ,
.Nm archive_read_data_block ,
.Nm archive_read_data_skip ,
.\" #if ARCHIVE_API_VERSION < 3
.Nm archive_read_data_into_buffer ,
.\" #endif
.Nm archive_read_data_into_fd ,
.Nm archive_read_extract ,
.Nm archive_read_extract2 ,
.Nm archive_read_extract_set_progress_callback ,
.Nm archive_read_close ,
.Nm archive_read_finish
.Nm archive_read
.Nd functions for reading streaming archives
.Sh LIBRARY
Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive.h
.Ft struct archive *
.Fn archive_read_new "void"
.Ft int
.Fn archive_read_support_compression_all "struct archive *"
.Ft int
.Fn archive_read_support_compression_bzip2 "struct archive *"
.Ft int
.Fn archive_read_support_compression_compress "struct archive *"
.Ft int
.Fn archive_read_support_compression_gzip "struct archive *"
.Ft int
.Fn archive_read_support_compression_lzma "struct archive *"
.Ft int
.Fn archive_read_support_compression_none "struct archive *"
.Ft int
.Fn archive_read_support_compression_xz "struct archive *"
.Ft int
.Fo archive_read_support_compression_program
.Fa "struct archive *"
.Fa "const char *cmd"
.Fc
.Ft int
.Fo archive_read_support_compression_program_signature
.Fa "struct archive *"
.Fa "const char *cmd"
.Fa "const void *signature"
.Fa "size_t signature_length"
.Fc
.Ft int
.Fn archive_read_support_format_all "struct archive *"
.Ft int
.Fn archive_read_support_format_ar "struct archive *"
.Ft int
.Fn archive_read_support_format_cpio "struct archive *"
.Ft int
.Fn archive_read_support_format_empty "struct archive *"
.Ft int
.Fn archive_read_support_format_iso9660 "struct archive *"
.Ft int
.Fn archive_read_support_format_mtree "struct archive *"
.Ft int
.Fn archive_read_support_format_raw "struct archive *"
.Ft int
.Fn archive_read_support_format_tar "struct archive *"
.Ft int
.Fn archive_read_support_format_zip "struct archive *"
.Ft int
.Fn archive_read_set_filter_options "struct archive *" "const char *"
.Ft int
.Fn archive_read_set_format_options "struct archive *" "const char *"
.Ft int
.Fn archive_read_set_options "struct archive *" "const char *"
.Ft int
.Fo archive_read_open
.Fa "struct archive *"
.Fa "void *client_data"
.Fa "archive_open_callback *"
.Fa "archive_read_callback *"
.Fa "archive_close_callback *"
.Fc
.Ft int
.Fo archive_read_open2
.Fa "struct archive *"
.Fa "void *client_data"
.Fa "archive_open_callback *"
.Fa "archive_read_callback *"
.Fa "archive_skip_callback *"
.Fa "archive_close_callback *"
.Fc
.Ft int
.Fn archive_read_open_FILE "struct archive *" "FILE *file"
.Ft int
.Fn archive_read_open_fd "struct archive *" "int fd" "size_t block_size"
.Ft int
.Fo archive_read_open_filename
.Fa "struct archive *"
.Fa "const char *filename"
.Fa "size_t block_size"
.Fc
.Ft int
.Fn archive_read_open_memory "struct archive *" "void *buff" "size_t size"
.Ft int
.Fn archive_read_next_header "struct archive *" "struct archive_entry **"
.Ft int
.Fn archive_read_next_header2 "struct archive *" "struct archive_entry *"
.Ft ssize_t
.Fn archive_read_data "struct archive *" "void *buff" "size_t len"
.Ft int
.Fo archive_read_data_block
.Fa "struct archive *"
.Fa "const void **buff"
.Fa "size_t *len"
.Fa "off_t *offset"
.Fc
.Ft int
.Fn archive_read_data_skip "struct archive *"
.\" #if ARCHIVE_API_VERSION < 3
.Ft int
.Fn archive_read_data_into_buffer "struct archive *" "void *" "ssize_t len"
.\" #endif
.Ft int
.Fn archive_read_data_into_fd "struct archive *" "int fd"
.Ft int
.Fo archive_read_extract
.Fa "struct archive *"
.Fa "struct archive_entry *"
.Fa "int flags"
.Fc
.Ft int
.Fo archive_read_extract2
.Fa "struct archive *src"
.Fa "struct archive_entry *"
.Fa "struct archive *dest"
.Fc
.Ft void
.Fo archive_read_extract_set_progress_callback
.Fa "struct archive *"
.Fa "void (*func)(void *)"
.Fa "void *user_data"
.Fc
.Ft int
.Fn archive_read_close "struct archive *"
.Ft int
.Fn archive_read_finish "struct archive *"
.Sh DESCRIPTION
These functions provide a complete API for reading streaming archives.
The general process is to first create the
@ -204,369 +41,120 @@ The general process is to first create the
object, set options, initialize the reader, iterate over the archive
headers and associated data, then close the archive and release all
resources.
The following summary describes the functions in approximately the
order they would be used:
.Bl -tag -compact -width indent
.It Fn archive_read_new
Allocates and initializes a
.Tn struct archive
object suitable for reading from an archive.
.It Fn archive_read_support_compression_bzip2 , \
Fn archive_read_support_compression_compress , \
Fn archive_read_support_compression_gzip , \
Fn archive_read_support_compression_lzma , \
Fn archive_read_support_compression_none , \
Fn archive_read_support_compression_xz
Enables auto-detection code and decompression support for the
specified compression.
Returns
.Cm ARCHIVE_OK
if the compression is fully supported, or
.Cm ARCHIVE_WARN
if the compression is supported only through an external program.
Note that decompression using an external program is usually slower than
decompression through built-in libraries.
Note that
.Dq none
is always enabled by default.
.It Fn archive_read_support_compression_all
Enables all available decompression filters.
.It Fn archive_read_support_compression_program
Data is fed through the specified external program before being dearchived.
Note that this disables automatic detection of the compression format,
so it makes no sense to specify this in conjunction with any other
decompression option.
.It Fn archive_read_support_compression_program_signature
This feeds data through the specified external program
but only if the initial bytes of the data match the specified
signature value.
.It Fn archive_read_support_format_all , \
Fn archive_read_support_format_ar , \
Fn archive_read_support_format_cpio , \
Fn archive_read_support_format_empty , \
Fn archive_read_support_format_iso9660 , \
Fn archive_read_support_format_mtree , \
Fn archive_read_support_format_tar , \
Fn archive_read_support_format_zip
Enables support---including auto-detection code---for the
specified archive format.
For example,
.Fn archive_read_support_format_tar
enables support for a variety of standard tar formats, old-style tar,
ustar, pax interchange format, and many common variants.
For convenience,
.Fn archive_read_support_format_all
enables support for all available formats.
Only empty archives are supported by default.
.It Fn archive_read_support_format_raw
The
.Dq raw
format handler allows libarchive to be used to read arbitrary data.
It treats any data stream as an archive with a single entry.
The pathname of this entry is
.Dq data ;
all other entry fields are unset.
This is not enabled by
.Fn archive_read_support_format_all
in order to avoid erroneous handling of damaged archives.
.It Fn archive_read_set_filter_options , \
Fn archive_read_set_format_options , \
Fn archive_read_set_options
Specifies options that will be passed to currently-registered
filters (including decompression filters) and/or format readers.
The argument is a comma-separated list of individual options.
Individual options have one of the following forms:
.Bl -tag -compact -width indent
.It Ar option=value
The option/value pair will be provided to every module.
Modules that do not accept an option with this name will ignore it.
.It Ar option
The option will be provided to every module with a value of
.Dq 1 .
.It Ar !option
The option will be provided to every module with a NULL value.
.It Ar module:option=value , Ar module:option , Ar module:!option
As above, but the corresponding option and value will be provided
only to modules whose name matches
.Ar module .
.El
The return value will be
.Cm ARCHIVE_OK
if any module accepts the option, or
.Cm ARCHIVE_WARN
if no module accepted the option, or
.Cm ARCHIVE_FATAL
if there was a fatal error while attempting to process the option.
.\"
.Ss Create archive object
See
.Xr archive_read_new 3 .
.Pp
The currently supported options are:
.Bl -tag -compact -width indent
.It Format iso9660
.Bl -tag -compact -width indent
.It Cm joliet
Support Joliet extensions.
Defaults to enabled, use
.Cm !joliet
to disable.
.El
.El
.It Fn archive_read_open
The same as
.Fn archive_read_open2 ,
except that the skip callback is assumed to be
.Dv NULL .
.It Fn archive_read_open2
Freeze the settings, open the archive, and prepare for reading entries.
This is the most generic version of this call, which accepts
four callback functions.
Most clients will want to use
.Fn archive_read_open_filename ,
.Fn archive_read_open_FILE ,
.Fn archive_read_open_fd ,
or
.Fn archive_read_open_memory
instead.
The library invokes the client-provided functions to obtain
raw bytes from the archive.
.It Fn archive_read_open_FILE
Like
.Fn archive_read_open ,
except that it accepts a
To read an archive, you must first obtain an initialized
.Tn struct archive
object from
.Fn archive_read_new .
.\"
.Ss Enable filters and formats
See
.Xr archive_read_filter 3
and
.Xr archive_read_format 3 .
.Pp
You can then modify this object for the desired operations with the
various
.Fn archive_read_set_XXX
and
.Fn archive_read_support_XXX
functions.
In particular, you will need to invoke appropriate
.Fn archive_read_support_XXX
functions to enable the corresponding compression and format
support.
Note that these latter functions perform two distinct operations:
they cause the corresponding support code to be linked into your
program, and they enable the corresponding auto-detect code.
Unless you have specific constraints, you will generally want
to invoke
.Fn archive_read_support_filter_all
and
.Fn archive_read_support_format_all
to enable auto-detect for all formats and compression types
currently supported by the library.
.\"
.Ss Set options
See
.Xr archive_read_set_options 3 .
.\"
.Ss Open archive
See
.Xr archive_read_open 3 .
.Pp
Once you have prepared the
.Tn struct archive
object, you call
.Fn archive_read_open
to actually open the archive and prepare it for reading.
There are several variants of this function;
the most basic expects you to provide pointers to several
functions that can provide blocks of bytes from the archive.
There are convenience forms that allow you to
specify a filename, file descriptor,
.Ft "FILE *"
pointer.
This function should not be used with tape drives or other devices
that require strict I/O blocking.
.It Fn archive_read_open_fd
Like
.Fn archive_read_open ,
except that it accepts a file descriptor and block size rather than
a set of function pointers.
Note that the file descriptor will not be automatically closed at
end-of-archive.
This function is safe for use with tape drives or other blocked devices.
.It Fn archive_read_open_file
This is a deprecated synonym for
.Fn archive_read_open_filename .
.It Fn archive_read_open_filename
Like
.Fn archive_read_open ,
except that it accepts a simple filename and a block size.
A NULL filename represents standard input.
This function is safe for use with tape drives or other blocked devices.
.It Fn archive_read_open_memory
Like
.Fn archive_read_open ,
except that it accepts a pointer and size of a block of
memory containing the archive data.
.It Fn archive_read_next_header
Read the header for the next entry and return a pointer to
a
.Tn struct archive_entry .
This is a convenience wrapper around
.Fn archive_read_next_header2
that reuses an internal
object, or a block of memory from which to read the archive data.
Note that the core library makes no assumptions about the
size of the blocks read;
callback functions are free to read whatever block size is
most appropriate for the medium.
.\"
.Ss Consume archive
See
.Xr archive_read_header 3 ,
.Xr archive_read_data 3
and
.Xr archive_read_extract 3 .
.Pp
Each archive entry consists of a header followed by a certain
amount of data.
You can obtain the next header with
.Fn archive_read_next_header ,
which returns a pointer to an
.Tn struct archive_entry
object for each request.
.It Fn archive_read_next_header2
Read the header for the next entry and populate the provided
.Tn struct archive_entry .
.It Fn archive_read_data
Read data associated with the header just read.
Internally, this is a convenience function that calls
.Fn archive_read_data_block
and fills any gaps with nulls so that callers see a single
continuous stream of data.
.It Fn archive_read_data_block
Return the next available block of data for this entry.
Unlike
.Fn archive_read_data ,
the
.Fn archive_read_data_block
function avoids copying data and allows you to correctly handle
sparse files, as supported by some archive formats.
The library guarantees that offsets will increase and that blocks
will not overlap.
Note that the blocks returned from this function can be much larger
than the block size read from disk, due to compression
and internal buffer optimizations.
.It Fn archive_read_data_skip
A convenience function that repeatedly calls
.Fn archive_read_data_block
to skip all of the data for this archive entry.
.\" #if ARCHIVE_API_VERSION < 3
.It Fn archive_read_data_into_buffer
This function is deprecated and will be removed.
Use
structure with information about the current archive element.
If the entry is a regular file, then the header will be followed
by the file data.
You can use
.Fn archive_read_data
instead.
.\" #endif
.It Fn archive_read_data_into_fd
A convenience function that repeatedly calls
(which works much like the
.Xr read 2
system call)
to read this data from the archive, or
.Fn archive_read_data_block
to copy the entire entry to the provided file descriptor.
.It Fn archive_read_extract , Fn archive_read_extract_set_skip_file
A convenience function that wraps the corresponding
.Xr archive_write_disk 3
interfaces.
The first call to
which provides a slightly more efficient interface.
You may prefer to use the higher-level
.Fn archive_read_data_skip ,
which reads and discards the data for this entry,
.Fn archive_read_data_into_fd ,
which copies the data to the provided file descriptor, or
.Fn archive_read_extract ,
which recreates the specified entry on disk and copies data
from the archive.
In particular, note that
.Fn archive_read_extract
creates a restore object using
.Xr archive_write_disk_new 3
and
.Xr archive_write_disk_set_standard_lookup 3 ,
then transparently invokes
.Xr archive_write_disk_set_options 3 ,
.Xr archive_write_header 3 ,
.Xr archive_write_data 3 ,
and
.Xr archive_write_finish_entry 3
to create the entry on disk and copy data into it.
The
.Va flags
argument is passed unmodified to
.Xr archive_write_disk_set_options 3 .
.It Fn archive_read_extract2
This is another version of
.Fn archive_read_extract
that allows you to provide your own restore object.
In particular, this allows you to override the standard lookup functions
using
.Xr archive_write_disk_set_group_lookup 3 ,
and
.Xr archive_write_disk_set_user_lookup 3 .
Note that
.Fn archive_read_extract2
does not accept a
.Va flags
argument; you should use
.Fn archive_write_disk_set_options
to set the restore options yourself.
.It Fn archive_read_extract_set_progress_callback
Sets a pointer to a user-defined callback that can be used
for updating progress displays during extraction.
The progress function will be invoked during the extraction of large
regular files.
The progress function will be invoked with the pointer provided to this call.
Generally, the data pointed to should include a reference to the archive
object and the archive_entry object so that various statistics
can be retrieved for the progress display.
.It Fn archive_read_close
Complete the archive and invoke the close callback.
.It Fn archive_read_finish
Invokes
.Fn archive_read_close
if it was not invoked manually, then release all resources.
Note: In libarchive 1.x, this function was declared to return
.Ft void ,
which made it impossible to detect certain errors when
.Fn archive_read_close
was invoked implicitly from this function.
The declaration is corrected beginning with libarchive 2.0.
.El
.Pp
Note that the library determines most of the relevant information about
the archive by inspection.
In particular, it automatically detects
.Xr gzip 1
or
.Xr bzip2 1
compression and transparently performs the appropriate decompression.
It also automatically detects the archive format.
.Pp
A complete description of the
.Tn struct archive
and
uses the
.Tn struct archive_entry
objects can be found in the overview manual page for
.Xr libarchive 3 .
.Sh CLIENT CALLBACKS
The callback functions must match the following prototypes:
.Bl -item -offset indent
.It
.Ft typedef ssize_t
.Fo archive_read_callback
.Fa "struct archive *"
.Fa "void *client_data"
.Fa "const void **buffer"
.Fc
.It
.\" #if ARCHIVE_API_VERSION < 2
.Ft typedef int
.Fo archive_skip_callback
.Fa "struct archive *"
.Fa "void *client_data"
.Fa "size_t request"
.Fc
.\" #else
.\" .Ft typedef off_t
.\" .Fo archive_skip_callback
.\" .Fa "struct archive *"
.\" .Fa "void *client_data"
.\" .Fa "off_t request"
.\" .Fc
.\" #endif
.It
.Ft typedef int
.Fn archive_open_callback "struct archive *" "void *client_data"
.It
.Ft typedef int
.Fn archive_close_callback "struct archive *" "void *client_data"
.El
structure that you provide it, which may differ from the
entry just read from the archive.
In particular, many applications will want to override the
pathname, file permissions, or ownership.
.\"
.Ss Release resources
See
.Xr archive_read_free 3 .
.Pp
The open callback is invoked by
.Fn archive_open .
It should return
.Cm ARCHIVE_OK
if the underlying file or data source is successfully
opened.
If the open fails, it should call
.Fn archive_set_error
to register an error code and message and return
.Cm ARCHIVE_FATAL .
.Pp
The read callback is invoked whenever the library
requires raw bytes from the archive.
The read callback should read data into a buffer,
set the
.Li const void **buffer
argument to point to the available data, and
return a count of the number of bytes available.
The library will invoke the read callback again
only after it has consumed this data.
The library imposes no constraints on the size
of the data blocks returned.
On end-of-file, the read callback should
return zero.
On error, the read callback should invoke
.Fn archive_set_error
to register an error code and message and
return -1.
.Pp
The skip callback is invoked when the
library wants to ignore a block of data.
The return value is the number of bytes actually
skipped, which may differ from the request.
If the callback cannot skip data, it should return
zero.
If the skip callback is not provided (the
function pointer is
.Dv NULL ),
the library will invoke the read function
instead and simply discard the result.
A skip callback can provide significant
performance gains when reading uncompressed
archives from slow disk drives or other media
that can skip quickly.
.Pp
The close callback is invoked by archive_close when
the archive processing is complete.
The callback should return
.Cm ARCHIVE_OK
on success.
On failure, the callback should invoke
.Fn archive_set_error
to register an error code and message and
return
.Cm ARCHIVE_FATAL.
Once you have finished reading data from the archive, you
should call
.Fn archive_read_close
to close the archive, then call
.Fn archive_read_free
to release all resources, including all memory allocated by the library.
.\"
.Sh EXAMPLE
The following illustrates basic usage of the library.
In this example,
@ -587,18 +175,18 @@ list_archive(const char *name)
mydata = malloc(sizeof(struct mydata));
a = archive_read_new();
mydata->name = name;
archive_read_support_compression_all(a);
archive_read_support_filter_all(a);
archive_read_support_format_all(a);
archive_read_open(a, mydata, myopen, myread, myclose);
while (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
printf("%s\en",archive_entry_pathname(entry));
archive_read_data_skip(a);
}
archive_read_finish(a);
archive_read_free(a);
free(mydata);
}
ssize_t
la_ssize_t
myread(struct archive *a, void *client_data, const void **buff)
{
struct mydata *mydata = client_data;
@ -626,62 +214,18 @@ myclose(struct archive *a, void *client_data)
return (ARCHIVE_OK);
}
.Ed
.Sh RETURN VALUES
Most functions return zero on success, non-zero on error.
The possible return codes include:
.Cm ARCHIVE_OK
(the operation succeeded),
.Cm ARCHIVE_WARN
(the operation succeeded but a non-critical error was encountered),
.Cm ARCHIVE_EOF
(end-of-archive was encountered),
.Cm ARCHIVE_RETRY
(the operation failed but can be retried),
and
.Cm ARCHIVE_FATAL
(there was a fatal error; the archive should be closed immediately).
Detailed error codes and textual descriptions are available from the
.Fn archive_errno
and
.Fn archive_error_string
functions.
.Pp
.Fn archive_read_new
returns a pointer to a freshly allocated
.Tn struct archive
object.
It returns
.Dv NULL
on error.
.Pp
.Fn archive_read_data
returns a count of bytes actually read or zero at the end of the entry.
On error, a value of
.Cm ARCHIVE_FATAL ,
.Cm ARCHIVE_WARN ,
or
.Cm ARCHIVE_RETRY
is returned and an error code and textual description can be retrieved from the
.Fn archive_errno
and
.Fn archive_error_string
functions.
.Pp
The library expects the client callbacks to behave similarly.
If there is an error, you can use
.Fn archive_set_error
to set an appropriate error code and description,
then return one of the non-zero values above.
(Note that the value eventually returned to the client may
not be the same; many errors that are not critical at the level
of basic I/O can prevent the archive from being properly read,
thus most I/O errors eventually cause
.Cm ARCHIVE_FATAL
to be returned.)
.\" .Sh ERRORS
.Sh SEE ALSO
.Xr tar 1 ,
.Xr archive 3 ,
.Xr libarchive 3 ,
.Xr archive_read_new 3 ,
.Xr archive_read_data 3 ,
.Xr archive_read_extract 3 ,
.Xr archive_read_filter 3 ,
.Xr archive_read_format 3 ,
.Xr archive_read_header 3 ,
.Xr archive_read_open 3 ,
.Xr archive_read_set_options 3 ,
.Xr archive_util 3 ,
.Xr tar 5
.Sh HISTORY
@ -694,7 +238,7 @@ library first appeared in
The
.Nm libarchive
library was written by
.An Tim Kientzle Aq Mt kientzle@acm.org .
.An Tim Kientzle Aq kientzle@acm.org .
.Sh BUGS
Many traditional archiver programs treat
empty files as valid empty archives.

View File

@ -22,13 +22,14 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD: head/lib/libarchive/archive_read_disk.3 190957 2009-04-12 05:04:02Z kientzle $
.\" $FreeBSD$
.\"
.Dd March 10, 2009
.Dt archive_read_disk 3
.Dd April 3, 2017
.Dt ARCHIVE_READ_DISK 3
.Os
.Sh NAME
.Nm archive_read_disk_new ,
.Nm archive_read_disk_set_behavior ,
.Nm archive_read_disk_set_symlink_logical ,
.Nm archive_read_disk_set_symlink_physical ,
.Nm archive_read_disk_set_symlink_hybrid ,
@ -37,15 +38,17 @@
.Nm archive_read_disk_uname ,
.Nm archive_read_disk_set_uname_lookup ,
.Nm archive_read_disk_set_gname_lookup ,
.Nm archive_read_disk_set_standard_lookup ,
.Nm archive_read_close ,
.Nm archive_read_finish
.Nm archive_read_disk_set_standard_lookup
.Nd functions for reading objects from disk
.Sh LIBRARY
Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive.h
.Ft struct archive *
.Fn archive_read_disk_new "void"
.Ft int
.Fn archive_read_disk_set_behavior "struct archive *" "int"
.Ft int
.Fn archive_read_disk_set_symlink_logical "struct archive *"
.Ft int
.Fn archive_read_disk_set_symlink_physical "struct archive *"
@ -78,10 +81,6 @@
.Fa "int fd"
.Fa "const struct stat *"
.Fc
.Ft int
.Fn archive_read_close "struct archive *"
.Ft int
.Fn archive_read_finish "struct archive *"
.Sh DESCRIPTION
These functions provide an API for reading information about
objects on disk.
@ -93,9 +92,56 @@ objects.
Allocates and initializes a
.Tn struct archive
object suitable for reading object information from disk.
.It Fn archive_read_disk_set_symlink_logical , \
Fn archive_read_disk_set_symlink_physical , \
Fn archive_read_disk_set_symlink_hybrid
.It Fn archive_read_disk_set_behavior
Configures various behavior options when reading entries from disk.
The flags field consists of a bitwise OR of one or more of the
following values:
.Bl -tag -compact -width "indent"
.It Cm ARCHIVE_READDISK_HONOR_NODUMP
Skip files and directories with the nodump file attribute (file flag) set.
By default, the nodump file atrribute is ignored.
.It Cm ARCHIVE_READDISK_MAC_COPYFILE
Mac OS X specific. Read metadata (ACLs and extended attributes) with
.Xr copyfile 3 .
By default, metadata is read using
.Xr copyfile 3 .
.It Cm ARCHIVE_READDISK_NO_ACL
Do not read Access Control Lists.
By default, ACLs are read from disk.
.It Cm ARCHIVE_READDISK_NO_FFLAGS
Do not read file attributes (file flags).
By default, file attributes are read from disk.
See
.Xr chattr 1
.Pq Linux
or
.Xr chflags 1
.Pq FreeBSD, Mac OS X
for more information on file attributes.
.It Cm ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS
Do not traverse mount points.
By defaut, moint points are traversed.
.It Cm ARCHIVE_READDISK_NO_XATTR
Do not read extended file attributes (xattrs).
By default, extended file attributes are read from disk.
See
.Xr xattr 7
.Pq Linux ,
.Xr xattr 2
.Pq Mac OS X ,
or
.Xr getextattr 8
.Pq FreeBSD
for more information on extended file attributes.
.It Cm ARCHIVE_READDISK_RESTORE_ATIME
Restore access time of traversed files.
By default, access time of traversed files is not restored.
.El
.It Xo
.Fn archive_read_disk_set_symlink_logical ,
.Fn archive_read_disk_set_symlink_physical ,
.Fn archive_read_disk_set_symlink_hybrid
.Xc
This sets the mode used for handling symbolic links.
The
.Dq logical
@ -108,12 +154,16 @@ The
mode currently behaves identically to the
.Dq logical
mode.
.It Fn archive_read_disk_gname , \
Fn archive_read_disk_uname
.It Xo
.Fn archive_read_disk_gname ,
.Fn archive_read_disk_uname
.Xc
Returns a user or group name given a gid or uid value.
By default, these always return a NULL string.
.It Fn archive_read_disk_set_gname_lookup , \
Fn archive_read_disk_set_uname_lookup
.It Xo
.Fn archive_read_disk_set_gname_lookup ,
.Fn archive_read_disk_set_uname_lookup
.Xc
These allow you to override the functions used for
user and group name lookups.
You may also provide a
@ -127,16 +177,16 @@ object is destroyed or when new lookup functions are registered.
This convenience function installs a standard set of user
and group name lookup functions.
These functions use
.Xr getpwid 3
.Xr getpwuid 3
and
.Xr getgrid 3
.Xr getgrgid 3
to convert ids to names, defaulting to NULL if the names cannot
be looked up.
These functions also implement a simple memory cache to reduce
the number of calls to
.Xr getpwid 3
.Xr getpwuid 3
and
.Xr getgrid 3 .
.Xr getgrgid 3 .
.It Fn archive_read_disk_entry_from_file
Populates a
.Tn struct archive_entry
@ -170,12 +220,6 @@ using the currently registered lookup functions above.
This affects the file ownership fields and ACL values in the
.Tn struct archive_entry
object.
.It Fn archive_read_close
This currently does nothing.
.It Fn archive_write_finish
Invokes
.Fn archive_write_close
if it was not invoked manually, then releases all resources.
.El
More information about the
.Va struct archive
@ -201,13 +245,13 @@ file_to_archive(struct archive *a, const char *name)
fd = open(name, O_RDONLY);
if (fd < 0)
return;
archive_entry_copy_sourcepath(entry, name);
archive_entry_copy_pathname(entry, name);
archive_read_disk_entry_from_file(ard, entry, fd, NULL);
archive_write_header(a, entry);
while ((bytes_read = read(fd, buff, sizeof(buff))) > 0)
archive_write_data(a, buff, bytes_read);
archive_write_finish_entry(a);
archive_read_finish(ard);
archive_read_free(ard);
archive_entry_free(entry);
}
.Ed
@ -223,15 +267,6 @@ for operations that might succeed if retried,
for unusual conditions that do not prevent further operations, and
.Cm ARCHIVE_FATAL
for serious errors that make remaining operations impossible.
The
.Xr archive_errno 3
and
.Xr archive_error_string 3
functions can be used to retrieve an appropriate error code and a
textual error message.
(See
.Xr archive_util 3
for details.)
.Pp
.Fn archive_read_disk_new
returns a pointer to a newly-allocated
@ -247,9 +282,17 @@ pointers to the textual name or NULL if the lookup failed for any reason.
The returned pointer points to internal storage that
may be reused on the next call to either of these functions;
callers should copy the string if they need to continue accessing it.
.Pp
.\"
.Sh ERRORS
Detailed error codes and textual descriptions are available from the
.Fn archive_errno
and
.Fn archive_error_string
functions.
.\"
.Sh SEE ALSO
.Xr archive_read 3 ,
.Xr archive_util 3 ,
.Xr archive_write 3 ,
.Xr archive_write_disk 3 ,
.Xr tar 1 ,
@ -270,14 +313,14 @@ and first appeared in
The
.Nm libarchive
library was written by
.An Tim Kientzle Aq Mt kientzle@freebsd.org .
.An Tim Kientzle Aq kientzle@FreeBSD.org .
.Sh BUGS
The
.Dq standard
user name and group name lookup functions are not the defaults because
.Xr getgrid 3
.Xr getgrgid 3
and
.Xr getpwid 3
.Xr getpwuid 3
are sometimes too large for particular applications.
The current design allows the application author to use a more
compact implementation when appropriate.

File diff suppressed because it is too large Load Diff

View File

@ -22,10 +22,10 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD: head/lib/libarchive/archive_util.3 201098 2009-12-28 02:58:14Z kientzle $
.\" $FreeBSD$
.\"
.Dd January 8, 2005
.Dt archive_util 3
.Dd February 2, 2012
.Dt ARCHIVE_UTIL 3
.Os
.Sh NAME
.Nm archive_clear_error ,
@ -35,10 +35,16 @@
.Nm archive_errno ,
.Nm archive_error_string ,
.Nm archive_file_count ,
.Nm archive_filter_code ,
.Nm archive_filter_count ,
.Nm archive_filter_name ,
.Nm archive_format ,
.Nm archive_format_name ,
.Nm archive_position ,
.Nm archive_set_error
.Nd libarchive utility functions
.Sh LIBRARY
Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive.h
.Ft void
@ -56,9 +62,17 @@
.Ft int
.Fn archive_file_count "struct archive *"
.Ft int
.Fn archive_filter_code "struct archive *" "int"
.Ft int
.Fn archive_filter_count "struct archive *" "int"
.Ft const char *
.Fn archive_filter_name "struct archive *" "int"
.Ft int
.Fn archive_format "struct archive *"
.Ft const char *
.Fn archive_format_name "struct archive *"
.Ft int64_t
.Fn archive_position "struct archive *" "int"
.Ft void
.Fo archive_set_error
.Fa "struct archive *"
@ -77,17 +91,21 @@ library.
Clears any error information left over from a previous call.
Not generally used in client code.
.It Fn archive_compression
Returns a numeric code indicating the current compression.
This value is set by
.Fn archive_read_open .
Synonym for
.Fn archive_filter_code(a, 0) .
.It Fn archive_compression_name
Returns a text description of the current compression suitable for display.
Synonym for
.Fn archive_filter_name(a, 0) .
.It Fn archive_copy_error
Copies error information from one archive to another.
.It Fn archive_errno
Returns a numeric error code (see
.Xr errno 2 )
indicating the reason for the most recent error return.
Note that this can not be reliably used to detect whether an
error has occurred.
It should be used only after another libarchive function
has returned an error status.
.It Fn archive_error_string
Returns a textual error message suitable for display.
The error message here is usually more specific than that
@ -98,9 +116,45 @@ to
.It Fn archive_file_count
Returns a count of the number of files processed by this archive object.
The count is incremented by calls to
.Xr archive_write_header
.Xr archive_write_header 3
or
.Xr archive_read_next_header .
.Xr archive_read_next_header 3 .
.It Fn archive_filter_code
Returns a numeric code identifying the indicated filter.
See
.Fn archive_filter_count
for details of the numbering.
.It Fn archive_filter_count
Returns the number of filters in the current pipeline.
For read archive handles, these filters are added automatically
by the automatic format detection.
For write archive handles, these filters are added by calls to the various
.Fn archive_write_add_filter_XXX
functions.
Filters in the resulting pipeline are numbered so that filter 0
is the filter closest to the format handler.
As a convenience, functions that expect a filter number will
accept -1 as a synonym for the highest-numbered filter.
.Pp
For example, when reading a uuencoded gzipped tar archive, there
are three filters:
filter 0 is the gunzip filter,
filter 1 is the uudecode filter,
and filter 2 is the pseudo-filter that wraps the archive read functions.
In this case, requesting
.Fn archive_position(a, -1)
would be a synonym for
.Fn archive_position(a, 2)
which would return the number of bytes currently read from the archive, while
.Fn archive_position(a, 1)
would return the number of bytes after uudecoding, and
.Fn archive_position(a, 0)
would return the number of bytes after decompression.
.It Fn archive_filter_name
Returns a textual name identifying the indicated filter.
See
.Fn archive_filter_count
for details of the numbering.
.It Fn archive_format
Returns a numeric code indicating the format of the current
archive entry.
@ -113,6 +167,16 @@ utilize GNU tar extensions and several entries that do not.
These entries will have different format codes.
.It Fn archive_format_name
A textual description of the format of the current entry.
.It Fn archive_position
Returns the number of bytes read from or written to the indicated filter.
In particular,
.Fn archive_position(a, 0)
returns the number of bytes read or written by the format handler, while
.Fn archive_position(a, -1)
returns the number of bytes read or written to the archive.
See
.Fn archive_filter_count
for details of the numbering here.
.It Fn archive_set_error
Sets the numeric error code and error description that will be returned
by
@ -157,4 +221,4 @@ library first appeared in
The
.Nm libarchive
library was written by
.An Tim Kientzle Aq Mt kientzle@acm.org .
.An Tim Kientzle Aq kientzle@acm.org .

View File

@ -1,4 +1,4 @@
.\" Copyright (c) 2003-2007 Tim Kientzle
.\" Copyright (c) 2003-2011 Tim Kientzle
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
@ -22,107 +22,18 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD: head/lib/libarchive/archive_write.3 201110 2009-12-28 03:31:29Z kientzle $
.\" $FreeBSD$
.\"
.Dd May 11, 2008
.Dt archive_write 3
.Dd February 2, 2012
.Dt ARCHIVE_WRITE 3
.Os
.Sh NAME
.Nm archive_write_new ,
.Nm archive_write_set_format_cpio ,
.Nm archive_write_set_format_pax ,
.Nm archive_write_set_format_pax_restricted ,
.Nm archive_write_set_format_shar ,
.Nm archive_write_set_format_ustar ,
.Nm archive_write_get_bytes_per_block ,
.Nm archive_write_set_bytes_per_block ,
.Nm archive_write_set_bytes_in_last_block ,
.Nm archive_write_set_compression_bzip2 ,
.Nm archive_write_set_compression_compress ,
.Nm archive_write_set_compression_gzip ,
.Nm archive_write_set_compression_none ,
.Nm archive_write_set_compression_program ,
.Nm archive_write_set_compressor_options ,
.Nm archive_write_set_format_options ,
.Nm archive_write_set_options ,
.Nm archive_write_open ,
.Nm archive_write_open_fd ,
.Nm archive_write_open_FILE ,
.Nm archive_write_open_filename ,
.Nm archive_write_open_memory ,
.Nm archive_write_header ,
.Nm archive_write_data ,
.Nm archive_write_finish_entry ,
.Nm archive_write_close ,
.Nm archive_write_finish
.Nm archive_write
.Nd functions for creating archives
.Sh LIBRARY
Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive.h
.Ft struct archive *
.Fn archive_write_new "void"
.Ft int
.Fn archive_write_get_bytes_per_block "struct archive *"
.Ft int
.Fn archive_write_set_bytes_per_block "struct archive *" "int bytes_per_block"
.Ft int
.Fn archive_write_set_bytes_in_last_block "struct archive *" "int"
.Ft int
.Fn archive_write_set_compression_bzip2 "struct archive *"
.Ft int
.Fn archive_write_set_compression_compress "struct archive *"
.Ft int
.Fn archive_write_set_compression_gzip "struct archive *"
.Ft int
.Fn archive_write_set_compression_none "struct archive *"
.Ft int
.Fn archive_write_set_compression_program "struct archive *" "const char * cmd"
.Ft int
.Fn archive_write_set_format_cpio "struct archive *"
.Ft int
.Fn archive_write_set_format_pax "struct archive *"
.Ft int
.Fn archive_write_set_format_pax_restricted "struct archive *"
.Ft int
.Fn archive_write_set_format_shar "struct archive *"
.Ft int
.Fn archive_write_set_format_ustar "struct archive *"
.Ft int
.Fn archive_write_set_format_options "struct archive *" "const char *"
.Ft int
.Fn archive_write_set_compressor_options "struct archive *" "const char *"
.Ft int
.Fn archive_write_set_options "struct archive *" "const char *"
.Ft int
.Fo archive_write_open
.Fa "struct archive *"
.Fa "void *client_data"
.Fa "archive_open_callback *"
.Fa "archive_write_callback *"
.Fa "archive_close_callback *"
.Fc
.Ft int
.Fn archive_write_open_fd "struct archive *" "int fd"
.Ft int
.Fn archive_write_open_FILE "struct archive *" "FILE *file"
.Ft int
.Fn archive_write_open_filename "struct archive *" "const char *filename"
.Ft int
.Fo archive_write_open_memory
.Fa "struct archive *"
.Fa "void *buffer"
.Fa "size_t bufferSize"
.Fa "size_t *outUsed"
.Fc
.Ft int
.Fn archive_write_header "struct archive *" "struct archive_entry *"
.Ft ssize_t
.Fn archive_write_data "struct archive *" "const void *" "size_t"
.Ft int
.Fn archive_write_finish_entry "struct archive *"
.Ft int
.Fn archive_write_close "struct archive *"
.Ft int
.Fn archive_write_finish "struct archive *"
.Sh DESCRIPTION
These functions provide a complete API for creating streaming
archive files.
@ -130,309 +41,83 @@ The general process is to first create the
.Tn struct archive
object, set any desired options, initialize the archive, append entries, then
close the archive and release all resources.
The following summary describes the functions in approximately
the order they are ordinarily used:
.Bl -tag -width indent
.It Fn archive_write_new
Allocates and initializes a
.Tn struct archive
object suitable for writing a tar archive.
.It Fn archive_write_set_bytes_per_block
Sets the block size used for writing the archive data.
Every call to the write callback function, except possibly the last one, will
use this value for the length.
The third parameter is a boolean that specifies whether or not the final block
written will be padded to the full block size.
If it is zero, the last block will not be padded.
If it is non-zero, padding will be added both before and after compression.
The default is to use a block size of 10240 bytes and to pad the last block.
Note that a block size of zero will suppress internal blocking
and cause writes to be sent directly to the write callback as they occur.
.It Fn archive_write_get_bytes_per_block
Retrieve the block size to be used for writing.
A value of -1 here indicates that the library should use default values.
A value of zero indicates that internal blocking is suppressed.
.It Fn archive_write_set_bytes_in_last_block
Sets the block size used for writing the last block.
If this value is zero, the last block will be padded to the same size
as the other blocks.
Otherwise, the final block will be padded to a multiple of this size.
In particular, setting it to 1 will cause the final block to not be padded.
For compressed output, any padding generated by this option
is applied only after the compression.
The uncompressed data is always unpadded.
The default is to pad the last block to the full block size (note that
.Fn archive_write_open_filename
will set this based on the file type).
Unlike the other
.Dq set
functions, this function can be called after the archive is opened.
.It Fn archive_write_get_bytes_in_last_block
Retrieve the currently-set value for last block size.
A value of -1 here indicates that the library should use default values.
.It Fn archive_write_set_format_cpio , \
Fn archive_write_set_format_pax , \
Fn archive_write_set_format_pax_restricted , \
Fn archive_write_set_format_shar , \
Fn archive_write_set_format_ustar
Sets the format that will be used for the archive.
The library can write
POSIX octet-oriented cpio format archives,
POSIX-standard
.Dq pax interchange
format archives,
traditional
.Dq shar
archives,
enhanced
.Dq binary
shar archives that store a variety of file attributes and handle binary files,
and
POSIX-standard
.Dq ustar
archives.
The pax interchange format is a backwards-compatible tar format that
adds key/value attributes to each entry and supports arbitrary
filenames, linknames, uids, sizes, etc.
.Dq Restricted pax interchange format
is the library default; this is the same as pax format, but suppresses
the pax extended header for most normal files.
In most cases, this will result in ordinary ustar archives.
.It Fn archive_write_set_compression_bzip2 , \
Fn archive_write_set_compression_compress , \
Fn archive_write_set_compression_gzip , \
Fn archive_write_set_compression_none
The resulting archive will be compressed as specified.
Note that the compressed output is always properly blocked.
.It Fn archive_write_set_compression_program
The archive will be fed into the specified compression program.
The output of that program is blocked and written to the client
write callbacks.
.It Fn archive_write_set_compressor_options , \
Fn archive_write_set_format_options , \
Fn archive_write_set_options
Specifies options that will be passed to the currently-enabled
compressor and/or format writer.
The argument is a comma-separated list of individual options.
Individual options have one of the following forms:
.Bl -tag -compact -width indent
.It Ar option=value
The option/value pair will be provided to every module.
Modules that do not accept an option with this name will ignore it.
.It Ar option
The option will be provided to every module with a value of
.Dq 1 .
.It Ar !option
The option will be provided to every module with a NULL value.
.It Ar module:option=value , Ar module:option , Ar module:!option
As above, but the corresponding option and value will be provided
only to modules whose name matches
.Ar module .
.El
The return value will be
.Cm ARCHIVE_OK
if any module accepts the option, or
.Cm ARCHIVE_WARN
if no module accepted the option, or
.Cm ARCHIVE_FATAL
if there was a fatal error while attempting to process the option.
.Pp
The currently supported options are:
.Bl -tag -compact -width indent
.It Compressor gzip
.Bl -tag -compact -width indent
.It Cm compression-level
The value is interpreted as a decimal integer specifying the
gzip compression level.
.El
.It Compressor xz
.Bl -tag -compact -width indent
.It Cm compression-level
The value is interpreted as a decimal integer specifying the
compression level.
.El
.It Format mtree
.Bl -tag -compact -width indent
.It Cm cksum , Cm device , Cm flags , Cm gid , Cm gname , Cm indent , Cm link , Cm md5 , Cm mode , Cm nlink , Cm rmd160 , Cm sha1 , Cm sha256 , Cm sha384 , Cm sha512 , Cm size , Cm time , Cm uid , Cm uname
Enable a particular keyword in the mtree output.
Prefix with an exclamation mark to disable the corresponding keyword.
The default is equivalent to
.Dq device, flags, gid, gname, link, mode, nlink, size, time, type, uid, uname .
.It Cm all
Enables all of the above keywords.
.It Cm use-set
Enables generation of
.Cm /set
lines that specify default values for the following files and/or directories.
.It Cm indent
XXX needs explanation XXX
.El
.El
.It Fn archive_write_open
Freeze the settings, open the archive, and prepare for writing entries.
This is the most generic form of this function, which accepts
pointers to three callback functions which will be invoked by
the compression layer to write the constructed archive.
.It Fn archive_write_open_fd
A convenience form of
.Fn archive_write_open
that accepts a file descriptor.
The
.Fn archive_write_open_fd
function is safe for use with tape drives or other
block-oriented devices.
.It Fn archive_write_open_FILE
A convenience form of
.Fn archive_write_open
that accepts a
.Ft "FILE *"
pointer.
Note that
.Fn archive_write_open_FILE
is not safe for writing to tape drives or other devices
that require correct blocking.
.It Fn archive_write_open_file
A deprecated synonym for
.Fn archive_write_open_filename .
.It Fn archive_write_open_filename
A convenience form of
.Fn archive_write_open
that accepts a filename.
A NULL argument indicates that the output should be written to standard output;
an argument of
.Dq -
will open a file with that name.
If you have not invoked
.Fn archive_write_set_bytes_in_last_block ,
then
.Fn archive_write_open_filename
will adjust the last-block padding depending on the file:
it will enable padding when writing to standard output or
to a character or block device node, it will disable padding otherwise.
You can override this by manually invoking
.Fn archive_write_set_bytes_in_last_block
before calling
.Fn archive_write_open .
The
.Fn archive_write_open_filename
function is safe for use with tape drives or other
block-oriented devices.
.It Fn archive_write_open_memory
A convenience form of
.Fn archive_write_open
that accepts a pointer to a block of memory that will receive
the archive.
The final
.Ft "size_t *"
argument points to a variable that will be updated
after each write to reflect how much of the buffer
is currently in use.
You should be careful to ensure that this variable
remains allocated until after the archive is
closed.
.It Fn archive_write_header
Build and write a header using the data in the provided
.Tn struct archive_entry
structure.
.\"
.Ss Create archive object
See
.Xr archive_entry 3
for information on creating and populating
.Tn struct archive_entry
objects.
.It Fn archive_write_data
Write data corresponding to the header just written.
Returns number of bytes written or -1 on error.
.It Fn archive_write_finish_entry
Close out the entry just written.
In particular, this writes out the final padding required by some formats.
Ordinarily, clients never need to call this, as it
is called automatically by
.Fn archive_write_next_header
.Xr archive_write_new 3 .
.Pp
To write an archive, you must first obtain an initialized
.Tn struct archive
object from
.Fn archive_write_new .
.\"
.Ss Enable filters and formats, configure block size and padding
See
.Xr archive_write_filter 3 ,
.Xr archive_write_format 3
and
.Fn archive_write_close
as needed.
.It Fn archive_write_close
Complete the archive and invoke the close callback.
.It Fn archive_write_finish
Invokes
.Fn archive_write_close
if it was not invoked manually, then releases all resources.
Note that this function was declared to return
.Ft void
in libarchive 1.x, which made it impossible to detect errors when
.Fn archive_write_close
was invoked implicitly from this function.
This is corrected beginning with libarchive 2.0.
.El
More information about the
.Va struct archive
object and the overall design of the library can be found in the
.Xr libarchive 3
overview.
.Sh IMPLEMENTATION
Compression support is built-in to libarchive, which uses zlib and bzlib
to handle gzip and bzip2 compression, respectively.
.Sh CLIENT CALLBACKS
To use this library, you will need to define and register
callback functions that will be invoked to write data to the
resulting archive.
These functions are registered by calling
.Fn archive_write_open :
.Bl -item -offset indent
.It
.Ft typedef int
.Fn archive_open_callback "struct archive *" "void *client_data"
.El
.Xr archive_write_blocksize 3 .
.Pp
The open callback is invoked by
.Fn archive_write_open .
It should return
.Cm ARCHIVE_OK
if the underlying file or data source is successfully
opened.
If the open fails, it should call
.Fn archive_set_error
to register an error code and message and return
.Cm ARCHIVE_FATAL .
.Bl -item -offset indent
.It
.Ft typedef ssize_t
.Fo archive_write_callback
.Fa "struct archive *"
.Fa "void *client_data"
.Fa "const void *buffer"
.Fa "size_t length"
.Fc
.El
You can then modify this object for the desired operations with the
various
.Fn archive_write_set_XXX
functions.
In particular, you will need to invoke appropriate
.Fn archive_write_add_XXX
and
.Fn archive_write_set_XXX
functions to enable the corresponding compression and format
support.
.\"
.Ss Set options
See
.Xr archive_read_set_options 3 .
.\"
.Ss Open archive
See
.Xr archive_write_open 3 .
.Pp
The write callback is invoked whenever the library
needs to write raw bytes to the archive.
For correct blocking, each call to the write callback function
should translate into a single
.Xr write 2
system call.
This is especially critical when writing archives to tape drives.
On success, the write callback should return the
number of bytes actually written.
On error, the callback should invoke
.Fn archive_set_error
to register an error code and message and return -1.
.Bl -item -offset indent
.It
.Ft typedef int
.Fn archive_close_callback "struct archive *" "void *client_data"
.El
Once you have prepared the
.Tn struct archive
object, you call
.Fn archive_write_open
to actually open the archive and prepare it for writing.
There are several variants of this function;
the most basic expects you to provide pointers to several
functions that can provide blocks of bytes from the archive.
There are convenience forms that allow you to
specify a filename, file descriptor,
.Ft "FILE *"
object, or a block of memory from which to write the archive data.
.\"
.Ss Produce archive
See
.Xr archive_write_header 3
and
.Xr archive_write_data 3 .
.Pp
The close callback is invoked by archive_close when
the archive processing is complete.
The callback should return
.Cm ARCHIVE_OK
on success.
On failure, the callback should invoke
.Fn archive_set_error
to register an error code and message and
return
.Cm ARCHIVE_FATAL.
Individual archive entries are written in a three-step
process:
You first initialize a
.Tn struct archive_entry
structure with information about the new entry.
At a minimum, you should set the pathname of the
entry and provide a
.Va struct stat
with a valid
.Va st_mode
field, which specifies the type of object and
.Va st_size
field, which specifies the size of the data portion of the object.
.\"
.Ss Release resources
See
.Xr archive_write_free 3 .
.Pp
After all entries have been written, use the
.Fn archive_write_free
function to release all resources.
.\"
.Sh EXAMPLE
The following sketch illustrates basic usage of the library.
In this example,
@ -454,8 +139,8 @@ system calls.
#include <unistd.h>
struct mydata {
const char *name;
int fd;
const char *name;
int fd;
};
int
@ -470,7 +155,7 @@ myopen(struct archive *a, void *client_data)
return (ARCHIVE_FATAL);
}
ssize_t
la_ssize_t
mywrite(struct archive *a, void *client_data, const void *buff, size_t n)
{
struct mydata *mydata = client_data;
@ -501,8 +186,13 @@ write_archive(const char *outname, const char **filename)
a = archive_write_new();
mydata->name = outname;
archive_write_set_compression_gzip(a);
archive_write_set_format_ustar(a);
/* Set archive format and filter according to output file extension.
* If it fails, set default format. Platform depended function.
* See supported formats in archive_write_set_format_filter_by_ext.c */
if (archive_write_set_format_filter_by_ext(a, outname) != ARCHIVE_OK) {
archive_write_add_filter_gzip(a);
archive_write_set_format_ustar(a);
}
archive_write_open(a, mydata, myopen, mywrite, myclose);
while (*filename) {
stat(*filename, &st);
@ -510,76 +200,35 @@ write_archive(const char *outname, const char **filename)
archive_entry_copy_stat(entry, &st);
archive_entry_set_pathname(entry, *filename);
archive_write_header(a, entry);
fd = open(*filename, O_RDONLY);
len = read(fd, buff, sizeof(buff));
while ( len > 0 ) {
archive_write_data(a, buff, len);
len = read(fd, buff, sizeof(buff));
if ((fd = open(*filename, O_RDONLY)) != -1) {
len = read(fd, buff, sizeof(buff));
while (len > 0) {
archive_write_data(a, buff, len);
len = read(fd, buff, sizeof(buff));
}
close(fd);
}
archive_entry_free(entry);
filename++;
}
archive_write_finish(a);
archive_write_free(a);
}
int main(int argc, const char **argv)
{
const char *outname;
argv++;
outname = argv++;
write_archive(outname, argv);
return 0;
const char *outname;
argv++;
outname = *argv++;
write_archive(outname, argv);
return 0;
}
.Ed
.Sh RETURN VALUES
Most functions return
.Cm ARCHIVE_OK
(zero) on success, or one of several non-zero
error codes for errors.
Specific error codes include:
.Cm ARCHIVE_RETRY
for operations that might succeed if retried,
.Cm ARCHIVE_WARN
for unusual conditions that do not prevent further operations, and
.Cm ARCHIVE_FATAL
for serious errors that make remaining operations impossible.
The
.Fn archive_errno
and
.Fn archive_error_string
functions can be used to retrieve an appropriate error code and a
textual error message.
.Pp
.Fn archive_write_new
returns a pointer to a newly-allocated
.Tn struct archive
object.
.Pp
.Fn archive_write_data
returns a count of the number of bytes actually written.
On error, -1 is returned and the
.Fn archive_errno
and
.Fn archive_error_string
functions will return appropriate values.
Note that if the client-provided write callback function
returns a non-zero value, that error will be propagated back to the caller
through whatever API function resulted in that call, which
may include
.Fn archive_write_header ,
.Fn archive_write_data ,
.Fn archive_write_close ,
or
.Fn archive_write_finish .
The client callback can call
.Fn archive_set_error
to provide values that can then be retrieved by
.Fn archive_errno
and
.Fn archive_error_string .
.Sh SEE ALSO
.Xr tar 1 ,
.Xr libarchive 3 ,
.Xr archive_write_set_options 3 ,
.Xr cpio 5 ,
.Xr mtree 5 ,
.Xr tar 5
.Sh HISTORY
The
@ -591,7 +240,7 @@ library first appeared in
The
.Nm libarchive
library was written by
.An Tim Kientzle Aq Mt kientzle@acm.org .
.An Tim Kientzle Aq kientzle@acm.org .
.Sh BUGS
There are many peculiar bugs in historic tar implementations that may cause
certain programs to reject archives written by this library.

View File

@ -22,10 +22,10 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD: src/lib/libarchive/archive_write_disk.3,v 1.4 2008/09/04 05:22:00 kientzle Exp $
.\" $FreeBSD$
.\"
.Dd August 5, 2008
.Dt archive_write_disk 3
.Dd April 3, 2017
.Dt ARCHIVE_WRITE_DISK 3
.Os
.Sh NAME
.Nm archive_write_disk_new ,
@ -33,13 +33,10 @@
.Nm archive_write_disk_set_skip_file ,
.Nm archive_write_disk_set_group_lookup ,
.Nm archive_write_disk_set_standard_lookup ,
.Nm archive_write_disk_set_user_lookup ,
.Nm archive_write_header ,
.Nm archive_write_data ,
.Nm archive_write_finish_entry ,
.Nm archive_write_close ,
.Nm archive_write_finish
.Nm archive_write_disk_set_user_lookup
.Nd functions for creating objects on disk
.Sh LIBRARY
Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive.h
.Ft struct archive *
@ -64,16 +61,6 @@
.Fa "uid_t (*)(void *, const char *uname, uid_t uid)"
.Fa "void (*cleanup)(void *)"
.Fc
.Ft int
.Fn archive_write_header "struct archive *" "struct archive_entry *"
.Ft ssize_t
.Fn archive_write_data "struct archive *" "const void *" "size_t"
.Ft int
.Fn archive_write_finish_entry "struct archive *"
.Ft int
.Fn archive_write_close "struct archive *"
.Ft int
.Fn archive_write_finish "struct archive *"
.Sh DESCRIPTION
These functions provide a complete API for creating objects on
disk from
@ -109,6 +96,33 @@ performance optimization in practice.
The options field consists of a bitwise OR of one or more of the
following values:
.Bl -tag -compact -width "indent"
.It Cm ARCHIVE_EXTRACT_ACL
Attempt to restore Access Control Lists.
By default, extended ACLs are ignored.
.It Cm ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS
Before removing a file system object prior to replacing it, clear
platform-specific file flags which might prevent its removal.
.It Cm ARCHIVE_EXTRACT_FFLAGS
Attempt to restore file attributes (file flags).
By default, file attributes are ignored.
See
.Xr chattr 1
.Pq Linux
or
.Xr chflags 1
.Pq FreeBSD, Mac OS X
for more information on file attributes.
.It Cm ARCHIVE_EXTRACT_MAC_METADATA
Mac OS X specific. Restore metadata using
.Xr copyfile 3 .
By default,
.Xr copyfile 3
metadata is ignored.
.It Cm ARCHIVE_EXTRACT_NO_OVERWRITE
Existing files on disk will not be overwritten.
By default, existing regular files are truncated and overwritten;
existing directories will have their permissions updated;
other pre-existing objects are unlinked and recreated from scratch.
.It Cm ARCHIVE_EXTRACT_OWNER
The user and group IDs should be set on the restored file.
By default, the user and group IDs are not restored.
@ -124,43 +138,9 @@ is not specified, then SUID and SGID bits will only be restored
if the default user and group IDs of newly-created objects on disk
happen to match those specified in the archive entry.
By default, only basic permissions are restored, and umask is obeyed.
.It Cm ARCHIVE_EXTRACT_TIME
The timestamps (mtime, ctime, and atime) should be restored.
By default, they are ignored.
Note that restoring of atime is not currently supported.
.It Cm ARCHIVE_EXTRACT_NO_OVERWRITE
Existing files on disk will not be overwritten.
By default, existing regular files are truncated and overwritten;
existing directories will have their permissions updated;
other pre-existing objects are unlinked and recreated from scratch.
.It Cm ARCHIVE_EXTRACT_UNLINK
Existing files on disk will be unlinked before any attempt to
create them.
In some cases, this can prove to be a significant performance improvement.
By default, existing files are truncated and rewritten, but
the file is not recreated.
In particular, the default behavior does not break existing hard links.
.It Cm ARCHIVE_EXTRACT_ACL
Attempt to restore ACLs.
By default, extended ACLs are ignored.
.It Cm ARCHIVE_EXTRACT_FFLAGS
Attempt to restore extended file flags.
By default, file flags are ignored.
.It Cm ARCHIVE_EXTRACT_XATTR
Attempt to restore POSIX.1e extended attributes.
By default, they are ignored.
.It Cm ARCHIVE_EXTRACT_SECURE_SYMLINKS
Refuse to extract any object whose final location would be altered
by a symlink on disk.
This is intended to help guard against a variety of mischief
caused by archives that (deliberately or otherwise) extract
files outside of the current directory.
The default is not to perform this check.
If
.Cm ARCHIVE_EXTRACT_UNLINK
is specified together with this option, the library will
remove any intermediate symlinks it finds and return an
error only if such symlink could not be removed.
.It Cm ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS
Refuse to extract an absolute path.
The default is to not refuse such paths.
.It Cm ARCHIVE_EXTRACT_SECURE_NODOTDOT
Refuse to extract a path that contains a
.Pa ..
@ -169,13 +149,50 @@ The default is to not refuse such paths.
Note that paths ending in
.Pa ..
always cause an error, regardless of this flag.
.It Cm ARCHIVE_EXTRACT_SECURE_SYMLINKS
Refuse to extract any object whose final location would be altered
by a symlink on disk.
This is intended to help guard against a variety of mischief
caused by archives that (deliberately or otherwise) extract
files outside of the current directory.
The default is not to perform this check.
If
.It Cm ARCHIVE_EXTRACT_SPARSE
Scan data for blocks of NUL bytes and try to recreate them with holes.
This results in sparse files, independent of whether the archive format
supports or uses them.
.Cm ARCHIVE_EXTRACT_UNLINK
is specified together with this option, the library will
remove any intermediate symlinks it finds and return an
error only if such symlink could not be removed.
.It Cm ARCHIVE_EXTRACT_TIME
The timestamps (mtime, ctime, and atime) should be restored.
By default, they are ignored.
Note that restoring of atime is not currently supported.
.It Cm ARCHIVE_EXTRACT_UNLINK
Existing files on disk will be unlinked before any attempt to
create them.
In some cases, this can prove to be a significant performance improvement.
By default, existing files are truncated and rewritten, but
the file is not recreated.
In particular, the default behavior does not break existing hard links.
.It Cm ARCHIVE_EXTRACT_XATTR
Attempt to restore extended file attributes.
By default, they are ignored.
See
.Xr xattr 7
.Pq Linux ,
.Xr xattr 2
.Pq Mac OS X ,
or
.Xr getextattr 8
.Pq FreeBSD
for more information on extended file attributes.
.El
.It Fn archive_write_disk_set_group_lookup , \
Fn archive_write_disk_set_user_lookup
.It Xo
.Fn archive_write_disk_set_group_lookup ,
.Fn archive_write_disk_set_user_lookup
.Xc
The
.Tn struct archive_entry
objects contain both names and ids that can be used to identify users
@ -207,40 +224,6 @@ the number of calls to
.Xr getpwnam 3
and
.Xr getgrnam 3 .
.It Fn archive_write_header
Build and write a header using the data in the provided
.Tn struct archive_entry
structure.
See
.Xr archive_entry 3
for information on creating and populating
.Tn struct archive_entry
objects.
.It Fn archive_write_data
Write data corresponding to the header just written.
Returns number of bytes written or -1 on error.
.It Fn archive_write_finish_entry
Close out the entry just written.
Ordinarily, clients never need to call this, as it
is called automatically by
.Fn archive_write_next_header
and
.Fn archive_write_close
as needed.
.It Fn archive_write_close
Set any attributes that could not be set during the initial restore.
For example, directory timestamps are not restored initially because
restoring a subsequent file would alter that timestamp.
Similarly, non-writable directories are initially created with
write permissions (so that their contents can be restored).
The
.Nm
library maintains a list of all such deferred attributes and
sets them when this function is invoked.
.It Fn archive_write_finish
Invokes
.Fn archive_write_close
if it was not invoked manually, then releases all resources.
.El
More information about the
.Va struct archive
@ -261,12 +244,6 @@ for operations that might succeed if retried,
for unusual conditions that do not prevent further operations, and
.Cm ARCHIVE_FATAL
for serious errors that make remaining operations impossible.
The
.Fn archive_errno
and
.Fn archive_error_string
functions can be used to retrieve an appropriate error code and a
textual error message.
.Pp
.Fn archive_write_disk_new
returns a pointer to a newly-allocated
@ -274,12 +251,18 @@ returns a pointer to a newly-allocated
object.
.Pp
.Fn archive_write_data
returns a count of the number of bytes actually written.
On error, -1 is returned and the
returns a count of the number of bytes actually written,
or
.Li -1
on error.
.\"
.Sh ERRORS
Detailed error codes and textual descriptions are available from the
.Fn archive_errno
and
.Fn archive_error_string
functions will return appropriate values.
functions.
.\"
.Sh SEE ALSO
.Xr archive_read 3 ,
.Xr archive_write 3 ,
@ -301,7 +284,7 @@ and first appeared in
The
.Nm libarchive
library was written by
.An Tim Kientzle Aq Mt kientzle@acm.org .
.An Tim Kientzle Aq kientzle@acm.org .
.Sh BUGS
Directories are actually extracted in two distinct phases.
Directories are created during
@ -337,7 +320,7 @@ In particular, the directory
.Pa aa
is created as well as the final object
.Pa bb .
In theory, this can be exploited to create an entire directory heirarchy
In theory, this can be exploited to create an entire directory hierarchy
with a single request.
Of course, this does not work if the
.Cm ARCHIVE_EXTRACT_NODOTDOT
@ -369,5 +352,5 @@ compact implementation when appropriate.
.Pp
There should be a corresponding
.Nm archive_read_disk
interface that walks a directory heirarchy and returns archive
entry objects.
interface that walks a directory hierarchy and returns archive
entry objects.

View File

@ -48,6 +48,7 @@ struct ar_w {
uint64_t entry_padding;
int is_strtab;
int has_strtab;
char wrote_global_header;
char *strtab;
};
@ -74,8 +75,8 @@ static int archive_write_ar_header(struct archive_write *,
struct archive_entry *);
static ssize_t archive_write_ar_data(struct archive_write *,
const void *buff, size_t s);
static int archive_write_ar_destroy(struct archive_write *);
static int archive_write_ar_finish(struct archive_write *);
static int archive_write_ar_free(struct archive_write *);
static int archive_write_ar_close(struct archive_write *);
static int archive_write_ar_finish_entry(struct archive_write *);
static const char *ar_basename(const char *path);
static int format_octal(int64_t v, char *p, int s);
@ -85,7 +86,11 @@ int
archive_write_set_format_ar_bsd(struct archive *_a)
{
struct archive_write *a = (struct archive_write *)_a;
int r = archive_write_set_format_ar(a);
int r;
archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
ARCHIVE_STATE_NEW, "archive_write_set_format_ar_bsd");
r = archive_write_set_format_ar(a);
if (r == ARCHIVE_OK) {
a->archive.archive_format = ARCHIVE_FORMAT_AR_BSD;
a->archive.archive_format_name = "ar (BSD)";
@ -97,7 +102,11 @@ int
archive_write_set_format_ar_svr4(struct archive *_a)
{
struct archive_write *a = (struct archive_write *)_a;
int r = archive_write_set_format_ar(a);
int r;
archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
ARCHIVE_STATE_NEW, "archive_write_set_format_ar_svr4");
r = archive_write_set_format_ar(a);
if (r == ARCHIVE_OK) {
a->archive.archive_format = ARCHIVE_FORMAT_AR_GNU;
a->archive.archive_format_name = "ar (GNU/SVR4)";
@ -114,22 +123,21 @@ archive_write_set_format_ar(struct archive_write *a)
struct ar_w *ar;
/* If someone else was already registered, unregister them. */
if (a->format_destroy != NULL)
(a->format_destroy)(a);
if (a->format_free != NULL)
(a->format_free)(a);
ar = (struct ar_w *)malloc(sizeof(*ar));
ar = (struct ar_w *)calloc(1, sizeof(*ar));
if (ar == NULL) {
archive_set_error(&a->archive, ENOMEM, "Can't allocate ar data");
return (ARCHIVE_FATAL);
}
memset(ar, 0, sizeof(*ar));
a->format_data = ar;
a->format_name = "ar";
a->format_write_header = archive_write_ar_header;
a->format_write_data = archive_write_ar_data;
a->format_finish = archive_write_ar_finish;
a->format_destroy = archive_write_ar_destroy;
a->format_close = archive_write_ar_close;
a->format_free = archive_write_ar_free;
a->format_finish_entry = archive_write_ar_finish_entry;
return (ARCHIVE_OK);
}
@ -156,7 +164,7 @@ archive_write_ar_header(struct archive_write *a, struct archive_entry *entry)
* Reject files with empty name.
*/
pathname = archive_entry_pathname(entry);
if (*pathname == '\0') {
if (pathname == NULL || *pathname == '\0') {
archive_set_error(&a->archive, EINVAL,
"Invalid filename");
return (ARCHIVE_WARN);
@ -166,8 +174,10 @@ archive_write_ar_header(struct archive_write *a, struct archive_entry *entry)
* If we are now at the beginning of the archive,
* we need first write the ar global header.
*/
if (a->archive.file_position == 0)
(a->compressor.write)(a, "!<arch>\n", 8);
if (!ar->wrote_global_header) {
__archive_write_output(a, "!<arch>\n", 8);
ar->wrote_global_header = 1;
}
memset(buff, ' ', 60);
strncpy(&buff[AR_fmag_offset], "`\n", 2);
@ -190,7 +200,7 @@ archive_write_ar_header(struct archive_write *a, struct archive_entry *entry)
ar->is_strtab = 1;
buff[AR_name_offset] = buff[AR_name_offset + 1] = '/';
/*
* For archive string table, only ar_size filed should
* For archive string table, only ar_size field should
* be set.
*/
goto size;
@ -330,7 +340,7 @@ size:
return (ARCHIVE_WARN);
}
ret = (a->compressor.write)(a, buff, 60);
ret = __archive_write_output(a, buff, 60);
if (ret != ARCHIVE_OK)
return (ret);
@ -338,7 +348,7 @@ size:
ar->entry_padding = ar->entry_bytes_remaining % 2;
if (append_fn > 0) {
ret = (a->compressor.write)(a, filename, strlen(filename));
ret = __archive_write_output(a, filename, strlen(filename));
if (ret != ARCHIVE_OK)
return (ret);
ar->entry_bytes_remaining -= strlen(filename);
@ -355,7 +365,7 @@ archive_write_ar_data(struct archive_write *a, const void *buff, size_t s)
ar = (struct ar_w *)a->format_data;
if (s > ar->entry_bytes_remaining)
s = ar->entry_bytes_remaining;
s = (size_t)ar->entry_bytes_remaining;
if (ar->is_strtab > 0) {
if (ar->has_strtab > 0) {
@ -374,7 +384,7 @@ archive_write_ar_data(struct archive_write *a, const void *buff, size_t s)
ar->has_strtab = 1;
}
ret = (a->compressor.write)(a, buff, s);
ret = __archive_write_output(a, buff, s);
if (ret != ARCHIVE_OK)
return (ret);
@ -383,7 +393,7 @@ archive_write_ar_data(struct archive_write *a, const void *buff, size_t s)
}
static int
archive_write_ar_destroy(struct archive_write *a)
archive_write_ar_free(struct archive_write *a)
{
struct ar_w *ar;
@ -403,16 +413,19 @@ archive_write_ar_destroy(struct archive_write *a)
}
static int
archive_write_ar_finish(struct archive_write *a)
archive_write_ar_close(struct archive_write *a)
{
struct ar_w *ar;
int ret;
/*
* If we haven't written anything yet, we need to write
* the ar global header now to make it a valid ar archive.
*/
if (a->archive.file_position == 0) {
ret = (a->compressor.write)(a, "!<arch>\n", 8);
ar = (struct ar_w *)a->format_data;
if (!ar->wrote_global_header) {
ar->wrote_global_header = 1;
ret = __archive_write_output(a, "!<arch>\n", 8);
return (ret);
}
@ -439,12 +452,12 @@ archive_write_ar_finish_entry(struct archive_write *a)
if (ar->entry_padding != 1) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Padding wrong size: %lld should be 1 or 0",
(long long)ar->entry_padding);
"Padding wrong size: %ju should be 1 or 0",
(uintmax_t)ar->entry_padding);
return (ARCHIVE_WARN);
}
ret = (a->compressor.write)(a, "\n", 1);
ret = __archive_write_output(a, "\n", 1);
return (ret);
}
@ -501,7 +514,7 @@ format_decimal(int64_t v, char *p, int s)
len = s;
h = p;
/* Negative values in ar header are meaningless , so use 0. */
/* Negative values in ar header are meaningless, so use 0. */
if (v < 0) {
while (len-- > 0)
*p++ = '0';

View File

@ -59,8 +59,8 @@ struct shar {
struct archive_string quoted_name;
};
static int archive_write_shar_finish(struct archive_write *);
static int archive_write_shar_destroy(struct archive_write *);
static int archive_write_shar_close(struct archive_write *);
static int archive_write_shar_free(struct archive_write *);
static int archive_write_shar_header(struct archive_write *,
struct archive_entry *);
static ssize_t archive_write_shar_data_sed(struct archive_write *,
@ -106,25 +106,25 @@ archive_write_set_format_shar(struct archive *_a)
struct archive_write *a = (struct archive_write *)_a;
struct shar *shar;
/* If someone else was already registered, unregister them. */
if (a->format_destroy != NULL)
(a->format_destroy)(a);
archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
ARCHIVE_STATE_NEW, "archive_write_set_format_shar");
shar = (struct shar *)malloc(sizeof(*shar));
/* If someone else was already registered, unregister them. */
if (a->format_free != NULL)
(a->format_free)(a);
shar = (struct shar *)calloc(1, sizeof(*shar));
if (shar == NULL) {
archive_set_error(&a->archive, ENOMEM, "Can't allocate shar data");
return (ARCHIVE_FATAL);
}
memset(shar, 0, sizeof(*shar));
archive_string_init(&shar->work);
archive_string_init(&shar->quoted_name);
a->format_data = shar;
a->pad_uncompressed = 0;
a->format_name = "shar";
a->format_write_header = archive_write_shar_header;
a->format_finish = archive_write_shar_finish;
a->format_destroy = archive_write_shar_destroy;
a->format_close = archive_write_shar_close;
a->format_free = archive_write_shar_free;
a->format_write_data = archive_write_shar_data_sed;
a->format_finish_entry = archive_write_shar_finish_entry;
a->archive.archive_format = ARCHIVE_FORMAT_SHAR_BASE;
@ -266,12 +266,12 @@ archive_write_shar_header(struct archive_write *a, struct archive_entry *entry)
shar->quoted_name.s, shar->quoted_name.s);
} else {
if (shar->dump) {
unsigned int mode = archive_entry_mode(entry) & 0777;
archive_string_sprintf(&shar->work,
"uudecode -p > %s << 'SHAR_END'\n",
shar->quoted_name.s);
archive_string_sprintf(&shar->work,
"begin %o ",
archive_entry_mode(entry) & 0777);
"begin %o ", mode);
shar_quote(&shar->work, name, 0);
archive_strcat(&shar->work, "\n");
} else {
@ -308,15 +308,15 @@ archive_write_shar_header(struct archive_write *a, struct archive_entry *entry)
break;
case AE_IFCHR:
archive_string_sprintf(&shar->work,
"mknod %s c %d %d\n", shar->quoted_name.s,
archive_entry_rdevmajor(entry),
archive_entry_rdevminor(entry));
"mknod %s c %ju %ju\n", shar->quoted_name.s,
(uintmax_t)archive_entry_rdevmajor(entry),
(uintmax_t)archive_entry_rdevminor(entry));
break;
case AE_IFBLK:
archive_string_sprintf(&shar->work,
"mknod %s b %d %d\n", shar->quoted_name.s,
archive_entry_rdevmajor(entry),
archive_entry_rdevminor(entry));
"mknod %s b %ju %ju\n", shar->quoted_name.s,
(uintmax_t)archive_entry_rdevmajor(entry),
(uintmax_t)archive_entry_rdevminor(entry));
break;
default:
return (ARCHIVE_WARN);
@ -349,11 +349,13 @@ archive_write_shar_data_sed(struct archive_write *a, const void *buff, size_t n)
* twice before entering the loop, so make sure three additional
* bytes can be written.
*/
if (archive_string_ensure(&shar->work, ensured + 3) == NULL)
__archive_errx(1, "Out of memory");
if (archive_string_ensure(&shar->work, ensured + 3) == NULL) {
archive_set_error(&a->archive, ENOMEM, "Out of memory");
return (ARCHIVE_FATAL);
}
if (shar->work.length > ensured) {
ret = (*a->compressor.write)(a, shar->work.s,
ret = __archive_write_output(a, shar->work.s,
shar->work.length);
if (ret != ARCHIVE_OK)
return (ARCHIVE_FATAL);
@ -377,7 +379,7 @@ archive_write_shar_data_sed(struct archive_write *a, const void *buff, size_t n)
if (buf >= buf_end) {
shar->work.length = buf - shar->work.s;
ret = (*a->compressor.write)(a, shar->work.s,
ret = __archive_write_output(a, shar->work.s,
shar->work.length);
if (ret != ARCHIVE_OK)
return (ARCHIVE_FATAL);
@ -406,16 +408,18 @@ uuencode_group(const char _in[3], char out[4])
out[3] = UUENC( 0x3f & t );
}
static void
uuencode_line(struct shar *shar, const char *inbuf, size_t len)
static int
_uuencode_line(struct archive_write *a, struct shar *shar, const char *inbuf, size_t len)
{
char *buf;
size_t alloc_len;
/* len <= 45 -> expanded to 60 + len byte + new line */
alloc_len = shar->work.length + 62;
if (archive_string_ensure(&shar->work, alloc_len) == NULL)
__archive_errx(1, "Out of memory");
if (archive_string_ensure(&shar->work, alloc_len) == NULL) {
archive_set_error(&a->archive, ENOMEM, "Out of memory");
return (ARCHIVE_FATAL);
}
buf = shar->work.s + shar->work.length;
*buf++ = UUENC(len);
@ -427,7 +431,6 @@ uuencode_line(struct shar *shar, const char *inbuf, size_t len)
}
if (len != 0) {
char tmp_buf[3];
tmp_buf[0] = inbuf[0];
if (len == 1)
tmp_buf[1] = '\0';
@ -438,11 +441,22 @@ uuencode_line(struct shar *shar, const char *inbuf, size_t len)
buf += 4;
}
*buf++ = '\n';
if ((buf - shar->work.s) > (ptrdiff_t)(shar->work.length + 62))
__archive_errx(1, "Buffer overflow");
if ((buf - shar->work.s) > (ptrdiff_t)(shar->work.length + 62)) {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC, "Buffer overflow");
return (ARCHIVE_FATAL);
}
shar->work.length = buf - shar->work.s;
return (ARCHIVE_OK);
}
#define uuencode_line(__a, __shar, __inbuf, __len) \
do { \
int r = _uuencode_line(__a, __shar, __inbuf, __len); \
if (r != ARCHIVE_OK) \
return (ARCHIVE_FATAL); \
} while (0)
static ssize_t
archive_write_shar_data_uuencode(struct archive_write *a, const void *buff,
size_t length)
@ -466,7 +480,7 @@ archive_write_shar_data_uuencode(struct archive_write *a, const void *buff,
shar->outpos += n;
return length;
}
uuencode_line(shar, shar->outbuff, 45);
uuencode_line(a, shar, shar->outbuff, 45);
src += n;
n = length - n;
} else {
@ -474,13 +488,13 @@ archive_write_shar_data_uuencode(struct archive_write *a, const void *buff,
}
while (n >= 45) {
uuencode_line(shar, src, 45);
uuencode_line(a, shar, src, 45);
src += 45;
n -= 45;
if (shar->work.length < 65536)
continue;
ret = (*a->compressor.write)(a, shar->work.s,
ret = __archive_write_output(a, shar->work.s,
shar->work.length);
if (ret != ARCHIVE_OK)
return (ARCHIVE_FATAL);
@ -508,7 +522,7 @@ archive_write_shar_finish_entry(struct archive_write *a)
/* Finish uuencoded data. */
if (shar->has_data) {
if (shar->outpos > 0)
uuencode_line(shar, shar->outbuff,
uuencode_line(a, shar, shar->outbuff,
shar->outpos);
archive_strcat(&shar->work, "`\nend\n");
archive_strcat(&shar->work, "SHAR_END\n");
@ -519,7 +533,7 @@ archive_write_shar_finish_entry(struct archive_write *a)
* directories; defer that to end of script.
*/
archive_string_sprintf(&shar->work, "chmod %o ",
archive_entry_mode(shar->entry) & 07777);
(unsigned int)(archive_entry_mode(shar->entry) & 07777));
shar_quote(&shar->work, archive_entry_pathname(shar->entry), 1);
archive_strcat(&shar->work, "\n");
@ -533,14 +547,14 @@ archive_write_shar_finish_entry(struct archive_write *a)
archive_strcat(&shar->work, ":");
shar_quote(&shar->work, g, 1);
}
archive_strcat(&shar->work, " ");
shar_quote(&shar->work,
archive_entry_pathname(shar->entry), 1);
archive_strcat(&shar->work, "\n");
}
if ((p = archive_entry_fflags_text(shar->entry)) != NULL) {
archive_string_sprintf(&shar->work, "chflags %s ",
p, archive_entry_pathname(shar->entry));
archive_string_sprintf(&shar->work, "chflags %s ", p);
shar_quote(&shar->work,
archive_entry_pathname(shar->entry), 1);
archive_strcat(&shar->work, "\n");
@ -563,7 +577,7 @@ archive_write_shar_finish_entry(struct archive_write *a)
if (shar->work.length < 65536)
return (ARCHIVE_OK);
ret = (*a->compressor.write)(a, shar->work.s, shar->work.length);
ret = __archive_write_output(a, shar->work.s, shar->work.length);
if (ret != ARCHIVE_OK)
return (ARCHIVE_FATAL);
archive_string_empty(&shar->work);
@ -572,7 +586,7 @@ archive_write_shar_finish_entry(struct archive_write *a)
}
static int
archive_write_shar_finish(struct archive_write *a)
archive_write_shar_close(struct archive_write *a)
{
struct shar *shar;
int ret;
@ -595,7 +609,7 @@ archive_write_shar_finish(struct archive_write *a)
archive_strcat(&shar->work, "exit\n");
ret = (*a->compressor.write)(a, shar->work.s, shar->work.length);
ret = __archive_write_output(a, shar->work.s, shar->work.length);
if (ret != ARCHIVE_OK)
return (ARCHIVE_FATAL);
@ -610,7 +624,7 @@ archive_write_shar_finish(struct archive_write *a)
}
static int
archive_write_shar_destroy(struct archive_write *a)
archive_write_shar_free(struct archive_write *a)
{
struct shar *shar;

View File

@ -1,5 +1,6 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* Copyright (c) 2011-2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -40,12 +41,17 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_ustar.c 191579
#include "archive.h"
#include "archive_entry.h"
#include "archive_entry_locale.h"
#include "archive_private.h"
#include "archive_write_private.h"
struct ustar {
uint64_t entry_bytes_remaining;
uint64_t entry_padding;
struct archive_string_conv *opt_sconv;
struct archive_string_conv *sconv_default;
int init_default_conversion;
};
/*
@ -108,9 +114,9 @@ static const char template_header[] = {
'0','0','0','0','0','0', ' ','\0',
/* gid, space-null termination: 8 bytes */
'0','0','0','0','0','0', ' ','\0',
/* size, space termation: 12 bytes */
/* size, space termination: 12 bytes */
'0','0','0','0','0','0','0','0','0','0','0', ' ',
/* mtime, space termation: 12 bytes */
/* mtime, space termination: 12 bytes */
'0','0','0','0','0','0','0','0','0','0','0', ' ',
/* Initial checksum value: 8 spaces */
' ',' ',' ',' ',' ',' ',' ',' ',
@ -143,15 +149,16 @@ static const char template_header[] = {
static ssize_t archive_write_ustar_data(struct archive_write *a, const void *buff,
size_t s);
static int archive_write_ustar_destroy(struct archive_write *);
static int archive_write_ustar_finish(struct archive_write *);
static int archive_write_ustar_free(struct archive_write *);
static int archive_write_ustar_close(struct archive_write *);
static int archive_write_ustar_finish_entry(struct archive_write *);
static int archive_write_ustar_header(struct archive_write *,
struct archive_entry *entry);
static int archive_write_ustar_options(struct archive_write *,
const char *, const char *);
static int format_256(int64_t, char *, int);
static int format_number(int64_t, char *, int size, int max, int strict);
static int format_octal(int64_t, char *, int);
static int write_nulls(struct archive_write *a, size_t);
/*
* Set output format to 'ustar' format.
@ -162,45 +169,98 @@ archive_write_set_format_ustar(struct archive *_a)
struct archive_write *a = (struct archive_write *)_a;
struct ustar *ustar;
archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
ARCHIVE_STATE_NEW, "archive_write_set_format_ustar");
/* If someone else was already registered, unregister them. */
if (a->format_destroy != NULL)
(a->format_destroy)(a);
if (a->format_free != NULL)
(a->format_free)(a);
/* Basic internal sanity test. */
if (sizeof(template_header) != 512) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Internal: template_header wrong size: %zd should be 512", sizeof(template_header));
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Internal: template_header wrong size: %zu should be 512",
sizeof(template_header));
return (ARCHIVE_FATAL);
}
ustar = (struct ustar *)malloc(sizeof(*ustar));
ustar = (struct ustar *)calloc(1, sizeof(*ustar));
if (ustar == NULL) {
archive_set_error(&a->archive, ENOMEM, "Can't allocate ustar data");
archive_set_error(&a->archive, ENOMEM,
"Can't allocate ustar data");
return (ARCHIVE_FATAL);
}
memset(ustar, 0, sizeof(*ustar));
a->format_data = ustar;
a->pad_uncompressed = 1; /* Mimic gtar in this respect. */
a->format_name = "ustar";
a->format_options = archive_write_ustar_options;
a->format_write_header = archive_write_ustar_header;
a->format_write_data = archive_write_ustar_data;
a->format_finish = archive_write_ustar_finish;
a->format_destroy = archive_write_ustar_destroy;
a->format_close = archive_write_ustar_close;
a->format_free = archive_write_ustar_free;
a->format_finish_entry = archive_write_ustar_finish_entry;
a->archive.archive_format = ARCHIVE_FORMAT_TAR_USTAR;
a->archive.archive_format_name = "POSIX ustar";
return (ARCHIVE_OK);
}
static int
archive_write_ustar_options(struct archive_write *a, const char *key,
const char *val)
{
struct ustar *ustar = (struct ustar *)a->format_data;
int ret = ARCHIVE_FAILED;
if (strcmp(key, "hdrcharset") == 0) {
if (val == NULL || val[0] == 0)
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"%s: hdrcharset option needs a character-set name",
a->format_name);
else {
ustar->opt_sconv = archive_string_conversion_to_charset(
&a->archive, val, 0);
if (ustar->opt_sconv != NULL)
ret = ARCHIVE_OK;
else
ret = ARCHIVE_FATAL;
}
return (ret);
}
/* Note: The "warn" return is just to inform the options
* supervisor that we didn't handle it. It will generate
* a suitable error if no one used this option. */
return (ARCHIVE_WARN);
}
static int
archive_write_ustar_header(struct archive_write *a, struct archive_entry *entry)
{
char buff[512];
int ret, ret2;
struct ustar *ustar;
struct archive_entry *entry_main;
struct archive_string_conv *sconv;
ustar = (struct ustar *)a->format_data;
/* Setup default string conversion. */
if (ustar->opt_sconv == NULL) {
if (!ustar->init_default_conversion) {
ustar->sconv_default =
archive_string_default_conversion_for_write(&(a->archive));
ustar->init_default_conversion = 1;
}
sconv = ustar->sconv_default;
} else
sconv = ustar->opt_sconv;
/* Sanity check. */
if (archive_entry_pathname(entry) == NULL) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Can't record entry in tar file without pathname");
return (ARCHIVE_FAILED);
}
/* Only regular files (not hardlinks) have data. */
if (archive_entry_hardlink(entry) != NULL ||
archive_entry_symlink(entry) != NULL ||
@ -209,37 +269,106 @@ archive_write_ustar_header(struct archive_write *a, struct archive_entry *entry)
if (AE_IFDIR == archive_entry_filetype(entry)) {
const char *p;
char *t;
size_t path_length;
/*
* Ensure a trailing '/'. Modify the entry so
* the client sees the change.
*/
p = archive_entry_pathname(entry);
if (p[strlen(p) - 1] != '/') {
t = (char *)malloc(strlen(p) + 2);
if (t == NULL) {
#if defined(_WIN32) && !defined(__CYGWIN__)
const wchar_t *wp;
wp = archive_entry_pathname_w(entry);
if (wp != NULL && wp[wcslen(wp) -1] != L'/') {
struct archive_wstring ws;
archive_string_init(&ws);
path_length = wcslen(wp);
if (archive_wstring_ensure(&ws,
path_length + 2) == NULL) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate ustar data");
"Can't allocate ustar data");
archive_wstring_free(&ws);
return(ARCHIVE_FATAL);
}
strcpy(t, p);
strcat(t, "/");
archive_entry_copy_pathname(entry, t);
free(t);
/* Should we keep '\' ? */
if (wp[path_length -1] == L'\\')
path_length--;
archive_wstrncpy(&ws, wp, path_length);
archive_wstrappend_wchar(&ws, L'/');
archive_entry_copy_pathname_w(entry, ws.s);
archive_wstring_free(&ws);
p = NULL;
} else
#endif
p = archive_entry_pathname(entry);
/*
* On Windows, this is a backup operation just in
* case getting WCS failed. On POSIX, this is a
* normal operation.
*/
if (p != NULL && p[0] != '\0' && p[strlen(p) - 1] != '/') {
struct archive_string as;
archive_string_init(&as);
path_length = strlen(p);
if (archive_string_ensure(&as,
path_length + 2) == NULL) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate ustar data");
archive_string_free(&as);
return(ARCHIVE_FATAL);
}
#if defined(_WIN32) && !defined(__CYGWIN__)
/* NOTE: This might break the pathname
* if the current code page is CP932 and
* the pathname includes a character '\'
* as a part of its multibyte pathname. */
if (p[strlen(p) -1] == '\\')
path_length--;
else
#endif
archive_strncpy(&as, p, path_length);
archive_strappend_char(&as, '/');
archive_entry_copy_pathname(entry, as.s);
archive_string_free(&as);
}
}
ret = __archive_write_format_header_ustar(a, buff, entry, -1, 1);
if (ret < ARCHIVE_WARN)
#if defined(_WIN32) && !defined(__CYGWIN__)
/* Make sure the path separators in pathname, hardlink and symlink
* are all slash '/', not the Windows path separator '\'. */
entry_main = __la_win_entry_in_posix_pathseparator(entry);
if (entry_main == NULL) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate ustar data");
return(ARCHIVE_FATAL);
}
if (entry != entry_main)
entry = entry_main;
else
entry_main = NULL;
#else
entry_main = NULL;
#endif
ret = __archive_write_format_header_ustar(a, buff, entry, -1, 1, sconv);
if (ret < ARCHIVE_WARN) {
if (entry_main)
archive_entry_free(entry_main);
return (ret);
ret2 = (a->compressor.write)(a, buff, 512);
if (ret2 < ARCHIVE_WARN)
}
ret2 = __archive_write_output(a, buff, 512);
if (ret2 < ARCHIVE_WARN) {
if (entry_main)
archive_entry_free(entry_main);
return (ret2);
}
if (ret2 < ret)
ret = ret2;
ustar->entry_bytes_remaining = archive_entry_size(entry);
ustar->entry_padding = 0x1ff & (-(int64_t)ustar->entry_bytes_remaining);
if (entry_main)
archive_entry_free(entry_main);
return (ret);
}
@ -255,10 +384,11 @@ archive_write_ustar_header(struct archive_write *a, struct archive_entry *entry)
*/
int
__archive_write_format_header_ustar(struct archive_write *a, char h[512],
struct archive_entry *entry, int tartype, int strict)
struct archive_entry *entry, int tartype, int strict,
struct archive_string_conv *sconv)
{
unsigned int checksum;
int i, ret;
int i, r, ret;
size_t copy_length;
const char *p, *pp;
int mytartype;
@ -277,13 +407,23 @@ __archive_write_format_header_ustar(struct archive_write *a, char h[512],
* are allowed to exactly fill their destination (without null),
* I use memcpy(dest, src, strlen()) here a lot to copy strings.
*/
pp = archive_entry_pathname(entry);
if (strlen(pp) <= USTAR_name_size)
memcpy(h + USTAR_name_offset, pp, strlen(pp));
r = archive_entry_pathname_l(entry, &pp, &copy_length, sconv);
if (r != 0) {
if (errno == ENOMEM) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate memory for Pathname");
return (ARCHIVE_FATAL);
}
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Can't translate pathname '%s' to %s",
pp, archive_string_conversion_charset_name(sconv));
ret = ARCHIVE_WARN;
}
if (copy_length <= USTAR_name_size)
memcpy(h + USTAR_name_offset, pp, copy_length);
else {
/* Store in two pieces, splitting at a '/'. */
p = strchr(pp + strlen(pp) - USTAR_name_size - 1, '/');
p = strchr(pp + copy_length - USTAR_name_size - 1, '/');
/*
* Look for the next '/' if we chose the first character
* as the separator. (ustar format doesn't permit
@ -302,7 +442,7 @@ __archive_write_format_header_ustar(struct archive_write *a, char h[512],
* The only feasible separator is a final '/';
* this would result in a non-empty prefix and
* an empty name, which POSIX doesn't
* explicity forbid, but it just feels wrong.
* explicitly forbid, but it just feels wrong.
*/
archive_set_error(&a->archive, ENAMETOOLONG,
"Pathname too long");
@ -315,17 +455,42 @@ __archive_write_format_header_ustar(struct archive_write *a, char h[512],
} else {
/* Copy prefix and remainder to appropriate places */
memcpy(h + USTAR_prefix_offset, pp, p - pp);
memcpy(h + USTAR_name_offset, p + 1, pp + strlen(pp) - p - 1);
memcpy(h + USTAR_name_offset, p + 1,
pp + copy_length - p - 1);
}
}
p = archive_entry_hardlink(entry);
if (p != NULL)
r = archive_entry_hardlink_l(entry, &p, &copy_length, sconv);
if (r != 0) {
if (errno == ENOMEM) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate memory for Linkname");
return (ARCHIVE_FATAL);
}
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Can't translate linkname '%s' to %s",
p, archive_string_conversion_charset_name(sconv));
ret = ARCHIVE_WARN;
}
if (copy_length > 0)
mytartype = '1';
else
p = archive_entry_symlink(entry);
if (p != NULL && p[0] != '\0') {
copy_length = strlen(p);
else {
r = archive_entry_symlink_l(entry, &p, &copy_length, sconv);
if (r != 0) {
if (errno == ENOMEM) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate memory for Linkname");
return (ARCHIVE_FATAL);
}
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Can't translate linkname '%s' to %s",
p, archive_string_conversion_charset_name(sconv));
ret = ARCHIVE_WARN;
}
}
if (copy_length > 0) {
if (copy_length > USTAR_linkname_size) {
archive_set_error(&a->archive, ENAMETOOLONG,
"Link contents too long");
@ -335,9 +500,20 @@ __archive_write_format_header_ustar(struct archive_write *a, char h[512],
memcpy(h + USTAR_linkname_offset, p, copy_length);
}
p = archive_entry_uname(entry);
if (p != NULL && p[0] != '\0') {
copy_length = strlen(p);
r = archive_entry_uname_l(entry, &p, &copy_length, sconv);
if (r != 0) {
if (errno == ENOMEM) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate memory for Uname");
return (ARCHIVE_FATAL);
}
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Can't translate uname '%s' to %s",
p, archive_string_conversion_charset_name(sconv));
ret = ARCHIVE_WARN;
}
if (copy_length > 0) {
if (copy_length > USTAR_uname_size) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Username too long");
@ -347,9 +523,20 @@ __archive_write_format_header_ustar(struct archive_write *a, char h[512],
memcpy(h + USTAR_uname_offset, p, copy_length);
}
p = archive_entry_gname(entry);
if (p != NULL && p[0] != '\0') {
copy_length = strlen(p);
r = archive_entry_gname_l(entry, &p, &copy_length, sconv);
if (r != 0) {
if (errno == ENOMEM) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate memory for Gname");
return (ARCHIVE_FATAL);
}
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Can't translate gname '%s' to %s",
p, archive_string_conversion_charset_name(sconv));
ret = ARCHIVE_WARN;
}
if (copy_length > 0) {
if (strlen(p) > USTAR_gname_size) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Group name too long");
@ -359,27 +546,36 @@ __archive_write_format_header_ustar(struct archive_write *a, char h[512],
memcpy(h + USTAR_gname_offset, p, copy_length);
}
if (format_number(archive_entry_mode(entry) & 07777, h + USTAR_mode_offset, USTAR_mode_size, USTAR_mode_max_size, strict)) {
archive_set_error(&a->archive, ERANGE, "Numeric mode too large");
if (format_number(archive_entry_mode(entry) & 07777,
h + USTAR_mode_offset, USTAR_mode_size, USTAR_mode_max_size, strict)) {
archive_set_error(&a->archive, ERANGE,
"Numeric mode too large");
ret = ARCHIVE_FAILED;
}
if (format_number(archive_entry_uid(entry), h + USTAR_uid_offset, USTAR_uid_size, USTAR_uid_max_size, strict)) {
archive_set_error(&a->archive, ERANGE, "Numeric user ID too large");
if (format_number(archive_entry_uid(entry),
h + USTAR_uid_offset, USTAR_uid_size, USTAR_uid_max_size, strict)) {
archive_set_error(&a->archive, ERANGE,
"Numeric user ID too large");
ret = ARCHIVE_FAILED;
}
if (format_number(archive_entry_gid(entry), h + USTAR_gid_offset, USTAR_gid_size, USTAR_gid_max_size, strict)) {
archive_set_error(&a->archive, ERANGE, "Numeric group ID too large");
if (format_number(archive_entry_gid(entry),
h + USTAR_gid_offset, USTAR_gid_size, USTAR_gid_max_size, strict)) {
archive_set_error(&a->archive, ERANGE,
"Numeric group ID too large");
ret = ARCHIVE_FAILED;
}
if (format_number(archive_entry_size(entry), h + USTAR_size_offset, USTAR_size_size, USTAR_size_max_size, strict)) {
archive_set_error(&a->archive, ERANGE, "File size out of range");
if (format_number(archive_entry_size(entry),
h + USTAR_size_offset, USTAR_size_size, USTAR_size_max_size, strict)) {
archive_set_error(&a->archive, ERANGE,
"File size out of range");
ret = ARCHIVE_FAILED;
}
if (format_number(archive_entry_mtime(entry), h + USTAR_mtime_offset, USTAR_mtime_size, USTAR_mtime_max_size, strict)) {
if (format_number(archive_entry_mtime(entry),
h + USTAR_mtime_offset, USTAR_mtime_size, USTAR_mtime_max_size, strict)) {
archive_set_error(&a->archive, ERANGE,
"File modification time too large");
ret = ARCHIVE_FAILED;
@ -387,15 +583,17 @@ __archive_write_format_header_ustar(struct archive_write *a, char h[512],
if (archive_entry_filetype(entry) == AE_IFBLK
|| archive_entry_filetype(entry) == AE_IFCHR) {
if (format_number(archive_entry_rdevmajor(entry), h + USTAR_rdevmajor_offset,
USTAR_rdevmajor_size, USTAR_rdevmajor_max_size, strict)) {
if (format_number(archive_entry_rdevmajor(entry),
h + USTAR_rdevmajor_offset, USTAR_rdevmajor_size,
USTAR_rdevmajor_max_size, strict)) {
archive_set_error(&a->archive, ERANGE,
"Major device number too large");
ret = ARCHIVE_FAILED;
}
if (format_number(archive_entry_rdevminor(entry), h + USTAR_rdevminor_offset,
USTAR_rdevminor_size, USTAR_rdevminor_max_size, strict)) {
if (format_number(archive_entry_rdevminor(entry),
h + USTAR_rdevminor_offset, USTAR_rdevminor_size,
USTAR_rdevminor_max_size, strict)) {
archive_set_error(&a->archive, ERANGE,
"Minor device number too large");
ret = ARCHIVE_FAILED;
@ -519,19 +717,13 @@ format_octal(int64_t v, char *p, int s)
}
static int
archive_write_ustar_finish(struct archive_write *a)
archive_write_ustar_close(struct archive_write *a)
{
int r;
if (a->compressor.write == NULL)
return (ARCHIVE_OK);
r = write_nulls(a, 512*2);
return (r);
return (__archive_write_nulls(a, 512*2));
}
static int
archive_write_ustar_destroy(struct archive_write *a)
archive_write_ustar_free(struct archive_write *a)
{
struct ustar *ustar;
@ -548,28 +740,12 @@ archive_write_ustar_finish_entry(struct archive_write *a)
int ret;
ustar = (struct ustar *)a->format_data;
ret = write_nulls(a,
ustar->entry_bytes_remaining + ustar->entry_padding);
ret = __archive_write_nulls(a,
(size_t)(ustar->entry_bytes_remaining + ustar->entry_padding));
ustar->entry_bytes_remaining = ustar->entry_padding = 0;
return (ret);
}
static int
write_nulls(struct archive_write *a, size_t padding)
{
int ret;
size_t to_write;
while (padding > 0) {
to_write = padding < a->null_length ? padding : a->null_length;
ret = (a->compressor.write)(a, a->nulls, to_write);
if (ret != ARCHIVE_OK)
return (ret);
padding -= to_write;
}
return (ARCHIVE_OK);
}
static ssize_t
archive_write_ustar_data(struct archive_write *a, const void *buff, size_t s)
{
@ -578,8 +754,8 @@ archive_write_ustar_data(struct archive_write *a, const void *buff, size_t s)
ustar = (struct ustar *)a->format_data;
if (s > ustar->entry_bytes_remaining)
s = ustar->entry_bytes_remaining;
ret = (a->compressor.write)(a, buff, s);
s = (size_t)ustar->entry_bytes_remaining;
ret = __archive_write_output(a, buff, s);
ustar->entry_bytes_remaining -= s;
if (ret != ARCHIVE_OK)
return (ret);

View File

@ -22,9 +22,9 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD: head/lib/libarchive/libarchive-formats.5 201077 2009-12-28 01:50:23Z kientzle $
.\" $FreeBSD$
.\"
.Dd May 31, 2016
.Dd December 27, 2016
.Dt LIBARCHIVE-FORMATS 5
.Os
.Sh NAME
@ -51,11 +51,11 @@ functions to enable all supported formats.
The
.Xr libarchive 3
library can read most tar archives.
However, it only writes POSIX-standard
It can write POSIX-standard
.Dq ustar
and
.Dq pax interchange
formats.
formats as well as v7 tar format and a subset of the legacy GNU tar format.
.Pp
All tar formats store each entry in one or more 512-byte records.
The first record is used for file metadata, including filename,
@ -69,13 +69,18 @@ subsequent entries.
.It Cm gnutar
The
.Xr libarchive 3
library can read GNU-format tar archives.
library can read most GNU-format tar archives.
It currently supports the most popular GNU extensions, including
modern long filename and linkname support, as well as atime and ctime data.
The libarchive library does not support multi-volume
archives, nor the old GNU long filename format.
It can read GNU sparse file entries, including the new POSIX-based
formats, but cannot write GNU sparse file entries.
formats.
.Pp
The
.Xr libarchive 3
library can write GNU tar format, including long filename
and linkname support, as well as atime and ctime data.
.It Cm pax
The
.Xr libarchive 3
@ -97,6 +102,14 @@ archiver and a few LIBARCHIVE keys.
The libarchive library can read most of the SCHILY keys
and most of the GNU keys introduced by GNU tar.
It silently ignores any keywords that it does not understand.
.Pp
The pax interchange format converts filenames to Unicode
and stores them using the UTF-8 encoding.
Prior to libarchive 3.0, libarchive erroneously assumed
that the system wide-character routines natively supported
Unicode.
This caused it to mis-handle non-ASCII filenames on systems
that did not satisfy this assumption.
.It Cm restricted pax
The libarchive library can also write pax archives in which it
attempts to suppress the extended attributes entry whenever
@ -134,6 +147,32 @@ security information cannot be stored.
Archive entries are limited to 8 gigabytes in size.
.El
Note that the pax interchange format has none of these restrictions.
The ustar format is old and widely supported.
It is recommended when compatibility is the primary concern.
.It Cm v7
The libarchive library can read and write the legacy v7 tar format.
This format has the following limitations:
.Bl -bullet -compact
.It
Only regular files, directories, and symbolic links can be archived.
Block and character device nodes, FIFOs, and sockets cannot be archived.
.It
Path names in the archive are limited to 100 bytes.
.It
Symbolic links and hard links are stored in the archive with
the name of the referenced file.
This name is limited to 100 bytes.
.It
User and group information are stored as numeric IDs; there
is no provision for storing user or group names.
.It
Extended attributes, file flags, and other extended
security information cannot be stored.
.It
Archive entries are limited to 8 gigabytes in size.
.El
Generally, users should prefer the ustar format for portability
as the v7 tar format is both less useful and less portable.
.El
.Pp
The libarchive library also reads a variety of commonly-used extensions to
@ -152,8 +191,6 @@ and device numbers.
.It Solaris extensions
Libarchive recognizes ACL and extended attribute records written
by Solaris tar.
Currently, libarchive only has support for old-style ACLs; the
newer NFSv4 ACLs are recognized but discarded.
.El
.Pp
The first tar program appeared in Seventh Edition Unix in 1979.
@ -195,7 +232,7 @@ This format stores the header contents as octal values in ASCII.
It is standard, portable, and immune from byte-order confusion.
File sizes and mtime are limited to 33 bits (8GB file size),
other fields are limited to 18 bits.
.It Cm SVR4
.It Cm SVR4/newc
The libarchive library can read both CRC and non-CRC variants of
this format.
The SVR4 format uses eight-digit hexadecimal values for
@ -267,19 +304,68 @@ If both extensions are present, the Joliet extensions will be
used and the Rockridge extensions will be ignored.
In particular, this can create problems with hardlinks and symlinks,
which are supported by Rockridge but not by Joliet.
.Pp
Libarchive reads ISO9660 images using a streaming strategy.
This allows it to read compressed images directly
(decompressing on the fly) and allows it to read images
directly from network sockets, pipes, and other non-seekable
data sources.
This strategy works well for optimized ISO9660 images created
by many popular programs.
Such programs collect all directory information at the beginning
of the ISO9660 image so it can be read from a physical disk
with a minimum of seeking.
However, not all ISO9660 images can be read in this fashion.
.Pp
Libarchive can also write ISO9660 images.
Such images are fully optimized with the directory information
preceding all file data.
This is done by storing all file data to a temporary file
while collecting directory information in memory.
When the image is finished, libarchive writes out the
directory structure followed by the file data.
The location used for the temporary file can be changed
by the usual environment variables.
.Ss Zip format
Libarchive can read and write zip format archives that have
uncompressed entries and entries compressed with the
.Dq deflate
algorithm.
Older zip compression algorithms are not supported.
It can extract jar archives, archives that use Zip64 extensions and many
Other zip compression algorithms are not supported.
It can extract jar archives, archives that use Zip64 extensions and
self-extracting zip archives.
Libarchive reads Zip archives as they are being streamed,
which allows it to read archives of arbitrary size.
It currently does not use the central directory; this
limits libarchive's ability to support some self-extracting
archives and ones that have been modified in certain ways.
Libarchive can use either of two different strategies for
reading Zip archives:
a streaming strategy which is fast and can handle extremely
large archives, and a seeking strategy which can correctly
process self-extracting Zip archives and archives with
deleted members or other in-place modifications.
.Pp
The streaming reader processes Zip archives as they are read.
It can read archives of arbitrary size from tape or
network sockets, and can decode Zip archives that have
been separately compressed or encoded.
However, self-extracting Zip archives and archives with
certain types of modifications cannot be correctly
handled.
Such archives require that the reader first process the
Central Directory, which is ordinarily located
at the end of a Zip archive and is thus inaccessible
to the streaming reader.
If the program using libarchive has enabled seek support, then
libarchive will use this to processes the central directory first.
.Pp
In particular, the seeking reader must be used to
correctly handle self-extracting archives.
Such archives consist of a program followed by a regular
Zip archive.
The streaming reader cannot parse the initial program
portion, but the seeking reader starts by reading the
Central Directory from the end of the archive.
Similarly, Zip archives that have been modified in-place
can have deleted entries or other garbage data that
can only be accurately detected by first reading the
Central Directory.
.Ss Archive (library) file format
The Unix archive format (commonly created by the
.Xr ar 1
@ -299,8 +385,10 @@ area adjacent to the entry.
Libarchive can read both extensions,
including archives that may include both types of long filenames.
Programs using libarchive can write GNU/SVR4 format
if they provide a filename table to be written into
the archive before any of the entries.
if they provide an entry called
.Pa //
containing a filename table to be written into the archive
before any of the entries.
Any entries whose names are not in the filename table
will be written using BSD-style long filenames.
This can cause problems for programs such as
@ -341,6 +429,29 @@ using libarchive.
If it cannot locate and open the file on disk, libarchive
will return an error for any attempt to read the entry
body.
.Ss 7-Zip
Libarchive can read and write 7-Zip format archives.
TODO: Need more information
.Ss CAB
Libarchive can read Microsoft Cabinet (
.Dq CAB )
format archives.
TODO: Need more information.
.Ss LHA
TODO: Information about libarchive's LHA support
.Ss RAR
Libarchive has limited support for reading RAR format archives.
Currently, libarchive can read RARv3 format archives
which have been either created uncompressed, or compressed using
any of the compression methods supported by the RARv3 format.
Libarchive can also read self-extracting RAR archives.
.Ss Warc
Libarchive can read and write
.Dq web archives .
TODO: Need more information
.Ss XAR
Libarchive can read and write the XAR format used by many Apple tools.
TODO: Need more information
.Sh SEE ALSO
.Xr ar 1 ,
.Xr cpio 1 ,

View File

@ -22,24 +22,25 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD: src/lib/libarchive/libarchive.3,v 1.11 2007/01/09 08:05:56 kientzle Exp $
.\" $FreeBSD$
.\"
.Dd August 19, 2006
.Dd March 18, 2012
.Dt LIBARCHIVE 3
.Os
.Sh NAME
.Nm libarchive
.Nd functions for reading and writing streaming archives
.Sh LIBRARY
.Lb libarchive
.Sh OVERVIEW
The
.Nm
library provides a flexible interface for reading and writing
streaming archive files such as tar and cpio.
archives in various formats such as tar and cpio.
.Nm
also supports reading and writing archives compressed using
various compression filters such as gzip and bzip2.
The library is inherently stream-oriented; readers serially iterate through
the archive, writers serially add things to the archive.
In particular, note that there is no built-in support for
In particular, note that there is currently no built-in support for
random access nor for in-place modification.
.Pp
When reading an archive, the library automatically detects the
@ -61,16 +62,35 @@ GNU-format tar archives,
.It
most common cpio archive formats,
.It
ISO9660 CD images (with or without RockRidge extensions),
ISO9660 CD images (including RockRidge and Joliet extensions),
.It
Zip archives.
Zip archives,
.It
ar archives (including GNU/SysV and BSD extensions),
.It
Microsoft CAB archives,
.It
LHA archives,
.It
mtree file tree descriptions,
.It
RAR archives,
.It
XAR archives.
.El
The library automatically detects archives compressed with
.Xr gzip 1 ,
.Xr bzip2 1 ,
.Xr xz 1 ,
.Xr lzip 1 ,
or
.Xr compress 1
and decompresses them transparently.
It can similarly detect and decode archives processed with
.Xr uuencode 1
or which have an
.Xr rpm 1
header.
.Pp
When writing an archive, you can specify the compression
to be used and the format to use.
@ -87,7 +107,19 @@ archives,
.It
POSIX octet-oriented cpio archives,
.It
two different variants of shar archives.
Zip archive,
.It
two different variants of shar archives,
.It
ISO9660 CD images,
.It
7-Zip archives,
.It
ar archives,
.It
mtree file tree descriptions,
.It
XAR archives.
.El
Pax interchange format is an extension of the tar archive format that
eliminates essentially all of the limitations of historic tar formats
@ -111,131 +143,49 @@ The rest of this manual page provides an overview of the library
operation.
More detailed information can be found in the individual manual
pages for each API or utility function.
.\"
.Sh READING AN ARCHIVE
To read an archive, you must first obtain an initialized
.Tn struct archive
object from
.Fn archive_read_new .
You can then modify this object for the desired operations with the
various
.Fn archive_read_set_XXX
and
.Fn archive_read_support_XXX
functions.
In particular, you will need to invoke appropriate
.Fn archive_read_support_XXX
functions to enable the corresponding compression and format
support.
Note that these latter functions perform two distinct operations:
they cause the corresponding support code to be linked into your
program, and they enable the corresponding auto-detect code.
Unless you have specific constraints, you will generally want
to invoke
.Fn archive_read_support_compression_all
and
.Fn archive_read_support_format_all
to enable auto-detect for all formats and compression types
currently supported by the library.
.Pp
Once you have prepared the
.Tn struct archive
object, you call
.Fn archive_read_open
to actually open the archive and prepare it for reading.
There are several variants of this function;
the most basic expects you to provide pointers to several
functions that can provide blocks of bytes from the archive.
There are convenience forms that allow you to
specify a filename, file descriptor,
.Ft "FILE *"
object, or a block of memory from which to read the archive data.
Note that the core library makes no assumptions about the
size of the blocks read;
callback functions are free to read whatever block size is
most appropriate for the medium.
.Pp
Each archive entry consists of a header followed by a certain
amount of data.
You can obtain the next header with
.Fn archive_read_next_header ,
which returns a pointer to an
.Tn struct archive_entry
structure with information about the current archive element.
If the entry is a regular file, then the header will be followed
by the file data.
You can use
.Fn archive_read_data
(which works much like the
.Xr read 2
system call)
to read this data from the archive.
You may prefer to use the higher-level
.Fn archive_read_data_skip ,
which reads and discards the data for this entry,
.Fn archive_read_data_to_buffer ,
which reads the data into an in-memory buffer,
.Fn archive_read_data_to_file ,
which copies the data to the provided file descriptor, or
.Fn archive_read_extract ,
which recreates the specified entry on disk and copies data
from the archive.
In particular, note that
.Fn archive_read_extract
uses the
.Tn struct archive_entry
structure that you provide it, which may differ from the
entry just read from the archive.
In particular, many applications will want to override the
pathname, file permissions, or ownership.
.Pp
Once you have finished reading data from the archive, you
should call
.Fn archive_read_close
to close the archive, then call
.Fn archive_read_finish
to release all resources, including all memory allocated by the library.
.Pp
The
.Xr archive_read 3
manual page provides more detailed calling information for this API.
See
.Xr archive_read 3 .
.\"
.Sh WRITING AN ARCHIVE
You use a similar process to write an archive.
See
.Xr archive_write 3 .
.\"
.Sh WRITING ENTRIES TO DISK
The
.Fn archive_write_new
function creates an archive object useful for writing,
the various
.Fn archive_write_set_XXX
functions are used to set parameters for writing the archive, and
.Fn archive_write_open
completes the setup and opens the archive for writing.
.Pp
Individual archive entries are written in a three-step
process:
You first initialize a
.Tn struct archive_entry
structure with information about the new entry.
At a minimum, you should set the pathname of the
entry and provide a
.Va struct stat
with a valid
.Va st_mode
field, which specifies the type of object and
.Va st_size
field, which specifies the size of the data portion of the object.
.Xr archive_write_disk 3
API allows you to write
.Xr archive_entry 3
objects to disk using the same API used by
.Xr archive_write 3 .
The
.Fn archive_write_header
function actually writes the header data to the archive.
You can then use
.Fn archive_write_data
to write the actual data.
.Pp
After all entries have been written, use the
.Fn archive_write_finish
function to release all resources.
.Pp
.Xr archive_write_disk 3
API is used internally by
.Fn archive_read_extract ;
using it directly can provide greater control over how entries
get written to disk.
This API also makes it possible to share code between
archive-to-archive copy and archive-to-disk extraction
operations.
.Sh READING ENTRIES FROM DISK
The
.Xr archive_write 3
manual page provides more detailed calling information for this API.
.Xr archive_read_disk 3
supports for populating
.Xr archive_entry 3
objects from information in the filesystem.
This includes the information accessible from the
.Xr stat 2
system call as well as ACLs, extended attributes,
and other metadata.
The
.Xr archive_read_disk 3
API also supports iterating over directory trees,
which allows directories of files to be read using
an API compatible with
the
.Xr archive_read 3
API.
.Sh DESCRIPTION
Detailed descriptions of each function are provided by the
corresponding manual pages.
@ -259,7 +209,9 @@ In particular, pax interchange format can easily accommodate pathnames
in arbitrary character sets that exceed
.Va PATH_MAX .
.Sh RETURN VALUES
Most functions return zero on success, non-zero on error.
Most functions return
.Cm ARCHIVE_OK
(zero) on success, non-zero on error.
The return value indicates the general severity of the error, ranging
from
.Cm ARCHIVE_WARN ,
@ -313,8 +265,8 @@ library first appeared in
.An -nosplit
The
.Nm libarchive
library was written by
.An Tim Kientzle Aq Mt kientzle@acm.org .
library was originally written by
.An Tim Kientzle Aq kientzle@acm.org .
.Sh BUGS
Some archive formats support information that is not supported by
.Tn struct archive_entry .
@ -329,3 +281,9 @@ stored in an
is supported by all formats.
For example, cpio formats do not support nanosecond timestamps;
old tar formats do not support large device numbers.
.Pp
The ISO9660 reader cannot yet read all ISO9660 images;
it should learn how to seek.
.Pp
The AR writer requires the client program to use
two passes, unlike all other libarchive writers.

View File

@ -22,10 +22,10 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD: src/lib/libarchive/libarchive_internals.3,v 1.2 2007/12/30 04:58:22 kientzle Exp $
.\" $FreeBSD$
.\"
.Dd April 16, 2007
.Dt LIBARCHIVE 3
.Dd January 26, 2011
.Dt LIBARCHIVE_INTERNALS 3
.Os
.Sh NAME
.Nm libarchive_internals
@ -41,15 +41,15 @@ make it easy to add new archive and compression formats.
Externally, libarchive exposes most operations through an
opaque, object-style interface.
The
.Xr archive_entry 1
.Xr archive_entry 3
objects store information about a single filesystem object.
The rest of the library provides facilities to write
.Xr archive_entry 1
.Xr archive_entry 3
objects to archive files,
read them from archive files,
and write them to disk.
(There are plans to add a facility to read
.Xr archive_entry 1
.Xr archive_entry 3
objects from disk as well.)
.Pp
The read and write APIs each have four layers: a public API
@ -347,11 +347,11 @@ Fortunately, such archives are very rare, and libarchive can read
most ZIP archives, though it cannot always extract as much information
as a dedicated ZIP program.
.Sh SEE ALSO
.Xr archive 3 ,
.Xr archive_entry 3 ,
.Xr archive_read 3 ,
.Xr archive_write 3 ,
.Xr archive_write_disk 3
.Xr libarchive 3 ,
.Sh HISTORY
The
.Nm libarchive
@ -362,4 +362,4 @@ library first appeared in
The
.Nm libarchive
library was written by
.An Tim Kientzle Aq Mt kientzle@acm.org .
.An Tim Kientzle Aq kientzle@acm.org .

View File

@ -1,4 +1,5 @@
.\" Copyright (c) 2003-2009 Tim Kientzle
.\" Copyright (c) 2016 Martin Matuska
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
@ -22,10 +23,10 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD: head/lib/libarchive/tar.5 201077 2009-12-28 01:50:23Z kientzle $
.\" $FreeBSD$
.\"
.Dd December 27, 2009
.Dt tar 5
.Dd December 27, 2016
.Dt TAR 5
.Os
.Sh NAME
.Nm tar
@ -171,9 +172,9 @@ These archives generally follow the POSIX ustar
format described below with the following variations:
.Bl -bullet -compact -width indent
.It
The magic value is
.Dq ustar\ \&
(note the following space).
The magic value consists of the five characters
.Dq ustar
followed by a space.
The version field contains a space character followed by a null.
.It
The numeric fields are generally filled with leading spaces
@ -322,6 +323,39 @@ characters.
Currently, most tar implementations comply with the ustar
format, occasionally extending it by adding new fields to the
blank area at the end of the header record.
.Ss Numeric Extensions
There have been several attempts to extend the range of sizes
or times supported by modifying how numbers are stored in the
header.
.Pp
One obvious extension to increase the size of files is to
eliminate the terminating characters from the various
numeric fields.
For example, the standard only allows the size field to contain
11 octal digits, reserving the twelfth byte for a trailing
NUL character.
Allowing 12 octal digits allows file sizes up to 64 GB.
.Pp
Another extension, utilized by GNU tar, star, and other newer
.Nm
implementations, permits binary numbers in the standard numeric fields.
This is flagged by setting the high bit of the first byte.
The remainder of the field is treated as a signed twos-complement
value.
This permits 95-bit values for the length and time fields
and 63-bit values for the uid, gid, and device numbers.
In particular, this provides a consistent way to handle
negative time values.
GNU tar supports this extension for the
length, mtime, ctime, and atime fields.
Joerg Schilling's star program and the libarchive library support
this extension for all numeric fields.
Note that this extension is largely obsoleted by the extended
attribute record provided by the pax interchange format.
.Pp
Another early GNU extension allowed base-64 values rather than octal.
This extension was short-lived and is no longer supported by any
implementation.
.Ss Pax Interchange Format
There are many attributes that cannot be portably stored in a
POSIX ustar archive.
@ -365,6 +399,27 @@ A description of some common keys follows:
.It Cm atime , Cm ctime , Cm mtime
File access, inode change, and modification times.
These fields can be negative or include a decimal point and a fractional value.
.It Cm hdrcharset
The character set used by the pax extension values.
By default, all textual values in the pax extended attributes
are assumed to be in UTF-8, including pathnames, user names,
and group names.
In some cases, it is not possible to translate local
conventions into UTF-8.
If this key is present and the value is the six-character ASCII string
.Dq BINARY ,
then all textual values are assumed to be in a platform-dependent
multi-byte encoding.
Note that there are only two valid values for this key:
.Dq BINARY
or
.Dq ISO-IR\ 10646\ 2000\ UTF-8 .
No other values are permitted by the standard, and
the latter value should generally not be used as it is the
default when this key is not specified.
In particular, this flag should not be used as a general
mechanism to allow filenames to be stored in arbitrary
encodings.
.It Cm uname , Cm uid , Cm gname , Cm gid
User name, group name, and numeric UID and GID values.
The user name and group name stored here are encoded in UTF8
@ -386,11 +441,11 @@ archives to store files much larger than the historic 8GB limit.
Vendor-specific attributes used by Joerg Schilling's
.Nm star
implementation.
.It Cm SCHILY.acl.access , Cm SCHILY.acl.default
Stores the access and default ACLs as textual strings in a format
.It Cm SCHILY.acl.access , Cm SCHILY.acl.default, Cm SCHILY.acl.ace
Stores the access, default and NFSv4 ACLs as textual strings in a format
that is an extension of the format specified by POSIX.1e draft 17.
In particular, each user or group access specification can include a fourth
colon-separated field with the numeric UID or GID.
In particular, each user or group access specification can include
an additional colon-separated field with the numeric UID or GID.
This allows ACLs to be restored on systems that may not have complete
user or group information available (such as when NIS/YP or LDAP services
are temporarily unavailable).
@ -408,6 +463,16 @@ Schilling's
.Cm SCHILY.*
extensions can store all of the data from
.Va struct stat .
.It Cm LIBARCHIVE.*
Vendor-specific attributes used by the
.Nm libarchive
library and programs that use it.
.It Cm LIBARCHIVE.creationtime
The time when the file was created.
(This should not be confused with the POSIX
.Dq ctime
attribute, which refers to the time when the file
metadata was last changed.)
.It Cm LIBARCHIVE.xattr. Ns Ar namespace Ns . Ns Ar key
Libarchive stores POSIX.1e-style extended attributes using
keys of this form.
@ -659,8 +724,11 @@ GNU tar 1.14 (XXX check this XXX) and later will write
pax interchange format archives when you specify the
.Fl -posix
flag.
This format uses custom keywords to store sparse file information.
There have been three iterations of this support, referred to
This format follows the pax interchange format closely,
using some
.Cm SCHILY
tags and introducing new keywords to store sparse file information.
There have been three iterations of the sparse file support, referred to
as
.Dq 0.0 ,
.Dq 0.1 ,
@ -735,7 +803,7 @@ entry.
.It
An additional
.Cm A
entry is used to store an ACL for the following regular entry.
header is used to store an ACL for the following regular entry.
The body of this entry contains a seven-digit octal number
followed by a zero byte, followed by the
textual ACL description.
@ -745,46 +813,95 @@ for POSIX.1e ACLs and 03000000 for NFSv4 ACLs.
.El
.Ss AIX Tar
XXX More details needed XXX
.Pp
AIX Tar uses a ustar-formatted header with the type
.Cm A
for storing coded ACL information.
Unlike the Solaris format, AIX tar writes this header after the
regular file body to which it applies.
The pathname in this header is either
.Cm NFS4
or
.Cm AIXC
to indicate the type of ACL stored.
The actual ACL is stored in platform-specific binary format.
.Ss Mac OS X Tar
The tar distributed with Apple's Mac OS X stores most regular files
as two separate entries in the tar archive.
The two entries have the same name except that the first
as two separate files in the tar archive.
The two files have the same name except that the first
one has
.Dq ._
added to the beginning of the name.
This first entry stores the
.Dq resource fork
with additional attributes for the file.
The Mac OS X
.Fn CopyFile
API is used to separate a file on disk into separate
resource and data streams and to reassemble those separate
streams when the file is restored to disk.
.Ss Other Extensions
One obvious extension to increase the size of files is to
eliminate the terminating characters from the various
numeric fields.
For example, the standard only allows the size field to contain
11 octal digits, reserving the twelfth byte for a trailing
NUL character.
Allowing 12 octal digits allows file sizes up to 64 GB.
prepended to the last path element.
This special file stores an AppleDouble-encoded
binary blob with additional metadata about the second file,
including ACL, extended attributes, and resources.
To recreate the original file on disk, each
separate file can be extracted and the Mac OS X
.Fn copyfile
function can be used to unpack the separate
metadata file and apply it to th regular file.
Conversely, the same function provides a
.Dq pack
option to encode the extended metadata from
a file into a separate file whose contents
can then be put into a tar archive.
.Pp
Another extension, utilized by GNU tar, star, and other newer
.Nm
implementations, permits binary numbers in the standard numeric fields.
This is flagged by setting the high bit of the first byte.
This permits 95-bit values for the length and time fields
and 63-bit values for the uid, gid, and device numbers.
GNU tar supports this extension for the
length, mtime, ctime, and atime fields.
Joerg Schilling's star program supports this extension for
all numeric fields.
Note that this extension is largely obsoleted by the extended attribute
record provided by the pax interchange format.
.Pp
Another early GNU extension allowed base-64 values rather than octal.
This extension was short-lived and is no longer supported by any
implementation.
Note that the Apple extended attributes interact
badly with long filenames.
Since each file is stored with the full name,
a separate set of extensions needs to be included
in the archive for each one, doubling the overhead
required for files with long names.
.Ss Summary of tar type codes
The following list is a condensed summary of the type codes
used in tar header records generated by different tar implementations.
More details about specific implementations can be found above:
.Bl -tag -compact -width XXX
.It NUL
Early tar programs stored a zero byte for regular files.
.It Cm 0
POSIX standard type code for a regular file.
.It Cm 1
POSIX standard type code for a hard link description.
.It Cm 2
POSIX standard type code for a symbolic link description.
.It Cm 3
POSIX standard type code for a character device node.
.It Cm 4
POSIX standard type code for a block device node.
.It Cm 5
POSIX standard type code for a directory.
.It Cm 6
POSIX standard type code for a FIFO.
.It Cm 7
POSIX reserved.
.It Cm 7
GNU tar used for pre-allocated files on some systems.
.It Cm A
Solaris tar ACL description stored prior to a regular file header.
.It Cm A
AIX tar ACL description stored after the file body.
.It Cm D
GNU tar directory dump.
.It Cm K
GNU tar long linkname for the following header.
.It Cm L
GNU tar long pathname for the following header.
.It Cm M
GNU tar multivolume marker, indicating the file is a continuation of a file from the previous volume.
.It Cm N
GNU tar long filename support. Deprecated.
.It Cm S
GNU tar sparse regular file.
.It Cm V
GNU tar tape/volume header name.
.It Cm X
Solaris tar general-purpose extension header.
.It Cm g
POSIX pax interchange format global extensions.
.It Cm x
POSIX pax interchange format per-file extensions.
.El
.Sh SEE ALSO
.Xr ar 1 ,
.Xr pax 1 ,
@ -819,7 +936,7 @@ and formed the basis of
(circa 1988).
Joerg Shilling's
.Nm star
archiver is another open-source (GPL) archiver (originally developed
archiver is another open-source (CDDL) archiver (originally developed
circa 1985) which features complete support for pax interchange
format.
.Pp
@ -828,4 +945,4 @@ This documentation was written as part of the
and
.Nm bsdtar
project by
.An Tim Kientzle Aq Mt kientzle@FreeBSD.org .
.An Tim Kientzle Aq kientzle@FreeBSD.org .

View File

@ -40,9 +40,35 @@ __FBSDID("$FreeBSD$");
#include "err.h"
const char *lafe_progname;
static void lafe_vwarnc(int, const char *, va_list) __LA_PRINTFLIKE(2, 0);
static __printflike(2, 0) void
static const char *lafe_progname;
const char *
lafe_getprogname(void)
{
return lafe_progname;
}
void
lafe_setprogname(const char *name, const char *defaultname)
{
if (name == NULL)
name = defaultname;
#if defined(_WIN32) && !defined(__CYGWIN__)
lafe_progname = strrchr(name, '\\');
if (strrchr(name, '/') > lafe_progname)
#endif
lafe_progname = strrchr(name, '/');
if (lafe_progname != NULL)
lafe_progname++;
else
lafe_progname = name;
}
static void
lafe_vwarnc(int code, const char *fmt, va_list ap)
{
fprintf(stderr, "%s: ", lafe_progname);

View File

@ -33,10 +33,18 @@
#define __LA_DEAD
#endif
extern const char *lafe_progname;
#if defined(__GNUC__) && (__GNUC__ > 2 || \
(__GNUC__ == 2 && __GNUC_MINOR__ >= 7))
#define __LA_PRINTFLIKE(f,a) __attribute__((__format__(__printf__, f, a)))
#else
#define __LA_PRINTFLIKE(f,a)
#endif
void lafe_warnc(int code, const char *fmt, ...) __printflike(2, 3);
void lafe_errc(int eval, int code, const char *fmt, ...)
__LA_DEAD __printflike(3, 4);
void lafe_warnc(int code, const char *fmt, ...) __LA_PRINTFLIKE(2, 3);
void lafe_errc(int eval, int code, const char *fmt, ...) __LA_DEAD
__LA_PRINTFLIKE(3, 4);
const char * lafe_getprogname(void);
void lafe_setprogname(const char *name, const char *defaultname);
#endif