Skip to content

Instantly share code, notes, and snippets.

@lattera
Created July 4, 2020 13:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lattera/d0b4653bc5942dbcdcd1db877d37c2dc to your computer and use it in GitHub Desktop.
Save lattera/d0b4653bc5942dbcdcd1db877d37c2dc to your computer and use it in GitHub Desktop.
diff --git a/libpkg/Makefile.autosetup b/libpkg/Makefile.autosetup
index ae722976..77854f16 100644
--- a/libpkg/Makefile.autosetup
+++ b/libpkg/Makefile.autosetup
@@ -42,7 +42,8 @@ SRCS= backup.c \
pkg_repo_create.c \
pkg_version.c \
rcscripts.c \
- flags.c
+ flags.c \
+ extattr.c
LOCAL_CFLAGS= -I$(top_srcdir)/compat \
-I$(top_srcdir)/external/blake2 \
diff --git a/libpkg/extattr.c b/libpkg/extattr.c
new file mode 100644
index 00000000..00618787
--- /dev/null
+++ b/libpkg/extattr.c
@@ -0,0 +1,119 @@
+/*-
+ * Copyright (c) 2020 Shawn Webb <shawn.webb@hardenedbsd.org>
+ *
+ * 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
+ * in this position and unchanged.
+ * 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 <archive.h>
+#include <archive_entry.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <fts.h>
+#include <string.h>
+#include <pwd.h>
+#include <grp.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/extattr.h>
+
+#include "pkg.h"
+#include "private/event.h"
+#include "private/pkg.h"
+
+int
+pkg_archive_extattrs(int fd, struct archive_entry *entry)
+{
+ const char *nameprefix = "system.";
+ char *endp, *name, *names, *namep;
+ ssize_t datasize, listsize;
+ int err, namespace;
+ uint8_t namesize;
+ void *attrdata;
+
+ err = EPKG_OK;
+ attrdata = NULL;
+ names = NULL;
+
+ namespace = EXTATTR_NAMESPACE_SYSTEM;
+
+ listsize = extattr_list_fd(fd, namespace, NULL, 0);
+ if (listsize < 0) {
+ return (EPKG_OK);
+ }
+
+ if (listsize == 0) {
+ return (EPKG_OK);
+ }
+
+ names = calloc(listsize, 1);
+ if (names == NULL) {
+ return (EPKG_OK);
+ }
+
+ if (extattr_list_fd(fd, namespace, names, listsize) !=
+ listsize) {
+ goto end;
+ }
+ endp = names + (size_t)listsize;
+ for (namep = names; namep < endp; namep += namesize) {
+ namesize = *((uint8_t *)(namep));
+ name = calloc(strlen(nameprefix) + namesize+1, 1);
+ if (name == NULL) {
+ goto end;
+ }
+ namep += sizeof(uint8_t);
+ strcpy(name, nameprefix);
+ strncat(name, namep, namesize);
+
+ datasize = extattr_get_fd(fd, namespace, name+strlen(nameprefix), NULL, 0);
+ if (datasize < 0) {
+ free(name);
+ continue;
+ }
+
+ attrdata = calloc(1, (size_t)datasize);
+ if (attrdata == NULL) {
+ free(name);
+ goto end;
+ }
+
+ if (extattr_get_fd(fd, namespace, name+strlen(nameprefix), attrdata,
+ datasize) != datasize) {
+ perror("extattr_get_fd");
+ free(name);
+ free(attrdata);
+ goto end;
+ }
+
+ archive_entry_xattr_add_entry(entry, name, attrdata,
+ datasize);
+
+ free(name);
+ free(attrdata);
+ }
+
+end:
+ free(names);
+ return (EPKG_OK);
+}
diff --git a/libpkg/packing.c b/libpkg/packing.c
index 1e0e35b1..7424aa11 100644
--- a/libpkg/packing.c
+++ b/libpkg/packing.c
@@ -232,17 +232,21 @@ packing_append_file_attr(struct packing *pack, const char *filepath,
if (sparse_entry != NULL && entry == NULL)
entry = sparse_entry;
- archive_write_header(pack->awrite, entry);
-
- if (archive_entry_size(entry) <= 0)
- goto cleanup;
-
if ((fd = open(filepath, O_RDONLY)) < 0) {
pkg_emit_errno("open", filepath);
retcode = EPKG_FATAL;
goto cleanup;
}
+ pkg_archive_extattrs(fd, entry);
+
+ archive_write_header(pack->awrite, entry);
+
+ if (archive_entry_size(entry) <= 0) {
+ close(fd);
+ goto cleanup;
+ }
+
while ((len = read(fd, buf, sizeof(buf))) > 0) {
if (archive_write_data(pack->awrite, buf, len) == -1) {
pkg_emit_errno("archive_write_data", "archive write error");
diff --git a/libpkg/pkg_add.c b/libpkg/pkg_add.c
index a2170bdc..dbf04f1e 100644
--- a/libpkg/pkg_add.c
+++ b/libpkg/pkg_add.c
@@ -43,6 +43,9 @@
#include <time.h>
#include <utstring.h>
+#include <sys/types.h>
+#include <sys/extattr.h>
+
#include "pkg.h"
#include "private/event.h"
#include "private/utils.h"
@@ -526,6 +529,9 @@ create_regfile(struct pkg *pkg, struct pkg_file *f, struct archive *a,
bool tried_mkdir = false;
size_t len;
char buf[32768];
+ const char *attrname;
+ void *attrval;
+ size_t attrsz;
pkg_hidden_tempfile(f->temppath, sizeof(f->temppath), f->path);
@@ -572,6 +578,25 @@ retry:
}
}
+ if (archive_entry_xattr_reset(ae)) {
+ attrname = NULL;
+ attrval = NULL;
+ attrsz = 0;
+
+ while (archive_entry_xattr_next(ae, &attrname,
+ &attrval, &attrsz) == ARCHIVE_OK) {
+ assert(attrname != NULL);
+ assert(attrval != NULL);
+ assert(attrsz > 0);
+
+ if (!strncmp(attrname, "system.", 7)) {
+ extattr_set_fd(fd,
+ EXTATTR_NAMESPACE_SYSTEM,
+ attrname+7, attrval, attrsz);
+ }
+ }
+ }
+
if (!f->config && archive_read_data_into_fd(a, fd) != ARCHIVE_OK) {
pkg_emit_error("Fail to extract %s from package: %s",
f->path, archive_error_string(a));
diff --git a/libpkg/private/pkg.h b/libpkg/private/pkg.h
index e9021ed8..0826c515 100644
--- a/libpkg/private/pkg.h
+++ b/libpkg/private/pkg.h
@@ -881,4 +881,7 @@ struct pkg_dep* pkg_adddep_chain(struct pkg_dep *chain,
void backup_library(struct pkgdb *, struct pkg *, const char *);
int suggest_arch(struct pkg *, bool);
+/* Filesystem extended attribute support */
+int pkg_archive_extattrs(int, struct archive_entry *);
+
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment