# #
#############################################################################*/
+#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include <errno.h>
+#include <syslog.h>
#include <pakfire/archive.h>
#include <pakfire/build.h>
#include <pakfire/constants.h>
+#include <pakfire/ctx.h>
#include <pakfire/dist.h>
-#include <pakfire/execute.h>
+#include <pakfire/jail.h>
#include <pakfire/logging.h>
+#include <pakfire/mount.h>
#include <pakfire/packagelist.h>
#include <pakfire/pakfire.h>
#include <pakfire/key.h>
#include <pakfire/repo.h>
#include <pakfire/repolist.h>
-#include <pakfire/request.h>
+#include <pakfire/transaction.h>
#include <pakfire/util.h>
#include "archive.h"
+#include "ctx.h"
#include "errors.h"
#include "key.h"
#include "pakfire.h"
static PyObject* Pakfire_new(PyTypeObject* type, PyObject* args, PyObject* kwds) {
PakfireObject* self = (PakfireObject *)type->tp_alloc(type, 0);
if (self) {
+ self->ctx = NULL;
self->pakfire = NULL;
- self->logger = NULL;
}
return (PyObject *)self;
}
-static void Pakfire_logging_callback(void* data, int priority, const char* file, int line,
- const char* fn, const char* format, va_list args) {
- PyObject* callback = (PyObject*)data;
-
- // Do nothing if callback isn't set
- if (!callback)
- return;
-
- // Translate priority to Python logging priorities
- switch (priority) {
- case LOG_DEBUG:
- priority = 10;
- break;
-
- case LOG_INFO:
- priority = 20;
- break;
-
- case LOG_ERR:
- priority = 40;
- break;
-
- // Drop messages of an unknown priority
- default:
- return;
- }
-
- PyObject* tuple = NULL;
- PyObject* result = NULL;
- char* buffer = NULL;
+static int Pakfire_init(PakfireObject* self, PyObject* args, PyObject* kwds) {
+ char* kwlist[] = {
+ "ctx",
+ "path",
+ "arch",
+ "conf",
+ NULL,
+ };
+ CtxObject* ctx = NULL;
+ const char* path = NULL;
+ const char* arch = NULL;
+ PyObject* conf = Py_None;
+ int r = 1;
- // Make line
- int r = vasprintf(&buffer, format, args);
- if (r < 0)
- goto ERROR;
+ FILE* fconf = NULL;
- // Build a tuple with the priority and the log message
- tuple = Py_BuildValue("(is)", priority, buffer);
- if (!tuple)
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|zzO", kwlist,
+ &CtxType, &ctx, &path, &arch, &conf))
goto ERROR;
- // Call the callback
- result = PyObject_CallObject(callback, tuple);
-
-ERROR:
- if (buffer)
- free(buffer);
- Py_XDECREF(tuple);
- Py_XDECREF(result);
-}
-
-static int Pakfire_init(PakfireObject* self, PyObject* args, PyObject* kwds) {
- char* kwlist[] = { "path", "arch", "logger", "offline", "conf", "build",
- "enable_ccache", "enable_snapshot", NULL };
- const char* path = NULL;
- const char* arch = NULL;
- const char* conf = NULL;
- int offline = 0;
- int build = 0;
- int enable_ccache = 1;
- int enable_snapshot = 1;
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|zzOpzppp", kwlist,
- &path, &arch, &self->logger, &offline, &conf, &build,
- &enable_ccache, &enable_snapshot))
- return -1;
-
- // Check if logger is callable
- if (self->logger && !PyCallable_Check(self->logger)) {
- PyErr_SetString(PyExc_TypeError, "logger must be callable\n");
- return -1;
+ // Map the configuration
+ if (conf != Py_None) {
+ fconf = PyObject_AsFileHandle(conf, "r");
+ if (!fconf)
+ goto ERROR;
}
int flags = 0;
- // Enable offline mode
- if (offline)
- flags |= PAKFIRE_FLAGS_OFFLINE;
+ Py_BEGIN_ALLOW_THREADS
- // Enable build mode
- if (build) {
- flags |= PAKFIRE_FLAGS_BUILD;
+ // Store a reference to the context
+ self->ctx = pakfire_ctx_ref(ctx->ctx);
- if (!enable_ccache)
- flags |= PAKFIRE_FLAGS_DISABLE_CCACHE;
+ // Create a new Pakfire instance
+ r = pakfire_create(&self->pakfire, self->ctx, path, arch, fconf, flags);
- if (!enable_snapshot)
- flags |= PAKFIRE_FLAGS_DISABLE_SNAPSHOT;
- }
+ Py_END_ALLOW_THREADS
+
+ if (r < 0) {
+ errno = -r;
- // Create a new Pakfire instance
- int r = pakfire_create(&self->pakfire, path, arch, conf, flags,
- (self->logger) ? Pakfire_logging_callback : NULL, self->logger);
- if (r) {
switch (errno) {
// Invalid architecture or path
case EINVAL:
PyErr_SetFromErrno(PyExc_OSError);
}
- return -1;
+ r = -1;
+ goto ERROR;
}
- Py_XINCREF(self->logger);
+ERROR:
+ if (fconf)
+ fclose(fconf);
- return 0;
+ return -r;
}
static void Pakfire_dealloc(PakfireObject* self) {
- if (self->pakfire)
+ if (self->pakfire) {
+ Py_BEGIN_ALLOW_THREADS
+
pakfire_unref(self->pakfire);
- if (self->logger)
- Py_DECREF(self->logger);
+ Py_END_ALLOW_THREADS
+ }
+ if (self->ctx)
+ pakfire_ctx_unref(self->ctx);
Py_TYPE(self)->tp_free((PyObject *)self);
}
static PyObject* Pakfire_repr(PakfireObject* self) {
- const char* path = pakfire_get_path(self->pakfire);
- const char* arch = pakfire_get_arch(self->pakfire);
+ const char* path = pakfire_get_path(self->pakfire);
+ const char* arch = pakfire_get_arch(self->pakfire);
return PyUnicode_FromFormat("<_pakfire.Pakfire %s (%s)>", path, arch);
}
static PyObject* Pakfire_get_path(PakfireObject* self) {
- const char* path = pakfire_get_path(self->pakfire);
+ const char* path = pakfire_get_path(self->pakfire);
- return PyUnicode_FromString(path);
+ return PyUnicode_FromString(path);
}
static PyObject* Pakfire_get_arch(PakfireObject* self) {
- const char* arch = pakfire_get_arch(self->pakfire);
+ const char* arch = pakfire_get_arch(self->pakfire);
- return PyUnicode_FromString(arch);
+ return PyUnicode_FromString(arch);
}
static PyObject* Pakfire_get_repo(PakfireObject* self, PyObject* args) {
if (!object)
goto ERROR;
+ // Nothing to do when object is None
+ if (object == Py_None)
+ return Py_CLEANUP_SUPPORTED;
+
if (!PySequence_Check(object)) {
PyErr_SetString(PyExc_ValueError, "Packages must be a sequence");
goto ERROR;
return 0;
}
-static PyObject* Pakfire_install(PakfireObject* self, PyObject* args, PyObject* kwargs) {
- char* kwlist[] = {
- "packages",
- "without_recommended",
- "allow_uninstall",
- "allow_downgrade",
- NULL
- };
- char** packages = NULL;
- int without_recommended = 0;
- int allow_uninstall = 0;
- int allow_downgrade = 0;
- int solver_flags = 0;
-
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$ppp", kwlist,
- convert_packages, &packages, &without_recommended, &allow_uninstall,
- &allow_downgrade))
- return NULL;
-
- // Do not install recommended packages
- if (without_recommended)
- solver_flags |= PAKFIRE_REQUEST_WITHOUT_RECOMMENDED;
-
- // Can the solver uninstall packages?
- if (allow_uninstall)
- solver_flags |= PAKFIRE_REQUEST_ALLOW_UNINSTALL;
-
- // Can the solver downgrade packages?
- if (allow_downgrade)
- solver_flags |= PAKFIRE_REQUEST_ALLOW_DOWNGRADE;
-
- // Run pakfire_install
- int r = pakfire_install(self->pakfire, solver_flags, (const char**)packages, NULL, 0, NULL);
- if (r)
- PyErr_SetFromErrno(PyExc_OSError);
-
- if (packages) {
- for (char** package = packages; *package; package++)
- free(*package);
- free(packages);
- }
-
- if (r)
- return NULL;
-
- Py_RETURN_NONE;
-}
-
-static PyObject* Pakfire_erase(PakfireObject* self, PyObject* args, PyObject* kwargs) {
- char* kwlist[] = {
- "packages",
- "keep_dependencies",
- NULL
- };
- char** packages = NULL;
- int keep_dependencies = 0;
- int flags = 0;
-
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$p", kwlist,
- convert_packages, &packages, &keep_dependencies))
- return NULL;
-
- if (keep_dependencies)
- flags |= PAKFIRE_REQUEST_KEEP_DEPS;
-
- // Run pakfire_erase
- int r = pakfire_erase(self->pakfire, 0, (const char**)packages, NULL, flags, NULL);
- if (r)
- PyErr_SetFromErrno(PyExc_OSError);
-
- if (packages) {
- for (char** package = packages; *package; package++)
- free(*package);
- free(packages);
- }
-
- if (r)
- return NULL;
-
- Py_RETURN_NONE;
-}
-
-static PyObject* Pakfire_update(PakfireObject* self, PyObject* args, PyObject* kwargs) {
- char* kwlist[] = {
- "packages",
- "excludes",
- "allow_uninstall",
- "allow_downgrade",
- NULL
- };
- char** packages = NULL;
- char** excludes = NULL;
- int allow_uninstall = 0;
- int allow_downgrade = 0;
- int solver_flags = 0;
-
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$O&pp", kwlist,
- convert_packages, &packages, convert_packages, &excludes,
- &allow_uninstall, &allow_downgrade))
- return NULL;
-
- // Can the solver uninstall packages?
- if (allow_uninstall)
- solver_flags |= PAKFIRE_REQUEST_ALLOW_UNINSTALL;
-
- // Can the solver downgrade packages?
- if (allow_downgrade)
- solver_flags |= PAKFIRE_REQUEST_ALLOW_DOWNGRADE;
-
- // Run pakfire_update
- int r = pakfire_update(self->pakfire, solver_flags, (const char**)packages,
- (const char**)excludes, 0, NULL);
- if (r)
- PyErr_SetFromErrno(PyExc_OSError);
-
- if (packages) {
- for (char** package = packages; *package; package++)
- free(*package);
- free(packages);
- }
-
- if (excludes) {
- for (char** exclude = excludes; *exclude; exclude++)
- free(*exclude);
- free(excludes);
- }
-
- if (r)
- return NULL;
-
- Py_RETURN_NONE;
-}
-
-static PyObject* Pakfire_keys_to_list(struct pakfire_key** keys) {
- PyObject* list = PyList_New(0);
-
- // Empty input?
- if (!keys)
- return list;
-
- // Push all keys onto the list
- for (struct pakfire_key** key = keys; *key; key++) {
- PyObject* object = new_key(&KeyType, *key);
- if (!object)
- goto ERROR;
-
- PyList_Append(list, object);
- Py_DECREF(object);
- }
-
- return list;
-
-ERROR:
- Py_DECREF(list);
- return NULL;
-}
-
-static PyObject* Pakfire_get_keys(PakfireObject* self) {
- struct pakfire_key** keys = NULL;
-
- int r = pakfire_list_keys(self->pakfire, &keys);
- if (r) {
- PyErr_SetFromErrno(PyExc_OSError);
- return NULL;
- }
-
- // Convert keys to list
- PyObject* list = Pakfire_keys_to_list(keys);
-
- // Free keys
- for (struct pakfire_key** key = keys; *key; key++)
- pakfire_key_unref(*key);
- free(keys);
-
- return list;
-}
-
-static PyObject* Pakfire_get_key(PakfireObject* self, PyObject* args) {
- const char* pattern = NULL;
-
- if (!PyArg_ParseTuple(args, "s", &pattern))
- return NULL;
-
- struct pakfire_key* key = pakfire_key_get(self->pakfire, pattern);
- if (!key)
- Py_RETURN_NONE;
-
- return new_key(&KeyType, key);
-}
-
+/*
+ XXX This could be moved out of here as this no longer depends on Pakfire
+*/
static PyObject* Pakfire_generate_key(PakfireObject* self, PyObject* args, PyObject* kwds) {
- char* kwlist[] = { "userid", "algorithm", NULL };
+ char* kwlist[] = { "algorithm", "comment", NULL };
struct pakfire_key* key = NULL;
- const char* userid = NULL;
- const char* algo = NULL;
+ pakfire_key_algo_t algo = PAKFIRE_KEY_ALGO_NULL;
+ const char* comment = NULL;
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|$z", kwlist, &userid, &algo))
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "is", kwlist, &algo, &comment))
return NULL;
// Generate a new key
- int r = pakfire_key_generate(&key, self->pakfire, algo, userid);
+ int r = pakfire_key_generate(&key, self->ctx, algo, comment);
if (r) {
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
- return new_key(&KeyType, key);
-}
+ PyObject* object = new_key(&KeyType, key);
+ pakfire_key_unref(key);
+ return object;
+}
+/*
+ XXX This could be moved out of here as this no longer depends on Pakfire
+*/
static PyObject* Pakfire_import_key(PakfireObject* self, PyObject* args) {
+ struct pakfire_key* key = NULL;
PyObject* object = NULL;
+ char* data = NULL;
+ Py_ssize_t data_length = 0;
+ int r;
- if (!PyArg_ParseTuple(args, "O", &object))
- return NULL;
-
- // Get a file descriptor from object
- int fd = PyObject_AsFileDescriptor(object);
- if (fd < 0)
+ // Parse arguments
+ if (!PyArg_ParseTuple(args, "s#", &data, &data_length))
return NULL;
- // Convert to FILE*
- FILE* f = fdopen(fd, "r");
- if (!f) {
- PyErr_SetFromErrno(PyExc_OSError);
+ // Map the object
+ FILE* f = fmemopen(data, data_length, "r");
+ if (!f)
return NULL;
- }
-
- struct pakfire_key** keys = NULL;
- // Import keys from f
- int r = pakfire_key_import(self->pakfire, f, &keys);
+ // Import the key
+ r = pakfire_key_import(&key, self->ctx, f);
if (r) {
PyErr_SetFromErrno(PyExc_OSError);
- return NULL;
+ goto ERROR;
}
- // Convert keys to list
- PyObject* list = Pakfire_keys_to_list(keys);
-
- // Free keys
- for (struct pakfire_key** key = keys; *key; key++)
- pakfire_key_unref(*key);
- free(keys);
-
- return list;
-}
-
-static PyObject* Pakfire_fetch_key(PakfireObject* self, PyObject* args, PyObject* kwds) {
- char* kwlist[] = { "userid", "fingerprint", NULL };
- struct pakfire_key* key = NULL;
- const char* userid = NULL;
- const char* fingerprint = NULL;
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|$zz", kwlist, &userid, &fingerprint))
- return NULL;
-
- // Fetch the key
- int r = pakfire_key_fetch(&key, self->pakfire, userid, fingerprint);
- if (r) {
- PyErr_SetFromErrno(PyExc_OSError);
- return NULL;
- }
+ // Convert the key into a Key object
+ object = new_key(&KeyType, key);
+ if (!object)
+ goto ERROR;
- // Return the result
+ERROR:
if (key)
- return new_key(&KeyType, key);
+ pakfire_key_unref(key);
+ if (f)
+ fclose(f);
- Py_RETURN_NONE;
+ return object;
}
static PyObject* Pakfire_whatprovides(PakfireObject* self, PyObject* args) {
const char* provides = NULL;
struct pakfire_packagelist* list = NULL;
+ PyObject* ret = NULL;
+ int r;
if (!PyArg_ParseTuple(args, "s", &provides))
return NULL;
- int r = pakfire_whatprovides(self->pakfire, provides, 0, &list);
+ // Create a new list
+ r = pakfire_packagelist_create(&list, self->ctx);
if (r) {
PyErr_SetFromErrno(PyExc_OSError);
- return NULL;
+ goto ERROR;
+ }
+
+ r = pakfire_whatprovides(self->pakfire, provides, 0, list);
+ if (r) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ goto ERROR;
}
- PyObject* obj = PyList_FromPackageList(list);
- pakfire_packagelist_unref(list);
+ // Create a Python list from the package list
+ ret = PyList_FromPackageList(list);
- return obj;
+ERROR:
+ if (list)
+ pakfire_packagelist_unref(list);
+
+ return ret;
}
static PyObject* Pakfire_whatrequires(PakfireObject* self, PyObject* args) {
const char* requires = NULL;
struct pakfire_packagelist* list = NULL;
+ PyObject* ret = NULL;
+ int r;
if (!PyArg_ParseTuple(args, "s", &requires))
return NULL;
- int r = pakfire_whatrequires(self->pakfire, requires, 0, &list);
+ Py_BEGIN_ALLOW_THREADS
+
+ // Create a new list
+ r = pakfire_packagelist_create(&list, self->ctx);
if (r) {
+ Py_BLOCK_THREADS
PyErr_SetFromErrno(PyExc_OSError);
- return NULL;
+ goto ERROR;
+ }
+
+ r = pakfire_whatrequires(self->pakfire, requires, 0, list);
+ if (r) {
+ Py_BLOCK_THREADS
+ PyErr_SetFromErrno(PyExc_OSError);
+ goto ERROR;
}
- PyObject* obj = PyList_FromPackageList(list);
- pakfire_packagelist_unref(list);
+ Py_END_ALLOW_THREADS
- return obj;
+ // Create a Python list from the package list
+ ret = PyList_FromPackageList(list);
+
+ERROR:
+ if (list)
+ pakfire_packagelist_unref(list);
+
+ return ret;
}
static PyObject* Pakfire_search(PakfireObject* self, PyObject* args, PyObject* kwds) {
const char* pattern = NULL;
int name_only = 0;
int flags = 0;
+ PyObject* ret = NULL;
+ int r;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|$p", kwlist, &pattern, &name_only))
return NULL;
if (name_only)
flags |= PAKFIRE_SEARCH_NAME_ONLY;
- int r = pakfire_search(self->pakfire, pattern, flags, &list);
+ r = pakfire_packagelist_create(&list, self->ctx);
if (r) {
PyErr_SetFromErrno(PyExc_OSError);
- return NULL;
+ goto ERROR;
+ }
+
+ r = pakfire_search(self->pakfire, pattern, flags, list);
+ if (r) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ goto ERROR;
}
- PyObject* obj = PyList_FromPackageList(list);
- pakfire_packagelist_unref(list);
+ ret = PyList_FromPackageList(list);
- return obj;
+ERROR:
+ if (list)
+ pakfire_packagelist_unref(list);
+
+ return ret;
}
static PyObject* Pakfire_version_compare(PakfireObject* self, PyObject* args) {
return PyLong_FromLong(cmp);
}
-static PyObject* Pakfire_execute_logging_callback = NULL;
-
-static int __Pakfire_execute_logging_callback(Pakfire pakfire, void* data,
- int priority, const char* line, size_t length) {
+static int Pakfire_execute_output_callback(struct pakfire_ctx* ctx, struct pakfire_jail* jail,
+ void* data, const char* line, size_t length) {
+ PyObject* callback = (PyObject*)data;
int r = 0;
// Do nothing if callback isn't set
- if (!Pakfire_execute_logging_callback)
+ if (!callback)
return 0;
- // Translate priority to Python logging priorities
- switch (priority) {
- case LOG_INFO:
- priority = 20;
- break;
-
- case LOG_ERR:
- priority = 40;
- break;
- }
-
// Remove the trailing newline
if (line && line[length - 1] == '\n')
length--;
// Create tuple with arguments for the callback function
- PyObject* args = Py_BuildValue("(is#)", priority, line, length);
+ PyObject* args = Py_BuildValue("(is#)", LOG_INFO, line, (Py_ssize_t)length);
if (!args)
return 1;
- PyObject* result = PyObject_CallObject(Pakfire_execute_logging_callback, args);
+ PyObject* result = PyObject_CallObject(callback, args);
if (result && PyLong_Check(result)) {
r = PyLong_AsLong(result);
}
}
static PyObject* Pakfire_execute(PakfireObject* self, PyObject* args, PyObject* kwds) {
- char* kwlist[] = {"command", "environ", "enable_network", "interactive",
- "logging_callback", NULL};
+ char* kwlist[] = {
+ "command",
+ "environ",
+ "bind",
+ "callback",
+ "nice",
+ NULL
+ };
+
+ struct pakfire_jail* jail = NULL;
+ const char** argv = NULL;
+ int r;
+ PyObject* ret = NULL;
PyObject* command = NULL;
PyObject* environ = NULL;
- int enable_network = 0;
- int interactive = 0;
- PyObject* logging_callback = NULL;
+ PyObject* bind = NULL;
+ PyObject* callback = NULL;
+ int nice = 0;
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OppO", kwlist, &command, &environ,
- &enable_network, &interactive, &logging_callback))
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOi", kwlist, &command, &environ,
+ &bind, &callback, &nice))
return NULL;
// Check if command is a list
if (!PyList_Check(command)) {
PyErr_SetString(PyExc_TypeError, "command must be a list");
- return NULL;
+ goto ERROR;
}
- ssize_t command_length = PyList_Size(command);
+ const ssize_t command_length = PyList_Size(command);
// Check if command is not empty
if (command_length == 0) {
PyErr_SetString(PyExc_ValueError, "command is empty");
- return NULL;
+ goto ERROR;
}
+ // Allocate argv
+ argv = calloc(command_length + 1, sizeof(*argv));
+ if (!argv)
+ goto ERROR;
+
// All arguments in command must be strings
for (unsigned int i = 0; i < command_length; i++) {
PyObject* item = PyList_GET_ITEM(command, i);
if (!PyUnicode_Check(item)) {
PyErr_Format(PyExc_TypeError, "Item %u in command is not a string", i);
- return NULL;
+ goto ERROR;
}
+
+ // Copy to argv
+ argv[i] = PyUnicode_AsUTF8(item);
}
- // Check if logging_callback is
- if (logging_callback && !PyCallable_Check(logging_callback)) {
- PyErr_SetString(PyExc_TypeError, "logging_callback must be callable\n");
- return NULL;
+ // Check if bind is a sequence
+ if (bind && !PySequence_Check(bind)) {
+ PyErr_SetString(PyExc_ValueError, "bind is not a sequence");
+ goto ERROR;
}
- ssize_t environ_length = 0;
- PyObject* key;
- PyObject* value;
+ // Check callback
+ if (callback && !PyCallable_Check(callback)) {
+ PyErr_SetString(PyExc_TypeError, "callback must be callable\n");
+ goto ERROR;
+ }
+
+ // Create jail
+ r = pakfire_jail_create(&jail, self->pakfire);
+ if (r) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ goto ERROR;
+ }
+
+ // Set nice
+ if (nice) {
+ r = pakfire_jail_nice(jail, nice);
+ if (r) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ goto ERROR;
+ }
+ }
+
+ PyObject* key = NULL;
+ PyObject* value = NULL;
Py_ssize_t p = 0;
+ // Parse the environment
if (environ) {
// Check if environ is a dictionary
if (!PyDict_Check(environ)) {
PyErr_SetString(PyExc_TypeError, "environ must be a dictionary");
- return NULL;
+ goto ERROR;
}
// All keys and values must be strings
while (PyDict_Next(environ, &p, &key, &value)) {
if (!PyUnicode_Check(key) || !PyUnicode_Check(value)) {
PyErr_SetString(PyExc_TypeError, "Environment contains a non-string object");
- return NULL;
+ goto ERROR;
}
- }
- environ_length = PyDict_Size(environ);
+ // Set environment value
+ r = pakfire_jail_set_env(jail, PyUnicode_AsUTF8(key), PyUnicode_AsUTF8(value));
+ if (r) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ goto ERROR;
+ }
+ }
}
- // All inputs look fine
-
- const char* argv[command_length + 1];
- char* envp[environ_length + 1];
- int flags = 0;
+ // Bind
+ if (bind && PySequence_Check(bind)) {
+ const Py_ssize_t num_bind = PySequence_Length(bind);
- // Parse arguments
- for (unsigned int i = 0; i < command_length; i++) {
- PyObject* item = PyList_GET_ITEM(command, i);
- argv[i] = PyUnicode_AsUTF8(item);
- }
+ for (unsigned int i = 0; i < num_bind; i++) {
+ PyObject* b = PySequence_ITEM(bind, i);
+ if (!b)
+ goto ERROR;
- // Parse environ
- if (environ) {
- unsigned int i = 0;
- p = 0;
-
- while (PyDict_Next(environ, &p, &key, &value)) {
- int r = asprintf(&envp[i++], "%s=%s",
- PyUnicode_AsUTF8(key), PyUnicode_AsUTF8(value));
+ // Check if this is a Unicode object
+ if (!PyUnicode_Check(b)) {
+ PyErr_SetString(PyExc_ValueError, "bind contains a non-Unicode object");
+ Py_DECREF(b);
+ goto ERROR;
+ }
- // Handle errors
- if (r < 0) {
- // Cleanup
- for (unsigned int i = 0; envp[i]; i++)
- free(envp[i]);
+ const char* path = PyUnicode_AsUTF8(b);
- return PyErr_NoMemory();
+ // Perform bind
+ r = pakfire_jail_bind(jail, path, path, 0);
+ if (r) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ Py_DECREF(b);
+ goto ERROR;
}
+
+ Py_DECREF(b);
}
}
- // Terminate argv and envp
- argv[command_length] = NULL;
- envp[environ_length] = NULL;
-
- // Enable network?
- if (enable_network)
- flags |= PAKFIRE_EXECUTE_ENABLE_NETWORK;
+ Py_BEGIN_ALLOW_THREADS
- // Interactive?
- if (interactive)
- flags |= PAKFIRE_EXECUTE_INTERACTIVE;
-
- // Set logging callback
- Pakfire_execute_logging_callback = logging_callback;
+ // Set callback
+ pakfire_jail_set_stdout_callback(jail, Pakfire_execute_output_callback, callback);
// Execute command
- int r = pakfire_execute(self->pakfire, argv, envp, flags,
- (logging_callback) ? __Pakfire_execute_logging_callback : NULL, NULL);
+ r = pakfire_jail_exec(jail, argv, 0);
- // Cleanup
- for (unsigned int i = 0; envp[i]; i++)
- free(envp[i]);
+ Py_END_ALLOW_THREADS
- // Raise an OS error if r < 0
+ // If the return code was negative, we had some internal error
if (r < 0) {
- errno = -r;
-
PyErr_SetFromErrno(PyExc_OSError);
- return NULL;
+ goto ERROR;
- // Raise exception when the command failed
+ // Otherwise the executed command returned some error code
} else if (r > 0) {
PyObject* code = PyLong_FromLong(r);
+ // Raise CommandExecutionError
PyErr_SetObject(PyExc_CommandExecutionError, code);
Py_DECREF(code);
- return NULL;
+ goto ERROR;
}
- // Return nothing
- Py_RETURN_NONE;
+ // The process has exited successfully
+
+ // Return None
+ ret = Py_None;
+ Py_INCREF(ret);
+
+ERROR:
+ if (argv)
+ free(argv);
+ if (jail)
+ pakfire_jail_unref(jail);
+
+ return ret;
}
static PyObject* Pakfire_dist(PakfireObject* self, PyObject* args) {
const char* path = NULL;
const char* target = NULL;
+ char* result = NULL;
+ int r;
if (!PyArg_ParseTuple(args, "s|z", &path, &target))
return NULL;
- int r = pakfire_dist(self->pakfire, path, target);
- if (r) {
- PyErr_SetFromErrno(PyExc_OSError);
- return NULL;
- }
-
- Py_RETURN_NONE;
-}
-
-static PyObject* Pakfire_bind(PakfireObject* self, PyObject* args) {
- const char* src = NULL;
- const char* dst = NULL;
+ Py_BEGIN_ALLOW_THREADS
- if (!PyArg_ParseTuple(args, "s|z", &src, &dst))
- return NULL;
-
- int r = pakfire_bind(self->pakfire, src, dst, 0);
+ r = pakfire_dist(self->pakfire, path, target, &result);
if (r) {
+ Py_BLOCK_THREADS
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
- Py_RETURN_NONE;
-}
-
-static PyObject* Pakfire_copy_in(PakfireObject* self, PyObject* args) {
- const char* src = NULL;
- const char* dst = NULL;
-
- if (!PyArg_ParseTuple(args, "ss", &src, &dst))
- return NULL;
+ Py_END_ALLOW_THREADS
- int r = pakfire_copy_in(self->pakfire, src, dst);
- if (r) {
- PyErr_SetFromErrno(PyExc_OSError);
- return NULL;
- }
+ PyObject* ret = PyUnicode_FromString(result);
+ free(result);
- Py_RETURN_NONE;
-}
-
-static PyObject* Pakfire_copy_out(PakfireObject* self, PyObject* args) {
- const char* src = NULL;
- const char* dst = NULL;
-
- if (!PyArg_ParseTuple(args, "ss", &src, &dst))
- return NULL;
-
- int r = pakfire_copy_out(self->pakfire, src, dst);
- if (r) {
- PyErr_SetFromErrno(PyExc_OSError);
- return NULL;
- }
-
- Py_RETURN_NONE;
+ return ret;
}
static PyObject* Pakfire_get_repos(PakfireObject* self) {
}
static PyObject* Pakfire_build(PakfireObject* self, PyObject* args, PyObject* kwargs) {
- char* kwlist[] = { "path", "build_id", "logging_callback", "interactive", NULL };
-
+ char* kwlist[] = {
+ "path",
+ "target",
+ "build_id",
+ "ccache_path",
+ "interactive",
+ "disable_snapshot",
+ "disable_ccache",
+ "disable_tests",
+ NULL,
+ };
+ struct pakfire_build* build = NULL;
const char* path = NULL;
+ const char* target = NULL;
const char* build_id = NULL;
- PyObject* logging_callback = NULL;
+ const char* ccache_path = NULL;
int interactive = 0;
-
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOp", kwlist, &path,
- &build_id, &logging_callback, &interactive))
+ int disable_snapshot = 0;
+ int disable_ccache = 0;
+ int disable_tests = 0;
+ int r;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzzpppp", kwlist,
+ &path, &target, &build_id, &ccache_path, &interactive,
+ &disable_snapshot, &disable_ccache, &disable_tests))
return NULL;
int flags = 0;
- // Enable interactive mode
if (interactive)
flags |= PAKFIRE_BUILD_INTERACTIVE;
- // Check if logging_callback is
- if (logging_callback && !PyCallable_Check(logging_callback)) {
- PyErr_SetString(PyExc_TypeError, "logging_callback must be callable\n");
- return NULL;
+ // Disable snapshot if requested
+ if (disable_snapshot)
+ flags |= PAKFIRE_BUILD_DISABLE_SNAPSHOT;
+
+ // Disable ccache if requested
+ if (disable_ccache)
+ flags |= PAKFIRE_BUILD_DISABLE_CCACHE;
+
+ // Disable tests if requested
+ if (disable_tests)
+ flags |= PAKFIRE_BUILD_DISABLE_TESTS;
+
+ // Create a new build environment
+ r = pakfire_build_create(&build, self->pakfire, build_id, flags);
+ if (r) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ goto ERROR;
}
- // Set logging callback
- Pakfire_execute_logging_callback = logging_callback;
+ // Set target
+ if (target) {
+ r = pakfire_build_set_target(build, target);
+ if (r) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ goto ERROR;
+ }
+ }
+
+ // Set ccache path
+ if (ccache_path) {
+ r = pakfire_build_set_ccache_path(build, ccache_path);
+ if (r) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ goto ERROR;
+ }
+ }
+
+ Py_BEGIN_ALLOW_THREADS
// Run build
- int r = pakfire_build(self->pakfire, path, NULL, build_id, flags,
- (logging_callback) ? __Pakfire_execute_logging_callback : NULL, NULL);
+ r = pakfire_build_exec(build, path);
+ if (r) {
+ Py_BLOCK_THREADS;
- return execute_return_value(r);
+ if (r < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+
+ // Raise a command execution error
+ } else {
+ PyObject* code = PyLong_FromLong(r);
+
+ PyErr_SetObject(PyExc_CommandExecutionError, code);
+ Py_DECREF(code);
+ }
+
+ goto ERROR;
+ }
+
+ Py_END_ALLOW_THREADS
+
+ERROR:
+ if (build)
+ pakfire_build_unref(build);
+
+ if (r)
+ return NULL;
+
+ Py_RETURN_NONE;
}
-static PyObject* Pakfire_shell(PakfireObject* self) {
- int r = pakfire_shell(self->pakfire);
+static PyObject* Pakfire_shell(PakfireObject* self, PyObject* args, PyObject* kwargs) {
+ char* kwlist[] = {
+ "install",
+ "disable_snapshot",
+ NULL,
+ };
+ char** packages = NULL;
+ int disable_snapshot = 0;
+ int r;
+
+ // Parse everything
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O&p", kwlist,
+ convert_packages, &packages, &disable_snapshot))
+ return NULL;
+
+ int flags = 0;
+
+ if (disable_snapshot)
+ flags |= PAKFIRE_BUILD_DISABLE_SNAPSHOT;
+
+ Py_BEGIN_ALLOW_THREADS
+
+ r = pakfire_shell(self->pakfire, (const char**)packages, flags);
+
+ Py_END_ALLOW_THREADS
return execute_return_value(r);
}
static PyObject* Pakfire_clean(PakfireObject* self) {
- int r = pakfire_clean(self->pakfire, 0);
+ int r;
+
+ Py_BEGIN_ALLOW_THREADS
+
+ r = pakfire_clean(self->pakfire, 0);
if (r) {
+ Py_BLOCK_THREADS
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
+ Py_END_ALLOW_THREADS
+
Py_RETURN_NONE;
}
static PyObject* Pakfire_refresh(PakfireObject* self, PyObject* args) {
int force = 0;
+ int r;
if (!PyArg_ParseTuple(args, "|p", &force))
return NULL;
- int r = pakfire_refresh(self->pakfire, force);
+ Py_BEGIN_ALLOW_THREADS
+
+ r = pakfire_refresh(self->pakfire, force);
if (r) {
+ Py_BLOCK_THREADS
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
+ Py_END_ALLOW_THREADS
+
Py_RETURN_NONE;
}
-static PyObject* Pakfire_check(PakfireObject* self) {
- int r = pakfire_check(self->pakfire);
+static PyObject* Pakfire_open(PakfireObject* self, PyObject* args) {
+ struct pakfire_archive* archive = NULL;
+ const char* path = NULL;
+
+ if (!PyArg_ParseTuple(args, "s", &path))
+ return NULL;
+
+ Py_BEGIN_ALLOW_THREADS
+
+ int r = pakfire_archive_open(&archive, self->pakfire, path);
if (r) {
+ Py_BLOCK_THREADS
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
- Py_RETURN_NONE;
+ Py_END_ALLOW_THREADS
+
+ // Create Python object
+ PyObject* object = new_archive(&ArchiveType, archive);
+ pakfire_archive_unref(archive);
+
+ return object;
}
-static PyObject* Pakfire_sync(PakfireObject* self, PyObject* args, PyObject* kwargs) {
- char* kwlist[] = {"keep_orphaned", NULL};
- int keep_orphaned = 0;
- int flags = 0;
+static PyObject* Pakfire_repo_compose(PakfireObject* self, PyObject* args, PyObject* kwargs) {
+ char* kwlist[] = { "path", "files", "key", NULL };
+ const char* path = NULL;
+ PyObject* list = NULL;
+ KeyObject* key = NULL;
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|$p", kwlist, &keep_orphaned))
+ PyObject* ret = NULL;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sO|O!", kwlist, &path, &list, &KeyType, &key))
+ return NULL;
+
+ // List must be a sequence
+ if (!PySequence_Check(list)) {
+ PyErr_SetString(PyExc_ValueError, "Expected a sequence.");
return NULL;
+ }
- if (keep_orphaned)
- flags |= PAKFIRE_REQUEST_KEEP_ORPHANED;
+ // How many new files do we have?
+ ssize_t num_files = PySequence_Length(list);
+ if (num_files < 0)
+ return NULL;
- int r = pakfire_sync(self->pakfire, 0, flags, NULL);
+ // Allocate files array
+ const char** files = calloc(num_files + 1, sizeof(*files));
+ if (!files) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ return NULL;
+ }
+
+ for (int i = 0; i < num_files; i++) {
+ PyObject* file = PySequence_GetItem(list, i);
+ if (!file)
+ goto ERROR;
+
+ // Check if file is a Unicode object
+ if (!PyUnicode_Check(file)) {
+ PyErr_SetString(PyExc_ValueError, "Expected a string.");
+ goto ERROR;
+ }
+
+ // Add pointer to string to files array
+ files[i] = PyUnicode_AsUTF8(file);
+ if (!files[i])
+ goto ERROR;
+
+ Py_DECREF(file);
+ }
+
+ Py_BEGIN_ALLOW_THREADS
+
+ int r = pakfire_repo_compose(self->pakfire, path, (key) ? key->key : NULL, files);
if (r) {
+ Py_BLOCK_THREADS
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
- Py_RETURN_NONE;
+ Py_END_ALLOW_THREADS
+
+ // Return None on success
+ ret = Py_None;
+ Py_INCREF(ret);
+
+ERROR:
+ if (files)
+ free(files);
+
+ return ret;
}
-static PyObject* Pakfire_open(PakfireObject* self, PyObject* args) {
- PakfireArchive archive = NULL;
- const char* path = NULL;
+static PyObject* Pakfire_mkimage(PakfireObject* self, PyObject* args, PyObject* kwargs) {
+ char* kwlist[] = {
+ "type",
+ "path",
+ NULL,
+ };
+ struct pakfire_build* build = NULL;
+ const char* type = NULL;
+ PyObject* file = NULL;
+ FILE* f = NULL;
+ int r;
- if (!PyArg_ParseTuple(args, "s", &path))
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sO", kwlist, &type, &file))
return NULL;
- int r = pakfire_archive_open(&archive, self->pakfire, path);
+ // Make a file handle out of file
+ f = PyObject_AsFileHandle(file, "w");
+ if (!f)
+ return NULL;
+
+ // Create a new build environment
+ r = pakfire_build_create(&build, self->pakfire, NULL, 0);
if (r) {
PyErr_SetFromErrno(PyExc_OSError);
- return NULL;
+ goto ERROR;
}
- // Create Python object
- PyObject* object = new_archive(&ArchiveType, archive);
- pakfire_archive_unref(archive);
+ Py_BEGIN_ALLOW_THREADS
- return object;
+ // Run mkimage
+ r = pakfire_build_mkimage(build, type, f);
+ if (r) {
+ Py_BLOCK_THREADS;
+
+ if (r < 0)
+ PyErr_SetFromErrno(PyExc_OSError);
+
+ goto ERROR;
+ }
+
+ Py_END_ALLOW_THREADS
+
+ERROR:
+ if (build)
+ pakfire_build_unref(build);
+ if (f)
+ fclose(f);
+ if (r)
+ return NULL;
+
+ Py_RETURN_NONE;
}
static struct PyMethodDef Pakfire_methods[] = {
- {
- "bind",
- (PyCFunction)Pakfire_bind,
- METH_VARARGS,
- NULL,
- },
{
"build",
(PyCFunction)Pakfire_build,
METH_VARARGS|METH_KEYWORDS,
NULL
},
- {
- "check",
- (PyCFunction)Pakfire_check,
- METH_NOARGS,
- NULL,
- },
{
"clean",
(PyCFunction)Pakfire_clean,
METH_NOARGS,
NULL,
},
- {
- "copy_in",
- (PyCFunction)Pakfire_copy_in,
- METH_VARARGS,
- NULL,
- },
- {
- "copy_out",
- (PyCFunction)Pakfire_copy_out,
- METH_VARARGS,
- NULL,
- },
{
"dist",
(PyCFunction)Pakfire_dist,
METH_VARARGS,
NULL
},
- {
- "erase",
- (PyCFunction)Pakfire_erase,
- METH_VARARGS|METH_KEYWORDS,
- NULL
- },
{
"execute",
(PyCFunction)Pakfire_execute,
METH_VARARGS|METH_KEYWORDS,
NULL
},
- {
- "fetch_key",
- (PyCFunction)Pakfire_fetch_key,
- METH_VARARGS|METH_KEYWORDS,
- NULL
- },
{
"generate_key",
(PyCFunction)Pakfire_generate_key,
METH_VARARGS|METH_KEYWORDS,
NULL
},
- {
- "get_key",
- (PyCFunction)Pakfire_get_key,
- METH_VARARGS,
- NULL
- },
{
"get_repo",
(PyCFunction)Pakfire_get_repo,
"import_key",
(PyCFunction)Pakfire_import_key,
METH_VARARGS,
- NULL
+ NULL,
},
{
- "install",
- (PyCFunction)Pakfire_install,
+ "mkimage",
+ (PyCFunction)Pakfire_mkimage,
METH_VARARGS|METH_KEYWORDS,
- NULL,
+ NULL
},
{
"open",
METH_VARARGS,
NULL,
},
+ {
+ "repo_compose",
+ (PyCFunction)Pakfire_repo_compose,
+ METH_VARARGS|METH_KEYWORDS,
+ NULL
+ },
{
"search",
(PyCFunction)Pakfire_search,
{
"shell",
(PyCFunction)Pakfire_shell,
- METH_NOARGS,
- NULL,
- },
- {
- "sync",
- (PyCFunction)Pakfire_sync,
METH_VARARGS|METH_KEYWORDS,
NULL,
},
- {
- "update",
- (PyCFunction)Pakfire_update,
- METH_VARARGS|METH_KEYWORDS,
- NULL
- },
{
"version_compare",
(PyCFunction)Pakfire_version_compare,
NULL,
NULL
},
- {
- "keys",
- (getter)Pakfire_get_keys,
- NULL,
- NULL,
- NULL
- },
{
"path",
(getter)Pakfire_get_path,