MFV r310796, r310797:

Sync libarchive with vendor.

Vendor changes (relevant to FreeBSD):
PR #771: Add NFSv4 ACL support to pax and restricted pax

NFSv4 ACL information may now be stored to and restored from tar archives.
ACL must be non-trivial and supported by the underlying filesystem, e.g.
natively by ZFS or by UFS with the NFSv4 ACL enable flag set.

MFC after:	2 weeks
Relnotes:	yes
This commit is contained in:
Martin Matuska 2016-12-30 22:18:22 +00:00
commit e9ed7ea4dc
27 changed files with 3377 additions and 1231 deletions

View File

@ -38,6 +38,8 @@
# xargs -n1 | sort | uniq -d;
# done
# 20161230: libarchive ACL pax test renamed to test_acl_pax_posix1e.tar.uu
OLD_FILES+=usr/tests/lib/libarchive/test_acl_pax.tar.uu
# 20161217: new clang import which bumps version from 3.9.0 to 3.9.1.
OLD_FILES+=usr/lib/clang/3.9.0/include/sanitizer/allocator_interface.h
OLD_FILES+=usr/lib/clang/3.9.0/include/sanitizer/asan_interface.h

View File

@ -1,3 +1,6 @@
Dec 27, 2016: NFSv4 ACL read and write support for pax
Deprecated functions: archive_entry_acl_text(), archive_entry_acl_text_w()
Oct 26, 2016: Remove liblzmadec support
Oct 23, 2016: libarchive 3.2.2 released

File diff suppressed because it is too large Load Diff

View File

@ -66,22 +66,17 @@ int archive_acl_add_entry_w_len(struct archive_acl *,
int archive_acl_add_entry_len(struct archive_acl *,
int, int, int, int, const char *, size_t);
const wchar_t *archive_acl_text_w(struct archive *, struct archive_acl *, int);
int archive_acl_text_l(struct archive_acl *, int, const char **, size_t *,
wchar_t *archive_acl_to_text_w(struct archive_acl *, ssize_t *, int,
struct archive *);
char *archive_acl_to_text_l(struct archive_acl *, ssize_t *, int,
struct archive_string_conv *);
/*
* Private ACL parser. This is private because it handles some
* very weird formats that clients should not be messing with.
* Clients should only deal with their platform-native formats.
* Because of the need to support many formats cleanly, new arguments
* are likely to get added on a regular basis. Clients who try to use
* this interface are likely to be surprised when it changes.
* ACL text parser.
*/
int archive_acl_parse_w(struct archive_acl *,
const wchar_t *, int /* type */);
int archive_acl_parse_l(struct archive_acl *,
const char *, int /* type */,
struct archive_string_conv *);
int archive_acl_from_text_w(struct archive_acl *, const wchar_t * /* wtext */,
int /* type */);
int archive_acl_from_text_l(struct archive_acl *, const char * /* text */,
int /* type */, struct archive_string_conv *);
#endif /* ARCHIVE_ENTRY_PRIVATE_H_INCLUDED */

View File

@ -1,5 +1,6 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* Copyright (c) 2016 Martin Matuska
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -1486,34 +1487,121 @@ archive_entry_acl_next(struct archive_entry *entry, int want_type, int *type,
}
/*
* Generate a text version of the ACL. The flags parameter controls
* Generate a text version of the ACL. The flags parameter controls
* the style of the generated ACL.
*/
wchar_t *
archive_entry_acl_to_text_w(struct archive_entry *entry, ssize_t *len,
int flags)
{
return (archive_acl_to_text_w(&entry->acl, len, flags,
entry->archive));
}
char *
archive_entry_acl_to_text(struct archive_entry *entry, ssize_t *len,
int flags)
{
return (archive_acl_to_text_l(&entry->acl, len, flags, NULL));
}
char *
_archive_entry_acl_to_text_l(struct archive_entry *entry, ssize_t *len,
int flags, struct archive_string_conv *sc)
{
return (archive_acl_to_text_l(&entry->acl, len, flags, sc));
}
/*
* ACL text parser.
*/
int
archive_entry_acl_from_text_w(struct archive_entry *entry,
const wchar_t *wtext, int type)
{
return (archive_acl_from_text_w(&entry->acl, wtext, type));
}
int
archive_entry_acl_from_text(struct archive_entry *entry,
const char *text, int type)
{
return (archive_acl_from_text_l(&entry->acl, text, type, NULL));
}
int
_archive_entry_acl_from_text_l(struct archive_entry *entry, const char *text,
int type, struct archive_string_conv *sc)
{
return (archive_acl_from_text_l(&entry->acl, text, type, sc));
}
/* Deprecated */
static int
archive_entry_acl_text_compat(int *flags)
{
if ((*flags & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) == 0)
return (1);
/* ABI compat with old ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID */
if ((*flags & OLD_ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) != 0)
*flags |= ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID;
/* ABI compat with old ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT */
if ((*flags & OLD_ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) != 0)
*flags |= ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT;
*flags |= ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA;
return (0);
}
/* Deprecated */
const wchar_t *
archive_entry_acl_text_w(struct archive_entry *entry, int flags)
{
const wchar_t *r;
r = archive_acl_text_w(entry->archive, &entry->acl, flags);
if (r == NULL && errno == ENOMEM)
__archive_errx(1, "No memory");
return (r);
if (entry->acl.acl_text_w != NULL) {
free(entry->acl.acl_text_w);
entry->acl.acl_text_w = NULL;
}
if (archive_entry_acl_text_compat(&flags) == 0)
entry->acl.acl_text_w = archive_acl_to_text_w(&entry->acl,
NULL, flags, entry->archive);
return (entry->acl.acl_text_w);
}
/* Deprecated */
const char *
archive_entry_acl_text(struct archive_entry *entry, int flags)
{
const char *p;
if (archive_acl_text_l(&entry->acl, flags, &p, NULL, NULL) != 0
&& errno == ENOMEM)
__archive_errx(1, "No memory");
return (p);
if (entry->acl.acl_text != NULL) {
free(entry->acl.acl_text);
entry->acl.acl_text = NULL;
}
if (archive_entry_acl_text_compat(&flags) == 0)
entry->acl.acl_text = archive_acl_to_text_l(&entry->acl, NULL,
flags, NULL);
return (entry->acl.acl_text);
}
/* Deprecated */
int
_archive_entry_acl_text_l(struct archive_entry *entry, int flags,
const char **acl_text, size_t *len, struct archive_string_conv *sc)
{
return (archive_acl_text_l(&entry->acl, flags, acl_text, len, sc));
if (entry->acl.acl_text != NULL) {
free(entry->acl.acl_text);
entry->acl.acl_text = NULL;
}
if (archive_entry_acl_text_compat(&flags) == 0)
entry->acl.acl_text = archive_acl_to_text_l(&entry->acl,
(ssize_t *)len, flags, sc);
*acl_text = entry->acl.acl_text;
return (0);
}
/*

View File

@ -1,5 +1,6 @@
/*-
* Copyright (c) 2003-2008 Tim Kientzle
* Copyright (c) 2016 Martin Matuska
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -420,6 +421,7 @@ __LA_DECL void archive_entry_copy_mac_metadata(struct archive_entry *, const voi
/*
* Inheritance values (NFS4 ACLs only); included in permset.
*/
#define ARCHIVE_ENTRY_ACL_ENTRY_INHERITED 0x01000000
#define ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT 0x02000000
#define ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT 0x04000000
#define ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT 0x08000000
@ -433,15 +435,16 @@ __LA_DECL void archive_entry_copy_mac_metadata(struct archive_entry *, const voi
| ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT \
| ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY \
| ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS \
| ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS)
| ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS \
| ARCHIVE_ENTRY_ACL_ENTRY_INHERITED)
/* We need to be able to specify combinations of these. */
#define ARCHIVE_ENTRY_ACL_TYPE_ACCESS 256 /* POSIX.1e only */
#define ARCHIVE_ENTRY_ACL_TYPE_DEFAULT 512 /* POSIX.1e only */
#define ARCHIVE_ENTRY_ACL_TYPE_ALLOW 1024 /* NFS4 only */
#define ARCHIVE_ENTRY_ACL_TYPE_DENY 2048 /* NFS4 only */
#define ARCHIVE_ENTRY_ACL_TYPE_AUDIT 4096 /* NFS4 only */
#define ARCHIVE_ENTRY_ACL_TYPE_ALARM 8192 /* NFS4 only */
#define ARCHIVE_ENTRY_ACL_TYPE_ACCESS 0x00000100 /* POSIX.1e only */
#define ARCHIVE_ENTRY_ACL_TYPE_DEFAULT 0x00000200 /* POSIX.1e only */
#define ARCHIVE_ENTRY_ACL_TYPE_ALLOW 0x00000400 /* NFS4 only */
#define ARCHIVE_ENTRY_ACL_TYPE_DENY 0x00000800 /* NFS4 only */
#define ARCHIVE_ENTRY_ACL_TYPE_AUDIT 0x00001000 /* NFS4 only */
#define ARCHIVE_ENTRY_ACL_TYPE_ALARM 0x00002000 /* NFS4 only */
#define ARCHIVE_ENTRY_ACL_TYPE_POSIX1E (ARCHIVE_ENTRY_ACL_TYPE_ACCESS \
| ARCHIVE_ENTRY_ACL_TYPE_DEFAULT)
#define ARCHIVE_ENTRY_ACL_TYPE_NFS4 (ARCHIVE_ENTRY_ACL_TYPE_ALLOW \
@ -492,21 +495,43 @@ __LA_DECL int archive_entry_acl_next_w(struct archive_entry *, int /* want_type
* Construct a text-format ACL. The flags argument is a bitmask that
* can include any of the following:
*
* Flags only for archive entries with POSIX.1e ACL:
* ARCHIVE_ENTRY_ACL_TYPE_ACCESS - Include POSIX.1e "access" entries.
* ARCHIVE_ENTRY_ACL_TYPE_DEFAULT - Include POSIX.1e "default" entries.
* ARCHIVE_ENTRY_ACL_TYPE_NFS4 - Include NFS4 entries.
* ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID - Include extra numeric ID field in
* each ACL entry. ('star' introduced this for POSIX.1e, this flag
* also applies to NFS4.)
* ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT - Include "default:" before each
* default ACL entry, as used in old Solaris ACLs.
* default ACL entry.
* ARCHIVE_ENTRY_ACL_STYLE_SOLARIS - Output only one colon after "other" and
* "mask" entries.
*
* Flags for for archive entries with POSIX.1e ACL or NFSv4 ACL:
* ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID - Include extra numeric ID field in
* each ACL entry.
* ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA - Separate entries with comma
* instead of newline.
*/
#define ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID 1024
#define ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT 2048
#define ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID 0x00000001
#define ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT 0x00000002
#define ARCHIVE_ENTRY_ACL_STYLE_SOLARIS 0x00000004
#define ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA 0x00000008
__LA_DECL wchar_t *archive_entry_acl_to_text_w(struct archive_entry *,
ssize_t * /* len */, int /* flags */);
__LA_DECL char *archive_entry_acl_to_text(struct archive_entry *,
ssize_t * /* len */, int /* flags */);
__LA_DECL int archive_entry_acl_from_text_w(struct archive_entry *,
const wchar_t * /* wtext */, int /* type */);
__LA_DECL int archive_entry_acl_from_text(struct archive_entry *,
const char * /* text */, int /* type */);
/* Deprecated constants */
#define OLD_ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID 1024
#define OLD_ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT 2048
/* Deprecated functions */
__LA_DECL const wchar_t *archive_entry_acl_text_w(struct archive_entry *,
int /* flags */);
int /* flags */) __attribute__ ((deprecated));
__LA_DECL const char *archive_entry_acl_text(struct archive_entry *,
int /* flags */);
int /* flags */) __attribute__ ((deprecated));
/* Return bitmask of ACL types in an archive entry */
__LA_DECL int archive_entry_acl_types(struct archive_entry *);

View File

