]> git.ipfire.org Git - pakfire.git/commitdiff
Replace support for capabilities from pyxattr to libcap.
authorMichael Tremer <michael.tremer@ipfire.org>
Sat, 15 Oct 2011 13:50:19 +0000 (15:50 +0200)
committerMichael Tremer <michael.tremer@ipfire.org>
Sat, 15 Oct 2011 16:20:21 +0000 (18:20 +0200)
INSTALL
po/pakfire.pot
python/pakfire/packages/file.py
python/pakfire/packages/packager.py
python/pakfire/util.py
python/src/Makefile
python/src/_pakfiremodule.c
python/src/capabilities.c [new file with mode: 0644]
python/src/capabilities.h [new file with mode: 0644]

diff --git a/INSTALL b/INSTALL
index c234ed000f43e68253612f776131851186e4110d..0eb1dd6a4f3139072e341a2bfcf15c4add07029b 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -5,8 +5,8 @@ Requirements:
  * Python 2.6 or greater (not Python 3.x)
  * pyliblzma
  * python-progressbar
- * python-xattr
  * python-argsparse (included in Python 2.7)
+ * libcap
  * libsolv
 
 
index 00eb0e9e00296f29024361cd30fd2882cd952a12..655af5e14b38cdd7e2dc1ef8c28f58b7b68b81fe 100644 (file)
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2011-10-14 23:03+0200\n"
+"POT-Creation-Date: 2011-10-15 16:48+0200\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -349,7 +349,7 @@ msgid "Do not verify build dependencies."
 msgstr ""
 
 #: ../python/pakfire/compress.py:133
-#: ../python/pakfire/packages/packager.py:496
+#: ../python/pakfire/packages/packager.py:495
 #, python-format
 msgid "Compressing %s"
 msgstr ""
@@ -487,27 +487,27 @@ msgstr ""
 msgid "Config file saved as %s."
 msgstr ""
 
-#: ../python/pakfire/packages/file.py:111
+#: ../python/pakfire/packages/file.py:95
 #, python-format
 msgid "Could not extract file: /%(src)s - %(dst)s"
 msgstr ""
 
-#: ../python/pakfire/packages/file.py:164
+#: ../python/pakfire/packages/file.py:145
 #, python-format
 msgid "Filename: %s"
 msgstr ""
 
-#: ../python/pakfire/packages/file.py:278
+#: ../python/pakfire/packages/file.py:259
 #, python-format
 msgid "File in archive is missing in file metadata: /%s. Skipping."
 msgstr ""
 
-#: ../python/pakfire/packages/file.py:329
+#: ../python/pakfire/packages/file.py:310
 #, python-format
 msgid "Config file created as %s"
 msgstr ""
 
-#: ../python/pakfire/packages/file.py:343
+#: ../python/pakfire/packages/file.py:324
 #, python-format
 msgid "Could not remove file: /%s"
 msgstr ""
@@ -521,11 +521,11 @@ msgid "Package version is undefined."
 msgstr ""
 
 #. Load progressbar.
-#: ../python/pakfire/packages/packager.py:334
+#: ../python/pakfire/packages/packager.py:333
 msgid "Packaging"
 msgstr ""
 
-#: ../python/pakfire/packages/packager.py:622
+#: ../python/pakfire/packages/packager.py:621
 #, python-format
 msgid "Building source package %s:"
 msgstr ""
index a2bd88c04982a59a8945f25c30ebb1bb1d10d12b..26a4e2ed36001a737fc0d9129590ee05a9cf57f7 100644 (file)
@@ -26,7 +26,6 @@ import re
 import shutil
 import tarfile
 import tempfile
-import xattr
 
 import pakfire.filelist
 import pakfire.util as util
@@ -43,8 +42,6 @@ PAYLOAD_COMPRESSION_MAGIC = {
 }
 
 class InnerTarFile(tarfile.TarFile):
-       SUPPORTED_XATTRS = ("security.capability",)
-
        def __init__(self, *args, **kwargs):
                # Force the PAX format.
                kwargs["format"] = tarfile.PAX_FORMAT
@@ -53,31 +50,18 @@ class InnerTarFile(tarfile.TarFile):
 
        def add(self, name, arcname=None, recursive=None, exclude=None, filter=None):
                """
-                       Emulate the add function with xattrs support.
+                       Emulate the add function with capability support.
                """
                tarinfo = self.gettarinfo(name, arcname)
 
                if tarinfo.isreg():
                        attrs = []
 
