static void preserve_fd_acls(int source_fd, int dest_fd, const char *source_path, const char *dest_path) { acl_t acl; acl_type_t acl_type; int acl_supported = 0, ret, trivial; ret = fpathconf(source_fd, _PC_ACL_NFS4); if (ret > 0 ) { acl_supported = 1; acl_type = ACL_TYPE_NFS4; } else if (ret < 0 && errno != EINVAL) { warn("fpathconf(..., _PC_ACL_NFS4) failed for %s", source_path); return; } if (acl_supported == 0) { ret = fpathconf(source_fd, _PC_ACL_EXTENDED); if (ret > 0 ) { acl_supported = 1; acl_type = ACL_TYPE_ACCESS; } else if (ret < 0 && errno != EINVAL) { warn("fpathconf(..., _PC_ACL_EXTENDED) failed for %s", source_path); return; } } if (acl_supported == 0) return; acl = acl_get_fd_np(source_fd, acl_type); if (acl == NULL) { warn("failed to get acl entries for %s", source_path); return; } if (acl_is_trivial_np(acl, &trivial)) { warn("acl_is_trivial() failed for %s", source_path); acl_free(acl); return; } if (trivial) { acl_free(acl); return; } if (acl_set_fd_np(dest_fd, acl, acl_type) < 0) { warn("failed to set acl entries for %s", dest_path); acl_free(acl); return; } acl_free(acl); }
/* * Add a + after the standard rwxrwxrwx mode if the file has an * ACL. strmode() reserves space at the end of the string. */ static void aclmode(char *buf, const FTSENT *p) { char name[MAXPATHLEN + 1]; int ret, trivial; static dev_t previous_dev = NODEV; static int supports_acls = -1; static int type = ACL_TYPE_ACCESS; acl_t facl; /* * XXX: ACLs are not supported on whiteouts and device files * residing on UFS. */ if (S_ISCHR(p->fts_statp->st_mode) || S_ISBLK(p->fts_statp->st_mode) || S_ISWHT(p->fts_statp->st_mode)) return; if (previous_dev == p->fts_statp->st_dev && supports_acls == 0) return; if (p->fts_level == FTS_ROOTLEVEL) snprintf(name, sizeof(name), "%s", p->fts_name); else snprintf(name, sizeof(name), "%s/%s", p->fts_parent->fts_accpath, p->fts_name); if (previous_dev != p->fts_statp->st_dev) { previous_dev = p->fts_statp->st_dev; supports_acls = 0; ret = lpathconf(name, _PC_ACL_NFS4); if (ret > 0) { type = ACL_TYPE_NFS4; supports_acls = 1; } else if (ret < 0 && errno != EINVAL) { xo_warn("%s", name); return; } if (supports_acls == 0) { ret = lpathconf(name, _PC_ACL_EXTENDED); if (ret > 0) { type = ACL_TYPE_ACCESS; supports_acls = 1; } else if (ret < 0 && errno != EINVAL) { xo_warn("%s", name); return; } } } if (supports_acls == 0) return; facl = acl_get_link_np(name, type); if (facl == NULL) { xo_warn("%s", name); return; } if (acl_is_trivial_np(facl, &trivial)) { acl_free(facl); xo_warn("%s", name); return; } if (!trivial) buf[10] = '+'; acl_free(facl); }
static int setup_acls(struct archive_read_disk *a, struct archive_entry *entry, int *fd) { const char *accpath; acl_t acl; #if HAVE_ACL_IS_TRIVIAL_NP int r; #endif accpath = archive_entry_sourcepath(entry); if (accpath == NULL) accpath = archive_entry_pathname(entry); archive_entry_acl_clear(entry); /* Try NFS4 ACL first. */ if (*fd >= 0) acl = acl_get_fd(*fd); #if HAVE_ACL_GET_LINK_NP else if (!a->follow_symlinks) acl = acl_get_link_np(accpath, ACL_TYPE_NFS4); #else else if ((!a->follow_symlinks) && (archive_entry_filetype(entry) == AE_IFLNK)) /* We can't get the ACL of a symlink, so we assume it can't have one. */ acl = NULL; #endif else acl = acl_get_file(accpath, ACL_TYPE_NFS4); #if HAVE_ACL_IS_TRIVIAL_NP /* Ignore "trivial" ACLs that just mirror the file mode. */ acl_is_trivial_np(acl, &r); if (r) { acl_free(acl); acl = NULL; } #endif if (acl != NULL) { translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4); acl_free(acl); return (ARCHIVE_OK); } /* Retrieve access ACL from file. */ if (*fd >= 0) acl = acl_get_fd(*fd); #if HAVE_ACL_GET_LINK_NP else if (!a->follow_symlinks) acl = acl_get_link_np(accpath, ACL_TYPE_ACCESS); #else else if ((!a->follow_symlinks) && (archive_entry_filetype(entry) == AE_IFLNK)) /* We can't get the ACL of a symlink, so we assume it can't have one. */ acl = NULL; #endif else acl = acl_get_file(accpath, ACL_TYPE_ACCESS); if (acl != NULL) { translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_ACCESS); acl_free(acl); } /* Only directories can have default ACLs. */ if (S_ISDIR(archive_entry_mode(entry))) { acl = acl_get_file(accpath, ACL_TYPE_DEFAULT); if (acl != NULL) { translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_DEFAULT); acl_free(acl); } } return (ARCHIVE_OK); }
int preserve_dir_acls(struct stat *fs, char *source_dir, char *dest_dir) { acl_t (*aclgetf)(const char *, acl_type_t); int (*aclsetf)(const char *, acl_type_t, acl_t); struct acl *aclp; acl_t acl; acl_type_t acl_type; int acl_supported = 0, ret, trivial; ret = pathconf(source_dir, _PC_ACL_NFS4); if (ret > 0) { acl_supported = 1; acl_type = ACL_TYPE_NFS4; } else if (ret < 0 && errno != EINVAL) { warn("fpathconf(..., _PC_ACL_NFS4) failed for %s", source_dir); return (1); } if (acl_supported == 0) { ret = pathconf(source_dir, _PC_ACL_EXTENDED); if (ret > 0) { acl_supported = 1; acl_type = ACL_TYPE_ACCESS; } else if (ret < 0 && errno != EINVAL) { warn("fpathconf(..., _PC_ACL_EXTENDED) failed for %s", source_dir); return (1); } } if (acl_supported == 0) return (0); /* * If the file is a link we will not follow it */ if (S_ISLNK(fs->st_mode)) { aclgetf = acl_get_link_np; aclsetf = acl_set_link_np; } else { aclgetf = acl_get_file; aclsetf = acl_set_file; } if (acl_type == ACL_TYPE_ACCESS) { /* * Even if there is no ACL_TYPE_DEFAULT entry here, a zero * size ACL will be returned. So it is not safe to simply * check the pointer to see if the default ACL is present. */ acl = aclgetf(source_dir, ACL_TYPE_DEFAULT); if (acl == NULL) { warn("failed to get default acl entries on %s", source_dir); return (1); } aclp = &acl->ats_acl; if (aclp->acl_cnt != 0 && aclsetf(dest_dir, ACL_TYPE_DEFAULT, acl) < 0) { warn("failed to set default acl entries on %s", dest_dir); acl_free(acl); return (1); } acl_free(acl); } acl = aclgetf(source_dir, acl_type); if (acl == NULL) { warn("failed to get acl entries on %s", source_dir); return (1); } if (acl_is_trivial_np(acl, &trivial)) { warn("acl_is_trivial() failed on %s", source_dir); acl_free(acl); return (1); } if (trivial) { acl_free(acl); return (0); } if (aclsetf(dest_dir, acl_type, acl) < 0) { warn("failed to set acl entries on %s", dest_dir); acl_free(acl); return (1); } acl_free(acl); return (0); }
int preserve_dir_acls(struct stat *fs, char *source_dir, char *dest_dir) { acl_t (*aclgetf)(const char *, acl_type_t); int (*aclsetf)(const char *, acl_type_t, acl_t); struct acl *aclp; acl_t acl; acl_type_t acl_type; int acl_supported = 0, ret, trivial; ret = pathconf(source_dir, _PC_ACL_NFS4); if (ret > 0) { acl_supported = 1; acl_type = ACL_TYPE_NFS4; } else if (ret < 0 && errno != EINVAL) { warn("fpathconf(..., _PC_ACL_NFS4) failed for %s", source_dir); return (1); } if (acl_supported == 0) { ret = pathconf(source_dir, _PC_ACL_EXTENDED); if (ret > 0) { acl_supported = 1; acl_type = ACL_TYPE_ACCESS; } else if (ret < 0 && errno != EINVAL) { warn("fpathconf(..., _PC_ACL_EXTENDED) failed for %s", source_dir); return (1); } } if (acl_supported == 0) return (0); if (S_ISLNK(fs->st_mode)) { aclgetf = acl_get_link_np; aclsetf = acl_set_link_np; } else { aclgetf = acl_get_file; aclsetf = acl_set_file; } if (acl_type == ACL_TYPE_ACCESS) { acl = aclgetf(source_dir, ACL_TYPE_DEFAULT); if (acl == NULL) { warn("failed to get default acl entries on %s", source_dir); return (1); } aclp = &acl->ats_acl; if (aclp->acl_cnt != 0 && aclsetf(dest_dir, ACL_TYPE_DEFAULT, acl) < 0) { warn("failed to set default acl entries on %s", dest_dir); acl_free(acl); return (1); } acl_free(acl); } acl = aclgetf(source_dir, acl_type); if (acl == NULL) { warn("failed to get acl entries on %s", source_dir); return (1); } if (acl_is_trivial_np(acl, &trivial)) { warn("acl_is_trivial() failed on %s", source_dir); acl_free(acl); return (1); } if (trivial) { acl_free(acl); return (0); } if (aclsetf(dest_dir, acl_type, acl) < 0) { warn("failed to set acl entries on %s", dest_dir); acl_free(acl); return (1); } acl_free(acl); return (0); }