@ -1,4 +1,5 @@
.\" Copyright (c) 2010 Joerg Sonnenberger
.\" Copyright (c) 2016 Martin Matuska
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
@ -22,7 +23,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.Dd February 2, 2012
.Dd December 27, 2016
.Dt ARCHIVE_ENTRY_ACL 3
.Os
.Sh NAME
@ -30,10 +31,13 @@
.Nm archive_entry_acl_add_entry_w ,
.Nm archive_entry_acl_clear ,
.Nm archive_entry_acl_count ,
.Nm archive_entry_acl_from_text ,
.Nm archive_entry_acl_from_text_w,
.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_acl_to_text ,
.Nm archive_entry_acl_to_text_w ,
.Nm archive_entry_acl_types
.Nd functions for manipulating Access Control Lists in archive entry descriptions
.Sh LIBRARY
@ -63,6 +67,18 @@ Streaming Archive Library (libarchive, -larchive)
.Ft int
.Fn archive_entry_acl_count "struct archive_entry *a" "int type"
.Ft int
.Fo archive_entry_acl_from_text
.Fa "struct archive_entry *a"
.Fa "const char *text"
.Fa "int type"
.Fc
.Ft int
.Fo archive_entry_acl_from_text_w
.Fa "struct archive_entry *a"
.Fa "const wchar_t *text"
.Fa "int type"
.Fc
.Ft int
.Fo archive_entry_acl_next
.Fa "struct archive_entry *a"
.Fa "int type"
@ -84,33 +100,48 @@ Streaming Archive Library (libarchive, -larchive)
.Fc
.Ft int
.Fn archive_entry_acl_reset "struct archive_entry *a" "int type"
.Ft const wchar_t *
.Fn archive_entry_acl_text_w "struct archive_entry *a" "int flags"
.Ft char *
.Fo archive_entry_acl_to_text
.Fa "struct archive_entry *a"
.Fa "ssize_t *len_p"
.Fa "int flags"
.Fc
.Ft wchar_t *
.Fo archive_entry_acl_to_text_w
.Fa "struct archive_entry *a"
.Fa "ssize_t *len_p"
.Fa "int flags"
.Fc
.Ft int
.Fn archive_entry_acl_types "struct archive_entry *a"
.\" enum?
.Sh DESCRIPTION
An
.Dq Access Control List
is a generalisation of the classic Unix permission system.
The
.Dq Access Control Lists (ACLs)
extend the standard Unix perssion model.
The ACL interface of
.Nm libarchive
is derived from the POSIX.1e draft, but restricted to simplify dealing
with practical implementations in various Operating Systems and archive formats.
.Pp
An ACL consists of a number of independent entries.
supports both POSIX.1e and NFSv4 style ACLs. Use of ACLs is restricted by
various levels of ACL support in operating systems, file systems and archive
formats.
.Ss POSIX.1e Access Control Lists
A POSIX.1e ACL consists of a number of independent entries.
Each entry specifies the permission set as bitmask of basic permissions.
Valid permissions are:
Valid permissions in the
.Fa permset
are:
.Bl -tag -offset indent -compact -width "ARCHIVE_ENTRY_ACL_EXECUTE"
.It Dv ARCHIVE_ENTRY_ACL_EXECUTE
.It Dv ARCHIVE_ENTRY_ACL_WRITE
.It Dv ARCHIVE_ENTRY_ACL_READ
.It Dv ARCHIVE_ENTRY_ACL_READ ( Sy r )
.It Dv ARCHIVE_ENTRY_ACL_WRITE ( Sy w )
.It Dv ARCHIVE_ENTRY_ACL_EXECUTE ( Sy x )
.El
The permissions correspond to the normal Unix permissions.
.Pp
The tag specifies the principal to which the permission applies.
The
.Fa tag
specifies the principal to which the permission applies.
Valid values are:
.Bl -tag -offset indent -compact -width "ARCHIVE_ENTRY_ACL_GROUP_OBJ"
.Bl -hang -offset indent -compact -width "ARCHIVE_ENTRY_ACL_GROUP_OBJ"
.It Dv ARCHIVE_ENTRY_ACL_USER
The user specified by the name field.
.It Dv ARCHIVE_ENTRY_ACL_USER_OBJ
@ -122,8 +153,9 @@ The group who owns the file.
.It Dv ARCHIVE_ENTRY_ACL_MASK
The maximum permissions to be obtained via group permissions.
.It Dv ARCHIVE_ENTRY_ACL_OTHER
Any principal who doesn't have a user or group entry.
Any principal who is not file owner or a member of the owning group.
.El
.Pp
The principals
.Dv ARCHIVE_ENTRY_ACL_USER_OBJ ,
.Dv ARCHIVE_ENTRY_ACL_GROUP_OBJ
@ -132,19 +164,123 @@ and
are equivalent to user, group and other in the classic Unix permission
model and specify non-extended ACL entries.
.Pp
All files have an access ACL
All files with have an access ACL
.Pq Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS .
This specifies the permissions required for access to the file itself.
Directories have an additional ACL
.Pq Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT ,
which controls the initial access ACL for newly created directory entries.
.Ss NFSv4 Access Control Lists
A NFSv4 ACL consists of multiple individual entries called Access Control
Entries (ACEs).
.Pp
There are four possible types of a NFSv4 ACE:
.Bl -hang -offset indent -compact -width "ARCHIVE_ENTRY_ACL_TYE_ALLOW"
.It Dv ARCHIVE_ENTRY_ACL_TYPE_ALLOW
Allow principal to perform actions requiring given permissions.
.It Dv ARCHIVE_ENTRY_ACL_TYPE_DENY
Prevent principal from performing actions requiring given permissions.
.It Dv ARCHIVE_ENTRY_ACL_TYPE_AUDIT
Log access attempts by principal which require given permissions.
.It Dv ARCHIVE_ENTRY_ACL_TYPE_ALARM
Trigger a system alarm on access attempts by principal which require given
permissions.
.El
.Pp
The
.Fa tag
specifies the principal to which the permission applies.
Valid values are:
.Bl -hang -offset indent -compact -width "ARCHIVE_ENTRY_ACL_GROUP_OBJ"
.It Dv ARCHIVE_ENTRY_ACL_USER
The user specified by the name field.
.It Dv ARCHIVE_ENTRY_ACL_USER_OBJ
The owner of the file.
.It Dv ARCHIVE_ENTRY_ACL_GROUP
The group specied by the name field.
.It Dv ARCHIVE_ENTRY_ACL_GROUP_OBJ
The group who owns the file.
.It Dv ARCHIVE_ENTRY_ACL_EVERYONE
Any principal who is not file owner or a member of the owning group.
.El
.Pp
Entries with the
.Dv ARCHIVE_ENTRY_ACL_USER
or
.Dv ARCHIVE_ENTRY_ACL_GROUP
tag store the user and group name in the
.Fa name
string and optionally the user or group ID in the
.Fa qualifier
integer.
.Pp
NFSv4 ACE permissions and flags are stored in the same
.Fa permset
bitfield. Some permissions share the same constant and permission character but
have different effect on directories than on files. The following ACE
permissions are supported:
.Bl -tag -offset indent -compact -width ARCHIV
.It Dv ARCHIVE_ENTRY_ACL_READ_DATA ( Sy r )
Read data (file).
.It Dv ARCHIVE_ENTRY_ACL_LIST_DIRECTORY ( Sy r )
List entries (directory).
.It ARCHIVE_ENTRY_ACL_WRITE_DATA ( Sy w )
Write data (file).
.It ARCHIVE_ENTRY_ACL_ADD_FILE ( Sy w )
Create files (directory).
.It Dv ARCHIVE_ENTRY_ACL_EXECUTE ( Sy x )
Execute file or change into a directory.
.It Dv ARCHIVE_ENTRY_ACL_APPEND_DATA ( Sy p )
Append data (file).
.It Dv ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY ( Sy p )
Create subdirectories (directory).
.It Dv ARCHIVE_ENTRY_ACL_DELETE_CHILD ( Sy D )
Remove files and subdirectories inside a directory.
.It Dv ARCHIVE_ENTRY_ACL_DELETE ( Sy d )
Remove file or directory.
.It Dv ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES ( Sy a )
Read file or directory attributes.
.It Dv ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES ( Sy A )
Write file or directory attributes.
.It Dv ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS ( Sy R )
Read named file or directory attributes.
.It Dv ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS ( Sy W )
Write named file or directory attributes.
.It Dv ARCHIVE_ENTRY_ACL_READ_ACL ( Sy c )
Read file or directory ACL.
.It Dv ARCHIVE_ENTRY_ACL_WRITE_ACL ( Sy C )
Write file or directory ACL.
.It Dv ARCHIVE_ENTRY_ACL_WRITE_OWNER ( Sy o )
Change owner of a file or directory.
.It Dv ARCHIVE_ENTRY_ACL_SYNCHRONIZE ( Sy s )
Use synchronous I/O.
.El
.Pp
The following NFSv4 ACL inheritance flags are supported:
.Bl -tag -offset indent -compact -width ARCHIV
.It Dv ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT ( Sy f )
Inherit parent directory ACE to files.
.It Dv ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT ( Sy d )
Inherit parent directory ACE to subdirectories.
.It Dv ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY ( Sy i )
Only inherit, do not apply the permission on the directory itself.
.It Dv ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT ( Sy n )
Do not propagate inherit flags. Only first-level entries inherit ACLs.
.It Dv ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS ( Sy S )
Trigger alarm or audit on succesful access.
.It Dv ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS ( Sy F )
Trigger alarm or audit on failed access.
.It Dv ARCHIVE_ENTRY_ACL_ENTRY_INHERITED ( Sy I )
Mark that ACE was inherited.
.El
.Ss Functions
.Fn archive_entry_acl_add_entry
and
.Fn archive_entry_acl_add_entry_w
add a single ACL entry.
For the access ACL and non-extended principals, the classic Unix permissions
are updated.
are updated. An archive enry cannot contain both POSIX.1e and NFSv4 ACL
entries.
.Pp
.Fn archive_entry_acl_clear
removes all ACL entries and resets the enumeration pointer.
@ -153,14 +289,58 @@ removes all ACL entries and resets the enumeration pointer.
counts the ACL entries that have the given type mask.
.Fa type
can be the bitwise-or of
.Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS
and
.Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT .
If
.Bl -tag -offset indent -compact -width "ARCHIVE_ENTRY_ACL_TYPE_DEFAULT"
.It Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS
.It Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT
.El
for POSIX.1e ACLs and
.Bl -tag -offset indent -compact -width "ARCHIVE_ENTRY_ACL_TYPE_ALLOW"
.It Dv ARCHIVE_ENTRY_ACL_TYPE_ALLOW
.It Dv ARCHIVE_ENTRY_ACL_TYPE_DENY
.It Dv ARCHIVE_ENTRY_ACL_TYPE_AUDIT
.It Dv ARCHIVE_ENTRY_ACL_TYPE_ALARM
.El
for NFSv4 ACLs. For POSIX.1e ACLs if
.Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS
is included and at least one extended ACL entry is found,
the three non-extened ACLs are added.
.Pp
.Fn archive_entry_acl_from_text
and
.Fn archive_entry_acl_from_text_w
add new
.Pq or merge with existing
ACL entries from
.Pq wide
text. The argument
.Fa type
may take one of the following values:
.Bl -tag -offset indent -compact -width "ARCHIVE_ENTRY_ACL_TYPE_DEFAULT"
.It Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS
.It Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT
.It Dv ARCHIVE_ENTRY_ACL_TYPE_NFS4
.El
Supports all formats that can be created with
.Fn archive_entry_acl_to_text
or respective
.Fn archive_entry_acl_to_text_w .
Existing ACL entries are preserved. To get a clean new ACL from text
.Fn archive_entry_acl_clear
must be called first. Entries prefixed with
.Dq default:
are treated as
.Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT
unless
.Fa type
is
.Dv ARCHIVE_ENTRY_ACL_TYPE_NFS4 .
Invalid entries, non-parseable ACL entries and entries beginning with
the
.Sq #
character
.Pq comments
are skipped.
.Pp
.Fn archive_entry_acl_next
and
.Fn archive_entry_acl_next_w
@ -182,19 +362,50 @@ or set using
Otherwise, the function returns the same value as
.Fn archive_entry_acl_count .
.Pp
.Fn archive_entry_acl_text_w
converts the ACL entries for the given type mask into a wide string.
In addition to the normal type flags,
.Dv ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID
.Fn archive_entry_acl_to_text
and
.Dv ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT
can be specified to further customize the result.
The returned long string is valid until the next call to
.Fn archive_entry_acl_clear ,
.Fn archive_entry_acl_add_entry ,
.Fn archive_entry_acl_add_entry_w
.Fn archive_entry_acl_to_text_w
convert the ACL entries for the given type into a
.Pq wide
string of ACL entries separated by newline. If the the pointer
.Fa len_p
is not NULL, then the function shall return the length of the string
.Pq not including the NULL terminator
in the location pointed to by
.Fa len_p .
The
.Fa flag
argument is a bitwise-or.
.Pp
The following flags are effective only on POSIX.1e ACL:
.Bl -tag -offset indent -compact -width ARCHIV
.It Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS
Output access ACLs.
.It Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT
Output POSIX.1e default ACLs.
.It Dv ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT
Prefix each default ACL entry with the word
.Dq default: .
.It Dv ARCHIVE_ENTRY_ACL_STYLE_SOLARIS
The mask and other ACLs don not contain a double colon.
.El
.Pp
The following flags are effective on both POSIX.1e and NFSv4 ACL:
.Bl -tag -offset indent -compact -width ARCHIV
.It Dv ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID
Add an additional colon-separated field containing the user or group id.
.It Dv ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA
Separate ACL entries with comma instead of newline.
.El
.Pp
If the archive entry contains NFSv4 ACLs, all types of NFSv4 ACLs are returned.
It the entry contains POSIX.1e ACLs and none of the flags
.Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS
or
.Fn archive_entry_acl_text_w .
.Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT
are specified, both access and default entries are returned and default entries
are prefixed with
.Dq default: .
.Pp
.Fn archive_entry_acl_types
get ACL entry types contained in an archive entry's ACL. As POSIX.1e and NFSv4
@ -205,11 +416,20 @@ an ACL already contains POSIX.1e or NFSv4 ACL entries.
and
.Fn archive_entry_acl_reset
returns the number of ACL entries that match the given type mask.
If the type mask includes
For POSIX.1e ACLS if the type mask includes
.Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS
and at least one extended ACL entry exists, the three classic Unix
permissions are counted.
.Pp
.Fn archive_entry_acl_from_text
and
.Fn archive_entry_acl_from_text_w
return
.Dv ARCHIVE_OK
if all entries were successfully parsed and
.Dv ARCHIVE_WARN
if one or more entries were invalid or non-parseable.
.Pp
.Fn archive_entry_acl_next
and
.Fn archive_entry_acl_next_w
@ -224,23 +444,16 @@ if
.Fn archive_entry_acl_reset
has not been called first.
.Pp
.Fn archive_entry_text_w
returns a wide string representation of the ACL entrise matching the
given type mask.
The returned long string is valid until the next call to
.Fn archive_entry_acl_clear ,
.Fn archive_entry_acl_add_entry ,
.Fn archive_entry_acl_add_entry_w
or
.Fn archive_entry_acl_text_w .
.Fn archive_entry_acl_to_text
returns a string representing the ACL entries matching the given type and
flags on success or NULL on error.
.Pp
.Fn archive_entry_acl_to_text_w
returns a wide string representing the ACL entries matching the given type
and flags on success or NULL on error.
.Pp
.Fn archive_entry_acl_types
returns a bitmask of ACL entry types or 0 if archive entry has no ACL entries.
.Sh SEE ALSO
.Xr archive_entry 3
.Xr libarchive 3 ,
.Sh BUGS
.Dv ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID
and
.Dv ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT
are not documented.
.Xr archive_entry 3 ,
.Xr libarchive 3

View File

@ -63,9 +63,14 @@ int _archive_entry_uname_l(struct archive_entry *,
const char **, size_t *, struct archive_string_conv *);
#define archive_entry_acl_text_l _archive_entry_acl_text_l
int _archive_entry_acl_text_l(struct archive_entry *, int,
const char **, size_t *, struct archive_string_conv *);
const char **, size_t *, struct archive_string_conv *)
__attribute__ ((deprecated));
#define archive_entry_acl_to_text_l _archive_entry_acl_to_text_l
char *_archive_entry_acl_to_text_l(struct archive_entry *, ssize_t *, int,
struct archive_string_conv *);
#define archive_entry_acl_from_text_l _archive_entry_acl_from_text_l
int _archive_entry_acl_from_text_l(struct archive_entry *, const char* text,
int type, struct archive_string_conv *);
#define archive_entry_copy_gname_l _archive_entry_copy_gname_l
int _archive_entry_copy_gname_l(struct archive_entry *,
const char *, size_t, struct archive_string_conv *);

View File

@ -1,6 +1,7 @@
/*-
* Copyright (c) 2003-2009 Tim Kientzle
* Copyright (c) 2010-2012 Michihiro NAKAJIMA
* Copyright (c) 2016 Martin Matuska
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -440,7 +441,7 @@ setup_acls(struct archive_read_disk *a,
acl = NULL;
#ifdef ACL_TYPE_NFS4
/* Try NFS4 ACL first. */
/* Try NFSv4 ACL first. */
if (*fd >= 0)
#if HAVE_ACL_GET_FD_NP
acl = acl_get_fd_np(*fd, ACL_TYPE_NFS4);

View File