-                       # Use new modules code...
-                       if hasattr(xattr, "get_all"):
-                               attrs = xattr.get_all(name)
-
-                       # ...or use the deprecated API.
-                       else:
-                               for attr in xattr.listxattr(name):
-                                       val = xattr.getxattr(name, attr)
-                                       attrs.append((attr, val))
-
-                       for attr, val in attrs:
-                               # Skip all attrs that are not supported (e.g. selinux).
-                               if not attr in self.SUPPORTED_XATTRS:
-                                       continue
-
-                               logging.debug("Saving xattr %s=%s from %s" % (attr, val, name))
-
-                               tarinfo.pax_headers[attr] = val
+                       # Save capabilities.
+                       caps = util.get_capabilities(name)
+                       if caps:
+                               logging.debug("Saving capabilities for %s: %s" % (name, caps))
+                               tarinfo.pax_headers["PAKFIRE.capabilities"] = caps
 
                # Append the tar header and data to the archive.
                        f = tarfile.bltn_open(name, "rb")
@@ -111,19 +95,16 @@ class InnerTarFile(tarfile.TarFile):
                        logging.warning(_("Could not extract file: /%(src)s - %(dst)s") \
                                % { "src" : member.name, "dst" : e, })
 
-               # ...and then apply the extended attributes.
-               if member.pax_headers:
-                       for attr, val in member.pax_headers.items():
-                               # Skip all attrs that are not supported (e.g. selinux).
-                               if not attr in self.SUPPORTED_XATTRS:
-                                       continue
-
-                               logging.debug("Restoring xattr %s=%s to %s" % (attr, val, target))
-                               if hasattr(xattr, "set"):
-                                       xattr.set(target, attr, val)
+               if path:
+                       target = os.path.join(path, member.name)
+               else:
+                       target = "/%s" % member.name
 
-                               else:
-                                       xattr.setxattr(target, attr, val)
+               # ...and then apply the capabilities.
+               caps = member.pax_headers.get("PAKFIRE.capabilities", None)
+               if caps:
+                       logging.debug("Restoring capabilities for /%s: %s" % (member.name, caps))
+                       util.set_capabilities(target, caps)
 
 
 class FilePackage(Package):
index 9a4b658aafd8ccb87000334e5861b9e5c465128f..57273c09245ae62610416167bfc1d9c0f9145d7e 100644 (file)
@@ -34,7 +34,6 @@ import tarfile
 import tempfile
 import time
 import uuid
-import xattr
 import zlib
 
 import pakfire.compress
index 7d1690ab55d9c5c831b3cd437101cf784bdb88f8..58c34a2abc9177c18103d0e8610d6f641de83a55 100644 (file)
@@ -39,8 +39,8 @@ import time
 from constants import *
 from i18n import _
 
-# Import binary version of version_compare
-from _pakfire import version_compare
+# Import binary version of version_compare and capability functions
+from _pakfire import version_compare, get_capabilities, set_capabilities
 
 def cli_is_interactive():
        """
index 2e00626230874ec682a1f4764aaa7e882f0912ba..190bfc8476b84ef493775e15856aeab54fbd8631 100644 (file)
@@ -5,7 +5,7 @@ include ../../Makeconfig
 MODULENAME = _pakfire.so
 
 # Libs that are to be linked into the module.
-MODULELIBS = -lpython$(PYTHON_VERSION) -lsolv -lsolvext
+MODULELIBS = -lcap -lpython$(PYTHON_VERSION) -lsolv -lsolvext
 
 SOURCES = $(wildcard *.c)
 OBJECTS = $(patsubst %.c,%.o,$(SOURCES))
index 6e1870fed9c0ae0047b3b8a577cb9d9d109681a9..d5e63db4de1a86d9521c101568845ccb60feed0d 100644 (file)
@@ -20,6 +20,7 @@
 
 #include <Python.h>
 
+#include "capabilities.h"
 #include "config.h"
 #include "pool.h"
 #include "problem.h"
@@ -35,6 +36,8 @@
 
 static PyMethodDef pakfireModuleMethods[] = {
        {"version_compare", (PyCFunction)version_compare, METH_VARARGS, NULL},
+       {"get_capabilities", (PyCFunction)get_capabilities, METH_VARARGS, NULL},
+       {"set_capabilities", (PyCFunction)set_capabilities, METH_VARARGS, NULL},
        { NULL, NULL, 0, NULL }
 };
 
diff --git a/python/src/capabilities.c b/python/src/capabilities.c
new file mode 100644 (file)
index 0000000..c33607a
--- /dev/null
@@ -0,0 +1,104 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2011 Pakfire development team                                 #
+#                                                                             #
+# This program is free software: you can redistribute it and/or modify        #
+# it under the terms of the GNU General Public License as published by        #
+# the Free Software Foundation, either version 3 of the License, or           #
+# (at your option) any later version.                                         #
+#                                                                             #
+# This program is distributed in the hope that it will be useful,             #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of              #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               #
+# GNU General Public License for more details.                                #
+#                                                                             #
+# You should have received a copy of the GNU General Public License           #
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.       #
+#                                                                             #
+#############################################################################*/
+
+#include <Python.h>
+
+#include <errno.h>
+#include <sys/capability.h>
+
+#include "config.h"
+
+PyObject *
+get_capabilities(PyObject *self, PyObject *args) {
+       const char *filename;
+       cap_t cap_d;
+       char *exception = NULL;
+
+        if (!PyArg_ParseTuple(args, "s", &filename)) {
+                /* XXX raise exception */
+                return NULL;
+        }
+
+       cap_d = cap_get_file(filename);
+       if (cap_d == NULL) {
+               if (errno != ENODATA) {
+                       snprintf(exception, STRING_SIZE - 1, "Failed to get capabilities of file %s (%s).",
+                               filename, strerror(errno));
+                       PyErr_SetString(PyExc_RuntimeError, exception);
+                       return NULL;
+               }
+               Py_RETURN_NONE;
+       }
+
+       char *result = cap_to_text(cap_d, NULL);
+       cap_free(cap_d);
+
+       if (!result) {
+               snprintf(exception, STRING_SIZE - 1, "Failed to get capabilities of human readable format at %s (%s).",
+                       filename, strerror(errno));
+               PyErr_SetString(PyExc_RuntimeError, exception);
+               return NULL;
+       }
+
+       // Remove leading two characters '= '.
+       int i;
+       for (i = 0; i < 2; i++) {
+               result++;
+       }
+
+       PyObject * ret = Py_BuildValue("s", result);
+       cap_free(result);
+
+       return ret;
+}
+
+PyObject *
+set_capabilities(PyObject *self, PyObject *args) {
+       const char *filename;
+       const char *input;
+       char *exception = NULL;
+       char buf[STRING_SIZE];
+       cap_t cap_d;
+       int ret;
+
+       if (!PyArg_ParseTuple(args, "ss", &filename, &input)) {
+               /* XXX raise exception */
+               return NULL;
+       }
+
+       snprintf(buf, STRING_SIZE - 1, "= %s", input);
+       cap_d = cap_from_text(buf);
+       if (cap_d == NULL) {
+               PyErr_SetString(PyExc_ValueError, "Could not read capability string.");
+               return NULL;
+       }
+
+       ret = cap_set_file(filename, cap_d);
+       cap_free(cap_d);
+
+       if (ret != 0) {
+               snprintf(exception, STRING_SIZE - 1, "Failed to set capabilities on file %s (%s).",
+                       filename, strerror(errno));
+               PyErr_SetString(PyExc_RuntimeError, exception);
+               return NULL;
+       }
+
+       return Py_BuildValue("i", ret);
+}
diff --git a/python/src/capabilities.h b/python/src/capabilities.h
new file mode 100644 (file)
index 0000000..8f820cd
--- /dev/null
@@ -0,0 +1,29 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2011 Pakfire development team                                 #
+#                                                                             #
+# This program is free software: you can redistribute it and/or modify        #
+# it under the terms of the GNU General Public License as published by        #
+# the Free Software Foundation, either version 3 of the License, or           #
+# (at your option) any later version.                                         #
+#                                                                             #
+# This program is distributed in the hope that it will be useful,             #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of              #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               #
+# GNU General Public License for more details.                                #
+#                                                                             #
+# You should have received a copy of the GNU General Public License           #
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.       #
+#                                                                             #
+#############################################################################*/
+
+#ifndef PAKFIRE_CAPS_H
+#define PAKFIRE_CAPS_H
+
+#include <Python.h>
+
+extern PyObject *get_capabilities(PyObject *self, PyObject *args);
+extern PyObject *set_capabilities(PyObject *self, PyObject *args);
+
+#endif