1238909Smm/*- 2238909Smm * Copyright (c) 2003-2010 Tim Kientzle 3238909Smm * All rights reserved. 4238909Smm * 5238909Smm * Redistribution and use in source and binary forms, with or without 6238909Smm * modification, are permitted provided that the following conditions 7238909Smm * are met: 8238909Smm * 1. Redistributions of source code must retain the above copyright 9238909Smm * notice, this list of conditions and the following disclaimer 10238909Smm * in this position and unchanged. 11238909Smm * 2. Redistributions in binary form must reproduce the above copyright 12238909Smm * notice, this list of conditions and the following disclaimer in the 13238909Smm * documentation and/or other materials provided with the distribution. 14238909Smm * 15238909Smm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 16238909Smm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17238909Smm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18238909Smm * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 19238909Smm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20238909Smm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21238909Smm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22238909Smm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23238909Smm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24238909Smm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25238909Smm */ 26238909Smm 27238909Smm#include "archive_platform.h" 28238909Smm__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_disk.c 201159 2009-12-29 05:35:40Z kientzle $"); 29238909Smm 30238909Smm#ifdef HAVE_SYS_TYPES_H 31238909Smm#include <sys/types.h> 32238909Smm#endif 33238909Smm#ifdef HAVE_SYS_ACL_H 34238909Smm#define _ACL_PRIVATE /* For debugging */ 35238909Smm#include <sys/acl.h> 36238909Smm#endif 37238909Smm#ifdef HAVE_ERRNO_H 38238909Smm#include <errno.h> 39238909Smm#endif 40238909Smm 41238909Smm#include "archive.h" 42238909Smm#include "archive_entry.h" 43238909Smm#include "archive_acl_private.h" 44238909Smm#include "archive_write_disk_private.h" 45238909Smm 46248616Smm#if !defined(HAVE_POSIX_ACL) || !defined(ACL_TYPE_NFS4) 47238909Smm/* Default empty function body to satisfy mainline code. */ 48238909Smmint 49238909Smmarchive_write_disk_set_acls(struct archive *a, int fd, const char *name, 50238909Smm struct archive_acl *abstract_acl) 51238909Smm{ 52238909Smm (void)a; /* UNUSED */ 53238909Smm (void)fd; /* UNUSED */ 54238909Smm (void)name; /* UNUSED */ 55238909Smm (void)abstract_acl; /* UNUSED */ 56238909Smm return (ARCHIVE_OK); 57238909Smm} 58238909Smm 59238909Smm#else 60238909Smm 61238909Smmstatic int set_acl(struct archive *, int fd, const char *, 62238909Smm struct archive_acl *, 63238909Smm acl_type_t, int archive_entry_acl_type, const char *tn); 64238909Smm 65238909Smm/* 66238909Smm * XXX TODO: What about ACL types other than ACCESS and DEFAULT? 67238909Smm */ 68238909Smmint 69238909Smmarchive_write_disk_set_acls(struct archive *a, int fd, const char *name, 70238909Smm struct archive_acl *abstract_acl) 71238909Smm{ 72238909Smm int ret; 73238909Smm 74238909Smm if (archive_acl_count(abstract_acl, ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) > 0) { 75238909Smm ret = set_acl(a, fd, name, abstract_acl, ACL_TYPE_ACCESS, 76238909Smm ARCHIVE_ENTRY_ACL_TYPE_ACCESS, "access"); 77238909Smm if (ret != ARCHIVE_OK) 78238909Smm return (ret); 79238909Smm ret = set_acl(a, fd, name, abstract_acl, ACL_TYPE_DEFAULT, 80238909Smm ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default"); 81238909Smm return (ret); 82238909Smm } else if (archive_acl_count(abstract_acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4) > 0) { 83238909Smm ret = set_acl(a, fd, name, abstract_acl, ACL_TYPE_NFS4, 84238909Smm ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4"); 85238909Smm return (ret); 86238909Smm } else 87238909Smm return ARCHIVE_OK; 88238909Smm} 89238909Smm 90238909Smmstatic struct { 91238909Smm int archive_perm; 92238909Smm int platform_perm; 93238909Smm} acl_perm_map[] = { 94238909Smm {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE}, 95238909Smm {ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE}, 96238909Smm {ARCHIVE_ENTRY_ACL_READ, ACL_READ}, 97238909Smm {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA}, 98238909Smm {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY}, 99238909Smm {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA}, 100238909Smm {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE}, 101238909Smm {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA}, 102238909Smm {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY}, 103238909Smm {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS}, 104238909Smm {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS}, 105238909Smm {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD}, 106238909Smm {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES}, 107238909Smm {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES}, 108238909Smm {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE}, 109238909Smm {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_ACL}, 110238909Smm {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL}, 111238909Smm {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER}, 112238909Smm {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE} 113238909Smm}; 114238909Smm 115238909Smmstatic struct { 116238909Smm int archive_inherit; 117238909Smm int platform_inherit; 118238909Smm} acl_inherit_map[] = { 119238909Smm {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT}, 120238909Smm {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT}, 121238909Smm {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT}, 122238909Smm {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY} 123238909Smm}; 124238909Smm 125238909Smmstatic int 126238909Smmset_acl(struct archive *a, int fd, const char *name, 127238909Smm struct archive_acl *abstract_acl, 128238909Smm acl_type_t acl_type, int ae_requested_type, const char *tname) 129238909Smm{ 130238909Smm acl_t acl; 131238909Smm acl_entry_t acl_entry; 132238909Smm acl_permset_t acl_permset; 133238909Smm acl_flagset_t acl_flagset; 134238909Smm int ret; 135238909Smm int ae_type, ae_permset, ae_tag, ae_id; 136238909Smm uid_t ae_uid; 137238909Smm gid_t ae_gid; 138238909Smm const char *ae_name; 139238909Smm int entries; 140238909Smm int i; 141238909Smm 142238909Smm ret = ARCHIVE_OK; 143238909Smm entries = archive_acl_reset(abstract_acl, ae_requested_type); 144238909Smm if (entries == 0) 145238909Smm return (ARCHIVE_OK); 146238909Smm acl = acl_init(entries); 147238909Smm while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type, 148238909Smm &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) { 149238909Smm acl_create_entry(&acl, &acl_entry); 150238909Smm 151238909Smm switch (ae_tag) { 152238909Smm case ARCHIVE_ENTRY_ACL_USER: 153238909Smm acl_set_tag_type(acl_entry, ACL_USER); 154238909Smm ae_uid = archive_write_disk_uid(a, ae_name, ae_id); 155238909Smm acl_set_qualifier(acl_entry, &ae_uid); 156238909Smm break; 157238909Smm case ARCHIVE_ENTRY_ACL_GROUP: 158238909Smm acl_set_tag_type(acl_entry, ACL_GROUP); 159238909Smm ae_gid = archive_write_disk_gid(a, ae_name, ae_id); 160238909Smm acl_set_qualifier(acl_entry, &ae_gid); 161238909Smm break; 162238909Smm case ARCHIVE_ENTRY_ACL_USER_OBJ: 163238909Smm acl_set_tag_type(acl_entry, ACL_USER_OBJ); 164238909Smm break; 165238909Smm case ARCHIVE_ENTRY_ACL_GROUP_OBJ: 166238909Smm acl_set_tag_type(acl_entry, ACL_GROUP_OBJ); 167238909Smm break; 168238909Smm case ARCHIVE_ENTRY_ACL_MASK: 169238909Smm acl_set_tag_type(acl_entry, ACL_MASK); 170238909Smm break; 171238909Smm case ARCHIVE_ENTRY_ACL_OTHER: 172238909Smm acl_set_tag_type(acl_entry, ACL_OTHER); 173238909Smm break; 174238909Smm case ARCHIVE_ENTRY_ACL_EVERYONE: 175238909Smm acl_set_tag_type(acl_entry, ACL_EVERYONE); 176238909Smm break; 177238909Smm default: 178238909Smm /* XXX */ 179238909Smm break; 180238909Smm } 181238909Smm 182238909Smm switch (ae_type) { 183238909Smm case ARCHIVE_ENTRY_ACL_TYPE_ALLOW: 184238909Smm acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALLOW); 185238909Smm break; 186238909Smm case ARCHIVE_ENTRY_ACL_TYPE_DENY: 187238909Smm acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_DENY); 188238909Smm break; 189238909Smm case ARCHIVE_ENTRY_ACL_TYPE_AUDIT: 190238909Smm acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_AUDIT); 191238909Smm break; 192238909Smm case ARCHIVE_ENTRY_ACL_TYPE_ALARM: 193238909Smm acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALARM); 194238909Smm break; 195238909Smm case ARCHIVE_ENTRY_ACL_TYPE_ACCESS: 196238909Smm case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT: 197238909Smm // These don't translate directly into the system ACL. 198238909Smm break; 199238909Smm default: 200238909Smm // XXX error handling here. 201238909Smm break; 202238909Smm } 203238909Smm 204238909Smm acl_get_permset(acl_entry, &acl_permset); 205238909Smm acl_clear_perms(acl_permset); 206238909Smm 207238909Smm for (i = 0; i < (int)(sizeof(acl_perm_map) / sizeof(acl_perm_map[0])); ++i) { 208238909Smm if (ae_permset & acl_perm_map[i].archive_perm) 209238909Smm acl_add_perm(acl_permset, 210238909Smm acl_perm_map[i].platform_perm); 211238909Smm } 212238909Smm 213238909Smm acl_get_flagset_np(acl_entry, &acl_flagset); 214238909Smm acl_clear_flags_np(acl_flagset); 215238909Smm for (i = 0; i < (int)(sizeof(acl_inherit_map) / sizeof(acl_inherit_map[0])); ++i) { 216238909Smm if (ae_permset & acl_inherit_map[i].archive_inherit) 217238909Smm acl_add_flag_np(acl_flagset, 218238909Smm acl_inherit_map[i].platform_inherit); 219238909Smm } 220238909Smm } 221238909Smm 222238909Smm /* Try restoring the ACL through 'fd' if we can. */ 223238909Smm#if HAVE_ACL_SET_FD 224238909Smm if (fd >= 0 && acl_type == ACL_TYPE_ACCESS && acl_set_fd(fd, acl) == 0) 225238909Smm ret = ARCHIVE_OK; 226238909Smm else 227238909Smm#else 228238909Smm#if HAVE_ACL_SET_FD_NP 229238909Smm if (fd >= 0 && acl_set_fd_np(fd, acl, acl_type) == 0) 230238909Smm ret = ARCHIVE_OK; 231238909Smm else 232238909Smm#endif 233238909Smm#endif 234238909Smm#if HAVE_ACL_SET_LINK_NP 235238909Smm if (acl_set_link_np(name, acl_type, acl) != 0) { 236238909Smm archive_set_error(a, errno, "Failed to set %s acl", tname); 237238909Smm ret = ARCHIVE_WARN; 238238909Smm } 239238909Smm#else 240238909Smm /* TODO: Skip this if 'name' is a symlink. */ 241238909Smm if (acl_set_file(name, acl_type, acl) != 0) { 242238909Smm archive_set_error(a, errno, "Failed to set %s acl", tname); 243238909Smm ret = ARCHIVE_WARN; 244238909Smm } 245238909Smm#endif 246238909Smm acl_free(acl); 247238909Smm return (ret); 248238909Smm} 249238909Smm#endif 250