@ -1,6 +1,7 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* Copyright (c) 2011-2012 Michihiro NAKAJIMA
* Copyright (c) 2016 Martin Matuska
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -204,6 +205,10 @@ static int archive_read_format_tar_read_header(struct archive_read *,
static int checksum(struct archive_read *, const void *);
static int pax_attribute(struct archive_read *, struct tar *,
struct archive_entry *, const char *key, const char *value);
static int pax_attribute_acl(struct archive_read *, struct tar *,
struct archive_entry *, const char *, int);
static int pax_attribute_xattr(struct archive_entry *, const char *,
const char *);
static int pax_header(struct archive_read *, struct tar *,
struct archive_entry *, char *attr);
static void pax_time(const char *, int64_t *sec, long *nanos);
@ -1016,7 +1021,7 @@ header_Solaris_ACL(struct archive_read *a, struct tar *tar,
return (ARCHIVE_FATAL);
}
archive_strncpy(&(tar->localname), acl, p - acl);
err = archive_acl_parse_l(archive_entry_acl(entry),
err = archive_acl_from_text_l(archive_entry_acl(entry),
tar->localname.s, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, tar->sconv_acl);
if (err != ARCHIVE_OK) {
if (errno == ENOMEM) {
@ -1758,6 +1763,52 @@ pax_attribute_xattr(struct archive_entry *entry,
return 0;
}
static int
pax_attribute_acl(struct archive_read *a, struct tar *tar,
struct archive_entry *entry, const char *value, int type)
{
int r;
const char* errstr;
switch (type) {
case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
errstr = "SCHILY.acl.access";
break;
case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
errstr = "SCHILY.acl.default";
break;
case ARCHIVE_ENTRY_ACL_TYPE_NFS4:
errstr = "SCHILY.acl.ace";
break;
default:
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Unknown ACL type: %d", type);
return(ARCHIVE_FATAL);
}
if (tar->sconv_acl == NULL) {
tar->sconv_acl =
archive_string_conversion_from_charset(
&(a->archive), "UTF-8", 1);
if (tar->sconv_acl == NULL)
return (ARCHIVE_FATAL);
}
r = archive_acl_from_text_l(archive_entry_acl(entry), value, type,
tar->sconv_acl);
if (r != ARCHIVE_OK) {
if (r == ARCHIVE_FATAL) {
archive_set_error(&a->archive, ENOMEM,
"%s %s", "Can't allocate memory for ",
errstr);
return (r);
}
archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC, "%s %s", "Parse error: ", errstr);
}
return (r);
}
/*
* Parse a single key=value attribute. key/value pointers are
* assumed to point into reasonably long-lived storage.
@ -1876,53 +1927,20 @@ pax_attribute(struct archive_read *a, struct tar *tar,
case 'S':
/* We support some keys used by the "star" archiver */
if (strcmp(key, "SCHILY.acl.access") == 0) {
if (tar->sconv_acl == NULL) {
tar->sconv_acl =
archive_string_conversion_from_charset(
&(a->archive), "UTF-8", 1);
if (tar->sconv_acl == NULL)
return (ARCHIVE_FATAL);
}
r = archive_acl_parse_l(archive_entry_acl(entry),
value, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
tar->sconv_acl);
if (r != ARCHIVE_OK) {
err = r;
if (err == ARCHIVE_FATAL) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate memory for "
"SCHILY.acl.access");
return (err);
}
archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC,
"Parse error: SCHILY.acl.access");
}
r = pax_attribute_acl(a, tar, entry, value,
ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
if (r == ARCHIVE_FATAL)
return (r);
} else if (strcmp(key, "SCHILY.acl.default") == 0) {
if (tar->sconv_acl == NULL) {
tar->sconv_acl =
archive_string_conversion_from_charset(
&(a->archive), "UTF-8", 1);
if (tar->sconv_acl == NULL)
return (ARCHIVE_FATAL);
}
r = archive_acl_parse_l(archive_entry_acl(entry),
value, ARCHIVE_ENTRY_ACL_TYPE_DEFAULT,
tar->sconv_acl);
if (r != ARCHIVE_OK) {
err = r;
if (err == ARCHIVE_FATAL) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate memory for "
"SCHILY.acl.default");
return (err);
}
archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC,
"Parse error: SCHILY.acl.default");
}
r = pax_attribute_acl(a, tar, entry, value,
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT);
if (r == ARCHIVE_FATAL)
return (r);
} else if (strcmp(key, "SCHILY.acl.ace") == 0) {
r = pax_attribute_acl(a, tar, entry, value,
ARCHIVE_ENTRY_ACL_TYPE_NFS4);
if (r == ARCHIVE_FATAL)
return (r);
} else if (strcmp(key, "SCHILY.devmajor") == 0) {
archive_entry_set_rdevmajor(entry,
(dev_t)tar_atol10(value, strlen(value)));

View File

@ -1,6 +1,7 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* Copyright (c) 2010-2012 Michihiro NAKAJIMA
* Copyright (c) 2016 Martin Matuska
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -70,6 +71,8 @@ static void add_pax_attr_int(struct archive_string *,
static void add_pax_attr_time(struct archive_string *,
const char *key, int64_t sec,
unsigned long nanos);
static int add_pax_acl(struct archive_write *,
struct archive_entry *, struct pax *, int);
static ssize_t archive_write_pax_data(struct archive_write *,
const void *, size_t);
static int archive_write_pax_close(struct archive_write *);
@ -449,6 +452,45 @@ get_entry_symlink(struct archive_write *a, struct archive_entry *entry,
return (ARCHIVE_OK);
}
/* Add ACL to pax header */
static int
add_pax_acl(struct archive_write *a,
struct archive_entry *entry, struct pax *pax, int flags)
{
char *p;
const char *attr;
int acl_types;
acl_types = archive_entry_acl_types(entry);
if ((acl_types & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0)
attr = "SCHILY.acl.ace";
else if ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0)
attr = "SCHILY.acl.access";
else if ((flags & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0)
attr = "SCHILY.acl.default";
else
return (ARCHIVE_FATAL);
p = archive_entry_acl_to_text_l(entry, NULL, flags, pax->sconv_utf8);
if (p == NULL) {
if (errno == ENOMEM) {
archive_set_error(&a->archive, ENOMEM, "%s %s",
"Can't allocate memory for ", attr);
return (ARCHIVE_FATAL);
}
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT, "%s %s %s",
"Can't translate ", attr, " to UTF-8");
return(ARCHIVE_WARN);
} else if (*p != '\0') {
add_pax_attr(&(pax->pax_header),
attr, p);
free(p);
}
return(ARCHIVE_OK);
}
/*
* TODO: Consider adding 'comment' and 'charset' fields to
* archive_entry so that clients can specify them. Also, consider
@ -465,6 +507,7 @@ archive_write_pax_header(struct archive_write *a,
const char *p;
const char *suffix;
int need_extension, r, ret;
int acl_types;
int sparse_count;
uint64_t sparse_total, real_size;
struct pax *pax;
@ -1016,16 +1059,6 @@ archive_write_pax_header(struct archive_write *a,
if (!need_extension && p != NULL && *p != '\0')
need_extension = 1;
/* If there are non-trivial ACL entries, we need an extension. */
if (!need_extension && archive_entry_acl_count(entry_original,
ARCHIVE_ENTRY_ACL_TYPE_ACCESS) > 0)
need_extension = 1;
/* If there are non-trivial ACL entries, we need an extension. */
if (!need_extension && archive_entry_acl_count(entry_original,
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) > 0)
need_extension = 1;
/* If there are extended attributes, we need an extension */
if (!need_extension && archive_entry_xattr_count(entry_original) > 0)
need_extension = 1;
@ -1034,6 +1067,12 @@ archive_write_pax_header(struct archive_write *a,
if (!need_extension && sparse_count > 0)
need_extension = 1;
acl_types = archive_entry_acl_types(entry_original);
/* If there are any ACL entries, we need an extension */
if (!need_extension && acl_types != 0)
need_extension = 1;
/*
* Libarchive used to include these in extended headers for
* restricted pax format, but that confused people who
@ -1085,43 +1124,28 @@ archive_write_pax_header(struct archive_write *a,
add_pax_attr(&(pax->pax_header), "SCHILY.fflags", p);
/* I use star-compatible ACL attributes. */
r = archive_entry_acl_text_l(entry_original,
ARCHIVE_ENTRY_ACL_TYPE_ACCESS |
ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID,
&p, NULL, pax->sconv_utf8);
if (r != 0) {
if (errno == ENOMEM) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate memory for "
"ACL.access");
if ((acl_types & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
ret = add_pax_acl(a, entry_original, pax,
ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID |
ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA);
if (ret == ARCHIVE_FATAL)
return (ARCHIVE_FATAL);
}
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Can't translate ACL.access to UTF-8");
ret = ARCHIVE_WARN;
} else if (p != NULL && *p != '\0') {
add_pax_attr(&(pax->pax_header),
"SCHILY.acl.access", p);
}
r = archive_entry_acl_text_l(entry_original,
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT |
ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID,
&p, NULL, pax->sconv_utf8);
if (r != 0) {
if (errno == ENOMEM) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate memory for "
"ACL.default");
if (acl_types & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) {
ret = add_pax_acl(a, entry_original, pax,
ARCHIVE_ENTRY_ACL_TYPE_ACCESS |
ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID |
ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA);
if (ret == ARCHIVE_FATAL)
return (ARCHIVE_FATAL);
}
if (acl_types & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) {
ret = add_pax_acl(a, entry_original, pax,
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT |
ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID |
ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA);
if (ret == ARCHIVE_FATAL)
return (ARCHIVE_FATAL);
}
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Can't translate ACL.default to UTF-8");
ret = ARCHIVE_WARN;
} else if (p != NULL && *p != '\0') {
add_pax_attr(&(pax->pax_header),
"SCHILY.acl.default", p);
}
/* We use GNU-tar-compatible sparse attributes. */

View File

@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd March 18, 2012
.Dd December 27, 2016
.Dt LIBARCHIVE-FORMATS 5
.Os
.Sh NAME
@ -191,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.

View File

@ -1,4 +1,5 @@
.\" Copyright (c) 2003-2009 Tim Kientzle
.\" Copyright (c) 2016 Martin Matuska
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
@ -24,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd December 23, 2011
.Dd December 27, 2016
.Dt TAR 5
.Os
.Sh NAME
@ -440,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).

View File

@ -2421,6 +2421,132 @@ extract_reference_files(const char **names)
extract_reference_file(*names++);
}
/* Set ACLs */
void
archive_test_set_acls(struct archive_entry *ae,
struct archive_test_acl_t *acls, int n)
{
int i;
archive_entry_acl_clear(ae);
for (i = 0; i < n; i++) {
failure("type=%#010x, permset=%#010x, tag=%d, qual=%d name=%s",
acls[i].type, acls[i].permset, acls[i].tag,
acls[i].qual, acls[i].name);
assertEqualInt(ARCHIVE_OK,
archive_entry_acl_add_entry(ae,
acls[i].type, acls[i].permset, acls[i].tag,
acls[i].qual, acls[i].name));
}
}
static int
archive_test_acl_match(struct archive_test_acl_t *acl, int type, int permset,
int tag, int qual, const char *name)
{
if (type != acl->type)
return (0);
if (permset != acl->permset)
return (0);
if (tag != acl->tag)
return (0);
if (tag == ARCHIVE_ENTRY_ACL_USER_OBJ)
return (1);
if (tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ)
return (1);
if (tag == ARCHIVE_ENTRY_ACL_EVERYONE)
return (1);
if (tag == ARCHIVE_ENTRY_ACL_OTHER)
return (1);
if (qual != acl->qual)
return (0);
if (name == NULL) {
if (acl->name == NULL || acl->name[0] == '\0')
return (1);
return (0);
}
if (acl->name == NULL) {
if (name[0] == '\0')
return (1);
return (0);
}
return (0 == strcmp(name, acl->name));
}
/* Compare ACLs */
void
archive_test_compare_acls(struct archive_entry *ae,
struct archive_test_acl_t *acls, int cnt, int want_type, int mode)
{
int *marker;
int i, r, n;
int type, permset, tag, qual;
int matched;
const char *name;
n = 0;
marker = malloc(sizeof(marker[0]) * cnt);
for (i = 0; i < cnt; i++) {
if ((acls[i].type & want_type) != 0) {
marker[n] = i;
n++;
}
}
failure("No ACL's to compare, type mask: %d", want_type);
assert(n > 0);
if (n == 0)
return;
while (0 == (r = archive_entry_acl_next(ae, want_type,
&type, &permset, &tag, &qual, &name))) {
for (i = 0, matched = 0; i < n && !matched; i++) {
if (archive_test_acl_match(&acls[marker[i]], type,
permset, tag, qual, name)) {
/* We found a match; remove it. */
marker[i] = marker[n - 1];
n--;
matched = 1;
}
}
if (type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS
&& tag == ARCHIVE_ENTRY_ACL_USER_OBJ) {
if (!matched) printf("No match for user_obj perm\n");
failure("USER_OBJ permset (%02o) != user mode (%02o)",
permset, 07 & (mode >> 6));
assert((permset << 6) == (mode & 0700));
} else if (type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS
&& tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ) {
if (!matched) printf("No match for group_obj perm\n");
failure("GROUP_OBJ permset %02o != group mode %02o",
permset, 07 & (mode >> 3));
assert((permset << 3) == (mode & 0070));
} else if (type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS
&& tag == ARCHIVE_ENTRY_ACL_OTHER) {
if (!matched) printf("No match for other perm\n");
failure("OTHER permset (%02o) != other mode (%02o)",
permset, mode & 07);
assert((permset << 0) == (mode & 0007));
} else {
failure("Could not find match for ACL "
"(type=%#010x,permset=%#010x,tag=%d,qual=%d,"
"name=``%s'')", type, permset, tag, qual, name);
assert(matched == 1);
}
}
assertEqualInt(ARCHIVE_EOF, r);
if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0)
assert((mode_t)(mode & 0777) == (archive_entry_mode(ae)
& 0777));
failure("Could not find match for ACL "
"(type=%#010x,permset=%#010x,tag=%d,qual=%d,name=``%s'')",
acls[marker[0]].type, acls[marker[0]].permset,
acls[marker[0]].tag, acls[marker[0]].qual, acls[marker[0]].name);
assert(n == 0); /* Number of ACLs not matched should == 0 */
free(marker);
}
/*
*
* TEST management

View File

@ -346,6 +346,23 @@ extern const char *testworkdir;
#include "archive.h"
#include "archive_entry.h"
/* ACL structure */
struct archive_test_acl_t {
int type; /* Type of ACL */
int permset; /* Permissions for this class of users. */
int tag; /* Owner, User, Owning group, group, other, etc. */
int qual; /* GID or UID of user/group, depending on tag. */
const char *name; /* Name of user/group, depending on tag. */
};
/* Set ACLs */
void archive_test_set_acls(struct archive_entry *, struct archive_test_acl_t *,
int);
/* Compare ACLs */
void archive_test_compare_acls(struct archive_entry *,
struct archive_test_acl_t *, int, int, int);
/* Special customized read-from-memory interface. */
int read_open_memory(struct archive *, const void *, size_t, size_t);
/* _minimal version exercises a slightly different set of libarchive APIs. */

View File

