Merge libarchive-3-3-2pre.
This commit is contained in:
parent
40b1a6e683
commit
62a2faf4ff
File diff suppressed because it is too large
Load Diff
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
File diff suppressed because it is too large
Load Diff
|
@ -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 .
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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, ©_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, ©_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, ©_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, ©_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, ©_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);
|
||||
|
|
|
@ -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 ,
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 .
|
||||
|
|
|
@ -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 .
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue