]> git.ipfire.org Git - pakfire.git/commitdiff
builder: Add mount/umount to _pakfire to avoid calling /bin/mount
authorMichael Tremer <michael.tremer@ipfire.org>
Sat, 13 Feb 2021 14:18:06 +0000 (14:18 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Sat, 13 Feb 2021 14:18:06 +0000 (14:18 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/_pakfire/_pakfiremodule.c
src/pakfire/builder.py

index e3410f8fef570a7a7eb99228eb564d4d8a389bf6..d8ff7b8e25a83b7b4b56f9dd795f3f6bbe3bab91 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <libintl.h>
 #include <locale.h>
+#include <sys/mount.h>
 
 #include <solv/solver.h>
 
@@ -66,6 +67,50 @@ static PyObject* _pakfire_arch_supported_by_host(PyObject* self, PyObject* args)
        Py_RETURN_FALSE;
 }
 
+static PyObject* _pakfire_mount(PyObject* self, PyObject* args, PyObject* kwds) {
+       char* kwlist[] = {
+               "path",
+               "target",
+               "type",
+               "flags",
+               "options",
+               NULL,
+        };
+
+       const char* path = NULL;
+       const char* target = NULL;
+       const char* type = NULL;
+       int flags = 0;
+       const char* options = NULL;
+
+       if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss|zis", kwlist,
+                       &path, &target, &type, &flags, &options))
+               return NULL;
+
+       int r = mount(path, target, type, flags, options);
+       if (r) {
+               PyErr_SetFromErrno(PyExc_OSError);
+               return NULL;
+       }
+
+       Py_RETURN_NONE;
+}
+
+static PyObject* _pakfire_umount(PyObject* self, PyObject* args) {
+       const char* path = NULL;
+
+       if (!PyArg_ParseTuple(args, "s", &path))
+               return NULL;
+
+       int r = umount(path);
+       if (r) {
+               PyErr_SetFromErrno(PyExc_OSError);
+               return NULL;
+       }
+
+       Py_RETURN_NONE;
+}
+
 static PyMethodDef pakfireModuleMethods[] = {
        {"performance_index", (PyCFunction)performance_index, METH_VARARGS, NULL},
        {"version_compare", (PyCFunction)version_compare, METH_VARARGS, NULL},
@@ -73,6 +118,8 @@ static PyMethodDef pakfireModuleMethods[] = {
        {"sync", (PyCFunction)_sync, METH_NOARGS, NULL},
        {"native_arch", (PyCFunction)_pakfire_native_arch, METH_NOARGS, NULL },
        {"arch_supported_by_host", (PyCFunction)_pakfire_arch_supported_by_host, METH_VARARGS, NULL },
+       {"mount", (PyCFunction)_pakfire_mount, METH_VARARGS|METH_KEYWORDS, NULL },
+       {"umount", (PyCFunction)_pakfire_umount, METH_VARARGS, NULL },
        { NULL, NULL, 0, NULL }
 };
 
@@ -257,5 +304,30 @@ PyMODINIT_FUNC PyInit__pakfire(void) {
        PyDict_SetItemString(d, "SOLVER_FLAG_SPLITPROVIDES", Py_BuildValue("i", SOLVER_FLAG_SPLITPROVIDES));
        PyDict_SetItemString(d, "SOLVER_FLAG_IGNORE_RECOMMENDED", Py_BuildValue("i", SOLVER_FLAG_IGNORE_RECOMMENDED));
 
+       // Mount Flags
+       if (PyModule_AddIntConstant(module, "MS_NOATIME", MS_NOATIME))
+               return NULL;
+
+       if (PyModule_AddIntConstant(module, "MS_NODEV", MS_NODEV))
+               return NULL;
+
+       if (PyModule_AddIntConstant(module, "MS_NOEXEC", MS_NOEXEC))
+               return NULL;
+
+       if (PyModule_AddIntConstant(module, "MS_RDONLY", MS_RDONLY))
+               return NULL;
+
+       if (PyModule_AddIntConstant(module, "MS_RELATIME", MS_RELATIME))
+               return NULL;
+
+       if (PyModule_AddIntConstant(module, "MS_STRICTATIME", MS_STRICTATIME))
+               return NULL;
+
+       if (PyModule_AddIntConstant(module, "MS_BIND", MS_BIND))
+               return NULL;
+
+       if (PyModule_AddIntConstant(module, "MS_REMOUNT", MS_REMOUNT))
+               return NULL;
+
        return module;
 }
index b65018f69b5e97c00f4d1b21d3f5cc69babacf43..37d09ea7aa4c27e6e296b1a032f15b8a2ef2ba51 100644 (file)
@@ -38,7 +38,6 @@ from . import downloaders
 from . import logger
 from . import packages
 from . import repository
-from . import shell
 from . import util
 
 import logging
@@ -74,7 +73,7 @@ class Builder(object):
                # Settings array.
                self.settings = {
                        "enable_ccache"       : self.config.get_bool("builder", "use_ccache", True),
-                       "buildroot_tmpfs"     : self.config.get_bool("builder", "use_tmpfs", False),
+                       "buildroot_tmpfs"     : self.config.get_bool("builder", "use_tmpfs", True),
                }
 
                # Add settings from keyword arguments
@@ -102,15 +101,8 @@ class Builder(object):
        def __enter__(self):
                self.log.debug("Entering %s" % self.path)
 
-               # Mount the directories
-               try:
-                       self._mountall()
-               except OSError as e:
-                       if e.errno == 30: # Read-only FS
-                               raise BuildError("Buildroot is read-only: %s" % self.path)
-
-                       # Raise all other errors
-                       raise
+               # Mount the build environment
+               self._mount()
 
                # Setup domain name resolution in chroot
                self.setup_dns()
@@ -128,7 +120,7 @@ class Builder(object):
                self.cgroup = None
 
                # Umount the build environment
-               self._umountall()
+               self._umount()
 
                # Delete everything
                self._destroy()
@@ -174,61 +166,37 @@ class Builder(object):
                if os.path.exists(self.path):
                        util.rm(self.path)
 
-       @property
-       def mountpoints(self):
-               mountpoints = []
+       def _mount(self):
+               """
+                       Mounts the build environment
+               """
+               os.makedirs(self.path)
 
-               # Make root as a tmpfs if enabled.
+               # Mount ramdisk if enabled
                if self.settings.get("buildroot_tmpfs"):
-                       mountpoints += [
-                               ("pakfire_root", "/", "tmpfs", "defaults"),
-                       ]
+                       _pakfire.mount("pakfire_root", self.path, "tmpfs")
 
-               # If ccache support is requested, we bind mount the cache.
+               # Bind-mount the ccache if enabled
                if self.settings.get("enable_ccache"):
-                       # Create ccache cache directory if it does not exist.
                        if not os.path.exists(CCACHE_CACHE_DIR):
                                os.makedirs(CCACHE_CACHE_DIR)
 
-                       mountpoints += [
-                               (CCACHE_CACHE_DIR, "/var/cache/ccache", "bind", "bind"),
-                       ]
-
-               return mountpoints
-
-       def _mountall(self):
-               self.log.debug("Mounting environment")
-
-               for src, dest, fs, options in self.mountpoints:
-                       mountpoint = self.chrootPath(dest)
-                       if options:
-                               options = "-o %s" % options
-
-                       # Eventually create mountpoint directory
-                       if not os.path.exists(mountpoint):
-                               os.makedirs(mountpoint)
-
-                       self.execute_root("mount -n -t %s %s %s %s" % (fs, options, src, mountpoint), shell=True)
+                       os.makedirs("%s/var/cache/ccache" % self.path)
 
-       def _umountall(self):
-               self.log.debug("Umounting environment")
+                       _pakfire.mount(CCACHE_CACHE_DIR, "%s/var/cache/ccache" % self.path,
+                               flags=_pakfire.MS_BIND)
 
-               mountpoints = []
-               for src, dest, fs, options in reversed(self.mountpoints):
-                       dest = self.chrootPath(dest)
-
-                       if not dest in mountpoints:
-                               mountpoints.append(dest)
-
-               while mountpoints:
-                       for mp in mountpoints:
-                               try:
-                                       self.execute_root("umount -n %s" % mp, shell=True)
-                               except ShellEnvironmentError:
-                                       pass
+       def _umount(self):
+               """
+                       Umounts the build environment
+               """
+               mountpoints = (
+                       "%s/var/cache/ccache" % self.path,
+                       self.path,
+               )
 
-                               if not os.path.ismount(mp):
-                                       mountpoints.remove(mp)
+               for mp in mountpoints:
+                       _pakfire.umount(mp)
 
        def copyin(self, file_out, file_in):
                if file_in.startswith("/"):
@@ -288,15 +256,6 @@ class Builder(object):
                for i in ("/etc/resolv.conf", "/etc/hosts"):
                        self.copyin(i, i)
 
-       def execute_root(self, command, **kwargs):
-               """
-                       Executes the given command outside the build chroot.
-               """
-               shellenv = shell.ShellExecuteEnvironment(command, logger=self.log, **kwargs)
-               shellenv.execute()
-
-               return shellenv
-
 
 class BuilderContext(object):
        def __init__(self, builder):