@ -334,7 +334,7 @@ compare_acls(acl_t acl, struct myacl_t *myacls, const char *filename, int start,
/* Dump entries in the myacls array that weren't in the system acl. */
for (i = 0; i < n; ++i) {
failure(" ACL entry %d missing from %s: "
"type=%d,permset=%x,tag=%d,qual=%d,name=``%s''\n",
"type=%#010x,permset=%#010x,tag=%d,qual=%d,name=``%s''\n",
marker[i], filename,
myacls[marker[i]].type, myacls[marker[i]].permset,
myacls[marker[i]].tag, myacls[marker[i]].qual,
@ -386,7 +386,7 @@ compare_entry_acls(struct archive_entry *ae, struct myacl_t *myacls, const char
}
failure("ACL entry on file that shouldn't be there: "
"type=%d,permset=%x,tag=%d,qual=%d",
"type=%#010x,permset=%#010x,tag=%d,qual=%d",
type,permset,tag,qual);
assert(matched == 1);
}
@ -394,7 +394,7 @@ compare_entry_acls(struct archive_entry *ae, struct myacl_t *myacls, const char
/* Dump entries in the myacls array that weren't in the system acl. */
for (i = 0; i < n; ++i) {
failure(" ACL entry %d missing from %s: "
"type=%d,permset=%x,tag=%d,qual=%d,name=``%s''\n",
"type=%#010x,permset=%#010x,tag=%d,qual=%d,name=``%s''\n",
marker[i], filename,
myacls[marker[i]].type, myacls[marker[i]].permset,
myacls[marker[i]].tag, myacls[marker[i]].qual,

View File

@ -28,15 +28,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/test/test_acl_freebsd.c 189427 2009-03-0
#if defined(__FreeBSD__) && __FreeBSD__ > 4
#include <sys/acl.h>
struct myacl_t {
int type; /* Type of ACL: "access" or "default" */
int permset; /* Permissions for this class of users. */
int tag; /* Owner, User, Owning group, group, other, etc. */
int qual; /* GID or UID of user/group, depending on tag. */
const char *name; /* Name of user/group, depending on tag. */
};
static struct myacl_t acls2[] = {
static struct archive_test_acl_t acls2[] = {
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE | ARCHIVE_ENTRY_ACL_READ,
ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ,
@ -53,22 +45,8 @@ static struct myacl_t acls2[] = {
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
ARCHIVE_ENTRY_ACL_WRITE | ARCHIVE_ENTRY_ACL_READ | ARCHIVE_ENTRY_ACL_EXECUTE,
ARCHIVE_ENTRY_ACL_MASK, -1, "" },
{ 0, 0, 0, 0, NULL }
};
static void
set_acls(struct archive_entry *ae, struct myacl_t *acls)
{
int i;
archive_entry_acl_clear(ae);
for (i = 0; acls[i].name != NULL; i++) {
archive_entry_acl_add_entry(ae,
acls[i].type, acls[i].permset, acls[i].tag, acls[i].qual,
acls[i].name);
}
}
static int
acl_entry_get_perm(acl_entry_t aclent) {
int permset = 0;
@ -127,7 +105,7 @@ acl_get_specific_entry(acl_t acl, acl_tag_t requested_tag_type, int requested_ta
#endif
static int
acl_match(acl_entry_t aclent, struct myacl_t *myacl)
acl_match(acl_entry_t aclent, struct archive_test_acl_t *myacl)
{
gid_t g, *gp;
uid_t u, *up;
@ -173,25 +151,20 @@ acl_match(acl_entry_t aclent, struct myacl_t *myacl)
}
static void
compare_acls(acl_t acl, struct myacl_t *myacls)
compare_acls(acl_t acl, struct archive_test_acl_t *myacls, int n)
{
int *marker;
int entry_id = ACL_FIRST_ENTRY;
int matched;
int i, n;
int i;
acl_entry_t acl_entry;
/* Count ACL entries in myacls array and allocate an indirect array. */
for (n = 0; myacls[n].name != NULL; ++n)
continue;
if (n) {
marker = malloc(sizeof(marker[0]) * n);
if (marker == NULL)
return;
for (i = 0; i < n; i++)
marker[i] = i;
} else
marker = NULL;
marker = malloc(sizeof(marker[0]) * n);
if (marker == NULL)
return;
for (i = 0; i < n; i++)
marker[i] = i;
/*
* Iterate over acls in system acl object, try to match each
@ -219,7 +192,7 @@ compare_acls(acl_t acl, struct myacl_t *myacls)
/* Dump entries in the myacls array that weren't in the system acl. */
for (i = 0; i < n; ++i) {
failure(" ACL entry missing from file: "
"type=%d,permset=%d,tag=%d,qual=%d,name=``%s''\n",
"type=%#010x,permset=%#010x,tag=%d,qual=%d,name=``%s''\n",
myacls[marker[i]].type, myacls[marker[i]].permset,
myacls[marker[i]].tag, myacls[marker[i]].qual,
myacls[marker[i]].name);
@ -291,7 +264,7 @@ DEFINE_TEST(test_acl_freebsd_posix1e_restore)
archive_entry_set_pathname(ae, "test0");
archive_entry_set_mtime(ae, 123456, 7890);
archive_entry_set_size(ae, 0);
set_acls(ae, acls2);
archive_test_set_acls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]));
assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
archive_entry_free(ae);
@ -304,7 +277,7 @@ DEFINE_TEST(test_acl_freebsd_posix1e_restore)
assertEqualInt(st.st_mtime, 123456);
acl = acl_get_file("test0", ACL_TYPE_ACCESS);
assert(acl != (acl_t)NULL);
compare_acls(acl, acls2);
compare_acls(acl, acls2, sizeof(acls2)/sizeof(acls2[0]));
acl_free(acl);
#endif
}
@ -332,7 +305,12 @@ DEFINE_TEST(test_acl_freebsd_posix1e_read)
*/
/* Create a test file f1 with acl1 */
acl1_text = "user::rwx,group::rwx,other::rwx,user:1:rw-,group:15:r-x,mask::rwx";
acl1_text = "user::rwx\n"
"group::rwx\n"
"other::rwx\n"
"user:1:rw-\n"
"group:15:r-x\n"
"mask::rwx";
acl1 = acl_from_text(acl1_text);
assert((void *)acl1 != NULL);
fd = open("f1", O_WRONLY | O_CREAT | O_EXCL, 0777);
@ -371,7 +349,12 @@ DEFINE_TEST(test_acl_freebsd_posix1e_read)
* to read ACLs, resulting in reading the ACL from a like-named
* file in the wrong directory.
*/
acl2_text = "user::rwx,group::rwx,other::---,user:1:r--,group:15:r--,mask::rwx";
acl2_text = "user::rwx\n"
"group::rwx\n"
"other::---\n"
"user:1:r--\n"
"group:15:r--\n"
"mask::rwx";
acl2 = acl_from_text(acl2_text);
assert((void *)acl2 != NULL);
fd = open("d/f1", O_WRONLY | O_CREAT | O_EXCL, 0777);
@ -406,10 +389,10 @@ DEFINE_TEST(test_acl_freebsd_posix1e_read)
while (ARCHIVE_OK == archive_read_next_header2(a, ae)) {
archive_read_disk_descend(a);
if (strcmp(archive_entry_pathname(ae), "./f1") == 0) {
assertEqualString(archive_entry_acl_text(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS), acl1_text);
assertEqualString(archive_entry_acl_to_text(ae, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS), acl1_text);
} else if (strcmp(archive_entry_pathname(ae), "./d/f1") == 0) {
assertEqualString(archive_entry_acl_text(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS), acl2_text);
assertEqualString(archive_entry_acl_to_text(ae, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS), acl2_text);
}
}

View File

@ -33,15 +33,7 @@ __FBSDID("$FreeBSD$");
* filesystems support ACLs or not.
*/
struct acl_t {
int type; /* Type of entry: "allow" or "deny" */
int permset; /* Permissions for this class of users. */
int tag; /* Owner, User, Owning group, group, everyone, etc. */
int qual; /* GID or UID of user/group, depending on tag. */
const char *name; /* Name of user/group, depending on tag. */
};
static struct acl_t acls1[] = {
static struct archive_test_acl_t acls1[] = {
{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
{ ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_READ_DATA,
@ -52,7 +44,7 @@ static struct acl_t acls1[] = {
ARCHIVE_ENTRY_ACL_EVERYONE, -1, "" },
};
static struct acl_t acls2[] = {
static struct archive_test_acl_t acls2[] = {
/* An entry for each type. */
{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, 0,
ARCHIVE_ENTRY_ACL_USER, 108, "user108" },
@ -136,7 +128,7 @@ static struct acl_t acls2[] = {
* Entries that should be rejected when we attempt to set them
* on an ACL that already has NFS4 entries.
*/
static struct acl_t acls_bad[] = {
static struct archive_test_acl_t acls_bad[] = {
/* POSIX.1e ACL types */
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE,
ARCHIVE_ENTRY_ACL_USER, 78, "" },
@ -156,95 +148,6 @@ static struct acl_t acls_bad[] = {
ARCHIVE_ENTRY_ACL_EVERYONE, -1, "" },
};
static void
set_acls(struct archive_entry *ae, struct acl_t *acls, int n)
{
int i;
archive_entry_acl_clear(ae);
for (i = 0; i < n; i++) {
failure("type=%d, permset=%d, tag=%d, qual=%d name=%s",
acls[i].type, acls[i].permset, acls[i].tag,
acls[i].qual, acls[i].name);
assertEqualInt(ARCHIVE_OK,
archive_entry_acl_add_entry(ae,
acls[i].type, acls[i].permset, acls[i].tag,
acls[i].qual, acls[i].name));
}
}
static int
acl_match(struct acl_t *acl, int type, int permset, int tag, int qual,
const char *name)
{
if (acl == NULL)
return (0);
if (type != acl->type)
return (0);
if (permset != acl->permset)
return (0);
if (tag != acl->tag)
return (0);
if (tag == ARCHIVE_ENTRY_ACL_USER_OBJ)
return (1);
if (tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ)
return (1);
if (tag == ARCHIVE_ENTRY_ACL_EVERYONE)
return (1);
if (qual != acl->qual)
return (0);
if (name == NULL) {
if (acl->name == NULL || acl->name[0] == '\0')
return (1);
return (0);
}
if (acl->name == NULL) {
if (name[0] == '\0')
return (1);
return (0);
}
return (0 == strcmp(name, acl->name));
}
static void
compare_acls(struct archive_entry *ae, struct acl_t *acls, int n)
{
int *marker = malloc(sizeof(marker[0]) * n);
int i;
int r;
int type, permset, tag, qual;
int matched;
const char *name;
for (i = 0; i < n; i++)
marker[i] = i;
while (0 == (r = archive_entry_acl_next(ae,
ARCHIVE_ENTRY_ACL_TYPE_NFS4,
&type, &permset, &tag, &qual, &name))) {
for (i = 0, matched = 0; i < n && !matched; i++) {
if (acl_match(&acls[marker[i]], type, permset,
tag, qual, name)) {
/* We found a match; remove it. */
marker[i] = marker[n - 1];
n--;
matched = 1;
}
}
failure("Could not find match for ACL "
"(type=%d,permset=%d,tag=%d,qual=%d,name=``%s'')",
type, permset, tag, qual, name);
assertEqualInt(1, matched);
}
assertEqualInt(ARCHIVE_EOF, r);
failure("Could not find match for ACL "
"(type=%d,permset=%d,tag=%d,qual=%d,name=``%s'')",
acls[marker[0]].type, acls[marker[0]].permset,
acls[marker[0]].tag, acls[marker[0]].qual, acls[marker[0]].name);
assertEqualInt(0, n); /* Number of ACLs not matched should == 0 */
free(marker);
}
DEFINE_TEST(test_acl_nfs4)
{
struct archive_entry *ae;
@ -256,22 +159,31 @@ DEFINE_TEST(test_acl_nfs4)
archive_entry_set_mode(ae, S_IFREG | 0777);
/* Store and read back some basic ACL entries. */
set_acls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]));
archive_test_set_acls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]));
/* Check that entry contains only NFSv4 types */
assert((archive_entry_acl_types(ae) &
ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) == 0);
assert((archive_entry_acl_types(ae) &
ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0);
assertEqualInt(4,
archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4));
compare_acls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]));
archive_test_compare_acls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]),
ARCHIVE_ENTRY_ACL_TYPE_NFS4, 0);
/* A more extensive set of ACLs. */
set_acls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]));
archive_test_set_acls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]));
assertEqualInt(32,
archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4));
compare_acls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]));
archive_test_compare_acls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]),
ARCHIVE_ENTRY_ACL_TYPE_NFS4, 0);
/*
* Check that clearing ACLs gets rid of them all by repeating
* the first test.
*/
set_acls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]));
archive_test_set_acls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]));
failure("Basic ACLs shouldn't be stored as extended ACLs");
assertEqualInt(4,
archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4));
@ -280,9 +192,9 @@ DEFINE_TEST(test_acl_nfs4)
* Different types of malformed ACL entries that should
* fail when added to existing NFS4 ACLs.
*/
set_acls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]));
archive_test_set_acls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]));
for (i = 0; i < (int)(sizeof(acls_bad)/sizeof(acls_bad[0])); ++i) {
struct acl_t *p = &acls_bad[i];
struct archive_test_acl_t *p = &acls_bad[i];
failure("Malformed ACL test #%d", i);
assertEqualInt(ARCHIVE_FAILED,
archive_entry_acl_add_entry(ae,

View File

@ -1,5 +1,6 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* Copyright (c) 2016 Martin Matuska
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -27,7 +28,7 @@ __FBSDID("$FreeBSD$");
/*
* Exercise the system-independent portion of the ACL support.
* Check that pax archive can save and restore ACL data.
* Check that pax archive can save and restore POSIX.1e ACL data.
*
* This should work on all systems, regardless of whether local
* filesystems support ACLs or not.
@ -35,15 +36,7 @@ __FBSDID("$FreeBSD$");
static unsigned char buff[16384];
struct acl_t {
int type; /* Type of ACL: "access" or "default" */
int permset; /* Permissions for this class of users. */
int tag; /* Owner, User, Owning group, group, other, etc. */
int qual; /* GID or UID of user/group, depending on tag. */
const char *name; /* Name of user/group, depending on tag. */
};
static struct acl_t acls0[] = {
static struct archive_test_acl_t acls0[] = {
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE,
ARCHIVE_ENTRY_ACL_USER_OBJ, 0, "" },
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ,
@ -52,7 +45,7 @@ static struct acl_t acls0[] = {
ARCHIVE_ENTRY_ACL_OTHER, 0, "" },
};
static struct acl_t acls1[] = {
static struct archive_test_acl_t acls1[] = {
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE,
ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ,
@ -63,7 +56,7 @@ static struct acl_t acls1[] = {
ARCHIVE_ENTRY_ACL_OTHER, -1, "" },
};
static struct acl_t acls2[] = {
static struct archive_test_acl_t acls2[] = {
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE | ARCHIVE_ENTRY_ACL_READ,
ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ,
@ -78,101 +71,149 @@ static struct acl_t acls2[] = {
ARCHIVE_ENTRY_ACL_OTHER, -1, "" },
};
static void
set_acls(struct archive_entry *ae, struct acl_t *acls, int n)
{
int i;
static struct archive_test_acl_t acls3[] = {
{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
ARCHIVE_ENTRY_ACL_READ_DATA |
ARCHIVE_ENTRY_ACL_WRITE_DATA |
ARCHIVE_ENTRY_ACL_EXECUTE |
ARCHIVE_ENTRY_ACL_APPEND_DATA |
ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES |
ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS |
ARCHIVE_ENTRY_ACL_READ_ACL |
ARCHIVE_ENTRY_ACL_WRITE_ACL |
ARCHIVE_ENTRY_ACL_WRITE_OWNER |
ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
ARCHIVE_ENTRY_ACL_USER_OBJ, 0, "" },
{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
ARCHIVE_ENTRY_ACL_READ_DATA |
ARCHIVE_ENTRY_ACL_WRITE_DATA |
ARCHIVE_ENTRY_ACL_APPEND_DATA |
ARCHIVE_ENTRY_ACL_READ_ACL |
ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
ARCHIVE_ENTRY_ACL_READ_ACL |
ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
ARCHIVE_ENTRY_ACL_GROUP_OBJ, 0, "" },
{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
ARCHIVE_ENTRY_ACL_READ_DATA |
ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
ARCHIVE_ENTRY_ACL_READ_ACL |
ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
ARCHIVE_ENTRY_ACL_EVERYONE, 0, "" },
};
archive_entry_acl_clear(ae);
for (i = 0; i < n; i++) {
archive_entry_acl_add_entry(ae,
acls[i].type, acls[i].permset, acls[i].tag, acls[i].qual,
acls[i].name);
}
}
static struct archive_test_acl_t acls4[] = {
{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
ARCHIVE_ENTRY_ACL_READ_DATA |
ARCHIVE_ENTRY_ACL_WRITE_DATA |
ARCHIVE_ENTRY_ACL_APPEND_DATA |
ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES |
ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS |
ARCHIVE_ENTRY_ACL_READ_ACL |
ARCHIVE_ENTRY_ACL_WRITE_ACL |
ARCHIVE_ENTRY_ACL_WRITE_OWNER |
ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
ARCHIVE_ENTRY_ACL_USER_OBJ, 0, "" },
{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
ARCHIVE_ENTRY_ACL_READ_DATA |
ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
ARCHIVE_ENTRY_ACL_READ_ACL |
ARCHIVE_ENTRY_ACL_SYNCHRONIZE |
ARCHIVE_ENTRY_ACL_ENTRY_INHERITED,
ARCHIVE_ENTRY_ACL_USER, 77, "user77" },
{ ARCHIVE_ENTRY_ACL_TYPE_DENY,
ARCHIVE_ENTRY_ACL_READ_DATA |
ARCHIVE_ENTRY_ACL_WRITE_DATA |
ARCHIVE_ENTRY_ACL_EXECUTE,
ARCHIVE_ENTRY_ACL_USER, 78, "user78" },
{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
ARCHIVE_ENTRY_ACL_READ_DATA |
ARCHIVE_ENTRY_ACL_WRITE_DATA |
ARCHIVE_ENTRY_ACL_APPEND_DATA |
ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
ARCHIVE_ENTRY_ACL_READ_ACL |
ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
ARCHIVE_ENTRY_ACL_GROUP_OBJ, 0, "" },
{ ARCHIVE_ENTRY_ACL_TYPE_DENY,
ARCHIVE_ENTRY_ACL_WRITE_DATA |
ARCHIVE_ENTRY_ACL_APPEND_DATA |
ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES |
ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS |
ARCHIVE_ENTRY_ACL_WRITE_ACL |
ARCHIVE_ENTRY_ACL_WRITE_OWNER,
ARCHIVE_ENTRY_ACL_GROUP, 78, "group78" },
{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
ARCHIVE_ENTRY_ACL_READ_DATA |
ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
ARCHIVE_ENTRY_ACL_READ_ACL |
ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
ARCHIVE_ENTRY_ACL_EVERYONE, 0, "" },
};
static int
acl_match(struct acl_t *acl, int type, int permset, int tag, int qual, const char *name)
{
if (type != acl->type)
return (0);
if (permset != acl->permset)
return (0);
if (tag != acl->tag)
return (0);
if (tag == ARCHIVE_ENTRY_ACL_USER_OBJ)
return (1);
if (tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ)
return (1);
if (tag == ARCHIVE_ENTRY_ACL_OTHER)
return (1);
if (qual != acl->qual)
return (0);
if (name == NULL)
return (acl->name == NULL || acl->name[0] == '\0');
if (acl->name == NULL)
return (name == NULL || name[0] == '\0');
return (0 == strcmp(name, acl->name));
}
static struct archive_test_acl_t acls5[] = {
{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
ARCHIVE_ENTRY_ACL_READ_DATA |
ARCHIVE_ENTRY_ACL_WRITE_DATA |
ARCHIVE_ENTRY_ACL_EXECUTE |
ARCHIVE_ENTRY_ACL_APPEND_DATA |
ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES |
ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS |
ARCHIVE_ENTRY_ACL_READ_ACL |
ARCHIVE_ENTRY_ACL_WRITE_ACL |
ARCHIVE_ENTRY_ACL_WRITE_OWNER |
ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
ARCHIVE_ENTRY_ACL_USER_OBJ, 0, "" },
{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
ARCHIVE_ENTRY_ACL_READ_DATA |
ARCHIVE_ENTRY_ACL_WRITE_DATA |
ARCHIVE_ENTRY_ACL_APPEND_DATA |
ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
ARCHIVE_ENTRY_ACL_READ_ACL |
ARCHIVE_ENTRY_ACL_WRITE_OWNER |
ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
ARCHIVE_ENTRY_ACL_USER, 77, "user77" },
{ ARCHIVE_ENTRY_ACL_TYPE_AUDIT,
ARCHIVE_ENTRY_ACL_WRITE_DATA |
ARCHIVE_ENTRY_ACL_APPEND_DATA |
ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS,
ARCHIVE_ENTRY_ACL_USER, 77, "user77" },
{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
ARCHIVE_ENTRY_ACL_READ_DATA |
ARCHIVE_ENTRY_ACL_WRITE_DATA |
ARCHIVE_ENTRY_ACL_APPEND_DATA |
ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
ARCHIVE_ENTRY_ACL_READ_ACL |
ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
ARCHIVE_ENTRY_ACL_GROUP_OBJ, 0, "" },
{ ARCHIVE_ENTRY_ACL_TYPE_ALARM,
ARCHIVE_ENTRY_ACL_READ_DATA |
ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
ARCHIVE_ENTRY_ACL_READ_ACL |
ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS,
ARCHIVE_ENTRY_ACL_GROUP, 78, "group78" },
{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
ARCHIVE_ENTRY_ACL_READ_DATA |
ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
ARCHIVE_ENTRY_ACL_READ_ACL |
ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
ARCHIVE_ENTRY_ACL_EVERYONE, 0, "" },
};
static void
compare_acls(struct archive_entry *ae, struct acl_t *acls, int n, int mode)
{
int *marker = malloc(sizeof(marker[0]) * n);
int i;
int r;
int type, permset, tag, qual;
int matched;
const char *name;
for (i = 0; i < n; i++)
marker[i] = i;
while (0 == (r = archive_entry_acl_next(ae,
ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
&type, &permset, &tag, &qual, &name))) {
for (i = 0, matched = 0; i < n && !matched; i++) {
if (acl_match(&acls[marker[i]], type, permset,
tag, qual, name)) {
/* We found a match; remove it. */
marker[i] = marker[n - 1];
n--;
matched = 1;
}
}
if (tag == ARCHIVE_ENTRY_ACL_USER_OBJ) {
if (!matched) printf("No match for user_obj perm\n");
failure("USER_OBJ permset (%02o) != user mode (%02o)",
permset, 07 & (mode >> 6));
assert((permset << 6) == (mode & 0700));
} else if (tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ) {
if (!matched) printf("No match for group_obj perm\n");
failure("GROUP_OBJ permset %02o != group mode %02o",
permset, 07 & (mode >> 3));
assert((permset << 3) == (mode & 0070));
} else if (tag == ARCHIVE_ENTRY_ACL_OTHER) {
if (!matched) printf("No match for other perm\n");
failure("OTHER permset (%02o) != other mode (%02o)",
permset, mode & 07);
assert((permset << 0) == (mode & 0007));
} else {
failure("Could not find match for ACL "
"(type=%d,permset=%d,tag=%d,qual=%d,name=``%s'')",
type, permset, tag, qual, name);
assert(matched == 1);
}
}
assertEqualInt(ARCHIVE_EOF, r);
assert((mode_t)(mode & 0777) == (archive_entry_mode(ae) & 0777));
failure("Could not find match for ACL "
"(type=%d,permset=%d,tag=%d,qual=%d,name=``%s'')",
acls[marker[0]].type, acls[marker[0]].permset,
acls[marker[0]].tag, acls[marker[0]].qual, acls[marker[0]].name);
assert(n == 0); /* Number of ACLs not matched should == 0 */
free(marker);
}
DEFINE_TEST(test_acl_pax)
DEFINE_TEST(test_acl_pax_posix1e)
{
struct archive *a;
struct archive_entry *ae;
@ -197,23 +238,23 @@ DEFINE_TEST(test_acl_pax)
archive_entry_set_mode(ae, S_IFREG | 0777);
/* Basic owner/owning group should just update mode bits. */
set_acls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]));
archive_test_set_acls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]));
assertA(0 == archive_write_header(a, ae));
/* With any extended ACL entry, we should read back a full set. */
set_acls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]));
archive_test_set_acls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]));
assertA(0 == archive_write_header(a, ae));
/* A more extensive set of ACLs. */
set_acls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]));
archive_test_set_acls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]));
assertA(0 == archive_write_header(a, ae));
/*
* Check that clearing ACLs gets rid of them all by repeating
* the first test.
*/
set_acls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]));
archive_test_set_acls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]));
assertA(0 == archive_write_header(a, ae));
archive_entry_free(ae);
@ -227,13 +268,13 @@ DEFINE_TEST(test_acl_pax)
fclose(f);
/* Write out the reference data to a file for manual inspection. */
extract_reference_file("test_acl_pax.tar");
reference = slurpfile(&reference_size, "test_acl_pax.tar");
extract_reference_file("test_acl_pax_posix1e.tar");
reference = slurpfile(&reference_size, "test_acl_pax_posix1e.tar");
/* Assert that the generated data matches the built-in reference data.*/
failure("Generated pax archive does not match reference; compare 'testout' to 'test_acl_pax.tar' reference file.");
failure("Generated pax archive does not match reference; compare 'testout' to 'test_acl_pax_posix1e.tar' reference file.");
assertEqualMem(buff, reference, reference_size);
failure("Generated pax archive does not match reference; compare 'testout' to 'test_acl_pax.tar' reference file.");
failure("Generated pax archive does not match reference; compare 'testout' to 'test_acl_pax_posix1e.tar' reference file.");
assertEqualInt((int)used, reference_size);
free(reference);
@ -255,15 +296,18 @@ DEFINE_TEST(test_acl_pax)
assertA(0 == archive_read_next_header(a, &ae));
failure("One extended ACL should flag all ACLs to be returned.");
assert(4 == archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
compare_acls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]), 0142);
archive_test_compare_acls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]),
ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0142);
failure("Basic ACLs should set mode to 0142, not %04o",
archive_entry_mode(ae)&0777);
assert((archive_entry_mode(ae) & 0777) == 0142);
/* Third item has pretty extensive ACLs */
assertA(0 == archive_read_next_header(a, &ae));
assertEqualInt(6, archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
compare_acls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]), 0543);
assertEqualInt(6, archive_entry_acl_reset(ae,
ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
archive_test_compare_acls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]),
ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0543);
failure("Basic ACLs should set mode to 0543, not %04o",
archive_entry_mode(ae)&0777);
assert((archive_entry_mode(ae) & 0777) == 0543);
@ -280,3 +324,93 @@ DEFINE_TEST(test_acl_pax)
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
}
DEFINE_TEST(test_acl_pax_nfs4)
{
struct archive *a;
struct archive_entry *ae;
size_t used;
FILE *f;
void *reference;
size_t reference_size;
/* Write an archive to memory. */
assert(NULL != (a = archive_write_new()));
assertA(0 == archive_write_set_format_pax(a));
assertA(0 == archive_write_add_filter_none(a));
assertA(0 == archive_write_set_bytes_per_block(a, 1));
assertA(0 == archive_write_set_bytes_in_last_block(a, 1));
assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &used));
/* Write a series of files to the archive with different ACL info. */
/* Create a simple archive_entry. */
assert((ae = archive_entry_new()) != NULL);
archive_entry_set_pathname(ae, "file");
archive_entry_set_mode(ae, S_IFREG | 0777);
/* NFS4 ACLs mirroring 0754 file mode */
archive_test_set_acls(ae, acls3, sizeof(acls3)/sizeof(acls3[0]));
assertA(0 == archive_write_header(a, ae));
/* A more extensive set of NFS4 ACLs. */
archive_test_set_acls(ae, acls4, sizeof(acls4)/sizeof(acls4[0]));
assertA(0 == archive_write_header(a, ae));
/* Set with special (audit, alarm) NFS4 ACLs. */
archive_test_set_acls(ae, acls5, sizeof(acls5)/sizeof(acls5[0]));
assertA(0 == archive_write_header(a, ae));
archive_entry_free(ae);
/* Close out the archive. */
assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
assertEqualInt(ARCHIVE_OK, archive_write_free(a));
/* Write out the data we generated to a file for manual inspection. */
assert(NULL != (f = fopen("testout", "wb")));
assertEqualInt(used, (size_t)fwrite(buff, 1, (unsigned int)used, f));
fclose(f);
/* Write out the reference data to a file for manual inspection. */
extract_reference_file("test_acl_pax_nfs4.tar");
reference = slurpfile(&reference_size, "test_acl_pax_nfs4.tar");
/* Assert that the generated data matches the built-in reference data.*/
failure("Generated pax archive does not match reference; compare 'testout' to 'test_acl_pax_nfs4.tar' reference file.");
assertEqualMem(buff, reference, reference_size);
failure("Generated pax archive does not match reference; compare 'testout' to 'test_acl_pax_nfs4.tar' reference file.");
assertEqualInt((int)used, reference_size);
free(reference);
/* Read back each entry and check that the ACL data is right. */
assert(NULL != (a = archive_read_new()));
assertA(0 == archive_read_support_format_all(a));
assertA(0 == archive_read_support_filter_all(a));
assertA(0 == archive_read_open_memory(a, buff, used));
/* First item has NFS4 ACLs mirroring file mode */
assertA(0 == archive_read_next_header(a, &ae));
assertEqualInt(3, archive_entry_acl_reset(ae,
ARCHIVE_ENTRY_ACL_TYPE_ALLOW));
archive_test_compare_acls(ae, acls3, sizeof(acls3)/sizeof(acls3[0]),
ARCHIVE_ENTRY_ACL_TYPE_ALLOW, 0);
/* Second item has has more fine-grained NFS4 ACLs */
assertA(0 == archive_read_next_header(a, &ae));
assertEqualInt(6, archive_entry_acl_reset(ae,
ARCHIVE_ENTRY_ACL_TYPE_NFS4));
archive_test_compare_acls(ae, acls4, sizeof(acls4)/sizeof(acls4[0]),
ARCHIVE_ENTRY_ACL_TYPE_NFS4, 0);
/* Third item has has audit and alarm NFS4 ACLs */
assertA(0 == archive_read_next_header(a, &ae));
assertEqualInt(6, archive_entry_acl_reset(ae,
ARCHIVE_ENTRY_ACL_TYPE_NFS4));
archive_test_compare_acls(ae, acls5, sizeof(acls5)/sizeof(acls5[0]),
ARCHIVE_ENTRY_ACL_TYPE_NFS4, 0);
/* Close the archive. */
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
}

View File

@ -0,0 +1,129 @@
begin 644 test_acl_pax_nfs4.tar
M4&%X2&5A9&5R+V9I;&4`````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````#`P,#<W-R``,#`P,#`P(``P,#`P,#`@`#`P,#`P,#`P,C`R
M(#`P,#`P,#`P,#`P(#`Q,C`P,0`@>```````````````````````````````
M````````````````````````````````````````````````````````````
M``````````````````````````````````````````!U<W1A<@`P,```````
M````````````````````````````````````````````````````````````
M```````````````````P,#`P,#`@`#`P,#`P,"``````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M```````````````````````Q,S`@4T-(24Q9+F%C;"YA8V4];W=N97)`.G)W
M>'`M+6%!4E=C0V]S.BTM+2TM+2TZ86QL;W<L9W)O=7!`.G)W+7`M+6$M4BUC
M+2US.BTM+2TM+2TZ86QL;W<L979E<GEO;F5`.G(M+2TM+6$M4BUC+2US.BTM
M+2TM+2TZ86QL;W<*````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````````````````````````````````````&9I;&4`````````
M````````````````````````````````````````````````````````````
M```````````````````````````````````````````````````````````P
M,#`W-S<@`#`P,#`P,"``,#`P,#`P(``P,#`P,#`P,#`P,"`P,#`P,#`P,#`P
M,"`P,3`P,C0`(#``````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````=7-T87(`,#``````````````````````
M````````````````````````````````````````````````````````````
M````,#`P,#`P(``P,#`P,#`@````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````4&%X2&5A9&5R+V9I;&4`````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````````````#`P,#<W-R``,#`P,#`P(``P,#`P,#`@`#`P,#`P
M,#`P-#`V(#`P,#`P,#`P,#`P(#`Q,C`P-P`@>```````````````````````
M````````````````````````````````````````````````````````````
M``````````````````````````````````````````````````!U<W1A<@`P
M,```````````````````````````````````````````````````````````
M```````````````````````````P,#`P,#`@`#`P,#`P,"``````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M```````````````````````````````R-C(@4T-(24Q9+F%C;"YA8V4];W=N
M97)`.G)W+7`M+6%!4E=C0V]S.BTM+2TM+2TZ86QL;W<L=7-E<CIU<V5R-S<Z
M<BTM+2TM82U2+6,M+7,Z+2TM+2TM23IA;&QO=SHW-RQU<V5R.G5S97(W.#IR
M=W@M+2TM+2TM+2TM+3HM+2TM+2TM.F1E;GDZ-S@L9W)O=7!`.G)W+7`M+6$M
M4BUC+2US.BTM+2TM+2TZ86QL;W<L9W)O=7`Z9W)O=7`W.#HM=RUP+2TM02U7
M+4-O+3HM+2TM+2TM.F1E;GDZ-S@L979E<GEO;F5`.G(M+2TM+6$M4BUC+2US
M.BTM+2TM+2TZ86QL;W<*````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````````````````````````````````````````````&9I;&4`
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M```````P,#`W-S<@`#`P,#`P,"``,#`P,#`P(``P,#`P,#`P,#`P,"`P,#`P
M,#`P,#`P,"`P,3`P,C0`(#``````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````=7-T87(`,#``````````````
M````````````````````````````````````````````````````````````
M````````````,#`P,#`P(``P,#`P,#`@````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````4&%X2&5A9&5R+V9I;&4`````````````````````````
M````````````````````````````````````````````````````````````
M`````````````````````````````#`P,#<W-R``,#`P,#`P(``P,#`P,#`@
M`#`P,#`P,#`P-#$P(#`P,#`P,#`P,#`P(#`Q,C`P,@`@>```````````````
M````````````````````````````````````````````````````````````
M``````````````````````````````````````````````````````````!U
M<W1A<@`P,```````````````````````````````````````````````````
M```````````````````````````````````P,#`P,#`@`#`P,#`P,"``````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M```````````````````````````````````````R-C0@4T-(24Q9+F%C;"YA
M8V4];W=N97)`.G)W>'`M+6%!4E=C0V]S.BTM+2TM+2TZ86QL;W<L=7-E<CIU
M<V5R-S<Z<G<M<"TM82U2+6,M;W,Z+2TM+2TM+3IA;&QO=SHW-RQU<V5R.G5S
M97(W-SHM=RUP+2TM+2TM+2TM+3HM+2TM4RTM.F%U9&ET.C<W+&=R;W5P0#IR
M=RUP+2UA+5(M8RTM<SHM+2TM+2TM.F%L;&]W+&=R;W5P.F=R;W5P-S@Z<BTM
M+2TM82U2+6,M+2TZ+2TM+2U&+3IA;&%R;3HW."QE=F5R>6]N94`Z<BTM+2TM
M82U2+6,M+7,Z+2TM+2TM+3IA;&QO=PH`````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`&9I;&4`````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M```````````````P,#`W-S<@`#`P,#`P,"``,#`P,#`P(``P,#`P,#`P,#`P
M,"`P,#`P,#`P,#`P,"`P,3`P,C0`(#``````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````=7-T87(`,#``````
M````````````````````````````````````````````````````````````
M````````````````````,#`P,#`P(``P,#`P,#`@````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
'````````````
`
end

View File

@ -1,4 +1,4 @@
begin 644 test_acl_pax.tar
begin 644 test_acl_pax_posix1e.tar
M9FEL90``````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````#`P,#$T,B``,#`P,#`P(``P,#`P,#`@`#`P,#`P,#`P,#`P

View File

@ -27,21 +27,14 @@ __FBSDID("$FreeBSD: src/lib/libarchive/test/test_acl_basic.c,v 1.6 2008/10/19 00
/*
* Exercise the system-independent portion of the ACL support.
* Check that archive_entry objects can save and restore POSIX.1e-style ACL data.
* Check that archive_entry objects can save and restore POSIX.1e-style
* ACL data.
*
* This should work on all systems, regardless of whether local
* filesystems support ACLs or not.
*/
struct acl_t {
int type; /* Type of ACL: "access" or "default" */
int permset; /* Permissions for this class of users. */
int tag; /* Owner, User, Owning group, group, other, etc. */
int qual; /* GID or UID of user/group, depending on tag. */
const char *name; /* Name of user/group, depending on tag. */
};
static struct acl_t acls0[] = {
static struct archive_test_acl_t acls0[] = {
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE,
ARCHIVE_ENTRY_ACL_USER_OBJ, 0, "" },
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ,
@ -50,7 +43,7 @@ static struct acl_t acls0[] = {
ARCHIVE_ENTRY_ACL_OTHER, 0, "" },
};
static struct acl_t acls1[] = {
static struct archive_test_acl_t acls1[] = {
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE,
ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ,
@ -61,7 +54,7 @@ static struct acl_t acls1[] = {
ARCHIVE_ENTRY_ACL_OTHER, -1, "" },
};
static struct acl_t acls2[] = {
static struct archive_test_acl_t acls2[] = {
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE | ARCHIVE_ENTRY_ACL_READ,
ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ,
@ -80,7 +73,7 @@ static struct acl_t acls2[] = {
* NFS4 entry types; attempts to set these on top of POSIX.1e
* attributes should fail.
*/
static struct acl_t acls_nfs4[] = {
static struct archive_test_acl_t acls_nfs4[] = {
/* NFS4 types */
{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ,
ARCHIVE_ENTRY_ACL_USER, 78, "" },
@ -104,106 +97,6 @@ static struct acl_t acls_nfs4[] = {
ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
};
static void
set_acls(struct archive_entry *ae, struct acl_t *acls, int n)
{
int i;
archive_entry_acl_clear(ae);
for (i = 0; i < n; i++) {
archive_entry_acl_add_entry(ae,
acls[i].type, acls[i].permset, acls[i].tag, acls[i].qual,
acls[i].name);
}
}
static int
acl_match(struct acl_t *acl, int type, int permset, int tag, int qual, const char *name)
{
if (type != acl->type)
return (0);
if (permset != acl->permset)
return (0);
if (tag != acl->tag)
return (0);
if (tag == ARCHIVE_ENTRY_ACL_USER_OBJ)
return (1);
if (tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ)
return (1);
if (tag == ARCHIVE_ENTRY_ACL_OTHER)
return (1);
if (qual != acl->qual)
return (0);
if (name == NULL) {
if (acl->name == NULL || acl->name[0] == '\0')
return (1);
return (0);
}
if (acl->name == NULL) {
if (name[0] == '\0')
return (1);
return (0);
}
return (0 == strcmp(name, acl->name));
}
static void
compare_acls(struct archive_entry *ae, struct acl_t *acls, int n, int mode)
{
int *marker = malloc(sizeof(marker[0]) * n);
int i;
int r;
int type, permset, tag, qual;
int matched;
const char *name;
for (i = 0; i < n; i++)
marker[i] = i;
while (0 == (r = archive_entry_acl_next(ae,
ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
&type, &permset, &tag, &qual, &name))) {
for (i = 0, matched = 0; i < n && !matched; i++) {
if (acl_match(&acls[marker[i]], type, permset,
tag, qual, name)) {
/* We found a match; remove it. */
marker[i] = marker[n - 1];
n--;
matched = 1;
}
}
if (tag == ARCHIVE_ENTRY_ACL_USER_OBJ) {
if (!matched) printf("No match for user_obj perm\n");
failure("USER_OBJ permset (%02o) != user mode (%02o)",
permset, 07 & (mode >> 6));
assert((permset << 6) == (mode & 0700));
} else if (tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ) {
if (!matched) printf("No match for group_obj perm\n");
failure("GROUP_OBJ permset %02o != group mode %02o",
permset, 07 & (mode >> 3));
assert((permset << 3) == (mode & 0070));
} else if (tag == ARCHIVE_ENTRY_ACL_OTHER) {
if (!matched) printf("No match for other perm\n");
failure("OTHER permset (%02o) != other mode (%02o)",
permset, mode & 07);
assert((permset << 0) == (mode & 0007));
} else {
failure("Could not find match for ACL "
"(type=%d,permset=%d,tag=%d,qual=%d,name=``%s'')",
type, permset, tag, qual, name);
assert(matched == 1);
}
}
assertEqualInt(ARCHIVE_EOF, r);
assert((mode_t)(mode & 0777) == (archive_entry_mode(ae) & 0777));
failure("Could not find match for ACL "
"(type=%d,permset=%d,tag=%d,qual=%d,name=``%s'')",
acls[marker[0]].type, acls[marker[0]].permset,
acls[marker[0]].tag, acls[marker[0]].qual, acls[marker[0]].name);
assert(n == 0); /* Number of ACLs not matched should == 0 */
free(marker);
}
DEFINE_TEST(test_acl_posix1e)
{
struct archive_entry *ae;
@ -223,7 +116,7 @@ DEFINE_TEST(test_acl_posix1e)
* triggering unnecessary extensions. It's better to identify
* trivial ACLs at the point they are being read from disk.
*/
set_acls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]));
archive_test_set_acls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]));
failure("Basic ACLs shouldn't be stored as extended ACLs");
assert(0 == archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
failure("Basic ACLs should set mode to 0142, not %04o",
@ -232,19 +125,28 @@ DEFINE_TEST(test_acl_posix1e)
/* With any extended ACL entry, we should read back a full set. */
set_acls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]));
archive_test_set_acls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]));
failure("One extended ACL should flag all ACLs to be returned.");
/* Check that entry contains only POSIX.1e types */
assert((archive_entry_acl_types(ae) &
ARCHIVE_ENTRY_ACL_TYPE_NFS4) == 0);
assert((archive_entry_acl_types(ae) &
ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0);
assert(4 == archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
compare_acls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]), 0142);
archive_test_compare_acls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]),
ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0142);
failure("Basic ACLs should set mode to 0142, not %04o",
archive_entry_mode(ae)&0777);
assert((archive_entry_mode(ae) & 0777) == 0142);
/* A more extensive set of ACLs. */
set_acls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]));
archive_test_set_acls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]));
assertEqualInt(6, archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
compare_acls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]), 0543);
archive_test_compare_acls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]),
ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0543);
failure("Basic ACLs should set mode to 0543, not %04o",
archive_entry_mode(ae)&0777);
assert((archive_entry_mode(ae) & 0777) == 0543);
@ -253,7 +155,7 @@ DEFINE_TEST(test_acl_posix1e)
* Check that clearing ACLs gets rid of them all by repeating
* the first test.
*/
set_acls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]));
archive_test_set_acls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]));
failure("Basic ACLs shouldn't be stored as extended ACLs");
assert(0 == archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
failure("Basic ACLs should set mode to 0142, not %04o",
@ -264,9 +166,9 @@ DEFINE_TEST(test_acl_posix1e)
* Different types of malformed ACL entries that should
* fail when added to existing POSIX.1e ACLs.
*/
set_acls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]));
archive_test_set_acls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]));
for (i = 0; i < (int)(sizeof(acls_nfs4)/sizeof(acls_nfs4[0])); ++i) {
struct acl_t *p = &acls_nfs4[i];
struct archive_test_acl_t *p = &acls_nfs4[i];
failure("Malformed ACL test #%d", i);
assertEqualInt(ARCHIVE_FAILED,
archive_entry_acl_add_entry(ae,

View File

@ -0,0 +1,456 @@
/*-
* Copyright (c) 2016 Martin Matuska
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test.h"
__FBSDID("$FreeBSD$");
/*
* Test converting ACLs to text, both wide and non-wide
*
* This should work on all systems, regardless of whether local
* filesystems support ACLs or not.
*/
static struct archive_test_acl_t acls0[] = {
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
ARCHIVE_ENTRY_ACL_EXECUTE |
ARCHIVE_ENTRY_ACL_READ |
ARCHIVE_ENTRY_ACL_WRITE,
ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
ARCHIVE_ENTRY_ACL_EXECUTE |
ARCHIVE_ENTRY_ACL_READ,
ARCHIVE_ENTRY_ACL_USER, 100, "user100" },
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0,
ARCHIVE_ENTRY_ACL_USER, 1000, "user1000" },
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
ARCHIVE_ENTRY_ACL_EXECUTE |
ARCHIVE_ENTRY_ACL_READ,
ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" },
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
ARCHIVE_ENTRY_ACL_EXECUTE |
ARCHIVE_ENTRY_ACL_READ |
ARCHIVE_ENTRY_ACL_WRITE,
ARCHIVE_ENTRY_ACL_GROUP, 78, "group78" },
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
ARCHIVE_ENTRY_ACL_READ |
ARCHIVE_ENTRY_ACL_EXECUTE,
ARCHIVE_ENTRY_ACL_OTHER, -1, "" },
{ ARCHIVE_ENTRY_ACL_TYPE_DEFAULT,
ARCHIVE_ENTRY_ACL_EXECUTE |
ARCHIVE_ENTRY_ACL_READ,
ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
{ ARCHIVE_ENTRY_ACL_TYPE_DEFAULT,
ARCHIVE_ENTRY_ACL_EXECUTE |
ARCHIVE_ENTRY_ACL_READ,
ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" },
{ ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, 0,
ARCHIVE_ENTRY_ACL_OTHER, -1, "" },
{ ARCHIVE_ENTRY_ACL_TYPE_DEFAULT,
ARCHIVE_ENTRY_ACL_EXECUTE |
ARCHIVE_ENTRY_ACL_READ,
ARCHIVE_ENTRY_ACL_USER, 101, "user101"},
{ ARCHIVE_ENTRY_ACL_TYPE_DEFAULT,
ARCHIVE_ENTRY_ACL_EXECUTE,
ARCHIVE_ENTRY_ACL_GROUP, 79, "group79" },
};
static struct archive_test_acl_t acls1[] = {
{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
ARCHIVE_ENTRY_ACL_READ_DATA |
ARCHIVE_ENTRY_ACL_WRITE_DATA |
ARCHIVE_ENTRY_ACL_APPEND_DATA |
ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
ARCHIVE_ENTRY_ACL_READ_ACL |
ARCHIVE_ENTRY_ACL_WRITE_OWNER,
ARCHIVE_ENTRY_ACL_USER, 77, "user77" },
{ ARCHIVE_ENTRY_ACL_TYPE_DENY,
ARCHIVE_ENTRY_ACL_WRITE_DATA |
ARCHIVE_ENTRY_ACL_APPEND_DATA |
ARCHIVE_ENTRY_ACL_DELETE_CHILD |
ARCHIVE_ENTRY_ACL_DELETE |
ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT |
ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT |
ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY |
ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT,
ARCHIVE_ENTRY_ACL_USER, 101, "user101" },
{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
ARCHIVE_ENTRY_ACL_READ_DATA |
ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
ARCHIVE_ENTRY_ACL_READ_ACL |
ARCHIVE_ENTRY_ACL_ENTRY_INHERITED,
ARCHIVE_ENTRY_ACL_GROUP, 78, "group78" },
{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
ARCHIVE_ENTRY_ACL_READ_DATA |
ARCHIVE_ENTRY_ACL_WRITE_DATA |
ARCHIVE_ENTRY_ACL_EXECUTE |
ARCHIVE_ENTRY_ACL_APPEND_DATA |
ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES |
ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS |
ARCHIVE_ENTRY_ACL_READ_ACL |
ARCHIVE_ENTRY_ACL_WRITE_ACL |
ARCHIVE_ENTRY_ACL_WRITE_OWNER,
ARCHIVE_ENTRY_ACL_USER_OBJ, 0, "" },
{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
ARCHIVE_ENTRY_ACL_READ_DATA |
ARCHIVE_ENTRY_ACL_WRITE_DATA |
ARCHIVE_ENTRY_ACL_APPEND_DATA |
ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
ARCHIVE_ENTRY_ACL_READ_ACL,
ARCHIVE_ENTRY_ACL_GROUP_OBJ, 0, "" },
{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
ARCHIVE_ENTRY_ACL_READ_DATA |
ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
ARCHIVE_ENTRY_ACL_READ_ACL |
ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
ARCHIVE_ENTRY_ACL_EVERYONE, 0, "" },
};
const char* acltext[] = {
"user::rwx\n"
"group::r-x\n"
"other::r-x\n"
"user:user100:r-x\n"
"user:user1000:---\n"
"group:group78:rwx\n"
"default:user::r-x\n"
"default:group::r-x\n"
"default:other::---\n"
"default:user:user101:r-x\n"
"default:group:group79:--x",
"user::rwx\n"
"group::r-x\n"
"other::r-x\n"
"user:user100:r-x:100\n"
"user:user1000:---:1000\n"
"group:group78:rwx:78\n"
"default:user::r-x\n"
"default:group::r-x\n"
"default:other::---\n"
"default:user:user101:r-x:101\n"
"default:group:group79:--x:79",
"u::rwx\n"
"g::r-x\n"
"o::r-x\n"
"u:user100:r-x:100\n"
"u:user1000:---:1000\n"
"g:group78:rwx:78\n"
"d:user::r-x\n"
"d:group::r-x\n"
"d:other::---\n"
"d:user:user101:r-x:101\n"
"d:group:group79:--x:79",
"user::rwx\n"
"group::r-x\n"
"other::r-x\n"
"user:user100:r-x\n"
"user:user1000:---\n"
"group:group78:rwx",
"user::rwx,"
"group::r-x,"
"other::r-x,"
"user:user100:r-x,"
"user:user1000:---,"
"group:group78:rwx",
"user::rwx\n"
"group::r-x\n"
"other::r-x\n"
"user:user100:r-x:100\n"
"user:user1000:---:1000\n"
"group:group78:rwx:78",
"user::r-x\n"
"group::r-x\n"
"other::---\n"
"user:user101:r-x\n"
"group:group79:--x",
"user::r-x\n"
"group::r-x\n"
"other::---\n"
"user:user101:r-x:101\n"
"group:group79:--x:79",
"default:user::r-x\n"
"default:group::r-x\n"
"default:other::---\n"
"default:user:user101:r-x\n"
"default:group:group79:--x",
"user:user77:rw-p--a-R-c-o-:-------:allow\n"
"user:user101:-w-pdD--------:fdin---:deny\n"
"group:group78:r-----a-R-c---:------I:allow\n"
"owner@:rwxp--aARWcCo-:-------:allow\n"
"group@:rw-p--a-R-c---:-------:allow\n"
"everyone@:r-----a-R-c--s:-------:allow",
"user:user77:rw-p--a-R-c-o-:-------:allow:77\n"
"user:user101:-w-pdD--------:fdin---:deny:101\n"
"group:group78:r-----a-R-c---:------I:allow:78\n"
"owner@:rwxp--aARWcCo-:-------:allow\n"
"group@:rw-p--a-R-c---:-------:allow\n"
"everyone@:r-----a-R-c--s:-------:allow"
};
static wchar_t *
convert_s_to_ws(const char *s)
{
size_t len;
wchar_t *ws = NULL;
if (s != NULL) {
len = strlen(s) + 1;
ws = malloc(len * sizeof(wchar_t));
assert(mbstowcs(ws, s, len) != (size_t)-1);
}
return (ws);
}
static void
compare_acl_text(struct archive_entry *ae, int flags, const char *s)
{
const char *text;
const wchar_t *wtext;
wchar_t *ws;
ssize_t slen;
ws = convert_s_to_ws(s);
text = archive_entry_acl_to_text(ae, &slen, flags);
assertEqualString(text, s);
if (text != NULL)
assertEqualInt(strlen(text), slen);
wtext = archive_entry_acl_to_text_w(ae, &slen, flags);
assertEqualWString(wtext, ws);
if (wtext != NULL) {
assertEqualInt(wcslen(wtext), slen);
free(ws);
ws = NULL;
}
}
DEFINE_TEST(test_acl_from_text)
{
struct archive_entry *ae;
wchar_t *ws = NULL;
/* Create an empty archive_entry. */
assert((ae = archive_entry_new()) != NULL);
/* 1a. Read POSIX.1e access ACLs from text */
assertEqualInt(ARCHIVE_OK,
archive_entry_acl_from_text(ae, acltext[5],
ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
archive_test_compare_acls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]),
ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0755);
assertEqualInt(6, archive_entry_acl_reset(ae,
ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
/* 1b. Now read POSIX.1e default ACLs and append them */
assertEqualInt(ARCHIVE_OK,
archive_entry_acl_from_text(ae, acltext[7],
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT));
archive_test_compare_acls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]),
ARCHIVE_ENTRY_ACL_TYPE_POSIX1E, 0755);
assertEqualInt(11, archive_entry_acl_reset(ae,
ARCHIVE_ENTRY_ACL_TYPE_POSIX1E));
archive_entry_acl_clear(ae);
/* 1a and 1b with wide strings */
ws = convert_s_to_ws(acltext[5]);
assertEqualInt(ARCHIVE_OK,
archive_entry_acl_from_text_w(ae, ws,
ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
archive_test_compare_acls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]),
ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0755);
assertEqualInt(6, archive_entry_acl_reset(ae,
ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
free(ws);
ws = convert_s_to_ws(acltext[7]);
assertEqualInt(ARCHIVE_OK,
archive_entry_acl_from_text_w(ae, ws,
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT));
archive_test_compare_acls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]),
ARCHIVE_ENTRY_ACL_TYPE_POSIX1E, 0755);
assertEqualInt(11, archive_entry_acl_reset(ae,
ARCHIVE_ENTRY_ACL_TYPE_POSIX1E));
archive_entry_acl_clear(ae);
/* 2. Read POSIX.1e default ACLs from text */
assertEqualInt(ARCHIVE_OK,
archive_entry_acl_from_text(ae, acltext[7],
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT));
archive_test_compare_acls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]),
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, 0);
assertEqualInt(5, archive_entry_acl_reset(ae,
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT));
archive_entry_acl_clear(ae);
/* ws is still acltext[7] */
assertEqualInt(ARCHIVE_OK,
archive_entry_acl_from_text_w(ae, ws,
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT));
archive_test_compare_acls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]),
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, 0);
assertEqualInt(5, archive_entry_acl_reset(ae,
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT));
archive_entry_acl_clear(ae);
/* 3. Read POSIX.1e access and default ACLs from text */
assertEqualInt(ARCHIVE_OK,
archive_entry_acl_from_text(ae, acltext[1],
ARCHIVE_ENTRY_ACL_TYPE_POSIX1E));
archive_test_compare_acls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]),
ARCHIVE_ENTRY_ACL_TYPE_POSIX1E, 0755);
assertEqualInt(11, archive_entry_acl_reset(ae,
ARCHIVE_ENTRY_ACL_TYPE_POSIX1E));
archive_entry_acl_clear(ae);
free(ws);
ws = convert_s_to_ws(acltext[1]);
assertEqualInt(ARCHIVE_OK,
archive_entry_acl_from_text_w(ae, ws,
ARCHIVE_ENTRY_ACL_TYPE_POSIX1E));
archive_test_compare_acls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]),
ARCHIVE_ENTRY_ACL_TYPE_POSIX1E, 0755);
assertEqualInt(11, archive_entry_acl_reset(ae,
ARCHIVE_ENTRY_ACL_TYPE_POSIX1E));
archive_entry_acl_clear(ae);
/* 4. Read POSIX.1e access and default ACLs from text (short form) */
assertEqualInt(ARCHIVE_OK,
archive_entry_acl_from_text(ae, acltext[2],
ARCHIVE_ENTRY_ACL_TYPE_POSIX1E));
archive_test_compare_acls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]),
ARCHIVE_ENTRY_ACL_TYPE_POSIX1E, 0755);
assertEqualInt(11, archive_entry_acl_reset(ae,
ARCHIVE_ENTRY_ACL_TYPE_POSIX1E));
archive_entry_acl_clear(ae);
free(ws);
ws = convert_s_to_ws(acltext[2]);
assertEqualInt(ARCHIVE_OK,
archive_entry_acl_from_text_w(ae, ws,
ARCHIVE_ENTRY_ACL_TYPE_POSIX1E));
archive_test_compare_acls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]),
ARCHIVE_ENTRY_ACL_TYPE_POSIX1E, 0755);
assertEqualInt(11, archive_entry_acl_reset(ae,
ARCHIVE_ENTRY_ACL_TYPE_POSIX1E));
archive_entry_acl_clear(ae);
/* 5. Read NFSv4 ACLs from text */
assertEqualInt(ARCHIVE_OK,
archive_entry_acl_from_text(ae, acltext[10],
ARCHIVE_ENTRY_ACL_TYPE_NFS4));
archive_test_compare_acls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]),
ARCHIVE_ENTRY_ACL_TYPE_NFS4, 0);
assertEqualInt(6, archive_entry_acl_reset(ae,
ARCHIVE_ENTRY_ACL_TYPE_NFS4));
archive_entry_acl_clear(ae);
free(ws);
ws = convert_s_to_ws(acltext[10]);
assertEqualInt(ARCHIVE_OK,
archive_entry_acl_from_text_w(ae, ws,
ARCHIVE_ENTRY_ACL_TYPE_NFS4));
archive_test_compare_acls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]),
ARCHIVE_ENTRY_ACL_TYPE_NFS4, 0);
assertEqualInt(6, archive_entry_acl_reset(ae,
ARCHIVE_ENTRY_ACL_TYPE_NFS4));
archive_entry_acl_clear(ae);
}
DEFINE_TEST(test_acl_to_text)
{
struct archive_entry *ae;
/* Create an empty archive_entry. */
assert((ae = archive_entry_new()) != NULL);
/* Write POSIX.1e ACLs */
archive_test_set_acls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]));
/* No flags should give output like getfacl(1) on linux */
compare_acl_text(ae, 0, acltext[0]);
/* This should give the same output as previous test */
compare_acl_text(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS |
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, acltext[0]);
/* This should give the same output as previous two tests */
compare_acl_text(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS |
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT |
ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT, acltext[0]);
/* POSIX.1e access and default ACLs with appended ID */
compare_acl_text(ae, ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID, acltext[1]);
/* POSIX.1e access acls only, like getfacl(1) on FreeBSD */
compare_acl_text(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, acltext[3]);
/* POSIX.1e access acls separated with comma */
compare_acl_text(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS |
ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA,
acltext[4]);
/* POSIX.1e access acls with appended user or group ID */
compare_acl_text(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS |
ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID, acltext[5]);
/* POSIX.1e default acls */
compare_acl_text(ae, ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, acltext[6]);
/* POSIX.1e default acls with appended user or group ID */
compare_acl_text(ae, ARCHIVE_ENTRY_ACL_TYPE_DEFAULT |
ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID, acltext[7]);
/* POSIX.1e default acls prefixed with default: */
compare_acl_text(ae, ARCHIVE_ENTRY_ACL_TYPE_DEFAULT |
ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT, acltext[8]);
/* Write NFSv4 ACLs */
archive_test_set_acls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]));
/* NFSv4 ACLs like getfacl(1) on FreeBSD */
compare_acl_text(ae, 0, acltext[9]);
/* NFSv4 ACLs like "getfacl -i" on FreeBSD */
compare_acl_text(ae, ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID, acltext[10]);
}

View File

@ -0,0 +1,321 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* Copyright (c) 2016 Martin Matuska
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test.h"
__FBSDID("$FreeBSD$");
/*
* Verify reading entries with POSIX.1e and NFSv4 ACLs from archives created
* by star.
*
* This should work on all systems, regardless of whether local filesystems
* support ACLs or not.
*/
static struct archive_test_acl_t acls0[] = {
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE,
ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ,
ARCHIVE_ENTRY_ACL_USER, -1, "user77" },
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ,
ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" },
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ,
ARCHIVE_ENTRY_ACL_MASK, -1, ""},
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_WRITE,
ARCHIVE_ENTRY_ACL_OTHER, -1, "" },
};
static struct archive_test_acl_t acls1[] = {
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE | ARCHIVE_ENTRY_ACL_READ,
ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ,
ARCHIVE_ENTRY_ACL_USER, -1, "user77" },
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0,
ARCHIVE_ENTRY_ACL_USER, -1, "user78" },
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ,
ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" },
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0007,
ARCHIVE_ENTRY_ACL_GROUP, -1, "group78" },
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0007,
ARCHIVE_ENTRY_ACL_MASK, -1, ""},
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_WRITE | ARCHIVE_ENTRY_ACL_EXECUTE,
ARCHIVE_ENTRY_ACL_OTHER, -1, "" },
};
static struct archive_test_acl_t acls2[] = {
{ ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, ARCHIVE_ENTRY_ACL_EXECUTE,
ARCHIVE_ENTRY_ACL_USER_OBJ, -1 ,"" },
{ ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, ARCHIVE_ENTRY_ACL_READ,
ARCHIVE_ENTRY_ACL_USER, -1, "user77" },
{ ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, ARCHIVE_ENTRY_ACL_READ,
ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" },
{ ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, ARCHIVE_ENTRY_ACL_EXECUTE,
ARCHIVE_ENTRY_ACL_GROUP, -1, "group78" },
{ ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, ARCHIVE_ENTRY_ACL_READ | ARCHIVE_ENTRY_ACL_EXECUTE,
ARCHIVE_ENTRY_ACL_MASK, -1, ""},
{ ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, ARCHIVE_ENTRY_ACL_WRITE,
ARCHIVE_ENTRY_ACL_OTHER, -1, "" },
};
static struct archive_test_acl_t acls3[] = {
{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
ARCHIVE_ENTRY_ACL_READ_DATA |
ARCHIVE_ENTRY_ACL_WRITE_DATA |
ARCHIVE_ENTRY_ACL_EXECUTE |
ARCHIVE_ENTRY_ACL_APPEND_DATA |
ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES |
ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS |
ARCHIVE_ENTRY_ACL_READ_ACL |
ARCHIVE_ENTRY_ACL_WRITE_ACL |
ARCHIVE_ENTRY_ACL_WRITE_OWNER |
ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
ARCHIVE_ENTRY_ACL_USER_OBJ, 0, "" },
{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
ARCHIVE_ENTRY_ACL_READ_DATA |
ARCHIVE_ENTRY_ACL_WRITE_DATA |
ARCHIVE_ENTRY_ACL_APPEND_DATA |
ARCHIVE_ENTRY_ACL_READ_ACL |
ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
ARCHIVE_ENTRY_ACL_READ_ACL |
ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
ARCHIVE_ENTRY_ACL_GROUP_OBJ, 0, "" },
{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
ARCHIVE_ENTRY_ACL_READ_DATA |
ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
ARCHIVE_ENTRY_ACL_READ_ACL |
ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
ARCHIVE_ENTRY_ACL_EVERYONE, 0, "" },
};
static struct archive_test_acl_t acls4[] = {
{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
ARCHIVE_ENTRY_ACL_READ_DATA |
ARCHIVE_ENTRY_ACL_WRITE_DATA |
ARCHIVE_ENTRY_ACL_APPEND_DATA |
ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES |
ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS |
ARCHIVE_ENTRY_ACL_READ_ACL |
ARCHIVE_ENTRY_ACL_WRITE_ACL |
ARCHIVE_ENTRY_ACL_WRITE_OWNER |
ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
ARCHIVE_ENTRY_ACL_USER_OBJ, 0, "" },
{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
ARCHIVE_ENTRY_ACL_READ_DATA |
ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
ARCHIVE_ENTRY_ACL_READ_ACL |
ARCHIVE_ENTRY_ACL_SYNCHRONIZE |
ARCHIVE_ENTRY_ACL_ENTRY_INHERITED,
ARCHIVE_ENTRY_ACL_USER, 77, "user77" },
{ ARCHIVE_ENTRY_ACL_TYPE_DENY,
ARCHIVE_ENTRY_ACL_READ_DATA |
ARCHIVE_ENTRY_ACL_WRITE_DATA |
ARCHIVE_ENTRY_ACL_EXECUTE,
ARCHIVE_ENTRY_ACL_USER, 78, "user78" },
{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
ARCHIVE_ENTRY_ACL_READ_DATA |
ARCHIVE_ENTRY_ACL_WRITE_DATA |
ARCHIVE_ENTRY_ACL_APPEND_DATA |
ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
ARCHIVE_ENTRY_ACL_READ_ACL |
ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
ARCHIVE_ENTRY_ACL_GROUP_OBJ, 0, "" },
{ ARCHIVE_ENTRY_ACL_TYPE_DENY,
ARCHIVE_ENTRY_ACL_WRITE_DATA |
ARCHIVE_ENTRY_ACL_APPEND_DATA |
ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES |
ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS |
ARCHIVE_ENTRY_ACL_WRITE_ACL |
ARCHIVE_ENTRY_ACL_WRITE_OWNER,
ARCHIVE_ENTRY_ACL_GROUP, 78, "group78" },
{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
ARCHIVE_ENTRY_ACL_READ_DATA |
ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
ARCHIVE_ENTRY_ACL_READ_ACL |
ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
ARCHIVE_ENTRY_ACL_EVERYONE, 0, "" },
};
static struct archive_test_acl_t acls5[] = {
{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
ARCHIVE_ENTRY_ACL_READ_DATA |
ARCHIVE_ENTRY_ACL_WRITE_DATA |
ARCHIVE_ENTRY_ACL_EXECUTE |
ARCHIVE_ENTRY_ACL_APPEND_DATA |
ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES |
ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS |
ARCHIVE_ENTRY_ACL_READ_ACL |
ARCHIVE_ENTRY_ACL_WRITE_ACL |
ARCHIVE_ENTRY_ACL_WRITE_OWNER |
ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
ARCHIVE_ENTRY_ACL_USER_OBJ, 0, "" },
{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
ARCHIVE_ENTRY_ACL_READ_DATA |
ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
ARCHIVE_ENTRY_ACL_READ_ACL |
ARCHIVE_ENTRY_ACL_SYNCHRONIZE |
ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT |
ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT,
ARCHIVE_ENTRY_ACL_USER, 77, "user77" },
{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
ARCHIVE_ENTRY_ACL_READ_DATA |
ARCHIVE_ENTRY_ACL_WRITE_DATA |
ARCHIVE_ENTRY_ACL_EXECUTE |
ARCHIVE_ENTRY_ACL_APPEND_DATA |
ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES |
ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS |
ARCHIVE_ENTRY_ACL_READ_ACL |
ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
ARCHIVE_ENTRY_ACL_GROUP_OBJ, 0, "" },
{ ARCHIVE_ENTRY_ACL_TYPE_DENY,
ARCHIVE_ENTRY_ACL_READ_DATA |
ARCHIVE_ENTRY_ACL_WRITE_DATA |
ARCHIVE_ENTRY_ACL_APPEND_DATA |
ARCHIVE_ENTRY_ACL_EXECUTE |
ARCHIVE_ENTRY_ACL_DELETE |
ARCHIVE_ENTRY_ACL_DELETE_CHILD |
ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES |
ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS |
ARCHIVE_ENTRY_ACL_READ_ACL |
ARCHIVE_ENTRY_ACL_WRITE_ACL |
ARCHIVE_ENTRY_ACL_WRITE_OWNER |
ARCHIVE_ENTRY_ACL_SYNCHRONIZE |
ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT |
ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT,
ARCHIVE_ENTRY_ACL_GROUP, 78, "group78" },
{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
ARCHIVE_ENTRY_ACL_READ_DATA |
ARCHIVE_ENTRY_ACL_EXECUTE |
ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
ARCHIVE_ENTRY_ACL_READ_ACL |
ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
ARCHIVE_ENTRY_ACL_EVERYONE, 0, "" },
};
DEFINE_TEST(test_compat_star_acl_posix1e)
{
char name[] = "test_compat_star_acl_posix1e.tar";
struct archive *a;
struct archive_entry *ae;
/* Read archive file */
assert(NULL != (a = archive_read_new()));
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
extract_reference_file(name);
assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name,
10240));
/* First item has a few ACLs */
assertA(0 == archive_read_next_header(a, &ae));
failure("One extended ACL should flag all ACLs to be returned.");
assertEqualInt(5, archive_entry_acl_reset(ae,
ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
archive_test_compare_acls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]),
ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0142);
failure("Basic ACLs should set mode to 0142, not %04o",
archive_entry_mode(ae)&0777);
assert((archive_entry_mode(ae) & 0777) == 0142);
/* Second item has pretty extensive ACLs */
assertA(0 == archive_read_next_header(a, &ae));
assertEqualInt(7, archive_entry_acl_reset(ae,
ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
archive_test_compare_acls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]),
ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0543);
failure("Basic ACLs should set mode to 0543, not %04o",
archive_entry_mode(ae)&0777);
assert((archive_entry_mode(ae) & 0777) == 0543);
/* Third item has default ACLs */
assertA(0 == archive_read_next_header(a, &ae));
assertEqualInt(6, archive_entry_acl_reset(ae,
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT));
archive_test_compare_acls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]),
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, 0142);
failure("Basic ACLs should set mode to 0142, not %04o",
archive_entry_mode(ae)&0777);
assert((archive_entry_mode(ae) & 0777) == 0142);
/* Close the archive. */
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
}
DEFINE_TEST(test_compat_star_acl_nfs4)
{
char name[] = "test_compat_star_acl_nfs4.tar";
struct archive *a;
struct archive_entry *ae;
/* Read archive file */
assert(NULL != (a = archive_read_new()));
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
extract_reference_file(name);
assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 10240
));
/* First item has NFS4 ACLs mirroring file mode */
assertA(0 == archive_read_next_header(a, &ae));
assertEqualInt(3, archive_entry_acl_reset(ae,
ARCHIVE_ENTRY_ACL_TYPE_ALLOW));
archive_test_compare_acls(ae, acls3, sizeof(acls3)/sizeof(acls3[0]),
ARCHIVE_ENTRY_ACL_TYPE_ALLOW, 0);
/* Second item has has fine-grained NFS4 ACLs */
assertA(0 == archive_read_next_header(a, &ae));
assertEqualInt(6, archive_entry_acl_reset(ae,
ARCHIVE_ENTRY_ACL_TYPE_NFS4));
archive_test_compare_acls(ae, acls4, sizeof(acls4)/sizeof(acls0[4]),
ARCHIVE_ENTRY_ACL_TYPE_NFS4, 0);
/* Third item has file and directory inheritance NFS4 ACLs */
assertA(0 == archive_read_next_header(a, &ae));
assertEqualInt(5, archive_entry_acl_reset(ae,
ARCHIVE_ENTRY_ACL_TYPE_NFS4));
archive_test_compare_acls(ae, acls5, sizeof(acls5)/sizeof(acls5[0]),
ARCHIVE_ENTRY_ACL_TYPE_NFS4, 0);
/* Close the archive. */
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
}

View File

@ -0,0 +1,231 @@
begin 644 test_compat_star_acl_nfs4.tar
M+B\N+T!087A(96%D97(`````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````#`P,#`V,#`@,#`P,#`P,"`P,#`P,#`P(#`P,#`P,#`P,C<R
M(#`P,#`P,#`P,#`P(#`P,38P-S0@9P``````````````````````````````
M````````````````````````````````````````````````````````````
M``````````````````````````````````````````!U<W1A<@`P,')O;W0`
M````````````````````````````````````=VAE96P`````````````````
M```````````````````P,#`P,#`P(#`P,#`P,#`@````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M```````````````````````````````````P,#`P,#`P,#`P,"`P,#`P,#`P
M,#`P,"`````````````````U-R!30TA)3%DN<F5L96%S93US=&%R(#$N-2XS
M("AA;60V-"UU;FMN;W=N+69R965B<V0Q,2XP*0HR-R!30TA)3%DN87)C:'1Y
M<&4]97AU<W1A<@HT-R!30TA)3%DN=F]L:&1R+F1U;7!D871E/3$T-SDQ-C<W
M,C<N,38W,C(U,C@Q"C(U(%-#2$E,62YV;VQH9'(N=F]L;F\],0HS,"!30TA)
M3%DN=F]L:&1R+F)L;V-K<VEZ93TR,`H`````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````````````````````````````````````"XO+B]`4&%X2&5A
M9&5R````````````````````````````````````````````````````````
M```````````````````````````````````````````````````````````P
M,#`P-C`P(#`P,#`P,#`@,#`P,#`P,"`P,#`P,#`P,#,S-"`P,#`P,#`P,#`P
M,"`P,#$V,3$T('@`````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````=7-T87(`,#!R;V]T````````````````
M`````````````````````'=H965L````````````````````````````````
M````,#`P,#`P,"`P,#`P,#`P(```````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````,#`P,#`P,#`P,#`@,#`P,#`P,#`P,#`@````````
M````````,S`@871I;64],30W.3$Q.34U-"XP-#,U-#DP,#`*,S`@8W1I;64]
M,30W.3$Q.3DQ,BXY,SDQ-C@P,#`*,S`@;71I;64],30W.3$Q.34U-"XP-#,U
M-#DP,#`*,3,P(%-#2$E,62YA8VPN86-E/6]W;F5R0#IR=WAP+2UA05)78T-O
M<SHM+2TM+2TM.F%L;&]W+&=R;W5P0#IR=RUP+2UA+5(M8RTM<SHM+2TM+2TM
M.F%L;&]W+&5V97)Y;VYE0#IR+2TM+2UA+5(M8RTM<SHM+2TM+2TM.F%L;&]W
M"@``````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M``````````````````````````````!F:6QE,0``````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````,#`P,#<V-"`P,#`P
M,#`P(#`P,#`P,#`@,#`P,#`P,#`P,#`@,3,P,3(S,3$S,#(@,#`Q-#8S-B`P
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````'5S=&%R`#`P<F]O=```````````````````````````````
M``````!W:&5E;````````````````````````````````````#`P,#`P,#`@
M,#`P,#`P,"``````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````#$S,#$R,S$Q,S`R(#$S,#$R,S$R,#4P(````````````````"XO+B]`
M4&%X2&5A9&5R````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M```````P,#`P-C`P(#`P,#`P,#`@,#`P,#`P,"`P,#`P,#`P,#4T,"`P,#`P
M,#`P,#`P,"`P,#$V,3$S('@`````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````=7-T87(`,#!R;V]T````````
M`````````````````````````````'=H965L````````````````````````
M````````````,#`P,#`P,"`P,#`P,#`P(```````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````,#`P,#`P,#`P,#`@,#`P,#`P,#`P,#`@
M````````````````,S`@871I;64],30W.3$Q.34U-2XR-C<P,3@P,#`*,S`@
M8W1I;64],30W.3$V,34Y."XY,SDV-#8P,#`*,S`@;71I;64],30W.3$Q.34U
M-2XR-C<P,3@P,#`*,C8R(%-#2$E,62YA8VPN86-E/75S97(Z=7-E<C<X.G)W
M>"TM+2TM+2TM+2TM.BTM+2TM+2TZ9&5N>3HW."QG<F]U<#IG<F]U<#<X.BUW
M+7`M+2U!+5<M0V\M.BTM+2TM+2TZ9&5N>3HW."QU<V5R.G5S97(W-SIR+2TM
M+2UA+5(M8RTM<SHM+2TM+2U).F%L;&]W.C<W+&]W;F5R0#IR=RUP+2UA05)7
M8T-O<SHM+2TM+2TM.F%L;&]W+&=R;W5P0#IR=RUP+2UA+5(M8RTM<SHM+2TM
M+2TM.F%L;&]W+&5V97)Y;VYE0#IR+2TM+2UA+5(M8RTM<SHM+2TM+2TM.F%L
M;&]W"@``````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M``````````````````````````````````````!F:6QE,@``````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````,#`P,#8V
M-"`P,#`P,#`P(#`P,#`P,#`@,#`P,#`P,#`P,#`@,3,P,3(S,3$S,#,@,#`Q
M-#8U-R`P````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````````````'5S=&%R`#`P<F]O=```````````````````````
M``````````````!W:&5E;````````````````````````````````````#`P
M,#`P,#`@,#`P,#`P,"``````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````#$S,#$R,S$Q,S`S(#$S,#$R-#,S,S<V(```````````````
M`"XO+B]`4&%X2&5A9&5R````````````````````````````````````````
M````````````````````````````````````````````````````````````
M```````````````P,#`P-C`P(#`P,#`P,#`@,#`P,#`P,"`P,#`P,#`P,#0V
M-2`P,#`P,#`P,#`P,"`P,#$V,3(Q('@`````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````=7-T87(`,#!R;V]T
M`````````````````````````````````````'=H965L````````````````
M````````````````````,#`P,#`P,"`P,#`P,#`P(```````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````,#`P,#`P,#`P,#`@,#`P,#`P
M,#`P,#`@````````````````,S`@871I;64],30W.3$V-S0Y-2XV.#<X-C8P
M,#`*,S`@8W1I;64],30W.3$V-S<R,RXT-#`X-C<P,#`*,S`@;71I;64],30W
M.3$R,#8W."XT-#$U.#`P,#`*,C$Y(%-#2$E,62YA8VPN86-E/6=R;W5P.F=R
M;W5P-S@Z<G=X<$1D84%25V-#;W,Z9F0M+2TM+3ID96YY.C<X+'5S97(Z=7-E
M<C<W.G(M+2TM+6$M4BUC+2US.F9D+2TM+2TZ86QL;W<Z-S<L;W=N97)`.G)W
M>'`M+6%!4E=C0V]S.BTM+2TM+2TZ86QL;W<L9W)O=7!`.G)W>'`M+6%!4E=C
M+2US.BTM+2TM+2TZ86QL;W<L979E<GEO;F5`.G(M>"TM+6$M4BUC+2US.BTM
M+2TM+2TZ86QL;W<*````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M``````````````````````````````````````````````!D:7(Q+P``````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M,#`P,#<W-2`P,#`P,#`P(#`P,#`P,#`@,#`P,#`P,#`P,#`@,3,P,3(S,3,T
M-#8@,#`Q-#8S,2`U````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````````````````````'5S=&%R`#`P<F]O=```````````````
M``````````````````````!W:&5E;```````````````````````````````
M`````#`P,#`P,#`@,#`P,#`P,"``````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````````````#$S,#$R-#0W,#`W(#$S,#$R-#0W,S4S(```````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
9````````````````````````````````````
`
end

View File

@ -1,215 +0,0 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test.h"
__FBSDID("$FreeBSD$");
/*
* Verify reading entries with POSIX.1e ACLs from archives created by star
*
* This should work on all systems, regardless of whether local filesystems
* support ACLs or not.
*/
struct acl_t {
int type; /* Type of ACL: "access" or "default" */
int permset; /* Permissions for this class of users. */
int tag; /* Owner, User, Owning group, group, other, etc. */
const char *name; /* Name of user/group, depending on tag. */
};
static struct acl_t acls0[] = {
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE,
ARCHIVE_ENTRY_ACL_USER_OBJ, "" },
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ,
ARCHIVE_ENTRY_ACL_USER, "user77" },
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ,
ARCHIVE_ENTRY_ACL_GROUP_OBJ, "" },
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ,
ARCHIVE_ENTRY_ACL_MASK, ""},
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_WRITE,
ARCHIVE_ENTRY_ACL_OTHER, "" },
};
static struct acl_t acls1[] = {
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE | ARCHIVE_ENTRY_ACL_READ,
ARCHIVE_ENTRY_ACL_USER_OBJ, "" },
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ,
ARCHIVE_ENTRY_ACL_USER, "user77" },
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0,
ARCHIVE_ENTRY_ACL_USER, "user78" },
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ,
ARCHIVE_ENTRY_ACL_GROUP_OBJ, "" },
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0007,
ARCHIVE_ENTRY_ACL_GROUP, "group78" },
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0007,
ARCHIVE_ENTRY_ACL_MASK, ""},
{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_WRITE | ARCHIVE_ENTRY_ACL_EXECUTE,
ARCHIVE_ENTRY_ACL_OTHER, "" },
};
static struct acl_t acls2[] = {
{ ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, ARCHIVE_ENTRY_ACL_EXECUTE,
ARCHIVE_ENTRY_ACL_USER_OBJ, "" },
{ ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, ARCHIVE_ENTRY_ACL_READ,
ARCHIVE_ENTRY_ACL_USER, "user77" },
{ ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, ARCHIVE_ENTRY_ACL_READ,
ARCHIVE_ENTRY_ACL_GROUP_OBJ, "" },
{ ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, ARCHIVE_ENTRY_ACL_EXECUTE,
ARCHIVE_ENTRY_ACL_GROUP, "group78" },
{ ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, ARCHIVE_ENTRY_ACL_READ | ARCHIVE_ENTRY_ACL_EXECUTE,
ARCHIVE_ENTRY_ACL_MASK, ""},
{ ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, ARCHIVE_ENTRY_ACL_WRITE,
ARCHIVE_ENTRY_ACL_OTHER, "" },
};
static int
acl_match(struct acl_t *acl, int type, int permset, int tag, const char *name)
{
if (type != acl->type)
return (0);
if (permset != acl->permset)
return (0);
if (tag != acl->tag)
return (0);
if (tag == ARCHIVE_ENTRY_ACL_USER_OBJ)
return (1);
if (tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ)
return (1);
if (tag == ARCHIVE_ENTRY_ACL_OTHER)
return (1);
if (tag == ARCHIVE_ENTRY_ACL_MASK)
return (1);
if (name == NULL)
return (acl->name == NULL || acl->name[0] == '\0');
if (acl->name == NULL)
return (name == NULL || name[0] == '\0');
return (0 == strcmp(name, acl->name));
}
static void
compare_acls(struct archive_entry *ae, struct acl_t *acls, int n, int mode,
int want_type)
{
int *marker = malloc(sizeof(marker[0]) * n);
int i;
int r;
int type, permset, tag, qual;
int matched;
const char *name;
for (i = 0; i < n; i++)
marker[i] = i;
while (0 == (r = archive_entry_acl_next(ae, want_type,
&type, &permset, &tag, &qual, &name))) {
for (i = 0, matched = 0; i < n && !matched; i++) {
if (acl_match(&acls[marker[i]], type, permset,
tag, name)) {
/* We found a match; remove it. */
marker[i] = marker[n - 1];
n--;
matched = 1;
}
}
if (tag == ARCHIVE_ENTRY_ACL_USER_OBJ) {
if (!matched) printf("No match for user_obj perm\n");
if (want_type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS) {
failure("USER_OBJ permset (%02o) != user mode (%02o)",
permset, 07 & (mode >> 6));
assert((permset << 6) == (mode & 0700));
}
} else if (tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ) {
if (!matched) printf("No match for group_obj perm\n");
if (want_type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS) {
failure("GROUP_OBJ permset %02o != group mode %02o",
permset, 07 & (mode >> 3));
assert((permset << 3) == (mode & 0070));
}
} else if (tag == ARCHIVE_ENTRY_ACL_OTHER) {
if (!matched) printf("No match for other perm\n");
if (want_type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS) {
failure("OTHER permset (%02o) != other mode (%02o)",
permset, mode & 07);
assert((permset << 0) == (mode & 0007));
}
} else if (tag != ARCHIVE_ENTRY_ACL_MASK) {
failure("Could not find match for ACL "
"(type=%d,permset=%d,tag=%d,name=``%s'')",
type, permset, tag, name);
assert(matched == 1);
}
}
assertEqualInt(ARCHIVE_EOF, r);
assert((mode_t)(mode & 0777) == (archive_entry_mode(ae) & 0777));
failure("Could not find match for ACL "
"(type=%d,permset=%d,tag=%d,name=``%s'')",
acls[marker[0]].type, acls[marker[0]].permset,
acls[marker[0]].tag, acls[marker[0]].name);
assert(n == 0); /* Number of ACLs not matched should == 0 */
free(marker);
}
DEFINE_TEST(test_compat_star_acl_posix1e)
{
char name[] = "test_compat_star_acl_posix1e.tar";
struct archive *a;
struct archive_entry *ae;
/* Read archive file */
assert(NULL != (a = archive_read_new()));
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
extract_reference_file(name);
assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 10240));
/* First item has a few ACLs */
assertA(0 == archive_read_next_header(a, &ae));
failure("One extended ACL should flag all ACLs to be returned.");
assertEqualInt(5, archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
compare_acls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]), 0142, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
failure("Basic ACLs should set mode to 0142, not %04o",
archive_entry_mode(ae)&0777);
assert((archive_entry_mode(ae) & 0777) == 0142);
/* Second item has pretty extensive ACLs */
assertA(0 == archive_read_next_header(a, &ae));
assertEqualInt(7, archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
compare_acls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]), 0543, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
failure("Basic ACLs should set mode to 0543, not %04o",
archive_entry_mode(ae)&0777);
assert((archive_entry_mode(ae) & 0777) == 0543);
/* Third item has default ACLs */
assertA(0 == archive_read_next_header(a, &ae));
assertEqualInt(6, archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_DEFAULT));
compare_acls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]), 0142, ARCHIVE_ENTRY_ACL_TYPE_DEFAULT);
failure("Basic ACLs should set mode to 0142, not %04o",
archive_entry_mode(ae)&0777);
assert((archive_entry_mode(ae) & 0777) == 0142);
/* Close the archive. */
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
}

View File

@ -27,6 +27,7 @@ TESTS_SRCS= \
test_acl_nfs4.c \
test_acl_pax.c \
test_acl_posix1e.c \
test_acl_text.c \
test_archive_api_feature.c \
test_archive_clear_error.c \
test_archive_cmdline.c \
@ -75,7 +76,7 @@ TESTS_SRCS= \
test_compat_plexus_archiver_tar.c \
test_compat_solaris_tar_acl.c \
test_compat_solaris_pax_sparse.c \
test_compat_star_acl_posix1e.c \
test_compat_star_acl.c \
test_compat_tar_hardlink.c \
test_compat_uudecode.c \
test_compat_uudecode_large.c \
@ -317,9 +318,9 @@ list.h: ${TESTS_SRCS} Makefile
@mv ${.TARGET}.tmp ${.TARGET}
CLEANTESTS+= list.h list.h.tmp
${PACKAGE}FILES+= README
${PACKAGE}FILES+= test_acl_pax.tar.uu
${PACKAGE}FILES+= test_acl_pax_posix1e.tar.uu
${PACKAGE}FILES+= test_acl_pax_nfs4.tar.uu
${PACKAGE}FILES+= test_archive_string_conversion.txt.Z.uu
${PACKAGE}FILES+= test_compat_bzip2_1.tbz.uu
${PACKAGE}FILES+= test_compat_bzip2_2.tbz.uu
@ -356,6 +357,7 @@ ${PACKAGE}FILES+= test_compat_plexus_archiver_tar.tar.uu
${PACKAGE}FILES+= test_compat_solaris_pax_sparse_1.pax.Z.uu
${PACKAGE}FILES+= test_compat_solaris_pax_sparse_2.pax.Z.uu
${PACKAGE}FILES+= test_compat_solaris_tar_acl.tar.uu
${PACKAGE}FILES+= test_compat_star_acl_nfs4.tar.uu
${PACKAGE}FILES+= test_compat_star_acl_posix1e.tar.uu
${PACKAGE}FILES+= test_compat_tar_hardlink_1.tar.uu
${PACKAGE}FILES+= test_compat_uudecode_large.tar.Z.uu