]> git.ipfire.org Git - people/ms/pakfire.git/commitdiff
Import libpakfire
authorMichael Tremer <michael.tremer@ipfire.org>
Tue, 13 Dec 2016 22:44:00 +0000 (23:44 +0100)
committerMichael Tremer <michael.tremer@ipfire.org>
Tue, 13 Dec 2016 22:44:00 +0000 (23:44 +0100)
libpakfire is a C implementation of some functionality
of pakfire. It is supposed to make code cleaner and avoid
too much wrapping in python. It is also intended to make
the code faster where ever performance is critical.

This patch adds a dependency to libarchive which is used
to read and write packages.

This implementation is not fully finished and possibly
rough around the edges. It has to be integrated into
the existing Python code and redundant code will have to
be dropped.

Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
47 files changed:
Makefile.am
configure.ac
po/POTFILES.in
src/libpakfire/archive.c [new file with mode: 0644]
src/libpakfire/cache.c [new file with mode: 0644]
src/libpakfire/errno.c [new file with mode: 0644]
src/libpakfire/file.c [new file with mode: 0644]
src/libpakfire/filelist.c [new file with mode: 0644]
src/libpakfire/filter.c [new file with mode: 0644]
src/libpakfire/include/pakfire/archive.h [new file with mode: 0644]
src/libpakfire/include/pakfire/cache.h [new file with mode: 0644]
src/libpakfire/include/pakfire/constants.h [new file with mode: 0644]
src/libpakfire/include/pakfire/errno.h [new file with mode: 0644]
src/libpakfire/include/pakfire/file.h [new file with mode: 0644]
src/libpakfire/include/pakfire/filelist.h [new file with mode: 0644]
src/libpakfire/include/pakfire/filter.h [new file with mode: 0644]
src/libpakfire/include/pakfire/i18n.h [new file with mode: 0644]
src/libpakfire/include/pakfire/package.h [new file with mode: 0644]
src/libpakfire/include/pakfire/packagecache.h [new file with mode: 0644]
src/libpakfire/include/pakfire/packagelist.h [new file with mode: 0644]
src/libpakfire/include/pakfire/pool.h [new file with mode: 0644]
src/libpakfire/include/pakfire/relation.h [new file with mode: 0644]
src/libpakfire/include/pakfire/relationlist.h [new file with mode: 0644]
src/libpakfire/include/pakfire/repo.h [new file with mode: 0644]
src/libpakfire/include/pakfire/repocache.h [new file with mode: 0644]
src/libpakfire/include/pakfire/request.h [new file with mode: 0644]
src/libpakfire/include/pakfire/selector.h [new file with mode: 0644]
src/libpakfire/include/pakfire/solver.h [new file with mode: 0644]
src/libpakfire/include/pakfire/step.h [new file with mode: 0644]
src/libpakfire/include/pakfire/transaction.h [new file with mode: 0644]
src/libpakfire/include/pakfire/types.h [new file with mode: 0644]
src/libpakfire/include/pakfire/util.h [new file with mode: 0644]
src/libpakfire/libpakfire.sym [new file with mode: 0644]
src/libpakfire/package.c [new file with mode: 0644]
src/libpakfire/packagecache.c [new file with mode: 0644]
src/libpakfire/packagelist.c [new file with mode: 0644]
src/libpakfire/pool.c [new file with mode: 0644]
src/libpakfire/relation.c [new file with mode: 0644]
src/libpakfire/relationlist.c [new file with mode: 0644]
src/libpakfire/repo.c [new file with mode: 0644]
src/libpakfire/repocache.c [new file with mode: 0644]
src/libpakfire/request.c [new file with mode: 0644]
src/libpakfire/selector.c [new file with mode: 0644]
src/libpakfire/solver.c [new file with mode: 0644]
src/libpakfire/step.c [new file with mode: 0644]
src/libpakfire/transaction.c [new file with mode: 0644]
src/libpakfire/util.c [new file with mode: 0644]

index df0713fd2151aba9eca45257552e850cff08a565..1e3467f1223bb7b02be651508f03da69ccb237eb 100644 (file)
@@ -30,6 +30,10 @@ AUTOMAKE_OPTIONS = color-tests
 
 SUBDIRS = . po
 
+LIBPAKFIRE_CURRENT=0
+LIBPAKFIRE_REVISION=0
+LIBPAKFIRE_AGE=0
+
 libexecdir = $(libdir)/pakfire
 pythondir  = $(pyexecdir)
 
@@ -54,6 +58,7 @@ AM_LDFLAGS = $(OUR_LDFLAGS)
 lib_LTLIBRARIES =
 libexec_PROGRAMS =
 pkgpyexec_LTLIBRARIES =
+pkginclude_HEADERS =
 
 DISTCHECK_CONFIGURE_FLAGS = \
         --with-systemdsystemunitdir=$$dc_install_base/$(systemdsystemunitdir)
@@ -216,6 +221,76 @@ _pakfire_la_LIBADD = \
 
 # ------------------------------------------------------------------------------
 
+lib_LTLIBRARIES += \
+       libpakfire.la
+
+libpakfire_la_SOURCES = \
+       src/libpakfire/archive.c \
+       src/libpakfire/cache.c \
+       src/libpakfire/errno.c \
+       src/libpakfire/file.c \
+       src/libpakfire/filter.c \
+       src/libpakfire/package.c \
+       src/libpakfire/packagelist.c \
+       src/libpakfire/pool.c \
+       src/libpakfire/relation.c \
+       src/libpakfire/relationlist.c \
+       src/libpakfire/repo.c \
+       src/libpakfire/repocache.c \
+       src/libpakfire/request.c \
+       src/libpakfire/selector.c \
+       src/libpakfire/solver.c \
+       src/libpakfire/step.c \
+       src/libpakfire/transaction.c \
+       src/libpakfire/util.c
+
+pkginclude_HEADERS += \
+       src/libpakfire/include/pakfire/archive.h \
+       src/libpakfire/include/pakfire/cache.h \
+       src/libpakfire/include/pakfire/constants.h \
+       src/libpakfire/include/pakfire/errno.h \
+       src/libpakfire/include/pakfire/file.h \
+       src/libpakfire/include/pakfire/filter.h \
+       src/libpakfire/include/pakfire/i18n.h \
+       src/libpakfire/include/pakfire/package.h \
+       src/libpakfire/include/pakfire/packagecache.h \
+       src/libpakfire/include/pakfire/packagelist.h \
+       src/libpakfire/include/pakfire/pool.h \
+       src/libpakfire/include/pakfire/relation.h \
+       src/libpakfire/include/pakfire/relationlist.h \
+       src/libpakfire/include/pakfire/repo.h \
+       src/libpakfire/include/pakfire/repocache.h \
+       src/libpakfire/include/pakfire/request.h \
+       src/libpakfire/include/pakfire/selector.h \
+       src/libpakfire/include/pakfire/solver.h \
+       src/libpakfire/include/pakfire/step.h \
+       src/libpakfire/include/pakfire/transaction.h \
+       src/libpakfire/include/pakfire/types.h \
+       src/libpakfire/include/pakfire/util.h
+
+libpakfire_la_CFLAGS = \
+       $(AM_CFLAGS)
+
+libpakfire_la_CPPFLAGS = \
+       $(AM_CPPFLAGS) \
+       -I$(top_srcdir)/src/libpakfire/include \
+       -include $(top_builddir)/config.h \
+       -DPAKFIRE_PRIVATE
+
+libpakfire_la_LDFLAGS = \
+       $(AM_LDFLAGS) \
+       -version-info $(LIBPAKFIRE_CURRENT):$(LIBPAKFIRE_REVISION):$(LIBPAKFIRE_AGE) \
+       -Wl,--version-script=$(top_srcdir)/src/libpakfire/libpakfire.sym
+
+libpakfire_la_LIBADD = \
+       $(ARCHIVE_LIBS) \
+       $(SOLV_LIBS)
+
+EXTRA_DIST += \
+       src/libpakfire/libpakfire.sym
+
+# ------------------------------------------------------------------------------
+
 lib_LTLIBRARIES += \
        libpakfire_preload.la
 
index 441120b446d9593e371599fba42b7500f5f8b740..509c92ada3856b828476c89ecac8cae57f115deb 100644 (file)
@@ -101,6 +101,24 @@ AC_SUBST([OUR_LDFLAGS], $with_ldflags)
 # Python
 AM_PATH_PYTHON([3.4])
 
+AC_C_CONST
+AC_CHECK_LIB([m], [round])
+
+AC_CHECK_HEADERS([ \
+       assert.h \
+       math.h \
+       stdlib.h \
+       string.h \
+       sys/stat.h \
+       unistd.h
+])
+
+AC_CHECK_FUNCS([ \
+       assert \
+       strcmp \
+       strdup
+])
+
 save_LIBS="$LIBS"
 
 # libdl
@@ -126,6 +144,7 @@ SOLV_LIBS="$LIBS"
 AC_SUBST(SOLV_LIBS)
 LIBS="$save_LIBS"
 
+PKG_CHECK_MODULES([ARCHIVE], [libarchive])
 PKG_CHECK_MODULES([PYTHON_DEVEL], [python-${PYTHON_VERSION}])
 PKG_CHECK_MODULES([LZMA], [liblzma])
 
index 5e4597650d870d86244e2f186575fd3459e711fd..8b9f99ce56c70ca5a7cf90857dac5d96bf9548b6 100644 (file)
@@ -1,3 +1,5 @@
+src/libpakfire/package.c
+
 src/_pakfire/problem.c
 src/_pakfire/solution.c
 
@@ -5,11 +7,13 @@ src/pakfire/actions.py
 src/pakfire/base.py
 src/pakfire/builder.py
 src/pakfire/cli.py
+src/pakfire/client.py
 src/pakfire/compress.py
 src/pakfire/config.py
 src/pakfire/daemon.py
 src/pakfire/downloader.py
 src/pakfire/errors.py
+src/pakfire/http.py
 src/pakfire/i18n.py
 src/pakfire/keyring.py
 src/pakfire/packages/base.py
@@ -29,4 +33,5 @@ src/pakfire/server.py
 src/pakfire/shell.py
 src/pakfire/system.py
 src/pakfire/transaction.py
+src/pakfire/ui/progressbar.py
 src/pakfire/util.py
diff --git a/src/libpakfire/archive.c b/src/libpakfire/archive.c
new file mode 100644 (file)
index 0000000..4576c28
--- /dev/null
@@ -0,0 +1,461 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2014 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 <assert.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+// libarchive
+#include <archive.h>
+#include <archive_entry.h>
+
+#include <pakfire/archive.h>
+#include <pakfire/errno.h>
+#include <pakfire/file.h>
+#include <pakfire/util.h>
+
+static void configure_archive(struct archive* a) {
+       archive_read_support_filter_all(a);
+       archive_read_support_format_all(a);     
+}
+
+static int archive_open(PakfireArchive archive, struct archive** a) {
+       *a = archive_read_new();
+       configure_archive(*a);
+
+       if (archive_read_open_filename(*a, archive->path, PAKFIRE_ARCHIVE_BLOCKSIZE) == ARCHIVE_OK) {
+               return 0;
+       }
+
+       archive_read_free(*a);
+       *a = NULL;
+
+       return -1;
+}
+
+static void archive_close(struct archive* a) {
+       archive_read_close(a);
+       archive_read_free(a);
+}
+
+static int archive_read(struct archive* a, void** data, size_t* data_size) {
+       *data = NULL;
+       *data_size = 0;
+
+       for (;;) {
+               *data = pakfire_realloc(*data, *data_size + PAKFIRE_ARCHIVE_BLOCKSIZE);
+
+               ssize_t size = archive_read_data(a, *data + *data_size,
+                       PAKFIRE_ARCHIVE_BLOCKSIZE);
+
+               if (size == 0)
+                       break;
+
+               if (size < 0) {
+                       pakfire_free(*data);
+                       *data = NULL;
+
+                       return 1;
+               }
+
+               *data_size += size;
+       }
+
+       return 0;
+}
+
+static int find_archive_entry(struct archive_entry** entry, struct archive* a, const char* filename) {
+       int r;
+
+       while ((r = archive_read_next_header(a, entry)) == ARCHIVE_OK) {
+               const char* entry_name = archive_entry_pathname(*entry);
+
+               if (strcmp(entry_name, filename) == 0) {
+                       return 0;
+               }
+       }
+
+       *entry = NULL;
+       return 1;
+}
+
+static ssize_t payload_archive_read(struct archive* a, void* client_data, const void** buf) {
+       struct payload_archive_data* data = client_data;
+       *buf = data->buffer;
+
+       return archive_read_data(data->archive, data->buffer, sizeof(data->buffer));
+}
+
+static int payload_archive_close(struct archive* a, void* client_data) {
+       struct payload_archive_data* data = client_data;
+
+       pakfire_free(data);
+
+       return ARCHIVE_OK;
+}
+
+static int payload_archive_open(struct archive** a, struct archive* source_archive) {
+       *a = archive_read_new();
+       configure_archive(*a);
+
+       struct payload_archive_data* data = pakfire_calloc(1, sizeof(*data));
+       data->archive = source_archive;
+
+       archive_read_set_callback_data(*a, data);
+       archive_read_set_read_callback(*a, payload_archive_read);
+       archive_read_set_close_callback(*a, payload_archive_close);
+
+       return archive_read_open1(*a);
+}
+
+PakfireArchive pakfire_archive_create() {
+       PakfireArchive archive = pakfire_calloc(1, sizeof(*archive));
+       if (archive) {
+               archive->format = -1;
+       }
+
+       return archive;
+}
+
+void pakfire_archive_free(PakfireArchive archive) {
+       if (archive->path)
+               pakfire_free(archive->path);
+
+       pakfire_free(archive);
+}
+
+static int pakfire_archive_parse_entry_format(PakfireArchive archive,
+               struct archive* a, struct archive_entry* e) {
+       char format[PAKFIRE_ARCHIVE_FORMAT_SIZE + 1];
+       format[PAKFIRE_ARCHIVE_FORMAT_SIZE] = '\0';
+
+       archive_read_data(a, &format, PAKFIRE_ARCHIVE_FORMAT_SIZE);
+       archive->format = atoi(format);
+
+       return (archive->format < 0);
+}
+
+static int pakfire_archive_parse_entry_metadata(PakfireArchive archive,
+               struct archive* a, struct archive_entry* e) {
+       void* data;
+       size_t data_size;
+
+       int r = archive_read(a, &data, &data_size);
+       if (r) {
+               return 1;
+       }
+
+       #warning actually parse this
+
+       pakfire_free(data);
+
+       return 0;
+}
+
+static int pakfire_archive_parse_entry_filelist(PakfireArchive archive,
+               struct archive* a, struct archive_entry* e) {
+       char* data;
+       size_t data_size;
+
+       int r = archive_read(a, (void**)&data, &data_size);
+       if (r) {
+               return 1;
+       }
+
+       // Terminate string.
+       data[data_size] = '\0';
+
+       if (data_size > 0) {
+               archive->filelist = pakfire_file_parse_from_file(data, archive->format);
+       }
+
+       pakfire_free(data);
+
+       return 0;
+}
+
+static int pakfire_archive_read_metadata(PakfireArchive archive, struct archive* a) {
+       int ret;
+
+       struct archive_entry* entry;
+       while ((ret = archive_read_next_header(a, &entry)) == ARCHIVE_OK) {
+               const char* entry_name = archive_entry_pathname(entry);
+
+               /* The first file in a pakfire package file must be
+                * the pakfire-format file, so we know with what version of
+                * the package format we are dealing with.
+                */
+               if (archive->format < 0) {
+                       if (strcmp(PAKFIRE_ARCHIVE_FN_FORMAT, entry_name) == 0) {
+                               ret = pakfire_archive_parse_entry_format(archive, a, entry);
+                               if (ret)
+                                       return PAKFIRE_E_PKG_INVALID;
+
+                       } else {
+                               return PAKFIRE_E_PKG_INVALID;
+                       }
+
+               // If the format is set, we can go on...
+               } else {
+                       // Parse the metadata
+                       if (strcmp(PAKFIRE_ARCHIVE_FN_METADATA, entry_name) == 0) {
+                               ret = pakfire_archive_parse_entry_metadata(archive, a, entry);
+                               if (ret)
+                                       return PAKFIRE_E_PKG_INVALID;
+
+                       // Parse the filelist
+                       } else if (strcmp(PAKFIRE_ARCHIVE_FN_FILELIST, entry_name) == 0) {
+                               ret = pakfire_archive_parse_entry_filelist(archive, a, entry);
+                               if (ret)
+                                       return PAKFIRE_E_PKG_INVALID;
+                       }
+               }
+       }
+
+       return 0;
+}
+
+static int archive_copy_data(struct archive* in, struct archive* out) {
+       int r;
+       const void* buff;
+
+       size_t size;
+       off_t offset;
+
+       for (;;) {
+               r = archive_read_data_block(in, &buff, &size, &offset);
+               if (r == ARCHIVE_EOF)
+                       break;
+
+               if (r != ARCHIVE_OK)
+                       return r;
+
+               r = archive_write_data_block(out, buff, size, offset);
+               if (r != ARCHIVE_OK)
+                       return r;
+       }
+
+       return 0;
+}
+
+static int archive_extract(struct archive* a, const char* prefix) {
+       struct archive_entry* entry;
+       int r;
+
+       // Unpack to the root filesystem if no prefix is given.
+       if (!prefix)
+               prefix = "/";
+
+       struct archive* ext = archive_write_disk_new();
+
+       // Set flags for extracting contents.
+       int flags = 0;
+       flags |= ARCHIVE_EXTRACT_ACL;
+       flags |= ARCHIVE_EXTRACT_FFLAGS;
+       flags |= ARCHIVE_EXTRACT_OWNER;
+       flags |= ARCHIVE_EXTRACT_PERM;
+       flags |= ARCHIVE_EXTRACT_SPARSE;
+       flags |= ARCHIVE_EXTRACT_TIME;
+       flags |= ARCHIVE_EXTRACT_UNLINK;
+       flags |= ARCHIVE_EXTRACT_XATTR;
+
+       archive_write_disk_set_options(ext, flags);
+       archive_write_disk_set_standard_lookup(ext);
+
+       char* pathname = NULL;
+       for (;;) {
+               r = archive_read_next_header(a, &entry);
+
+               // Reached the end of the archive.
+               if (r == ARCHIVE_EOF)
+                       break;
+
+               // Prepend the prefix to the path the file is extracted to.
+               if (prefix) {
+                       const char* archive_pathname = archive_entry_pathname(entry);
+                       pathname = pakfire_path_join(prefix, archive_pathname);
+
+                       archive_entry_set_pathname(entry, pathname);
+               }
+
+               r = archive_write_header(ext, entry);
+               if (r != ARCHIVE_OK)
+                       goto out;
+
+               size_t size = archive_entry_size(entry);
+               if (size > 0) {
+                       r = archive_copy_data(a, ext);
+
+                       if (r != ARCHIVE_OK)
+                               goto out;
+               }
+
+#warning need to handle extended attributes
+#if 0
+               const char* name;
+               const void* data;
+               size_t size;
+
+               while (archive_entry_xattr_next(entry, &name, &data, &size) == ARCHIVE_OK) {
+                       printf("name=%s\n", name);
+               }
+#endif
+
+               r = archive_write_finish_entry(ext);
+
+               pakfire_free(pathname);
+       }
+
+out:
+       archive_write_close(ext);
+       archive_write_free(ext);
+
+       return r;
+}
+
+
+PakfireArchive pakfire_archive_open(const char* path) {
+       PakfireArchive archive = pakfire_archive_create();
+       archive->path = pakfire_strdup(path);
+
+       // Open the archive file for reading.
+       struct archive* a;
+       int r = archive_open(archive, &a);
+       if (r) {
+               pakfire_errno = r;
+               goto error;
+       }
+
+       // Parse all entries in the archive.
+       r = pakfire_archive_read_metadata(archive, a);
+       if (r) {
+               pakfire_errno = r;
+               return NULL;
+       }
+
+       return archive;
+
+error:
+       if (a)
+               archive_read_free(a);
+
+       pakfire_archive_free(archive);
+
+       return NULL;
+}
+
+static struct archive* archive_open_payload(struct archive* a) {
+       struct archive_entry* entry;
+       int r;
+
+       r = find_archive_entry(&entry, a, PAKFIRE_ARCHIVE_FN_PAYLOAD);
+       if (r) {
+               pakfire_errno = r;
+               return NULL;
+       }
+
+       struct archive* payload_archive;
+       r = payload_archive_open(&payload_archive, a);
+       if (r) {
+               pakfire_errno = r;
+               return NULL;
+       }
+
+       return payload_archive;
+}
+
+int pakfire_archive_read(PakfireArchive archive, const char* filename,
+               void** data, size_t* data_size, int flags) {
+       struct archive* a;
+       struct archive* pa = NULL;
+       struct archive_entry* entry;
+
+       int r = archive_open(archive, &a);
+       if (r) {
+               pakfire_errno = r;
+               goto out;
+       }
+
+       int use_payload = (flags & PAKFIRE_ARCHIVE_USE_PAYLOAD);
+
+       if (use_payload) {
+               pa = archive_open_payload(a);
+
+               // Strip leading / from filenames, because the payload does
+               // not have leading slashes.
+               if (*filename == '/')
+                       filename++;
+       }
+
+       r = find_archive_entry(&entry, use_payload ? pa : a, filename);
+       if (r) {
+               goto out;
+       }
+
+       r = archive_read(use_payload ? pa : a, data, data_size);
+
+out:
+       if (pa)
+               archive_close(pa);
+
+       archive_close(a);
+
+       return r;
+}
+
+int pakfire_archive_extract(PakfireArchive archive, const char* prefix, int flags) {
+       struct archive* a;
+       struct archive* pa = NULL;
+
+       int r = archive_open(archive, &a);
+       if (r) {
+               pakfire_errno = r;
+               return 1;
+       }
+
+       int use_payload = (flags & PAKFIRE_ARCHIVE_USE_PAYLOAD);
+
+       if (use_payload)
+               pa = archive_open_payload(a);
+
+       r = archive_extract(use_payload ? pa : a, prefix);
+
+       if (pa)
+               archive_close(pa);
+
+       archive_close(a);
+
+       return r;
+}
+
+const char* pakfire_archive_get_path(PakfireArchive archive) {
+       return archive->path;
+}
+
+unsigned int pakfire_archive_get_format(PakfireArchive archive) {
+       return archive->format;
+}
+
+PakfireFile pakfire_archive_get_filelist(PakfireArchive archive) {
+       return archive->filelist;
+}
diff --git a/src/libpakfire/cache.c b/src/libpakfire/cache.c
new file mode 100644 (file)
index 0000000..5b99c1a
--- /dev/null
@@ -0,0 +1,163 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2013 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 <assert.h>
+#include <errno.h>
+#include <libgen.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <pakfire/cache.h>
+#include <pakfire/constants.h>
+#include <pakfire/package.h>
+#include <pakfire/types.h>
+#include <pakfire/util.h>
+
+PakfireCache pakfire_cache_create(PakfirePool pool, const char* path) {
+       PakfireCache cache = pakfire_calloc(1, sizeof(*cache));
+
+       cache->pool = pool;
+       cache->path = pakfire_strdup(path);
+
+       return cache;
+}
+
+void pakfire_cache_free(PakfireCache cache) {
+       pakfire_free(cache->path);
+       pakfire_free(cache);
+}
+
+const char* pakfire_cache_get_path(PakfireCache cache) {
+       return cache->path;
+}
+
+char* pakfire_cache_get_full_path(PakfireCache cache, const char* path) {
+       const char* cache_path = pakfire_cache_get_path(cache);
+
+       return pakfire_path_join(cache_path, path);
+}
+
+static int pakfire_cache_stat(PakfireCache cache, const char* filename, struct stat* buf) {
+       char* cache_filename = pakfire_cache_get_full_path(cache, filename);
+
+       int r = stat(cache_filename, buf);
+       pakfire_free(cache_filename);
+
+       return r;
+}
+
+int pakfire_cache_has_file(PakfireCache cache, const char* filename) {
+       struct stat buf;
+       int r = pakfire_cache_stat(cache, filename, &buf);
+
+       // Just check if stat() was sucessful.
+       return (r == 0);
+}
+
+char* pakfire_cache_get_package_path(PakfireCache cache, PakfirePackage pkg) {
+       char buffer[STRING_SIZE] = "";
+
+       const char* filename = pakfire_package_get_filename(pkg);
+       const char* checksum = pakfire_package_get_checksum(pkg);
+
+       if (strlen(checksum) < 3)
+               return NULL;
+
+       snprintf(buffer, sizeof(buffer), "%c%c/%s/%s", checksum[0], checksum[1],
+               checksum + 2, filename);
+
+       return pakfire_strdup(buffer);
+}
+
+int pakfire_cache_has_package(PakfireCache cache, PakfirePackage pkg) {
+       char* filename = pakfire_cache_get_package_path(cache, pkg);
+
+       int r = pakfire_cache_has_file(cache, filename);
+       pakfire_free(filename);
+
+       return r;
+}
+
+int pakfire_cache_age(PakfireCache cache, const char* filename) {
+       struct stat buf;
+       int r = pakfire_cache_stat(cache, filename, &buf);
+
+       if (r == 0) {
+               // Get timestamp.
+               time_t now = time(NULL);
+
+               // Calculate the difference since the file has been created and now.
+               time_t age = now - buf.st_ctime;
+
+               return (int)age;
+       }
+
+       return -1;
+}
+
+static int pakfire_cache_mkdir(PakfireCache cache, const char* path, mode_t mode) {
+       int r = 0;
+
+       if ((strcmp(path, "/") == 0) || (strcmp(path, ".") == 0)) {
+               return 0;
+       }
+
+       // If parent does not exists, we try to create it.
+       char* parent_path = pakfire_dirname(path);
+       r = access(parent_path, F_OK);
+       if (r) {
+               r = pakfire_cache_mkdir(cache, parent_path, mode);
+       }
+       pakfire_free(parent_path);
+
+       if (!r) {
+               // Finally, create the directory we want.
+               r = mkdir(path, mode);
+
+               if (r) {
+                       switch (errno) {
+                               // If the directory already exists, this is fine.
+                               case EEXIST:
+                                       r = 0;
+                                       break;
+                       }
+               }
+       }
+
+       return r;
+}
+
+FILE* pakfire_cache_open(PakfireCache cache, const char* filename, const char* flags) {
+       assert(filename);
+
+       char* cache_filename = pakfire_cache_get_full_path(cache, filename);
+
+       char* cache_dirname = pakfire_dirname(cache_filename);
+       pakfire_cache_mkdir(cache, cache_dirname, S_IRUSR|S_IWUSR|S_IXUSR);
+
+       FILE* fp = fopen(cache_filename, flags);
+
+       pakfire_free(cache_filename);
+       pakfire_free(cache_dirname);
+
+       return fp;
+}
diff --git a/src/libpakfire/errno.c b/src/libpakfire/errno.c
new file mode 100644 (file)
index 0000000..1f34a84
--- /dev/null
@@ -0,0 +1,27 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2013 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 "errno.h"
+
+__thread int pakfire_errno = 0;
+
+int pakfire_get_errno(void) {
+       return pakfire_errno;
+}
diff --git a/src/libpakfire/file.c b/src/libpakfire/file.c
new file mode 100644 (file)
index 0000000..a2382f6
--- /dev/null
@@ -0,0 +1,474 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2014 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 <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <tar.h>
+#include <time.h>
+
+#include <pakfire/constants.h>
+#include <pakfire/file.h>
+#include <pakfire/util.h>
+
+PakfireFile pakfire_file_create() {
+       PakfireFile file = pakfire_calloc(1, sizeof(*file));
+       if (file) {
+               file->name = NULL;
+
+               file->prev = NULL;
+               file->next = NULL;
+       }
+
+       return file;
+}
+
+void pakfire_file_free(PakfireFile file) {
+       if (file->name)
+               pakfire_free(file->name);
+
+       if (file->user)
+               pakfire_free(file->user);
+       if (file->group)
+               pakfire_free(file->group);
+
+       // Update pointers in the previous and next element in the list.
+       if (file->next)
+               file->next->prev = NULL;
+       if (file->prev)
+               file->prev->next = NULL;
+
+       pakfire_free(file);
+}
+
+void pakfire_file_free_all(PakfireFile file) {
+       file = pakfire_file_get_first(file);
+
+       while (file) {
+               PakfireFile next = file->next;
+               pakfire_file_free(file);
+
+               file = next;
+       }
+}
+
+int pakfire_file_cmp(PakfireFile file1, PakfireFile file2) {
+       const char* name1 = pakfire_file_get_name(file1);
+       const char* name2 = pakfire_file_get_name(file2);
+
+       return strcmp(name1, name2);
+}
+
+void pakfire_file_swap(PakfireFile file1, PakfireFile file2) {
+       PakfireFile file_prev = file1->prev;
+       PakfireFile file_next = file2->next;
+
+       if (file_prev)
+               file_prev->next = file2;
+       file2->prev = file_prev;
+
+       if (file_next)
+               file_next->prev = file1;
+       file1->next = file_next;
+
+       file2->next = file1;
+       file1->prev = file2;
+}
+
+PakfireFile pakfire_file_sort(PakfireFile head) {
+       unsigned int count = pakfire_file_count(head);
+
+       for (unsigned int i = 0; i < count; i++) {
+               PakfireFile file = head;
+               PakfireFile next = pakfire_file_get_next(file);
+
+               while (next) {
+                       if (pakfire_file_cmp(file, next) > 0) {
+                               if (head == file)
+                                       head = next;
+
+                               pakfire_file_swap(file, next);
+                       }
+
+                       file = next;
+                       next = pakfire_file_get_next(file);
+               }
+       }
+
+       return head;
+}
+
+PakfireFile pakfire_file_get_prev(PakfireFile file) {
+       return file->prev;
+}
+
+PakfireFile pakfire_file_get_next(PakfireFile file) {
+       return file->next;
+}
+
+PakfireFile pakfire_file_get_first(PakfireFile file) {
+       if (file->prev)
+               return pakfire_file_get_first(file->prev);
+
+       return file;
+}
+
+PakfireFile pakfire_file_get_last(PakfireFile file) {
+       if (file->next)
+               return pakfire_file_get_last(file->next);
+
+       return file;
+}
+
+static PakfireFile __pakfire_file_append(PakfireFile file, PakfireFile appended_file) {
+       // Get the last file in the queue.
+       file = pakfire_file_get_last(file);
+
+       // Set the links.
+       file->next = appended_file;
+       appended_file->prev = file;
+
+       return appended_file;
+}
+
+PakfireFile pakfire_file_append(PakfireFile file) {
+       // Create a new file object.
+       PakfireFile appended_file = pakfire_file_create();
+
+       return __pakfire_file_append(file, appended_file);
+}
+
+unsigned int pakfire_file_count(PakfireFile file) {
+       unsigned int counter = 0;
+
+       while (file) {
+               file = pakfire_file_get_next(file);
+               ++counter;
+       }
+
+       return counter;
+}
+
+static char pakfire_file_sprintf_type(PakfireFile file) {
+       if (pakfire_file_is_dir(file))
+               return 'd';
+
+       if (pakfire_file_is_symlink(file))
+               return 'l';
+
+       if (pakfire_file_is_char(file))
+               return 'c';
+
+       return '-';
+}
+
+static char* pakfire_file_format_perms(PakfireFile file) {
+       char buffer[11];
+
+       mode_t mode = pakfire_file_get_mode(file);
+
+       buffer[0] = pakfire_file_sprintf_type(file);
+       buffer[1] = (S_IRUSR & mode) ? 'r' : '-';
+       buffer[2] = (S_IWUSR & mode) ? 'w' : '-';
+       buffer[3] = (S_IXUSR & mode) ? 'x' : '-';
+       buffer[4] = (S_IRGRP & mode) ? 'r' : '-';
+       buffer[5] = (S_IWGRP & mode) ? 'w' : '-';
+       buffer[6] = (S_IXGRP & mode) ? 'x' : '-';
+       buffer[7] = (S_IROTH & mode) ? 'r' : '-';
+       buffer[8] = (S_IWOTH & mode) ? 'w' : '-';
+       buffer[9] = (S_IXOTH & mode) ? 'x' : '-';
+       buffer[10] = '\0';
+
+       #warning TODO SUID bits, etc...
+
+       return pakfire_strdup(buffer);
+}
+
+static char* pakfire_file_format_mtime(PakfireFile file) {
+       struct tm* timer = gmtime((time_t *)&file->time);
+
+       char buffer[STRING_SIZE];
+       strftime(buffer, sizeof(buffer), "%d %b %Y %T", timer);
+
+       return pakfire_strdup(buffer);
+}
+
+void pakfire_file_sprintf(PakfireFile file, char* str, size_t len) {
+       const char* name = pakfire_file_get_name(file);
+       ssize_t size = pakfire_file_get_size(file);
+
+       const char* user  = pakfire_file_get_user(file);
+       const char* group = pakfire_file_get_group(file);
+
+       char* perms = pakfire_file_format_perms(file);
+       char* mtime = pakfire_file_format_mtime(file);
+
+       snprintf(str, len, "%s %-8s %-8s %8d %s %s", perms, user, group,
+               (int)size, mtime, name);
+
+       pakfire_free(perms);
+       pakfire_free(mtime);
+}
+
+const char* pakfire_file_get_name(PakfireFile file) {
+       return file->name;
+}
+
+void pakfire_file_set_name(PakfireFile file, const char* name) {
+       if (file->name)
+               pakfire_free(file->name);
+
+       if (*name == '/') {
+               file->name = pakfire_strdup(name);
+       } else {
+               asprintf(&file->name, "/%s", name);
+       }
+}
+
+char pakfire_file_get_type(PakfireFile file) {
+       return file->type;
+}
+
+void pakfire_file_set_type(PakfireFile file, char type) {
+       file->type = type;
+}
+
+int pakfire_file_is_file(PakfireFile file) {
+       return (file->type == REGTYPE) || (file->type == AREGTYPE);
+}
+
+int pakfire_file_is_link(PakfireFile file) {
+       return (file->type == LNKTYPE);
+}
+
+int pakfire_file_is_symlink(PakfireFile file) {
+       return (file->type == SYMTYPE);
+}
+
+int pakfire_file_is_char(PakfireFile file) {
+       return (file->type == CHRTYPE);
+}
+
+int pakfire_file_is_block(PakfireFile file) {
+       return (file->type == BLKTYPE);
+}
+
+int pakfire_file_is_dir(PakfireFile file) {
+       return (file->type == DIRTYPE);
+}
+
+ssize_t pakfire_file_get_size(PakfireFile file) {
+       return file->size;
+}
+
+void pakfire_file_set_size(PakfireFile file, ssize_t size) {
+       file->size = size;
+}
+
+const char* pakfire_file_get_user(PakfireFile file) {
+       return file->user;
+}
+
+void pakfire_file_set_user(PakfireFile file, const char* user) {
+       file->user = pakfire_strdup(user);
+}
+
+const char* pakfire_file_get_group(PakfireFile file) {
+       return file->group;
+}
+
+void pakfire_file_set_group(PakfireFile file, const char* group) {
+       file->group = pakfire_strdup(group);
+}
+
+mode_t pakfire_file_get_mode(PakfireFile file) {
+       return file->mode;
+}
+
+void pakfire_file_set_mode(PakfireFile file, mode_t mode) {
+       file->mode = mode;
+}
+
+time_t pakfire_file_get_time(PakfireFile file) {
+       return file->time;
+}
+
+void pakfire_file_set_time(PakfireFile file, time_t time) {
+       file->time = time;
+}
+
+const char* pakfire_file_get_chksum(PakfireFile file) {
+       return file->chksum;
+}
+
+void pakfire_file_set_chksum(PakfireFile file, const char* chksum) {
+       file->chksum = pakfire_strdup(chksum);
+}
+
+static PakfireFile pakfire_file_parse_line(char* line, unsigned int format) {
+       unsigned int i = 0;
+
+       PakfireFile file = pakfire_file_create();
+       ssize_t size;
+       mode_t mode;
+       time_t time;
+
+       unsigned int bytes_read = 0;
+
+       char* word = strtok(line, " ");
+       while (word) {
+               if (format >= 4) {
+                       switch (i) {
+                               // type
+                               case 0:
+                                       pakfire_file_set_type(file, *word);
+                                       break;
+
+                               // size
+                               case 1:
+                                       size = atoi(word);
+                                       pakfire_file_set_size(file, size);
+                                       break;
+
+                               // user
+                               case 2:
+                                       pakfire_file_set_user(file, word);
+                                       break;
+
+                               // group
+                               case 3:
+                                       pakfire_file_set_group(file, word);
+                                       break;
+
+                               // mode
+                               case 4:
+                                       mode = atoi(word);
+                                       pakfire_file_set_mode(file, mode);
+                                       break;
+
+                               // time
+                               case 5:
+                                       time = atoi(word);
+                                       pakfire_file_set_time(file, time);
+                                       break;
+
+                               // checksum
+                               case 6:
+                                       pakfire_file_set_chksum(file, word);
+                                       break;
+
+                               // name
+                               #warning handle filenames with spaces
+                               case 8:
+                                       pakfire_file_set_name(file, line + bytes_read);
+                                       break;
+                       }
+
+               } else if (format >= 3) {
+                       switch (i) {
+                               // name
+                               case 0:
+                                       pakfire_file_set_name(file, word);
+                                       break;
+
+                               // type
+                               case 1:
+                                       pakfire_file_set_type(file, *word);
+                                       break;
+
+                               // size
+                               case 2:
+                                       size = atoi(word);
+                                       pakfire_file_set_size(file, size);
+                                       break;
+
+                               // user
+                               case 3:
+                                       pakfire_file_set_user(file, word);
+                                       break;
+
+                               // group
+                               case 4:
+                                       pakfire_file_set_group(file, word);
+                                       break;
+
+                               // mode
+                               case 5:
+                                       mode = atoi(word);
+                                       pakfire_file_set_mode(file, mode);
+                                       break;
+
+                               // time
+                               case 6:
+                                       time = atoi(word);
+                                       pakfire_file_set_time(file, time);
+                                       break;
+
+                               // checksum
+                               case 7:
+                                       pakfire_file_set_chksum(file, word);
+                                       break;
+                       }
+               }
+
+               // Count the bytes of the line that have been processed so far
+               // (Skip all padding spaces)
+               bytes_read += strlen(word) + 1;
+               while (*(line + bytes_read) == ' ')
+                       bytes_read += 1;
+
+               word = strtok(NULL, " ");
+               ++i;
+       }
+
+       return file;
+}
+
+PakfireFile pakfire_file_parse_from_file(const char* list, unsigned int format) {
+       PakfireFile head = NULL;
+
+       char* plist = (char *)list;
+       char line[32 * 1024];
+
+       for (;;) {
+               line[0] = '\0';
+
+               pakfire_sgets(line, sizeof(line), &plist);
+               pakfire_remove_trailing_newline(line);
+
+               if (*line == '\0')
+                       break;
+
+               PakfireFile file = pakfire_file_parse_line(line, format);
+
+               if (!file)
+                       continue;
+
+               if (head)
+                       file = __pakfire_file_append(head, file);
+               else
+                       head = file;
+       }
+
+       return head;
+}
diff --git a/src/libpakfire/filelist.c b/src/libpakfire/filelist.c
new file mode 100644 (file)
index 0000000..56c799d
--- /dev/null
@@ -0,0 +1,68 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2014 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 <pakfire/file.h>
+#include <pakfire/filelist.h>
+#include <pakfire/util.h>
+
+PakfireFilelist pakfire_filelist_create(PakfirePackage pkg) {
+       PakfireFilelist list = pakfire_calloc(1, sizeof(*list));
+       if (list) {
+               list->pkg = pkg;
+
+               list->first = NULL;
+               list->last  = NULL;
+       }
+
+       return list;
+}
+
+void pakfire_filelist_free(PakfireFilelist list) {
+       pakfire_filelist_remove_all();
+       pakfire_free(list);
+}
+
+static void pakfire_filelist_remove_first(PakfireFilelist list) {
+       if (!list->first)
+               return;
+
+       PakfireFile file = list->first;
+
+       list->first = file->next;
+       list->first->prev = NULL;
+
+       pakfire_file_free(file);
+}
+
+void pakfire_filelist_remove_all(PakfireFilelist list) {
+       while (list->first) {
+               pakfire_filelist_remove_first(list);
+       }
+}
+
+void pakfire_filelist_append(PakfireFilelist list, PakfireFile file) {
+       if (list->first && list->last) {
+               list->last->next = file;
+               list->last = file;
+       } else {
+               list->first = file;
+               list->last  = file;
+       }
+}
diff --git a/src/libpakfire/filter.c b/src/libpakfire/filter.c
new file mode 100644 (file)
index 0000000..95dbd2d
--- /dev/null
@@ -0,0 +1,34 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2013 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 <pakfire/filter.h>
+#include <pakfire/types.h>
+#include <pakfire/util.h>
+
+PakfireFilter pakfire_filter_create(void) {
+       PakfireFilter filter = pakfire_calloc(1, sizeof(*filter));
+
+       return filter;
+}
+
+void pakfire_filter_free(PakfireFilter filter) {
+       pakfire_free(filter->match);
+       pakfire_free(filter);
+}
diff --git a/src/libpakfire/include/pakfire/archive.h b/src/libpakfire/include/pakfire/archive.h
new file mode 100644 (file)
index 0000000..3e3e65d
--- /dev/null
@@ -0,0 +1,73 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2014 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_ARCHIVE_H
+#define PAKFIRE_ARCHIVE_H
+
+#include <archive.h>
+
+#include <pakfire/types.h>
+
+PakfireArchive pakfire_archive_create();
+void pakfire_archive_free(PakfireArchive archive);
+
+PakfireArchive pakfire_archive_open(const char* path);
+
+int pakfire_archive_read(PakfireArchive archive, const char* filename,
+       void** data, size_t* data_size, int flags);
+int pakfire_archive_extract(PakfireArchive archive, const char* prefix, int flags);
+
+const char* pakfire_archive_get_path(PakfireArchive archive);
+
+unsigned int pakfire_archive_get_format(PakfireArchive archive);
+
+PakfireFile pakfire_archive_get_filelist(PakfireArchive archive);
+
+enum pakfire_archive_flags {
+       PAKFIRE_ARCHIVE_USE_PAYLOAD = 1 << 0,
+};
+
+#define PAKFIRE_ARCHIVE_FN_FILELIST                    "filelist"
+#define PAKFIRE_ARCHIVE_FN_FORMAT                      "pakfire-format"
+#define PAKFIRE_ARCHIVE_FN_METADATA                    "info"
+#define PAKFIRE_ARCHIVE_FN_PAYLOAD                     "data.img"
+
+#ifdef PAKFIRE_PRIVATE
+
+#define PAKFIRE_ARCHIVE_BLOCKSIZE                      10240
+#define PAKFIRE_ARCHIVE_FORMAT_SIZE                    5
+
+struct _PakfireArchive {
+       char* path;
+
+       // metadata
+       int format;
+
+       PakfireFile filelist;
+};
+
+struct payload_archive_data {
+       struct archive* archive;
+       char buffer[PAKFIRE_ARCHIVE_BLOCKSIZE];
+};
+
+#endif
+
+#endif /* PAKFIRE_ARCHIVE_H */
diff --git a/src/libpakfire/include/pakfire/cache.h b/src/libpakfire/include/pakfire/cache.h
new file mode 100644 (file)
index 0000000..c302c56
--- /dev/null
@@ -0,0 +1,50 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2013 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_CACHE_H
+#define PAKFIRE_CACHE_H
+
+#include <stdio.h>
+
+#include <pakfire/types.h>
+
+PakfireCache pakfire_cache_create(PakfirePool pool, const char* path);
+void pakfire_cache_free(PakfireCache cache);
+
+const char* pakfire_cache_get_path(PakfireCache cache);
+char* pakfire_cache_get_full_path(PakfireCache cache, const char* path);
+
+int pakfire_cache_has_file(PakfireCache cache, const char* filename);
+char* pakfire_cache_get_package_path(PakfireCache cache, PakfirePackage pkg);
+int pakfire_cache_has_package(PakfireCache cache, PakfirePackage pkg);
+int pakfire_cache_age(PakfireCache cache, const char* filename);
+
+FILE* pakfire_cache_open(PakfireCache cache, const char* filename, const char* flags);
+
+#ifdef PAKFIRE_PRIVATE
+
+struct _PakfireCache {
+       PakfirePool pool;
+       char* path;
+};
+
+#endif
+
+#endif /* PAKFIRE_CACHE_H */
diff --git a/src/libpakfire/include/pakfire/constants.h b/src/libpakfire/include/pakfire/constants.h
new file mode 100644 (file)
index 0000000..8f587c0
--- /dev/null
@@ -0,0 +1,28 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2013 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_CONSTANTS_H
+#define PAKFIRE_CONSTANTS_H
+
+#define STRING_SIZE 1024
+
+#define PAKFIRE_REPO_SYSTEM_NAME "@system"
+
+#endif /* PAKFIRE_CONSTANTS_H */
diff --git a/src/libpakfire/include/pakfire/errno.h b/src/libpakfire/include/pakfire/errno.h
new file mode 100644 (file)
index 0000000..4ac4111
--- /dev/null
@@ -0,0 +1,39 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2013 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_ERRNO_H
+#define PAKFIRE_ERRNO_H
+
+enum _pakfire_errors {
+       PAKFIRE_E_FAILED = 1,                                   // general runtime error
+       PAKFIRE_E_OP,                                                   // client programming error
+       PAKFIRE_E_LIBSOLV,                                              // error propagated from libsolv
+       PAKFIRE_E_IO,                                                   // I/O error
+       PAKFIRE_E_ARCH,
+       PAKFIRE_E_SELECTOR,
+       PAKFIRE_E_PKG_INVALID,                                  // when a package is not in the pakfire format
+       PAKFIRE_E_EOF,
+};
+
+extern __thread int pakfire_errno;
+
+int pakfire_get_errno(void);
+
+#endif /* PAKFIRE_ERRNO_H */
diff --git a/src/libpakfire/include/pakfire/file.h b/src/libpakfire/include/pakfire/file.h
new file mode 100644 (file)
index 0000000..9d24d84
--- /dev/null
@@ -0,0 +1,108 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2014 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_FILE_H
+#define PAKFIRE_FILE_H
+
+#include <sys/types.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <pakfire/types.h>
+
+PakfireFile pakfire_file_create();
+void pakfire_file_free(PakfireFile file);
+void pakfire_file_free_all(PakfireFile file);
+
+int pakfire_file_cmp(PakfireFile file1, PakfireFile file2);
+void pakfire_file_swap(PakfireFile file1, PakfireFile file2);
+PakfireFile pakfire_file_sort(PakfireFile head);
+
+PakfireFile pakfire_file_get_prev(PakfireFile file);
+PakfireFile pakfire_file_get_next(PakfireFile file);
+PakfireFile pakfire_file_get_first(PakfireFile file);
+PakfireFile pakfire_file_get_last(PakfireFile file);
+
+PakfireFile pakfire_file_append(PakfireFile file);
+
+unsigned int pakfire_file_count(PakfireFile file);
+
+void pakfire_file_sprintf(PakfireFile file, char* str, size_t len);
+
+const char* pakfire_file_get_name(PakfireFile file);
+void pakfire_file_set_name(PakfireFile file, const char* name);
+
+char pakfire_file_get_type(PakfireFile file);
+void pakfire_file_set_type(PakfireFile file, char type);
+
+int pakfire_file_is_file(PakfireFile file);
+int pakfire_file_is_link(PakfireFile file);
+int pakfire_file_is_symlink(PakfireFile file);
+int pakfire_file_is_char(PakfireFile file);
+int pakfire_file_is_block(PakfireFile file);
+int pakfire_file_is_dir(PakfireFile file);
+
+ssize_t pakfire_file_get_size(PakfireFile file);
+void pakfire_file_set_size(PakfireFile file, ssize_t size);
+
+const char* pakfire_file_get_user(PakfireFile file);
+void pakfire_file_set_user(PakfireFile file, const char* user);
+
+const char* pakfire_file_get_group(PakfireFile file);
+void pakfire_file_set_group(PakfireFile file, const char* group);
+
+mode_t pakfire_file_get_mode(PakfireFile file);
+void pakfire_file_set_mode(PakfireFile file, mode_t mode);
+
+time_t pakfire_file_get_time(PakfireFile file);
+void pakfire_file_set_time(PakfireFile file, time_t time);
+
+const char* pakfire_file_get_chksum(PakfireFile file);
+void pakfire_file_set_chksum(PakfireFile file, const char* chksum);
+
+PakfireFile pakfire_file_parse_from_file(const char* list, unsigned int format);
+
+#ifdef PAKFIRE_PRIVATE
+
+struct _PakfireFile {
+       char* name;
+       char type;
+       ssize_t size;
+
+       char* user;
+       char* group;
+
+       mode_t mode;
+       time_t time;
+
+       char* chksum;
+
+       #warning TODO capabilities, config, data
+       // capabilities
+       //int is_configfile;
+       //int is_datafile;
+
+       PakfireFile prev;
+       PakfireFile next;
+};
+
+#endif
+
+#endif /* PAKFIRE_FILE_H */
diff --git a/src/libpakfire/include/pakfire/filelist.h b/src/libpakfire/include/pakfire/filelist.h
new file mode 100644 (file)
index 0000000..737b0e7
--- /dev/null
@@ -0,0 +1,41 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2014 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_FILELIST_H
+#define PAKFIRE_FILELIST_H
+
+#include <pakfire/types.h>
+
+PakfireFilelist pakfire_filelist_create(PakfirePackage pkg);
+void pakfire_filelist_free(PakfireFilelist list);
+
+
+#ifdef PAKFIRE_PRIVATE
+
+struct _PakfireFilelist {
+       PakfirePackage pkg;
+
+       PakfireFile first;
+       PakfireFile last;
+};
+
+#endif
+
+#endif /* PAKFIRE_FILELIST_H */
diff --git a/src/libpakfire/include/pakfire/filter.h b/src/libpakfire/include/pakfire/filter.h
new file mode 100644 (file)
index 0000000..508d55a
--- /dev/null
@@ -0,0 +1,39 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2013 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_FILTER_H
+#define PAKFIRE_FILTER_H
+
+#include <pakfire/types.h>
+
+PakfireFilter pakfire_filter_create(void);
+void pakfire_filter_free(PakfireFilter filter);
+
+#ifdef PAKFIRE_PRIVATE
+
+struct _PakfireFilter {
+       int cmp_type;
+       int keyname;
+       char* match;
+};
+
+#endif
+
+#endif /* PAKFIRE_FILTER_H */
diff --git a/src/libpakfire/include/pakfire/i18n.h b/src/libpakfire/include/pakfire/i18n.h
new file mode 100644 (file)
index 0000000..0ea1e5d
--- /dev/null
@@ -0,0 +1,30 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2013 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_I18N_H
+#define PAKFIRE_I18N_H
+
+#include <libintl.h>
+
+#define PAKFIRE_TEXTDOMAIN "pakfire"
+
+#define _(x) dgettext(PAKFIRE_TEXTDOMAIN, x)
+
+#endif /* PAKFIRE_I18N_H */
diff --git a/src/libpakfire/include/pakfire/package.h b/src/libpakfire/include/pakfire/package.h
new file mode 100644 (file)
index 0000000..5cfc545
--- /dev/null
@@ -0,0 +1,167 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2013 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_PACKAGE_H
+#define PAKFIRE_PACKAGE_H
+
+#include <solv/pooltypes.h>
+
+#include <pakfire/relation.h>
+#include <pakfire/relationlist.h>
+#include <pakfire/pool.h>
+#include <pakfire/types.h>
+
+PakfirePackage pakfire_package_create(PakfirePool pool, Id id);
+PakfirePackage pakfire_package_create2(PakfirePool pool, PakfireRepo repo, const char* name, const char* evr, const char* arch);
+void pakfire_package_free(PakfirePackage pkg);
+
+int pakfire_package_identical(PakfirePackage pkg1, PakfirePackage pkg2);
+int pakfire_package_cmp(PakfirePackage pkg1, PakfirePackage pkg2);
+int pakfire_package_evr_cmp(PakfirePackage pkg1, PakfirePackage pkg2);
+
+Id pakfire_package_id(PakfirePackage pkg);
+
+char* pakfire_package_get_nevra(PakfirePackage pkg);
+const char* pakfire_package_get_name(PakfirePackage pkg);
+void pakfire_package_set_name(PakfirePackage pkg, const char* name);
+const char* pakfire_package_get_evr(PakfirePackage pkg);
+void pakfire_package_set_evr(PakfirePackage pkg, const char* evr);
+unsigned long pakfire_package_get_epoch(PakfirePackage pkg);
+const char* pakfire_package_get_version(PakfirePackage pkg);
+const char* pakfire_package_get_release(PakfirePackage pkg);
+const char* pakfire_package_get_arch(PakfirePackage pkg);
+void pakfire_package_set_arch(PakfirePackage pkg, const char* arch);
+
+const char* pakfire_package_get_uuid(PakfirePackage pkg);
+void pakfire_package_set_uuid(PakfirePackage pkg, const char* uuid);
+const char* pakfire_package_get_checksum(PakfirePackage pkg);
+void pakfire_package_set_checksum(PakfirePackage pkg, const char* checksum);
+const char* pakfire_package_get_summary(PakfirePackage pkg);
+void pakfire_package_set_summary(PakfirePackage pkg, const char* summary);
+const char* pakfire_package_get_description(PakfirePackage pkg);
+void pakfire_package_set_description(PakfirePackage pkg, const char* description);
+const char* pakfire_package_get_license(PakfirePackage pkg);
+void pakfire_package_set_license(PakfirePackage pkg, const char* license);
+const char* pakfire_package_get_url(PakfirePackage pkg);
+void pakfire_package_set_url(PakfirePackage pkg, const char* url);
+const char** pakfire_package_get_groups(PakfirePackage pkg);
+void pakfire_package_set_groups(PakfirePackage pkg, const char** grouplist);
+const char* pakfire_package_get_vendor(PakfirePackage pkg);
+void pakfire_package_set_vendor(PakfirePackage pkg, const char* vendor);
+const char* pakfire_package_get_maintainer(PakfirePackage pkg);
+void pakfire_package_set_maintainer(PakfirePackage pkg, const char* maintainer);
+const char* pakfire_package_get_filename(PakfirePackage pkg);
+void pakfire_package_set_filename(PakfirePackage pkg, const char* filename);
+int pakfire_package_is_installed(PakfirePackage pkg);
+unsigned long long pakfire_package_get_downloadsize(PakfirePackage pkg);
+void pakfire_package_set_downloadsize(PakfirePackage pkg, unsigned long long downloadsize);
+unsigned long long pakfire_package_get_installsize(PakfirePackage pkg);
+void pakfire_package_set_installsize(PakfirePackage pkg, unsigned long long installsize);
+unsigned long long pakfire_package_get_size(PakfirePackage pkg);
+const char* pakfire_package_get_buildhost(PakfirePackage pkg);
+void pakfire_package_set_buildhost(PakfirePackage pkg, const char* buildhost);
+unsigned long long pakfire_package_get_buildtime(PakfirePackage pkg);
+void pakfire_package_set_buildtime(PakfirePackage pkg, unsigned long long buildtime);
+unsigned long long pakfire_package_get_installtime(PakfirePackage pkg);
+
+PakfireRelationList pakfire_package_get_provides(PakfirePackage pkg);
+void pakfire_package_set_provides(PakfirePackage pkg, PakfireRelationList relationlist);
+void pakfire_package_add_provides(PakfirePackage pkg, PakfireRelation relation);
+PakfireRelationList pakfire_package_get_requires(PakfirePackage pkg);
+void pakfire_package_set_requires(PakfirePackage pkg, PakfireRelationList relationlist);
+void pakfire_package_add_requires(PakfirePackage pkg, PakfireRelation relation);
+PakfireRelationList pakfire_package_get_conflicts(PakfirePackage pkg);
+void pakfire_package_set_conflicts(PakfirePackage pkg, PakfireRelationList relationlist);
+void pakfire_package_add_conflicts(PakfirePackage pkg, PakfireRelation relation);
+PakfireRelationList pakfire_package_get_obsoletes(PakfirePackage pkg);
+void pakfire_package_set_obsoletes(PakfirePackage pkg, PakfireRelationList relationlist);
+void pakfire_package_add_obsoletes(PakfirePackage pkg, PakfireRelation relation);
+PakfireRelationList pakfire_package_get_recommends(PakfirePackage pkg);
+void pakfire_package_set_recommends(PakfirePackage pkg, PakfireRelationList relationlist);
+void pakfire_package_add_recommends(PakfirePackage pkg, PakfireRelation relation);
+PakfireRelationList pakfire_package_get_suggests(PakfirePackage pkg);
+void pakfire_package_set_suggests(PakfirePackage pkg, PakfireRelationList relationlist);
+void pakfire_package_add_suggests(PakfirePackage pkg, PakfireRelation relation);
+
+PakfireRepo pakfire_package_get_repo(PakfirePackage pkg);
+void pakfire_package_set_repo(PakfirePackage pkg, PakfireRepo repo);
+
+char* pakfire_package_get_location(PakfirePackage pkg);
+
+char* pakfire_package_dump(PakfirePackage pkg, int flags);
+
+int pakfire_package_is_cached(PakfirePackage pkg);
+char* pakfire_package_get_cache_path(PakfirePackage pkg);
+char* pakfire_package_get_cache_full_path(PakfirePackage pkg);
+
+PakfireFile pakfire_package_get_filelist(PakfirePackage pkg);
+PakfireFile pakfire_package_filelist_append(PakfirePackage pkg, const char* filename);
+#if 0
+PakfireFile pakfire_package_filelist_append(PakfirePackage pkg);
+#endif
+void pakfire_package_filelist_remove(PakfirePackage pkg);
+
+enum pakfire_package_keynames {
+    PAKFIRE_PKG,
+    PAKFIRE_PKG_ALL,
+    PAKFIRE_PKG_ARCH,
+    PAKFIRE_PKG_CONFLICTS,
+    PAKFIRE_PKG_DESCRIPTION,
+    PAKFIRE_PKG_EPOCH,
+    PAKFIRE_PKG_EVR,
+    PAKFIRE_PKG_FILE,
+    PAKFIRE_PKG_NAME,
+    PAKFIRE_PKG_OBSOLETES,
+    PAKFIRE_PKG_PROVIDES,
+    PAKFIRE_PKG_RELEASE,
+    PAKFIRE_PKG_REPONAME,
+    PAKFIRE_PKG_REQUIRES,
+    PAKFIRE_PKG_SOURCERPM,
+    PAKFIRE_PKG_SUMMARY,
+    PAKFIRE_PKG_URL,
+    PAKFIRE_PKG_VERSION,
+    PAKFIRE_PKG_LOCATION
+};
+
+enum pakfire_package_dump_flags {
+       PAKFIRE_PKG_DUMP_FILELIST = 1 << 0,
+       PAKFIRE_PKG_DUMP_LONG     = 1 << 1,
+};
+
+#ifdef PAKFIRE_PRIVATE
+
+struct _PakfirePackage {
+       PakfirePool pool;
+       Id id;
+       int nrefs;
+       PakfireFile filelist;
+};
+
+static inline PakfirePool pakfire_package_pool(PakfirePackage pkg) {
+       return pkg->pool;
+}
+
+static inline Pool* pakfire_package_solv_pool(PakfirePackage pkg) {
+       return pakfire_package_pool(pkg)->pool;
+}
+
+#endif
+
+#endif /* PAKFIRE_PACKAGE_H */
diff --git a/src/libpakfire/include/pakfire/packagecache.h b/src/libpakfire/include/pakfire/packagecache.h
new file mode 100644 (file)
index 0000000..9c07273
--- /dev/null
@@ -0,0 +1,41 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2013 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_PACKAGECACHE_H
+#define PAKFIRE_PACKAGECACHE_H
+
+#include <pakfire/types.h>
+
+PakfirePackageCache pakfire_packagecache_create(PakfirePool pool, const char* path);
+void pakfire_packagecache_free(PakfirePackageCache cache);
+
+const char* pakfire_packagecache_get_path(PakfirePackageCache cache);
+
+int pakfire_packagecache_has_package(PakfirePackageCache cache, PakfirePackage pkg);
+
+#ifdef PAKFIRE_PRIVATE
+
+struct _PakfirePackageCache {
+       PakfirePool pool;
+};
+
+#endif
+
+#endif /* PAKFIRE_PACKAGECACHE_H */
diff --git a/src/libpakfire/include/pakfire/packagelist.h b/src/libpakfire/include/pakfire/packagelist.h
new file mode 100644 (file)
index 0000000..a6d05a2
--- /dev/null
@@ -0,0 +1,52 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2013 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_PACKAGELIST_H
+#define PAKFIRE_PACKAGELIST_H
+
+#include <solv/queue.h>
+
+#include <pakfire/types.h>
+
+PakfirePackageList pakfire_packagelist_create(void);
+void pakfire_packagelist_free(PakfirePackageList list);
+
+int pakfire_packagelist_count(PakfirePackageList list);
+int pakfire_packagelist_has(PakfirePackageList list, PakfirePackage pkg);
+PakfirePackage pakfire_packagelist_get(PakfirePackageList list, int index);
+
+void pakfire_packagelist_push(PakfirePackageList list, PakfirePackage pkg);
+void pakfire_packagelist_push_if_not_exists(PakfirePackageList list, PakfirePackage pkg);
+
+#define FOR_PACKAGELIST(pkg, list, i) \
+       for (i = 0; (pkg = pakfire_packagelist_get(list, i)) != NULL; i++)
+
+#ifdef PAKFIRE_PRIVATE
+
+struct _PakfirePackageList {
+       PakfirePackage* elements;
+       int count;
+};
+
+PakfirePackageList pakfire_packagelist_from_queue(PakfirePool _pool, Queue* q);
+
+#endif
+
+#endif /* PAKFIRE_PACKAGELIST_H */
diff --git a/src/libpakfire/include/pakfire/pool.h b/src/libpakfire/include/pakfire/pool.h
new file mode 100644 (file)
index 0000000..0613879
--- /dev/null
@@ -0,0 +1,62 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2013 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_POOL_H
+#define PAKFIRE_POOL_H
+
+#include <solv/pool.h>
+
+#include <pakfire/types.h>
+
+PakfirePool pakfire_pool_create(const char* arch);
+void pakfire_pool_free(PakfirePool pool);
+
+int pakfire_pool_version_compare(PakfirePool pool, const char* evr1, const char* evr2);
+int pakfire_pool_count(PakfirePool pool);
+
+PakfireRepo pakfire_pool_get_installed_repo(PakfirePool pool);
+void pakfire_pool_set_installed_repo(PakfirePool pool, PakfireRepo repo);
+
+const char** pakfire_pool_get_installonly(PakfirePool pool);
+void pakfire_pool_set_installonly(PakfirePool pool, const char** installonly);
+
+const char* pakfire_pool_get_cache_path(PakfirePool pool);
+void pakfire_pool_set_cache_path(PakfirePool pool, const char* path);
+PakfireCache pakfire_pool_get_cache(PakfirePool pool);
+
+PakfirePackageList pakfire_pool_whatprovides(PakfirePool pool, const char* provides, int flags);
+PakfirePackageList pakfire_pool_search(PakfirePool pool, const char* what, int flags);
+
+#ifdef PAKFIRE_PRIVATE
+
+struct _PakfirePool {
+       Pool* pool;
+       int provides_ready;
+       Queue installonly;
+
+       PakfireCache cache;
+};
+
+void pakfire_pool_make_provides_ready(PakfirePool pool);
+char* pakfire_pool_tmpdup(Pool* pool, const char* s);
+
+#endif
+
+#endif /* PAKFIRE_POOL_H */
diff --git a/src/libpakfire/include/pakfire/relation.h b/src/libpakfire/include/pakfire/relation.h
new file mode 100644 (file)
index 0000000..7df9886
--- /dev/null
@@ -0,0 +1,59 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2013 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_RELATION_H
+#define PAKFIRE_RELATION_H
+
+#include <solv/pool.h>
+#include <solv/pooltypes.h>
+#include <solv/queue.h>
+
+#include <pakfire/pool.h>
+#include <pakfire/types.h>
+
+PakfireRelation pakfire_relation_create(PakfirePool pool, const char* name, int cmp_type, const char* evr);
+PakfireRelation pakfire_relation_create_from_id(PakfirePool pool, Id id);
+void pakfire_relation_free(PakfireRelation relation);
+
+Id pakfire_relation_id(PakfireRelation relation);
+char* pakfire_relation_str(PakfireRelation relation);
+
+PakfirePackageList pakfire_relation_providers(PakfireRelation relation);
+
+int pakfire_relation2queue(const PakfireRelation relation, Queue* queue, int solver_action);
+
+#ifdef PAKFIRE_PRIVATE
+
+struct _PakfireRelation {
+       PakfirePool pool;
+       Id id;
+};
+
+static inline PakfirePool pakfire_relation_pool(PakfireRelation relation) {
+       return relation->pool;
+}
+
+static inline Pool* pakfire_relation_solv_pool(PakfireRelation relation) {
+       return pakfire_relation_pool(relation)->pool;
+}
+
+#endif
+
+#endif /* PAKFIRE_RELATION_H */
diff --git a/src/libpakfire/include/pakfire/relationlist.h b/src/libpakfire/include/pakfire/relationlist.h
new file mode 100644 (file)
index 0000000..55d89c5
--- /dev/null
@@ -0,0 +1,50 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2013 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_RELATIONLIST_H
+#define PAKFIRE_RELATIONLIST_H
+
+#include <solv/queue.h>
+
+#include <pakfire/pool.h>
+#include <pakfire/relation.h>
+#include <pakfire/types.h>
+
+PakfireRelationList pakfire_relationlist_create(PakfirePool pool);
+void pakfire_relationlist_free(PakfireRelationList reldeplist);
+
+void pakfire_relationlist_add(PakfireRelationList relationlist, PakfireRelation relation);
+int pakfire_relationlist_count(PakfireRelationList relationlist);
+
+PakfireRelation pakfire_relationlist_get_clone(PakfireRelationList relationlist, int index);
+
+#ifdef PAKFIRE_PRIVATE
+
+struct _PakfireRelationList {
+       PakfirePool pool;
+       Queue queue;
+};
+
+PakfireRelationList pakfire_relationlist_from_queue(PakfirePool pool, Queue q);
+void pakfire_relationlist_clone_to_queue(PakfireRelationList relationlist, Queue* q);
+
+#endif
+
+#endif /* PAKFIRE_RELATIONLIST_H */
diff --git a/src/libpakfire/include/pakfire/repo.h b/src/libpakfire/include/pakfire/repo.h
new file mode 100644 (file)
index 0000000..7cdcee1
--- /dev/null
@@ -0,0 +1,82 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2013 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_REPO_H
+#define PAKFIRE_REPO_H
+
+#include <solv/repo.h>
+
+#include <pakfire/types.h>
+
+PakfireRepo pakfire_repo_create(PakfirePool pool, const char* name);
+PakfireRepo pakfire_repo_create_from_repo(PakfirePool pool, Repo* r);
+void pakfire_repo_free(PakfireRepo pkg);
+
+PakfirePool pakfire_repo_pool(PakfireRepo repo);
+
+int pakfire_repo_identical(PakfireRepo repo1, PakfireRepo repo2);
+int pakfire_repo_cmp(PakfireRepo repo1, PakfireRepo repo2);
+int pakfire_repo_count(PakfireRepo repo);
+
+void pakfire_repo_internalize(PakfireRepo repo);
+
+const char* pakfire_repo_get_name(PakfireRepo repo);
+void pakfire_repo_set_name(PakfireRepo repo, const char* name);
+
+int pakfire_repo_get_enabled(PakfireRepo repo);
+void pakfire_repo_set_enabled(PakfireRepo repo, int enabled);
+
+int pakfire_repo_get_priority(PakfireRepo repo);
+void pakfire_repo_set_priority(PakfireRepo repo, int priority);
+
+int pakfire_repo_is_installed_repo(PakfireRepo repo);
+
+int pakfire_repo_read_solv(PakfireRepo repo, const char* filename, int flags);
+int pakfire_repo_read_solv_fp(PakfireRepo repo, FILE *f, int flags);
+
+int pakfire_repo_write_solv(PakfireRepo repo, const char* filename, int flags);
+int pakfire_repo_write_solv_fp(PakfireRepo repo, FILE *f, int flags);
+
+PakfireRepoCache pakfire_repo_get_cache(PakfireRepo repo);
+
+#ifdef PAKFIRE_PRIVATE
+
+struct _PakfireRepo {
+       PakfirePool pool;
+       Repo* repo;
+       PakfireRepoCache cache;
+       int nrefs;
+
+       Repodata* filelist;
+};
+
+PakfirePackage pakfire_repo_add_package(PakfireRepo repo);
+
+static inline Pool* pakfire_repo_solv_pool(PakfireRepo repo) {
+       return pakfire_repo_pool(repo)->pool;
+}
+
+static inline Repo* pakfire_repo_get_solv_repo(PakfireRepo repo) {
+       return repo->repo;
+}
+
+#endif
+
+#endif /* PAKFIRE_REPO_H */
diff --git a/src/libpakfire/include/pakfire/repocache.h b/src/libpakfire/include/pakfire/repocache.h
new file mode 100644 (file)
index 0000000..5d426a3
--- /dev/null
@@ -0,0 +1,58 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2013 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_REPOCACHE_H
+#define PAKFIRE_REPOCACHE_H
+
+#include <stdio.h>
+
+#include <pakfire/types.h>
+
+PakfireRepoCache pakfire_repocache_create(PakfireRepo repo);
+void pakfire_repocache_free(PakfireRepoCache repo_cache);
+
+char* pakfire_repocache_get_cache_path(PakfireRepoCache repo_cache, const char* path);
+char* pakfire_repocache_get_full_path(PakfireRepoCache repo_cache, const char* path);
+
+int pakfire_repocache_has_file(PakfireRepoCache repo_cache, const char* filename);
+int pakfire_repocache_age(PakfireRepoCache repo_cache, const char* filename);
+
+FILE* pakfire_repocache_open(PakfireRepoCache repo_cache, const char* filename, const char* flags);
+
+#ifdef PAKFIRE_PRIVATE
+
+struct _PakfireRepoCache {
+       PakfireRepo repo;
+       char* prefix;
+};
+
+inline PakfirePool pakfire_repocache_pool(PakfireRepoCache repo_cache) {
+       return pakfire_repo_pool(repo_cache->repo);
+}
+
+inline PakfireCache pakfire_repocache_cache(PakfireRepoCache repo_cache) {
+       PakfirePool pool = pakfire_repocache_pool(repo_cache);
+
+       return pakfire_pool_get_cache(pool);
+}
+
+#endif
+
+#endif /* PAKFIRE_REPOCACHE_H */
diff --git a/src/libpakfire/include/pakfire/request.h b/src/libpakfire/include/pakfire/request.h
new file mode 100644 (file)
index 0000000..01f70a5
--- /dev/null
@@ -0,0 +1,80 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2013 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_REQUEST_H
+#define PAKFIRE_REQUEST_H
+
+#include <solv/queue.h>
+#include <solv/solver.h>
+#include <solv/transaction.h>
+
+#include <pakfire/types.h>
+
+enum _pakfire_request_op_flags {
+       PAKFIRE_CHECK_INSTALLED = 1 << 0,
+       PAKFIRE_CLEAN_DEPS      = 1 << 1,
+};
+
+enum _pakfire_solver_flags {
+       PAKFIRE_SOLVER_ALLOW_UNINSTALL = 1 << 0,
+       PAKFIRE_SOLVER_FORCE_BEST      = 1 << 1,
+};
+
+PakfireRequest pakfire_request_create(PakfirePool pool);
+void pakfire_request_free(PakfireRequest request);
+
+PakfirePool pakfire_request_pool(PakfireRequest request);
+
+int pakfire_request_solve(PakfireRequest request, int flags);
+PakfireTransaction pakfire_request_get_transaction(PakfireRequest request);
+
+int pakfire_request_install(PakfireRequest request, PakfirePackage package);
+int pakfire_request_install_relation(PakfireRequest request, PakfireRelation relation);
+int pakfire_request_install_selector(PakfireRequest request, PakfireSelector selector);
+
+int pakfire_request_erase(PakfireRequest request, PakfirePackage package, int flags);
+int pakfire_request_erase_relation(PakfireRequest request, PakfireRelation relation, int flags);
+int pakfire_request_erase_selector(PakfireRequest request, PakfireSelector selector, int flags);
+
+int pakfire_request_upgrade(PakfireRequest request, PakfirePackage package);
+int pakfire_request_upgrade_relation(PakfireRequest request, PakfireRelation relation);
+int pakfire_request_upgrade_selector(PakfireRequest request, PakfireSelector selector);
+
+int pakfire_request_upgrade_all(PakfireRequest request);
+int pakfire_request_distupgrade(PakfireRequest request);
+
+int pakfire_request_lock(PakfireRequest request, PakfirePackage package);
+int pakfire_request_lock_relation(PakfireRequest request, PakfireRelation relation);
+int pakfire_request_lock_selector(PakfireRequest request, PakfireSelector selector);
+
+int pakfire_request_verify(PakfireRequest request);
+
+#ifdef PAKFIRE_PRIVATE
+
+struct _PakfireRequest {
+       PakfirePool pool;
+       Queue queue;
+       Solver* solver;
+       Transaction* transaction;
+};
+
+#endif
+
+#endif /* PAKFIRE_REQUEST_H */
diff --git a/src/libpakfire/include/pakfire/selector.h b/src/libpakfire/include/pakfire/selector.h
new file mode 100644 (file)
index 0000000..8b96734
--- /dev/null
@@ -0,0 +1,60 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2013 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_SELECTOR_H
+#define PAKFIRE_SELECTOR_H
+
+#include <solv/pool.h>
+#include <solv/queue.h>
+
+#include <pakfire/filter.h>
+#include <pakfire/packagelist.h>
+#include <pakfire/pool.h>
+
+PakfireSelector pakfire_selector_create(PakfirePool pool);
+void pakfire_selector_free(PakfireSelector selector);
+
+int pakfire_selector_set(PakfireSelector selector, int keyname, int cmp_type, const char* match);
+
+PakfirePackageList pakfire_selector_providers(PakfireSelector selector);
+
+int pakfire_selector2queue(const PakfireSelector selector, Queue* queue, int solver_action);
+
+#ifdef PAKFIRE_PRIVATE
+
+struct _PakfireSelector {
+       PakfirePool pool;
+       PakfireFilter f_name;
+       PakfireFilter f_provides;
+       PakfireFilter f_evr;
+       PakfireFilter f_arch;
+};
+
+static inline PakfirePool pakfire_selector_pool(PakfireSelector selector) {
+       return selector->pool;
+}
+
+static inline Pool* pakfire_selector_solv_pool(PakfireSelector selector) {
+       return pakfire_selector_pool(selector)->pool;
+}
+
+#endif
+
+#endif /* PAKFIRE_SELECTOR_H */
diff --git a/src/libpakfire/include/pakfire/solver.h b/src/libpakfire/include/pakfire/solver.h
new file mode 100644 (file)
index 0000000..ba01258
--- /dev/null
@@ -0,0 +1,24 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2013 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_SOLVER_H
+#define PAKFIRE_SOLVER_H
+
+#endif /* PAKFIRE_SOLVER_H */
diff --git a/src/libpakfire/include/pakfire/step.h b/src/libpakfire/include/pakfire/step.h
new file mode 100644 (file)
index 0000000..4c56587
--- /dev/null
@@ -0,0 +1,54 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2013 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_STEP_H
+#define PAKFIRE_STEP_H
+
+#include <solv/pooltypes.h>
+
+#include <pakfire/types.h>
+
+PakfireStep pakfire_step_create(PakfireTransaction transaction, Id id);
+void pakfire_step_free(PakfireStep step);
+
+PakfirePackage pakfire_step_get_package(PakfireStep step);
+int pakfire_step_get_type(PakfireStep step);
+const char* pakfire_step_get_type_string(PakfireStep step);
+
+unsigned long long pakfire_step_get_downloadsize(PakfireStep step);
+long pakfire_step_get_installsizechange(PakfireStep step);
+
+int pakfire_step_needs_download(PakfireStep step);
+
+#ifdef PAKFIRE_PRIVATE
+
+struct _PakfireStep {
+       PakfirePool pool;
+       PakfireTransaction transaction;
+       Id id;
+};
+
+static inline PakfirePool pakfire_step_pool(PakfireStep step) {
+       return step->pool;
+}
+
+#endif
+
+#endif /* PAKFIRE_STEP_H */
diff --git a/src/libpakfire/include/pakfire/transaction.h b/src/libpakfire/include/pakfire/transaction.h
new file mode 100644 (file)
index 0000000..3ead263
--- /dev/null
@@ -0,0 +1,51 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2013 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_TRANSACTION_H
+#define PAKFIRE_TRANSACTION_H
+
+#include <solv/transaction.h>
+
+#include <pakfire/types.h>
+
+PakfireTransaction pakfire_transaction_create(PakfirePool pool, Transaction* trans);
+void pakfire_transaction_free(PakfireTransaction transaction);
+
+int pakfire_transaction_count(PakfireTransaction transaction);
+
+int pakfire_transaction_installsizechange(PakfireTransaction transaction);
+
+PakfireStep pakfire_transaction_get_step(PakfireTransaction transaction, int index);
+PakfirePackageList pakfire_transaction_get_packages(PakfireTransaction transaction, int type);
+
+#ifdef PAKFIRE_PRIVATE
+
+struct _PakfireTransaction {
+       PakfirePool pool;
+       Transaction* transaction;
+};
+
+static inline PakfirePool pakfire_transaction_pool(PakfireTransaction transaction) {
+       return transaction->pool;
+}
+
+#endif
+
+#endif /* PAKFIRE_TRANSACTION_H */
diff --git a/src/libpakfire/include/pakfire/types.h b/src/libpakfire/include/pakfire/types.h
new file mode 100644 (file)
index 0000000..4ea175b
--- /dev/null
@@ -0,0 +1,60 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2013 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_TYPES_H
+#define PAKFIRE_TYPES_H
+
+typedef struct _PakfireArchive* PakfireArchive;
+typedef struct _PakfireCache* PakfireCache;
+typedef struct _PakfireFile* PakfireFile;
+typedef struct _PakfireFilter* PakfireFilter;
+typedef struct _PakfirePackage* PakfirePackage;
+typedef struct _PakfirePackageCache* PakfirePackageCache;
+typedef struct _PakfirePackageList* PakfirePackageList;
+typedef struct _PakfirePool* PakfirePool;
+typedef struct _PakfireRelation* PakfireRelation;
+typedef struct _PakfireRelationList* PakfireRelationList;
+typedef struct _PakfireRepo* PakfireRepo;
+typedef struct _PakfireRepoCache* PakfireRepoCache;
+typedef struct _PakfireRequest* PakfireRequest;
+typedef struct _PakfireSelector* PakfireSelector;
+typedef struct _PakfireStep* PakfireStep;
+typedef struct _PakfireTransaction* PakfireTransaction;
+
+enum _pakfire_comparison_types {
+       PAKFIRE_ICASE     = 1 << 0,
+       PAKFIRE_NOT       = 1 << 1,
+       PAKFIRE_NAME_ONLY = 1 << 2,
+       PAKFIRE_SUBSTRING = 1 << 3,
+
+       PAKFIRE_EQ        = 1 << 8,
+       PAKFIRE_LT        = 1 << 9,
+       PAKFIRE_LE        = PAKFIRE_EQ|PAKFIRE_LT,
+       PAKFIRE_GT        = 1 << 10,
+       PAKFIRE_GE        = PAKFIRE_EQ|PAKFIRE_GT,
+       PAKFIRE_NEQ       = PAKFIRE_EQ|PAKFIRE_NOT,
+
+       PAKFIRE_SUBSTR    = 1 << 11,
+       PAKFIRE_GLOB      = 1 << 12,
+};
+
+#define PAKFIRE_SOLVABLE_FILEMARKER "solvable:filemarker"
+
+#endif /* PAKFIRE_TYPES_H */
diff --git a/src/libpakfire/include/pakfire/util.h b/src/libpakfire/include/pakfire/util.h
new file mode 100644 (file)
index 0000000..d4ba90b
--- /dev/null
@@ -0,0 +1,46 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2013 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_UTIL_H
+#define PAKFIRE_UTIL_H
+
+#include <stddef.h>
+
+void pakfire_oom(size_t num, size_t len);
+
+void* pakfire_malloc(size_t len);
+void* pakfire_calloc(size_t num, size_t len);
+void* pakfire_realloc(void* ptr, size_t size);
+
+void* pakfire_free(void* mem);
+
+char* pakfire_strdup(const char* s);
+
+char* pakfire_format_size(double size);
+
+char* pakfire_path_join(const char* first, const char* second);
+
+char* pakfire_basename(const char* path);
+char* pakfire_dirname(const char* path);
+
+char* pakfire_sgets(char* str, int num, char** input);
+char* pakfire_remove_trailing_newline(char* str);
+
+#endif /* PAKFIRE_UTIL_H */
diff --git a/src/libpakfire/libpakfire.sym b/src/libpakfire/libpakfire.sym
new file mode 100644 (file)
index 0000000..f283586
--- /dev/null
@@ -0,0 +1,258 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2013 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/>.       #
+#                                                                             #
+#############################################################################*/
+
+LIBPAKFIRE_0 {
+global:
+       # archive
+       pakfire_archive_create;
+       pakfire_archive_extract;
+       pakfire_archive_free;
+       pakfire_archive_get_filelist;
+       pakfire_archive_get_format;
+       pakfire_archive_get_path;
+       pakfire_archive_open;
+       pakfire_archive_read;
+
+       # file
+       pakfire_file_append;
+       pakfire_file_cmp;
+       pakfire_file_count;
+       pakfire_file_create;
+       pakfire_file_free;
+       pakfire_file_free_all;
+       pakfire_file_get_first;
+       pakfire_file_get_group;
+       pakfire_file_get_last;
+       pakfire_file_get_mode;
+       pakfire_file_get_name;
+       pakfire_file_get_next;
+       pakfire_file_get_prev;
+       pakfire_file_get_time;
+       pakfire_file_get_user;
+       pakfire_file_is_file;
+       pakfire_file_is_link;
+       pakfire_file_is_symlink;
+       pakfire_file_is_char;
+       pakfire_file_is_block;
+       pakfire_file_is_dir;
+       pakfire_file_set_group;
+       pakfire_file_set_mode;
+       pakfire_file_set_name;
+       pakfire_file_set_time;
+       pakfire_file_set_user;
+       pakfire_file_sprintf;
+       pakfire_file_sort;
+       pakfire_file_swap;
+
+       # package
+       pakfire_package_add_conflicts;
+       pakfire_package_add_obsoletes;
+       pakfire_package_add_provides;
+       pakfire_package_add_recommends;
+       pakfire_package_add_requires;
+       pakfire_package_add_suggests;
+       pakfire_package_cmp;
+       pakfire_package_create;
+       pakfire_package_create2;
+       pakfire_package_dump;
+       pakfire_package_filelist_append;
+       pakfire_package_filelist_remove;
+       pakfire_package_free;
+       pakfire_package_get_arch;
+       pakfire_package_get_buildhost;
+       pakfire_package_get_buildtime;
+       pakfire_package_get_cache_path;
+       pakfire_package_get_cache_full_path;
+       pakfire_package_get_checksum;
+       pakfire_package_get_conflicts;
+       pakfire_package_get_description;
+       pakfire_package_get_downloadsize;
+       pakfire_package_get_epoch;
+       pakfire_package_get_evr;
+       pakfire_package_get_filelist;
+       pakfire_package_get_filename;
+       pakfire_package_get_groups;
+       pakfire_package_get_license;
+       pakfire_package_get_location;
+       pakfire_package_get_installsize;
+       pakfire_package_get_installtime;
+       pakfire_package_get_maintainer;
+       pakfire_package_get_name;
+       pakfire_package_get_nevra;
+       pakfire_package_get_obsoletes;
+       pakfire_package_get_provides;
+       pakfire_package_get_recommends;
+       pakfire_package_get_release;
+       pakfire_package_get_repo;
+       pakfire_package_get_requires;
+       pakfire_package_get_size;
+       pakfire_package_get_suggests;
+       pakfire_package_get_summary;
+       pakfire_package_get_url;
+       pakfire_package_get_uuid;
+       pakfire_package_get_vendor;
+       pakfire_package_get_version;
+       pakfire_package_id;
+       pakfire_package_is_installed;
+       pakfire_package_set_arch;
+       pakfire_package_set_buildhost;
+       pakfire_package_set_buildtime;
+       pakfire_package_set_checksum;
+       pakfire_package_set_conflicts;
+       pakfire_package_set_description;
+       pakfire_package_set_downloadsize;
+       pakfire_package_set_evr;
+       pakfire_package_set_filename;
+       pakfire_package_set_groups;
+       pakfire_package_set_installsize;
+       pakfire_package_set_license;
+       pakfire_package_set_maintainer;
+       pakfire_package_set_name;
+       pakfire_package_set_obsoletes;
+       pakfire_package_set_provides;
+       pakfire_package_set_recommends;
+       pakfire_package_set_repo;
+       pakfire_package_set_requires;
+       pakfire_package_set_suggests;
+       pakfire_package_set_summary;
+       pakfire_package_set_url;
+       pakfire_package_set_uuid;
+       pakfire_package_set_vendor;
+
+       # packagelist
+       pakfire_packagelist_count;
+       pakfire_packagelist_create;
+       pakfire_packagelist_free;
+       pakfire_packagelist_get;
+       pakfire_packagelist_has;
+       pakfire_packagelist_push;
+       pakfire_packagelist_push_if_not_exists;
+
+       # pool
+       pakfire_pool_count;
+       pakfire_pool_create;
+       pakfire_pool_free;
+       pakfire_pool_get_cache_path;
+       pakfire_pool_get_installed_repo;
+       pakfire_pool_get_installonly;
+       pakfire_pool_search;
+       pakfire_pool_set_cache_path;
+       pakfire_pool_set_installed_repo;
+       pakfire_pool_set_installonly;
+       pakfire_pool_version_compare;
+       pakfire_pool_whatprovides;
+
+       # repo
+       pakfire_repo_cmp;
+       pakfire_repo_count;
+       pakfire_repo_create;
+       pakfire_repo_free;
+       pakfire_repo_get_cache;
+       pakfire_repo_get_name;
+       pakfire_repo_get_enabled;
+       pakfire_repo_get_priority;
+       pakfire_repo_identical;
+       pakfire_repo_internalize;
+       pakfire_repo_is_installed_repo;
+       pakfire_repo_pool;
+       pakfire_repo_read_solv;
+       pakfire_repo_read_solv_fp;
+       pakfire_repo_set_enabled;
+       pakfire_repo_set_name;
+       pakfire_repo_set_priority;
+       pakfire_repo_write_solv;
+       pakfire_repo_write_solv_fp;
+
+       # repocache
+       pakfire_repocache_age;
+       pakfire_repocache_create;
+       pakfire_repocache_free;
+       pakfire_repocache_get_cache_path;
+       pakfire_repocache_get_full_path;
+       pakfire_repocache_has_file;
+       pakfire_repocache_open;
+
+       # relation
+       pakfire_relation_create;
+       pakfire_relation_create_from_id;
+       pakfire_relation_free;
+       pakfire_relation_id;
+       pakfire_relation_providers;
+       pakfire_relation_str;
+
+       # relationlist
+       pakfire_relationlist_add;
+       pakfire_relationlist_count;
+       pakfire_relationlist_create;
+       pakfire_relationlist_free;
+       pakfire_relationlist_get_clone;
+
+       # request
+       pakfire_request_create;
+       pakfire_request_distupgrade;
+       pakfire_request_free;
+       pakfire_request_erase;
+       pakfire_request_erase_relation;
+       pakfire_request_erase_selector;
+       pakfire_request_get_transaction;
+       pakfire_request_install;
+       pakfire_request_install_relation;
+       pakfire_request_install_selector;
+       pakfire_request_lock;
+       pakfire_request_lock_relation;
+       pakfire_request_lock_selector;
+       pakfire_request_pool;
+       pakfire_request_solve;
+       pakfire_request_upgrade;
+       pakfire_request_upgrade_all;
+       pakfire_request_upgrade_relation;
+       pakfire_request_upgrade_selector;
+       pakfire_request_verify;
+
+       # selector
+       pakfire_selector_create;
+       pakfire_selector_free;
+       pakfire_selector_providers;
+       pakfire_selector_set;
+
+       # step
+       pakfire_step_create;
+       pakfire_step_free;
+       pakfire_step_get_downloadsize;
+       pakfire_step_get_installsizechange;
+       pakfire_step_get_package;
+       pakfire_step_get_type;
+       pakfire_step_get_type_string;
+       pakfire_step_needs_download;
+
+       # transaction
+       pakfire_transaction_create;
+       pakfire_transaction_free;
+       pakfire_transaction_get_packages;
+       pakfire_transaction_get_step;
+       pakfire_transaction_installsizechange;
+
+       # util
+       pakfire_free;
+       pakfire_get_errno;
+
+local:
+       *;
+};
diff --git a/src/libpakfire/package.c b/src/libpakfire/package.c
new file mode 100644 (file)
index 0000000..38771d3
--- /dev/null
@@ -0,0 +1,1000 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2013 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 <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <solv/evr.h>
+#include <solv/pool.h>
+#include <solv/pooltypes.h>
+#include <solv/repo.h>
+#include <solv/solvable.h>
+
+#include <pakfire/cache.h>
+#include <pakfire/constants.h>
+#include <pakfire/file.h>
+#include <pakfire/i18n.h>
+#include <pakfire/package.h>
+#include <pakfire/packagecache.h>
+#include <pakfire/pool.h>
+#include <pakfire/relation.h>
+#include <pakfire/relationlist.h>
+#include <pakfire/repo.h>
+#include <pakfire/repocache.h>
+#include <pakfire/util.h>
+
+static void pakfire_package_add_self_provides(PakfirePool pool, PakfirePackage pkg, const char* name, const char* evr) {
+#if 1
+       PakfireRelation relation = pakfire_relation_create(pool, name, PAKFIRE_EQ, evr);
+
+       pakfire_package_add_provides(pkg, relation);
+
+       pakfire_relation_free(relation);
+#else
+       Id iname = pool_str2id(pool->pool, name, 1);
+       Id ievr  = pool_str2id(pool->pool, evr,  1);
+
+       Id rel = pool_rel2id(pool->pool, iname, ievr, REL_EQ, 1);
+
+       Solvable* s = get_solvable(pkg);
+
+       PakfireRepo repo = pakfire_package_get_repo(pkg);
+
+       s->provides = repo_addid_dep(repo->repo, s->provides, rel, 0);
+#endif
+}
+
+PakfirePackage pakfire_package_create(PakfirePool pool, Id id) {
+       PakfirePackage pkg = pakfire_calloc(1, sizeof(*pkg));
+
+       if (pkg) {
+               pkg->pool = pool;
+               pkg->id = id;
+
+               // Initialize reference counter
+               pkg->nrefs = 1;
+       }
+
+       return pkg;
+}
+
+PakfirePackage pakfire_package_create2(PakfirePool pool, PakfireRepo repo, const char* name, const char* evr, const char* arch) {
+       PakfirePackage pkg = pakfire_repo_add_package(repo);
+
+       pakfire_package_set_name(pkg, name);
+       pakfire_package_set_evr(pkg, evr);
+       pakfire_package_set_arch(pkg, arch);
+
+       pakfire_package_add_self_provides(pool, pkg, name, evr);
+
+       return pkg;
+}
+
+void pakfire_package_free(PakfirePackage pkg) {
+       if (--pkg->nrefs > 0)
+               return;
+
+       pakfire_package_filelist_remove(pkg);
+       pakfire_free(pkg);
+}
+
+static Solvable* get_solvable(PakfirePackage pkg) {
+       PakfirePool pool = pakfire_package_pool(pkg);
+
+       return pool_id2solvable(pool->pool, pkg->id);
+}
+
+static Repo* pakfire_package_solv_repo(PakfirePackage pkg) {
+       Solvable* s = get_solvable(pkg);
+
+       return s->repo;
+}
+
+static Id pakfire_package_get_handle(PakfirePackage pkg) {
+       Pool* pool = pakfire_package_solv_pool(pkg);
+       Solvable* s = get_solvable(pkg);
+
+       return s - pool->solvables;
+}
+
+int pakfire_package_identical(PakfirePackage pkg1, PakfirePackage pkg2) {
+       return pkg1->id == pkg2->id;
+}
+
+int pakfire_package_cmp(PakfirePackage pkg1, PakfirePackage pkg2) {
+       Pool* pool = pakfire_package_solv_pool(pkg1);
+
+       Solvable* s1 = get_solvable(pkg1);
+       Solvable* s2 = get_solvable(pkg2);
+
+       // Check names
+       const char* str1 = pool_id2str(pool, s1->name);
+       const char* str2 = pool_id2str(pool, s2->name);
+
+       int ret = strcmp(str1, str2);
+       if (ret)
+               return ret;
+
+       // Check the version string
+       ret = pakfire_package_evr_cmp(pkg1, pkg2);
+       if (ret)
+               return ret;
+
+       // Check repositories
+       PakfireRepo repo1 = pakfire_package_get_repo(pkg1);
+       PakfireRepo repo2 = pakfire_package_get_repo(pkg2);
+
+       if (repo1 && repo2) {
+               ret = pakfire_repo_cmp(repo1, repo2);
+
+               pakfire_repo_free(repo1);
+               pakfire_repo_free(repo2);
+
+               if (ret)
+                       return ret;
+       }
+
+       // Check package architectures
+       str1 = pool_id2str(pool, s1->arch);
+       str2 = pool_id2str(pool, s2->arch);
+
+       return strcmp(str1, str2);
+}
+
+int pakfire_package_evr_cmp(PakfirePackage pkg1, PakfirePackage pkg2) {
+       Pool* pool = pakfire_package_solv_pool(pkg1);
+
+       Solvable* s1 = get_solvable(pkg1);
+       Solvable* s2 = get_solvable(pkg2);
+
+       return pool_evrcmp(pool, s1->evr, s2->evr, EVRCMP_COMPARE);
+}
+
+Id pakfire_package_id(PakfirePackage pkg) {
+       return pkg->id;
+}
+
+char* pakfire_package_get_nevra(PakfirePackage pkg) {
+       Pool* pool = pakfire_package_solv_pool(pkg);
+       Solvable* s = get_solvable(pkg);
+
+       const char* nevra = pool_solvable2str(pool, s);
+
+       return pakfire_strdup(nevra);
+}
+
+const char* pakfire_package_get_name(PakfirePackage pkg) {
+       Pool* pool = pakfire_package_solv_pool(pkg);
+       Solvable* s = get_solvable(pkg);
+
+       return pool_id2str(pool, s->name);
+}
+
+void pakfire_package_set_name(PakfirePackage pkg, const char* name) {
+       Pool* pool = pakfire_package_solv_pool(pkg);
+       Solvable* s = get_solvable(pkg);
+
+       s->name = pool_str2id(pool, name, 1);
+}
+
+const char* pakfire_package_get_evr(PakfirePackage pkg) {
+       Pool* pool = pakfire_package_solv_pool(pkg);
+       Solvable* s = get_solvable(pkg);
+
+       return pool_id2str(pool, s->evr);
+}
+
+void pakfire_package_set_evr(PakfirePackage pkg, const char* evr) {
+       Pool* pool = pakfire_package_solv_pool(pkg);
+       Solvable* s = get_solvable(pkg);
+
+       s->evr = pool_str2id(pool, evr, 1);
+}
+
+static void split_evr(Pool* pool, const char* evr_c, char** epoch, char** version, char** release) {
+    char* evr = pakfire_pool_tmpdup(pool, evr_c);
+    char *e, *v, *r;
+
+    for (e = evr + 1; *e != ':' && *e != '-'; ++e)
+       ;
+
+    if (*e == '-') {
+               *e = '\0';
+               v = evr;
+               r = e + 1;
+               e = NULL;
+       } else { /* *e == ':' */
+               *e = '\0';
+               v = e + 1;
+               e = evr;
+               for (r = v + 1; *r != '-'; ++r)
+                       ;
+               *r = '\0';
+               r++;
+       }
+
+    *epoch = e;
+    *version = v;
+    *release = r;
+}
+
+unsigned long pakfire_package_get_epoch(PakfirePackage pkg) {
+       Pool* pool = pakfire_package_solv_pool(pkg);
+       char *e, *v, *r, *endptr;
+
+    unsigned long epoch = 0;
+
+       split_evr(pool, pakfire_package_get_evr(pkg), &e, &v, &r);
+
+       if (e) {
+               long int converted = strtol(e, &endptr, 10);
+               assert(converted > 0);
+               assert(*endptr == '\0');
+               epoch = converted;
+       }
+
+       return epoch;
+}
+
+const char* pakfire_package_get_version(PakfirePackage pkg) {
+       Pool* pool = pakfire_package_solv_pool(pkg);
+       char *e, *v, *r;
+
+       split_evr(pool, pakfire_package_get_evr(pkg), &e, &v, &r);
+       return pakfire_strdup(v);
+}
+
+const char* pakfire_package_get_release(PakfirePackage pkg) {
+       Pool* pool = pakfire_package_solv_pool(pkg);
+       char *e, *v, *r;
+
+       split_evr(pool, pakfire_package_get_evr(pkg), &e, &v, &r);
+       return pakfire_strdup(r);
+}
+
+const char* pakfire_package_get_arch(PakfirePackage pkg) {
+       Pool* pool = pakfire_package_solv_pool(pkg);
+       Solvable* s = get_solvable(pkg);
+
+       return pool_id2str(pool, s->arch);
+}
+
+void pakfire_package_set_arch(PakfirePackage pkg, const char* arch) {
+       Pool* pool = pakfire_package_solv_pool(pkg);
+       Solvable* s = get_solvable(pkg);
+
+       s->arch = pool_str2id(pool, arch, 1);
+}
+
+static void pakfire_package_internalize_repo(PakfirePackage pkg) {
+       PakfireRepo repo = pakfire_package_get_repo(pkg);
+       if (repo) {
+               pakfire_repo_internalize(repo);
+               pakfire_repo_free(repo);
+       }
+}
+
+static const char* pakfire_package_get_string(PakfirePackage pkg, int key) {
+       pakfire_package_internalize_repo(pkg);
+
+       Solvable* s = get_solvable(pkg);
+       const char* str = solvable_lookup_str(s, key);
+
+       if (!str)
+               return NULL;
+
+       if (strlen(str) == 0)
+               return NULL;
+
+       return str;
+}
+
+static void pakfire_package_set_string(PakfirePackage pkg, int key, const char* value) {
+       Solvable* s = get_solvable(pkg);
+
+       if (!value)
+               value = "";
+
+       solvable_set_str(s, key, value);
+}
+
+const char* pakfire_package_get_uuid(PakfirePackage pkg) {
+       return pakfire_package_get_string(pkg, SOLVABLE_PKGID);
+}
+
+void pakfire_package_set_uuid(PakfirePackage pkg, const char* uuid) {
+       pakfire_package_set_string(pkg, SOLVABLE_PKGID, uuid);
+}
+
+const char* pakfire_package_get_checksum(PakfirePackage pkg) {
+       return pakfire_package_get_string(pkg, SOLVABLE_CHECKSUM);
+}
+
+void pakfire_package_set_checksum(PakfirePackage pkg, const char* checksum) {
+       pakfire_package_set_string(pkg, SOLVABLE_CHECKSUM, checksum);
+}
+
+const char* pakfire_package_get_summary(PakfirePackage pkg) {
+       return pakfire_package_get_string(pkg, SOLVABLE_SUMMARY);
+}
+
+void pakfire_package_set_summary(PakfirePackage pkg, const char* summary) {
+       pakfire_package_set_string(pkg, SOLVABLE_SUMMARY, summary);
+}
+
+const char* pakfire_package_get_description(PakfirePackage pkg) {
+       return pakfire_package_get_string(pkg, SOLVABLE_DESCRIPTION);
+}
+
+void pakfire_package_set_description(PakfirePackage pkg, const char* description) {
+       pakfire_package_set_string(pkg, SOLVABLE_DESCRIPTION, description);
+}
+
+const char* pakfire_package_get_license(PakfirePackage pkg) {
+       return pakfire_package_get_string(pkg, SOLVABLE_LICENSE);
+}
+
+void pakfire_package_set_license(PakfirePackage pkg, const char* license) {
+       pakfire_package_set_string(pkg, SOLVABLE_LICENSE, license);
+}
+
+const char* pakfire_package_get_url(PakfirePackage pkg) {
+       return pakfire_package_get_string(pkg, SOLVABLE_URL);
+}
+
+void pakfire_package_set_url(PakfirePackage pkg, const char* url) {
+       pakfire_package_set_string(pkg, SOLVABLE_URL, url);
+}
+
+#warning the groups functions need to be refactored
+
+const char** pakfire_package_get_groups(PakfirePackage pkg) {
+       const char* groups = pakfire_package_get_string(pkg, SOLVABLE_GROUP);
+
+       const char** grouplist = NULL;
+       char* group = strtok((char *)groups, " ");
+
+       int i = 0;
+       while (group != NULL) {
+               grouplist = realloc(grouplist, sizeof(char *) * ++i);
+               assert(grouplist);
+               grouplist[i - 1] = group;
+
+               group = strtok(NULL, " ");
+       }
+       grouplist[i] = NULL;
+
+       return grouplist;
+}
+
+void pakfire_package_set_groups(PakfirePackage pkg, const char** grouplist) {
+       char groups[2048] = "";
+
+       if (grouplist) {
+               const char* group;
+               while ((group = *grouplist++) != NULL) {
+                       if (groups[0])
+                               strcat(groups, " ");
+
+                       strcat(groups, group);
+               }
+               groups[sizeof(groups) - 1] = '\0';
+       } else
+               groups[0] = '\0';
+
+       pakfire_package_set_string(pkg, SOLVABLE_GROUP, (const char *)&groups);
+}
+
+const char* pakfire_package_get_vendor(PakfirePackage pkg) {
+       return pakfire_package_get_string(pkg, SOLVABLE_VENDOR);
+}
+
+void pakfire_package_set_vendor(PakfirePackage pkg, const char* vendor) {
+       pakfire_package_set_string(pkg, SOLVABLE_VENDOR, vendor);
+}
+
+const char* pakfire_package_get_maintainer(PakfirePackage pkg) {
+       return pakfire_package_get_string(pkg, SOLVABLE_PACKAGER);
+}
+
+void pakfire_package_set_maintainer(PakfirePackage pkg, const char* maintainer) {
+       pakfire_package_set_string(pkg, SOLVABLE_PACKAGER, maintainer);
+}
+
+const char* pakfire_package_get_filename(PakfirePackage pkg) {
+       return pakfire_package_get_string(pkg, SOLVABLE_MEDIAFILE);
+}
+
+void pakfire_package_set_filename(PakfirePackage pkg, const char* filename) {
+       pakfire_package_set_string(pkg, SOLVABLE_MEDIAFILE, filename);
+}
+
+int pakfire_package_is_installed(PakfirePackage pkg) {
+       Pool* pool = pakfire_package_solv_pool(pkg);
+       Solvable* s = get_solvable(pkg);
+
+       return pool->installed == s->repo;
+}
+
+static unsigned long long pakfire_package_get_num(PakfirePackage pkg, Id type) {
+       pakfire_package_internalize_repo(pkg);
+
+       Solvable* s = get_solvable(pkg);
+       return solvable_lookup_num(s, type, 0);
+}
+
+static void pakfire_package_set_num(PakfirePackage pkg, Id type, unsigned long long value) {
+       Solvable* s = get_solvable(pkg);
+
+       solvable_set_num(s, type, value);
+}
+
+unsigned long long pakfire_package_get_downloadsize(PakfirePackage pkg) {
+       return pakfire_package_get_num(pkg, SOLVABLE_DOWNLOADSIZE);
+}
+
+void pakfire_package_set_downloadsize(PakfirePackage pkg, unsigned long long downloadsize) {
+       return pakfire_package_set_num(pkg, SOLVABLE_DOWNLOADSIZE, downloadsize);
+}
+
+unsigned long long pakfire_package_get_installsize(PakfirePackage pkg) {
+       return pakfire_package_get_num(pkg, SOLVABLE_INSTALLSIZE);
+}
+
+void pakfire_package_set_installsize(PakfirePackage pkg, unsigned long long installsize) {
+       return pakfire_package_set_num(pkg, SOLVABLE_INSTALLSIZE, installsize);
+}
+
+unsigned long long pakfire_package_get_size(PakfirePackage pkg) {
+       if (pakfire_package_is_installed(pkg))
+               return pakfire_package_get_installsize(pkg);
+
+       return pakfire_package_get_downloadsize(pkg);
+}
+
+const char* pakfire_package_get_buildhost(PakfirePackage pkg) {
+       return pakfire_package_get_string(pkg, SOLVABLE_BUILDHOST);
+}
+
+void pakfire_package_set_buildhost(PakfirePackage pkg, const char* buildhost) {
+       pakfire_package_set_string(pkg, SOLVABLE_BUILDHOST, buildhost);
+}
+
+unsigned long long pakfire_package_get_buildtime(PakfirePackage pkg) {
+       return pakfire_package_get_num(pkg, SOLVABLE_BUILDTIME);
+}
+
+void pakfire_package_set_buildtime(PakfirePackage pkg, unsigned long long buildtime) {
+       pakfire_package_set_num(pkg, SOLVABLE_BUILDTIME, buildtime);
+}
+
+unsigned long long pakfire_package_get_installtime(PakfirePackage pkg) {
+       return pakfire_package_get_num(pkg, SOLVABLE_INSTALLTIME);
+}
+
+static PakfireRelationList pakfire_package_get_relationlist(PakfirePackage pkg, Id type) {
+       Queue q;
+       queue_init(&q);
+
+       Solvable* s = get_solvable(pkg);
+       solvable_lookup_idarray(s, type, &q);
+
+       PakfirePool pool = pakfire_package_pool(pkg);
+       PakfireRelationList relationlist = pakfire_relationlist_from_queue(pool, q);
+
+       queue_free(&q);
+
+       return relationlist;
+}
+
+static void pakfire_package_set_relationlist(PakfirePackage pkg, Id type, PakfireRelationList relationlist) {
+#if 0
+       // This implemention should be the fastest, but unfortunately does not work.
+       Queue q;
+       pakfire_relationlist_clone_to_queue(relationlist, &q);
+
+       Solvable* s = get_solvable(pkg);
+       solvable_set_idarray(s, type, &q);
+
+       queue_free(&q);
+#endif
+
+       Solvable* s = get_solvable(pkg);
+       solvable_unset(s, type);
+
+       int count = pakfire_relationlist_count(relationlist);
+       for (int i = 0; i < count; i++) {
+               PakfireRelation relation = pakfire_relationlist_get_clone(relationlist, i);
+               solvable_add_idarray(s, type, relation->id);
+
+               pakfire_relation_free(relation);
+       }
+}
+
+static void pakfire_package_add_relation(PakfirePackage pkg, Id type, PakfireRelation relation) {
+       Solvable* s = get_solvable(pkg);
+
+       solvable_add_idarray(s, type, relation->id);
+}
+
+PakfireRelationList pakfire_package_get_provides(PakfirePackage pkg) {
+       return pakfire_package_get_relationlist(pkg, SOLVABLE_PROVIDES);
+}
+
+void pakfire_package_set_provides(PakfirePackage pkg, PakfireRelationList relationlist) {
+       pakfire_package_set_relationlist(pkg, SOLVABLE_PROVIDES, relationlist);
+}
+
+void pakfire_package_add_provides(PakfirePackage pkg, PakfireRelation relation) {
+       pakfire_package_add_relation(pkg, SOLVABLE_PROVIDES, relation);
+}
+
+PakfireRelationList pakfire_package_get_prerequires(PakfirePackage pkg) {
+       #warning TODO
+       return NULL;
+}
+
+PakfireRelationList pakfire_package_get_requires(PakfirePackage pkg) {
+       return pakfire_package_get_relationlist(pkg, SOLVABLE_REQUIRES);
+}
+
+void pakfire_package_set_requires(PakfirePackage pkg, PakfireRelationList relationlist) {
+       pakfire_package_set_relationlist(pkg, SOLVABLE_REQUIRES, relationlist);
+}
+
+void pakfire_package_add_requires(PakfirePackage pkg, PakfireRelation relation) {
+       pakfire_package_add_relation(pkg, SOLVABLE_REQUIRES, relation);
+}
+
+PakfireRelationList pakfire_package_get_conflicts(PakfirePackage pkg) {
+       return pakfire_package_get_relationlist(pkg, SOLVABLE_CONFLICTS);
+}
+
+void pakfire_package_set_conflicts(PakfirePackage pkg, PakfireRelationList relationlist) {
+       pakfire_package_set_relationlist(pkg, SOLVABLE_CONFLICTS, relationlist);
+}
+
+void pakfire_package_add_conflicts(PakfirePackage pkg, PakfireRelation relation) {
+       pakfire_package_add_relation(pkg, SOLVABLE_CONFLICTS, relation);
+}
+
+PakfireRelationList pakfire_package_get_obsoletes(PakfirePackage pkg) {
+       return pakfire_package_get_relationlist(pkg, SOLVABLE_OBSOLETES);
+}
+
+void pakfire_package_set_obsoletes(PakfirePackage pkg, PakfireRelationList relationlist) {
+       pakfire_package_set_relationlist(pkg, SOLVABLE_OBSOLETES, relationlist);
+}
+
+void pakfire_package_add_obsoletes(PakfirePackage pkg, PakfireRelation relation) {
+       pakfire_package_add_relation(pkg, SOLVABLE_OBSOLETES, relation);
+}
+
+PakfireRelationList pakfire_package_get_recommends(PakfirePackage pkg) {
+       return pakfire_package_get_relationlist(pkg, SOLVABLE_RECOMMENDS);
+}
+
+void pakfire_package_set_recommends(PakfirePackage pkg, PakfireRelationList relationlist) {
+       pakfire_package_set_relationlist(pkg, SOLVABLE_RECOMMENDS, relationlist);
+}
+
+void pakfire_package_add_recommends(PakfirePackage pkg, PakfireRelation relation) {
+       pakfire_package_add_relation(pkg, SOLVABLE_RECOMMENDS, relation);
+}
+
+PakfireRelationList pakfire_package_get_suggests(PakfirePackage pkg) {
+       return pakfire_package_get_relationlist(pkg, SOLVABLE_SUGGESTS);
+}
+
+void pakfire_package_set_suggests(PakfirePackage pkg, PakfireRelationList relationlist) {
+       pakfire_package_set_relationlist(pkg, SOLVABLE_SUGGESTS, relationlist);
+}
+
+void pakfire_package_add_suggests(PakfirePackage pkg, PakfireRelation relation) {
+       pakfire_package_add_relation(pkg, SOLVABLE_SUGGESTS, relation);
+}
+
+PakfireRepo pakfire_package_get_repo(PakfirePackage pkg) {
+       Solvable* s = get_solvable(pkg);
+
+       return pakfire_repo_create_from_repo(pkg->pool, s->repo);
+}
+
+void pakfire_package_set_repo(PakfirePackage pkg, PakfireRepo repo) {
+       Solvable* s = get_solvable(pkg);
+
+       s->repo = pakfire_repo_get_solv_repo(repo);
+}
+
+char* pakfire_package_get_location(PakfirePackage pkg) {
+       pakfire_package_internalize_repo(pkg);
+
+       Solvable* s = get_solvable(pkg);
+
+       const char* location = solvable_get_location(s, NULL);
+       return pakfire_strdup(location);
+}
+
+static void pakfire_package_dump_add_line(char** str, const char* key, const char* val) {
+       if (val)
+               asprintf(str, "%s%-15s: %s\n", *str, key ? key : "", val);
+}
+
+static void pakfire_package_dump_add_lines(char** str, const char* key, const char* val) {
+       const char* string = val;
+
+       while (*string) {
+               char line[STRING_SIZE];
+               int counter = 0;
+
+               while (*string) {
+                       if (*string == '\n') {
+                               string++;
+                               break;
+                       }
+
+                       line[counter++] = *string++;
+               }
+               line[counter] = '\0';
+
+               if (*line) {
+                       pakfire_package_dump_add_line(str, key, line);
+                       key = NULL;
+               }
+       }
+}
+
+static void pakfire_package_dump_add_line_date(char** str, const char* key, unsigned long long date) {
+       // Convert from integer to tm struct.
+       struct tm* timer = gmtime((time_t *)&date);
+
+       char val[STRING_SIZE];
+       strftime(val, STRING_SIZE, "%a, %d %b %Y %T %z", timer);
+
+       pakfire_package_dump_add_line(str, key, val);
+}
+
+static void pakfire_package_dump_add_line_relations(char** str, const char* key, PakfireRelationList deps) {
+       int count = pakfire_relationlist_count(deps);
+       for (int i = 0; i < count; i++) {
+               PakfireRelation relation = pakfire_relationlist_get_clone(deps, i);
+
+               if (relation) {
+                       char* dep = pakfire_relation_str(relation);
+                       pakfire_relation_free(relation);
+
+                       // Stop here and don't list any files.
+                       if (strcmp(PAKFIRE_SOLVABLE_FILEMARKER, dep) == 0)
+                               break;
+
+                       if (dep) {
+                               pakfire_package_dump_add_line(str, (i == 0) ? key : "", dep);
+                               pakfire_free(dep);
+                       }
+               }
+       }
+}
+
+static void pakfire_package_dump_add_line_size(char** str, const char* key, unsigned long long size) {
+       char* val = pakfire_format_size(size);
+
+       if (val) {
+               pakfire_package_dump_add_line(str, key, val);
+               pakfire_free(val);
+       }
+}
+
+char* pakfire_package_dump(PakfirePackage pkg, int flags) {
+       char* string = "";
+
+       // Name
+       const char* name = pakfire_package_get_name(pkg);
+       pakfire_package_dump_add_line(&string, _("Name"), name);
+
+       // Version
+       const char* version = pakfire_package_get_version(pkg);
+       pakfire_package_dump_add_line(&string, _("Version"), version);
+
+       // Release
+       const char* release = pakfire_package_get_release(pkg);
+       pakfire_package_dump_add_line(&string, _("Release"), release);
+
+       // Size
+       unsigned long long size = pakfire_package_get_size(pkg);
+       pakfire_package_dump_add_line_size(&string, _("Size"), size);
+
+       // Installed size
+       if (pakfire_package_is_installed(pkg)) {
+               unsigned long long installsize = pakfire_package_get_installsize(pkg);
+               pakfire_package_dump_add_line_size(&string, _("Installed size"), installsize);
+
+       // Downloadsize
+       } else {
+               unsigned long long downloadsize = pakfire_package_get_downloadsize(pkg);
+               pakfire_package_dump_add_line_size(&string, _("Download size"), downloadsize);
+       }
+
+       PakfireRepo repo = pakfire_package_get_repo(pkg);
+       if (repo) {
+               const char* repo_name = pakfire_repo_get_name(repo);
+               pakfire_package_dump_add_line(&string, _("Repo"), repo_name);
+
+               pakfire_repo_free(repo);
+       }
+
+       // Summary
+       const char* summary = pakfire_package_get_summary(pkg);
+       pakfire_package_dump_add_line(&string, _("Summary"), summary);
+
+       // Description
+       const char* description = pakfire_package_get_description(pkg);
+       pakfire_package_dump_add_lines(&string, _("Description"), description);
+
+       // Groups
+       #warning TODO groups
+
+       // URL
+       const char* url = pakfire_package_get_url(pkg);
+       pakfire_package_dump_add_line(&string, _("URL"), url);
+
+       // License
+       const char* license = pakfire_package_get_license(pkg);
+       pakfire_package_dump_add_line(&string, _("License"), license);
+
+       if (flags & PAKFIRE_PKG_DUMP_LONG) {
+               // Maintainer
+               const char* maintainer = pakfire_package_get_maintainer(pkg);
+               pakfire_package_dump_add_line(&string, _("Maintainer"), maintainer);
+
+               // Vendor
+               const char* vendor = pakfire_package_get_vendor(pkg);
+               pakfire_package_dump_add_line(&string, _("Vendor"), vendor);
+
+               // UUID
+               const char* uuid = pakfire_package_get_uuid(pkg);
+               pakfire_package_dump_add_line(&string, _("UUID"), uuid);
+
+               // Build time
+               unsigned long long buildtime = pakfire_package_get_buildtime(pkg);
+               pakfire_package_dump_add_line_date(&string, _("Build date"), buildtime);
+
+               // Build host
+               const char* buildhost = pakfire_package_get_buildhost(pkg);
+               pakfire_package_dump_add_line(&string, _("Build host"), buildhost);
+
+               PakfireRelationList provides = pakfire_package_get_provides(pkg);
+               if (provides) {
+                       pakfire_package_dump_add_line_relations(&string, _("Provides"), provides);
+                       pakfire_relationlist_free(provides);
+               }
+
+               PakfireRelationList requires = pakfire_package_get_requires(pkg);
+               if (requires) {
+                       pakfire_package_dump_add_line_relations(&string, _("Requires"), requires);
+                       pakfire_relationlist_free(requires);
+               }
+
+               PakfireRelationList conflicts = pakfire_package_get_conflicts(pkg);
+               if (conflicts) {
+                       pakfire_package_dump_add_line_relations(&string, _("Conflicts"), conflicts);
+                       pakfire_relationlist_free(conflicts);
+               }
+
+               PakfireRelationList obsoletes = pakfire_package_get_obsoletes(pkg);
+               if (obsoletes) {
+                       pakfire_package_dump_add_line_relations(&string, _("Obsoletes"), obsoletes);
+                       pakfire_relationlist_free(obsoletes);
+               }
+
+               PakfireRelationList recommends = pakfire_package_get_recommends(pkg);
+               if (recommends) {
+                       pakfire_package_dump_add_line_relations(&string, _("Recommends"), recommends);
+                       pakfire_relationlist_free(recommends);
+               }
+
+               PakfireRelationList suggests = pakfire_package_get_suggests(pkg);
+               if (suggests) {
+                       pakfire_package_dump_add_line_relations(&string, _("Suggests"), suggests);
+                       pakfire_relationlist_free(suggests);
+               }
+       }
+
+       if (flags & PAKFIRE_PKG_DUMP_FILELIST) {
+               PakfireFile file = pakfire_package_get_filelist(pkg);
+
+               char* prefix = _("Filelist");
+               while (file) {
+                       const char* name = pakfire_file_get_name(file);
+                       pakfire_package_dump_add_line(&string, prefix, name);
+
+                       file = pakfire_file_get_next(file);
+
+                       // Only prefix the first line.
+                       prefix = NULL;
+               }
+       }
+
+       return string;
+}
+
+int pakfire_package_is_cached(PakfirePackage pkg) {
+       PakfireCache cache = pakfire_pool_get_cache(pkg->pool);
+       if (!cache)
+               return 1;
+
+       return pakfire_cache_has_package(cache, pkg);
+}
+
+char* pakfire_package_get_cache_path(PakfirePackage pkg) {
+       PakfireCache cache = pakfire_pool_get_cache(pkg->pool);
+       if (!cache)
+               return NULL;
+
+       return pakfire_cache_get_package_path(cache, pkg);
+}
+
+char* pakfire_package_get_cache_full_path(PakfirePackage pkg) {
+       char* cache_path = NULL;
+
+       char* pkg_cache_path = pakfire_package_get_cache_path(pkg);
+       if (!pkg_cache_path)
+               return NULL;
+
+       PakfireRepo repo = pakfire_package_get_repo(pkg);
+       if (!repo)
+               goto out;
+
+       PakfireRepoCache repo_cache = pakfire_repo_get_cache(repo);
+       if (!repo_cache) {
+               goto out;
+       }
+
+       cache_path = pakfire_repocache_get_full_path(repo_cache, pkg_cache_path);
+
+out:
+       if (repo)
+               pakfire_repo_free(repo);
+
+       return cache_path;
+}
+
+static PakfireFile pakfire_package_fetch_legacy_filelist(PakfirePackage pkg) {
+       pakfire_package_internalize_repo(pkg);
+
+       PakfireFile file = NULL;
+       PakfireRepo repo = pakfire_package_get_repo(pkg);
+       Solvable* s = get_solvable(pkg);
+       Pool* p = pakfire_package_solv_pool(pkg);
+       Repo* r = pakfire_repo_get_solv_repo(repo);
+
+       int found_marker = 0;
+
+       Id id, *ids;
+       ids = r->idarraydata + s->provides;
+       while((id = *ids++) != 0) {
+               const char* filename = pool_dep2str(p, id);
+
+               if (found_marker) {
+                       if (file) {
+                               file = pakfire_file_append(file);
+                       } else {
+                               file = pakfire_file_create();
+                       }
+
+                       pakfire_file_set_name(file, filename);
+                       continue;
+               }
+
+               if (strcmp(filename, PAKFIRE_SOLVABLE_FILEMARKER) == 0)
+                       ++found_marker;
+       }
+
+       if (file) {
+               file = pakfire_file_get_first(file);
+
+               // Sort the output
+               file = pakfire_file_sort(file);
+       }
+
+       return file;
+}
+
+static PakfireFile pakfire_package_fetch_filelist(PakfirePackage pkg) {
+       pakfire_package_internalize_repo(pkg);
+
+       PakfireFile file = NULL;
+       Pool* pool = pakfire_package_solv_pool(pkg);
+       Repo* repo = pakfire_package_solv_repo(pkg);
+       Id handle = pakfire_package_get_handle(pkg);
+
+       Dataiterator di;
+       dataiterator_init(&di, pool, repo, handle,
+               SOLVABLE_FILELIST, NULL, SEARCH_FILES | SEARCH_COMPLETE_FILELIST);
+       while (dataiterator_step(&di)) {
+               if (file) {
+                       file = pakfire_file_append(file);
+               } else {
+                       file = pakfire_file_create();
+               }
+
+               pakfire_file_set_name(file, di.kv.str);
+       }
+       dataiterator_free(&di);
+
+       if (file) {
+               file = pakfire_file_get_first(file);
+
+               // Sort the result.
+               file = pakfire_file_sort(file);
+       }
+
+       // If the file list is empty, we fall back to read files
+       // in the older format.
+       if (!file)
+               file = pakfire_package_fetch_legacy_filelist(pkg);
+
+       return file;
+}
+
+PakfireFile pakfire_package_get_filelist(PakfirePackage pkg) {
+       if (!pkg->filelist) {
+               pkg->filelist = pakfire_package_fetch_filelist(pkg);
+       }
+
+       return pkg->filelist;
+}
+
+PakfireFile pakfire_package_filelist_append(PakfirePackage pkg, const char* filename) {
+       PakfireRepo repo = pakfire_package_get_repo(pkg);
+
+       Id handle = pakfire_package_get_handle(pkg);
+
+       char* dirname  = pakfire_dirname(filename);
+       char* basename = pakfire_basename(filename);
+
+       Id did = repodata_str2dir(repo->filelist, dirname, 1);
+       if (!did)
+               did = repodata_str2dir(repo->filelist, "/", 1);
+
+       repodata_add_dirstr(repo->filelist, handle,
+               SOLVABLE_FILELIST, did, basename);
+
+       return NULL;
+}
+
+#if 0
+PakfireFile pakfire_package_filelist_append(PakfirePackage pkg) {
+       if (pkg->filelist) {
+               return pakfire_file_append(pkg->filelist);
+       }
+
+       PakfireFile file = pakfire_file_create();
+       pkg->filelist = file;
+
+       return file;
+}
+#endif
+
+void pakfire_package_filelist_remove(PakfirePackage pkg) {
+       if (pkg->filelist)
+               pakfire_file_free_all(pkg->filelist);
+}
diff --git a/src/libpakfire/packagecache.c b/src/libpakfire/packagecache.c
new file mode 100644 (file)
index 0000000..14b0616
--- /dev/null
@@ -0,0 +1,71 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2013 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 <sys/stat.h>
+
+#include <pakfire/constants.h>
+#include <pakfire/package.h>
+#include <pakfire/packagecache.h>
+#include <pakfire/types.h>
+#include <pakfire/util.h>
+
+PakfirePackageCache pakfire_packagecache_create(PakfirePool pool, const char* path) {
+       PakfirePackageCache cache = pakfire_calloc(1, sizeof(*cache));
+
+       cache->pool = pool;
+       cache->path = pakfire_strdup(path);
+
+       return cache;
+}
+
+void pakfire_packagecache_free(PakfirePackageCache cache) {
+       pakfire_free(cache->path);
+       pakfire_free(cache);
+}
+
+const char* pakfire_packagecache_get_path(PakfirePackageCache cache) {
+       return cache->path;
+}
+
+char* pakfire_packagecache_get_package_path(PakfirePackageCache cache, PakfirePackage pkg) {
+       char buffer[STRING_SIZE] = "";
+
+       const char* filename = pakfire_package_get_filename(pkg);
+       const char* checksum = pakfire_package_get_checksum(pkg);
+
+       if (strlen(checksum) < 3)
+               return NULL;
+
+       snprintf(buffer, sizeof(buffer), "%s/%c%c/%s/%s", cache->path,
+               checksum[0], checksum[1], checksum + 2, filename);
+
+       return pakfire_strdup(buffer);
+}
+
+int pakfire_packagecache_has_package(PakfirePackageCache cache, PakfirePackage pkg) {
+       char* filename = pakfire_packagecache_get_package_path(cache, pkg);
+
+       // Check if stat() is successful.
+       struct stat buf;
+       int r = stat(filename, &buf);
+
+       pakfire_free(filename);
+       return (r == 0);
+}
diff --git a/src/libpakfire/packagelist.c b/src/libpakfire/packagelist.c
new file mode 100644 (file)
index 0000000..9190eef
--- /dev/null
@@ -0,0 +1,96 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2013 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 <solv/pool.h>
+#include <solv/pooltypes.h>
+#include <solv/solver.h>
+#include <solv/util.h>
+
+#include <pakfire/package.h>
+#include <pakfire/packagelist.h>
+#include <pakfire/types.h>
+#include <pakfire/util.h>
+
+#define BLOCK_SIZE 31
+
+PakfirePackageList pakfire_packagelist_create(void) {
+       PakfirePackageList list = pakfire_calloc(1, sizeof(*list));
+
+       return list;
+}
+
+void pakfire_packagelist_free(PakfirePackageList list) {
+       for (int i = 0; i < list->count; i++) {
+               PakfirePackage pkg = list->elements[i];
+               pakfire_package_free(pkg);
+       }
+
+       pakfire_free(list->elements);
+       pakfire_free(list);
+}
+
+int pakfire_packagelist_count(PakfirePackageList list) {
+       return list->count;
+}
+
+PakfirePackage pakfire_packagelist_get(PakfirePackageList list, int index) {
+       if (index < list->count)
+               return list->elements[index];
+
+       return NULL;
+}
+
+int pakfire_packagelist_has(PakfirePackageList list, PakfirePackage pkg) {
+       for (int i = 0; i < list->count; i++) {
+               PakfirePackage _pkg = list->elements[i];
+
+               if (pakfire_package_identical(pkg, _pkg))
+                       return 1;
+       }
+
+       return 0;
+}
+
+void pakfire_packagelist_push(PakfirePackageList list, PakfirePackage pkg) {
+       list->elements = solv_extend(list->elements, list->count, 1, sizeof(pkg), BLOCK_SIZE);
+       list->elements[list->count++] = pkg;
+}
+
+void pakfire_packagelist_push_if_not_exists(PakfirePackageList list, PakfirePackage pkg) {
+       if (pakfire_packagelist_has(list, pkg))
+               return;
+
+       pakfire_packagelist_push(list, pkg);
+}
+
+PakfirePackageList pakfire_packagelist_from_queue(PakfirePool _pool, Queue* q) {
+       PakfirePackageList list = pakfire_packagelist_create();
+
+       Pool* pool = _pool->pool;
+       Id p, pp;
+       for (int i = 0; i < q->count; i += 2) {
+               FOR_JOB_SELECT(p, pp, q->elements[i], q->elements[i + 1]) {
+                       PakfirePackage pkg = pakfire_package_create(_pool, p);
+                       pakfire_packagelist_push(list, pkg);
+               }
+       }
+
+       return list;
+}
diff --git a/src/libpakfire/pool.c b/src/libpakfire/pool.c
new file mode 100644 (file)
index 0000000..3fd11b7
--- /dev/null
@@ -0,0 +1,254 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2013 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 <assert.h>
+
+#include <solv/evr.h>
+#include <solv/pool.h>
+#include <solv/poolarch.h>
+#include <solv/queue.h>
+#include <solv/repo.h>
+
+#include <pakfire/cache.h>
+#include <pakfire/package.h>
+#include <pakfire/packagelist.h>
+#include <pakfire/pool.h>
+#include <pakfire/repo.h>
+#include <pakfire/types.h>
+#include <pakfire/util.h>
+
+PakfirePool pakfire_pool_create(const char* arch) {
+       PakfirePool pool = pakfire_calloc(1, sizeof(*pool));
+       pool->pool = pool_create();
+
+       queue_init(&pool->installonly);
+
+       // Set architecture
+       pool_setarch(pool->pool, arch);
+
+       return pool;
+}
+
+static void pakfire_pool_free_repos(Pool* pool) {
+       Repo* repo;
+       int i;
+
+       FOR_REPOS(i, repo) {
+               PakfireRepo r = repo->appdata;
+               if (r == NULL)
+                       continue;
+
+               pakfire_repo_free(r);
+       }
+}
+
+void pakfire_pool_free(PakfirePool pool) {
+       pakfire_pool_free_repos(pool->pool);
+
+       queue_free(&pool->installonly);
+
+       pool_free(pool->pool);
+       pakfire_free(pool);
+}
+
+int pakfire_pool_version_compare(PakfirePool pool, const char* evr1, const char* evr2) {
+       return pool_evrcmp_str(pool->pool, evr1, evr2, EVRCMP_COMPARE);
+}
+
+int pakfire_pool_count(PakfirePool pool) {
+       int cnt = 0;
+
+       for (int i = 2; i < pool->pool->nsolvables; i++) {
+               Solvable* s = pool->pool->solvables + i;
+               if (s->repo)
+                       cnt++;
+       }
+
+       return cnt;
+}
+
+void pakfire_pool_make_provides_ready(PakfirePool pool) {
+       if (!pool->provides_ready) {
+               pool_addfileprovides(pool->pool);
+               pool_createwhatprovides(pool->pool);
+               pool->provides_ready = 1;
+       }
+}
+
+PakfireRepo pakfire_pool_get_installed_repo(PakfirePool pool) {
+       Pool* p = pool->pool;
+
+       if (!p->installed)
+               return NULL;
+
+       return pakfire_repo_create_from_repo(pool, p->installed);
+}
+
+void pakfire_pool_set_installed_repo(PakfirePool pool, PakfireRepo repo) {
+       if (!repo) {
+               pool_set_installed(pool->pool, NULL);
+               return;
+       }
+
+       assert(pool == repo->pool);
+       pool_set_installed(pool->pool, repo->repo);
+}
+
+const char** pakfire_pool_get_installonly(PakfirePool pool) {
+       Queue q;
+       queue_init_clone(&q, &pool->installonly);
+
+       const char** installonly = pakfire_malloc(sizeof(const char*) * (q.count + 1));
+
+       int i = 0;
+       while (q.count) {
+               installonly[i++] = pool_id2str(pool->pool, queue_shift(&q));
+       }
+       installonly[i] = NULL;
+
+       queue_free(&q);
+
+       return installonly;
+}
+
+void pakfire_pool_set_installonly(PakfirePool pool, const char** installonly) {
+       queue_empty(&pool->installonly);
+
+       if (installonly == NULL)
+               return;
+
+       const char* name;
+       while ((name = *installonly++) != NULL)
+               queue_pushunique(&pool->installonly, pool_str2id(pool->pool, name, 1));
+}
+
+const char* pakfire_pool_get_cache_path(PakfirePool pool) {
+       if (!pool->cache)
+               return NULL;
+
+       return pakfire_cache_get_path(pool->cache);
+}
+
+void pakfire_pool_set_cache_path(PakfirePool pool, const char* path) {
+       if (pool->cache)
+               pakfire_cache_free(pool->cache);
+
+       pool->cache = pakfire_cache_create(pool, path);
+}
+
+PakfireCache pakfire_pool_get_cache(PakfirePool pool) {
+       return pool->cache;
+}
+
+static PakfirePackageList pakfire_pool_dataiterator(PakfirePool pool, const char* what, int key, int flags) {
+       PakfirePackageList list = pakfire_packagelist_create();
+       pakfire_pool_make_provides_ready(pool);
+
+       int di_flags = 0;
+       if (flags & PAKFIRE_SUBSTRING)
+               di_flags |= SEARCH_SUBSTRING;
+       else
+               di_flags |= SEARCH_STRING;
+
+       if (flags & PAKFIRE_ICASE)
+               di_flags |= SEARCH_NOCASE;
+       if (flags & PAKFIRE_GLOB)
+               di_flags |= SEARCH_GLOB;
+
+       Dataiterator di;
+       dataiterator_init(&di, pool->pool, 0, 0, key, what, di_flags);
+       while (dataiterator_step(&di)) {
+               PakfirePackage pkg = pakfire_package_create(pool, di.solvid);
+               pakfire_packagelist_push_if_not_exists(list, pkg);
+       }
+       dataiterator_free(&di);
+
+       return list;
+}
+
+static PakfirePackageList pakfire_pool_search_name(PakfirePool _pool, const char* name, int flags) {
+       if (!flags) {
+               PakfirePackageList list = pakfire_packagelist_create();
+               pakfire_pool_make_provides_ready(_pool);
+
+               Pool* pool = _pool->pool;
+               Id id = pool_str2id(pool, name, 0);
+               if (id == 0)
+                       return list;
+
+               Id p, pp;
+               FOR_PROVIDES(p, pp, id) {
+                       Solvable* s = pool_id2solvable(pool, p);
+
+                       if (s->name == id) {
+                               PakfirePackage pkg = pakfire_package_create(_pool, p);
+                               pakfire_packagelist_push_if_not_exists(list, pkg);
+                       }
+               }
+
+               return list;
+       }
+
+       return pakfire_pool_dataiterator(_pool, name, SOLVABLE_NAME, flags);
+}
+
+static PakfirePackageList pakfire_pool_search_provides(PakfirePool _pool, const char* provides, int flags) {
+       if (!flags) {
+               PakfirePackageList list = pakfire_packagelist_create();
+               pakfire_pool_make_provides_ready(_pool);
+
+               Pool* pool = _pool->pool;
+               Id id = pool_str2id(pool, provides, 0);
+               if (id == 0)
+                       return list;
+
+               Id p, pp;
+               FOR_PROVIDES(p, pp, id) {
+                       PakfirePackage pkg = pakfire_package_create(_pool, p);
+                       pakfire_packagelist_push_if_not_exists(list, pkg);
+               }
+
+               return list;
+       }
+
+       return pakfire_pool_dataiterator(_pool, provides, SOLVABLE_PROVIDES, flags);
+}
+
+PakfirePackageList pakfire_pool_whatprovides(PakfirePool pool, const char* what, int flags) {
+       assert((flags & ~(PAKFIRE_ICASE|PAKFIRE_NAME_ONLY|PAKFIRE_GLOB)) == 0);
+
+       if (flags & PAKFIRE_NAME_ONLY) {
+               flags &= ~PAKFIRE_NAME_ONLY;
+
+               return pakfire_pool_search_name(pool, what, flags);
+       } else {
+               return pakfire_pool_search_provides(pool, what, flags);
+       }
+}
+
+PakfirePackageList pakfire_pool_search(PakfirePool pool, const char* what, int flags) {
+       return pakfire_pool_dataiterator(pool, what, 0, PAKFIRE_SUBSTRING);
+}
+
+char* pakfire_pool_tmpdup(Pool* pool, const char* s) {
+       char* dup = pool_alloctmpspace(pool, strlen(s) + 1);
+
+       return strcpy(dup, s);
+}
diff --git a/src/libpakfire/relation.c b/src/libpakfire/relation.c
new file mode 100644 (file)
index 0000000..e380692
--- /dev/null
@@ -0,0 +1,107 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2013 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 <assert.h>
+
+#include <solv/pooltypes.h>
+#include <solv/queue.h>
+#include <solv/solver.h>
+
+#include <pakfire/packagelist.h>
+#include <pakfire/pool.h>
+#include <pakfire/relation.h>
+#include <pakfire/types.h>
+#include <pakfire/util.h>
+
+static int cmptype2relflags(int type) {
+       int flags = 0;
+
+       if (type & PAKFIRE_EQ)
+               flags |= REL_EQ;
+       if (type & PAKFIRE_LT)
+               flags |= REL_LT;
+       if (type & PAKFIRE_GT)
+               flags |= REL_GT;
+
+       return flags;
+}
+
+PakfireRelation pakfire_relation_create(PakfirePool pool, const char* name, int cmp_type, const char* evr) {
+       Pool* p = pool->pool;
+
+       Id id = pool_str2id(p, name, 1);
+
+       if (id == STRID_NULL || id == STRID_EMPTY)
+               return NULL;
+
+       if (evr) {
+               assert(cmp_type);
+
+               Id ievr = pool_str2id(p, evr, 1);
+               int flags = cmptype2relflags(cmp_type);
+               id = pool_rel2id(p, id, ievr, flags, 1);
+       }
+
+       return pakfire_relation_create_from_id(pool, id);
+}
+
+PakfireRelation pakfire_relation_create_from_id(PakfirePool pool, Id id) {
+       PakfireRelation relation = pakfire_calloc(1, sizeof(*relation));
+
+       relation->pool = pool;
+       relation->id = id;
+
+       return relation;
+}
+
+void pakfire_relation_free(PakfireRelation relation) {
+       pakfire_free(relation);
+}
+
+Id pakfire_relation_id(PakfireRelation relation) {
+       return relation->id;
+}
+
+char* pakfire_relation_str(PakfireRelation relation) {
+       Pool* pool = pakfire_relation_solv_pool(relation);
+
+       const char* str = pool_dep2str(pool, relation->id);
+
+       return pakfire_strdup(str);
+}
+
+int pakfire_relation2queue(const PakfireRelation relation, Queue* queue, int solver_action) {
+       queue_push2(queue, SOLVER_SOLVABLE_PROVIDES|solver_action, relation->id);
+
+       return 0;
+}
+
+PakfirePackageList pakfire_relation_providers(PakfireRelation relation) {
+       Queue q;
+       queue_init(&q);
+
+       pakfire_relation2queue(relation, &q, 0);
+
+       PakfirePackageList list = pakfire_packagelist_from_queue(relation->pool, &q);
+
+       queue_free(&q);
+
+       return list;
+}
diff --git a/src/libpakfire/relationlist.c b/src/libpakfire/relationlist.c
new file mode 100644 (file)
index 0000000..fbf214d
--- /dev/null
@@ -0,0 +1,71 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2013 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 <solv/pooltypes.h>
+#include <solv/queue.h>
+
+#include <pakfire/pool.h>
+#include <pakfire/relation.h>
+#include <pakfire/relationlist.h>
+#include <pakfire/types.h>
+#include <pakfire/util.h>
+
+PakfireRelationList pakfire_relationlist_create(PakfirePool pool) {
+       PakfireRelationList relationlist = pakfire_calloc(1, sizeof(*relationlist));
+       if (relationlist) {
+               relationlist->pool = pool;
+               queue_init(&relationlist->queue);
+       }
+
+       return relationlist;
+}
+
+void pakfire_relationlist_free(PakfireRelationList relationlist) {
+       queue_free(&relationlist->queue);
+       pakfire_free(relationlist);
+}
+
+void pakfire_relationlist_add(PakfireRelationList relationlist, PakfireRelation relation) {
+       queue_push(&relationlist->queue, relation->id);
+}
+
+int pakfire_relationlist_count(PakfireRelationList relationlist) {
+       return relationlist->queue.count;
+}
+
+PakfireRelationList pakfire_relationlist_from_queue(PakfirePool pool, Queue q) {
+       PakfireRelationList relationlist = pakfire_calloc(1, sizeof(*relationlist));
+       if (relationlist) {
+               relationlist->pool = pool;
+               queue_init_clone(&relationlist->queue, &q);
+       }
+
+       return relationlist;
+}
+
+PakfireRelation pakfire_relationlist_get_clone(PakfireRelationList relationlist, int index) {
+       Id id = relationlist->queue.elements[index];
+
+       return pakfire_relation_create_from_id(relationlist->pool, id);
+}
+
+void pakfire_relationlist_clone_to_queue(PakfireRelationList relationlist, Queue* q) {
+       queue_init_clone(q, &relationlist->queue);
+}
diff --git a/src/libpakfire/repo.c b/src/libpakfire/repo.c
new file mode 100644 (file)
index 0000000..5f17f2a
--- /dev/null
@@ -0,0 +1,235 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2013 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 <string.h>
+
+#include <solv/repo.h>
+#include <solv/repo_solv.h>
+#include <solv/repo_write.h>
+
+#include <pakfire/constants.h>
+#include <pakfire/errno.h>
+#include <pakfire/package.h>
+#include <pakfire/pool.h>
+#include <pakfire/repo.h>
+#include <pakfire/repocache.h>
+#include <pakfire/types.h>
+#include <pakfire/util.h>
+
+static Repo* get_repo_by_name(Pool* pool, const char* name) {
+       Repo* repo;
+       int i;
+
+       FOR_REPOS(i, repo) {
+               if (strcmp(repo->name, name) == 0)
+                       return repo;
+       }
+
+       return NULL;
+}
+
+static PakfireRepo get_pakfire_repo_by_name(PakfirePool pool, const char* name) {
+       Repo* repo = get_repo_by_name(pool->pool, name);
+
+       if (repo)
+               return repo->appdata;
+
+       return NULL;
+}
+
+PakfireRepo pakfire_repo_create(PakfirePool pool, const char* name) {
+       PakfireRepo repo = get_pakfire_repo_by_name(pool, name);
+       if (repo) {
+               repo->nrefs++;
+               return repo;
+       }
+
+       Repo* r = get_repo_by_name(pool->pool, name);
+       if (!r)
+               r = repo_create(pool->pool, name);
+
+       return pakfire_repo_create_from_repo(pool, r);
+}
+
+PakfireRepo pakfire_repo_create_from_repo(PakfirePool pool, Repo* r) {
+       PakfireRepo repo;
+
+       if (r->appdata) {
+               repo = r->appdata;
+               repo->nrefs++;
+
+       } else {
+               repo = pakfire_calloc(1, sizeof(*repo));
+               if (repo) {
+                       repo->pool = pool;
+
+                       repo->repo = r;
+                       repo->cache = pakfire_repocache_create(repo);
+                       repo->repo->appdata = repo;
+
+                       repo->filelist = repo_add_repodata(r, REPO_EXTEND_SOLVABLES|REPO_LOCALPOOL|REPO_NO_INTERNALIZE|REPO_NO_LOCATION);
+
+                       // Initialize reference counter
+                       repo->nrefs = 1;
+               }
+       }
+
+       return repo;
+}
+
+void pakfire_repo_free(PakfireRepo repo) {
+       if (--repo->nrefs > 0)
+               return;
+
+       if (repo->repo)
+               repo->repo->appdata = NULL;
+
+       // Free repodata.
+       repodata_free(repo->filelist);
+
+       pakfire_free(repo);
+
+       if (repo->cache)
+               pakfire_repocache_free(repo->cache);
+}
+
+PakfirePool pakfire_repo_pool(PakfireRepo repo) {
+       return repo->pool;
+}
+
+int pakfire_repo_identical(PakfireRepo repo1, PakfireRepo repo2) {
+       Repo* r1 = repo1->repo;
+       Repo* r2 = repo2->repo;
+
+       return strcmp(r1->name, r2->name);
+}
+
+int pakfire_repo_cmp(PakfireRepo repo1, PakfireRepo repo2) {
+       Repo* r1 = repo1->repo;
+       Repo* r2 = repo2->repo;
+
+       if (r1->priority > r2->priority)
+               return 1;
+
+       else if (r1->priority < r2->priority)
+               return -1;
+
+       return strcmp(r1->name, r2->name);
+}
+
+int pakfire_repo_count(PakfireRepo repo) {
+       Pool* pool = pakfire_repo_solv_pool(repo);
+       int cnt = 0;
+
+       for (int i = 2; i < pool->nsolvables; i++) {
+               Solvable* s = pool->solvables + i;
+               if (s->repo && s->repo == repo->repo)
+                       cnt++;
+       }
+
+       return cnt;
+}
+
+void pakfire_repo_internalize(PakfireRepo repo) {
+       repo_internalize(repo->repo);
+}
+
+const char* pakfire_repo_get_name(PakfireRepo repo) {
+       return repo->repo->name;
+}
+
+void pakfire_repo_set_name(PakfireRepo repo, const char* name) {
+       repo->repo->name = pakfire_strdup(name);
+}
+
+int pakfire_repo_get_enabled(PakfireRepo repo) {
+       return !repo->repo->disabled;
+}
+
+void pakfire_repo_set_enabled(PakfireRepo repo, int enabled) {
+       repo->repo->disabled = !enabled;
+
+       PakfirePool pool = pakfire_repo_pool(repo);
+       pool->provides_ready = 0;
+}
+
+int pakfire_repo_get_priority(PakfireRepo repo) {
+       return repo->repo->priority;
+}
+
+void pakfire_repo_set_priority(PakfireRepo repo, int priority) {
+       repo->repo->priority = priority;
+}
+
+int pakfire_repo_is_installed_repo(PakfireRepo repo) {
+       PakfirePool pool = pakfire_repo_pool(repo);
+
+       PakfireRepo installed_repo = pakfire_pool_get_installed_repo(pool);
+
+       return pakfire_repo_identical(repo, installed_repo);
+}
+
+int pakfire_repo_read_solv(PakfireRepo repo, const char* filename, int flags) {
+       FILE* f = fopen(filename, "rb");
+       if (!f) {
+               return PAKFIRE_E_IO;
+       }
+
+       int ret = pakfire_repo_read_solv_fp(repo, f, flags);
+       fclose(f);
+
+       return ret;
+}
+
+int pakfire_repo_read_solv_fp(PakfireRepo repo, FILE *f, int flags) {
+       int ret = repo_add_solv(repo->repo, f, flags);
+
+       repo->pool->provides_ready = 0;
+
+       return ret;
+}
+
+int pakfire_repo_write_solv(PakfireRepo repo, const char* filename, int flags) {
+       FILE* f = fopen(filename, "wb");
+       if (!f) {
+               return PAKFIRE_E_IO;
+       }
+
+       int ret = pakfire_repo_write_solv_fp(repo, f, flags);
+       fclose(f);
+
+       return ret;
+}
+
+int pakfire_repo_write_solv_fp(PakfireRepo repo, FILE *f, int flags) {
+       pakfire_repo_internalize(repo);
+
+       return repo_write(repo->repo, f);
+}
+
+PakfirePackage pakfire_repo_add_package(PakfireRepo repo) {
+       Id id = repo_add_solvable(repo->repo);
+
+       return pakfire_package_create(repo->pool, id);
+}
+
+PakfireRepoCache pakfire_repo_get_cache(PakfireRepo repo) {
+       return repo->cache;
+}
diff --git a/src/libpakfire/repocache.c b/src/libpakfire/repocache.c
new file mode 100644 (file)
index 0000000..257606f
--- /dev/null
@@ -0,0 +1,98 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2013 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 <stdio.h>
+#include <sys/stat.h>
+
+#include <pakfire/cache.h>
+#include <pakfire/constants.h>
+#include <pakfire/package.h>
+#include <pakfire/repo.h>
+#include <pakfire/repocache.h>
+#include <pakfire/types.h>
+#include <pakfire/util.h>
+
+static char* pakfire_repocache_prefix(PakfireRepoCache repo_cache) {
+       const char* repo_name = pakfire_repo_get_name(repo_cache->repo);
+
+       char buffer[STRING_SIZE] = "";
+       snprintf(buffer, sizeof(buffer), "repodata/%s", repo_name);
+
+       return pakfire_strdup(buffer);
+}
+
+PakfireRepoCache pakfire_repocache_create(PakfireRepo repo) {
+       PakfireRepoCache repo_cache = pakfire_calloc(1, sizeof(*repo_cache));
+
+       repo_cache->repo = repo;
+       repo_cache->prefix = pakfire_repocache_prefix(repo_cache);
+
+       return repo_cache;
+}
+
+void pakfire_repocache_free(PakfireRepoCache repo_cache) {
+       pakfire_free(repo_cache->prefix);
+       pakfire_free(repo_cache);
+}
+
+char* pakfire_repocache_get_cache_path(PakfireRepoCache repo_cache, const char* path) {
+       return pakfire_path_join(repo_cache->prefix, path);
+}
+
+char* pakfire_repocache_get_full_path(PakfireRepoCache repo_cache, const char* path) {
+       char* cache_path = pakfire_repocache_get_cache_path(repo_cache, path);
+
+       PakfireCache cache = pakfire_repocache_cache(repo_cache);
+       char* full_path = pakfire_cache_get_full_path(cache, cache_path);
+
+       pakfire_free(cache_path);
+
+       return full_path;
+}
+
+int pakfire_repocache_has_file(PakfireRepoCache repo_cache, const char* filename) {
+       char* cache_filename = pakfire_repocache_get_cache_path(repo_cache, filename);
+
+       PakfireCache cache = pakfire_repocache_cache(repo_cache);
+       int r = pakfire_cache_has_file(cache, cache_filename);
+
+       pakfire_free(cache_filename);
+       return r;
+}
+
+int pakfire_repocache_age(PakfireRepoCache repo_cache, const char* filename) {
+       char* cache_filename = pakfire_repocache_get_cache_path(repo_cache, filename);
+
+       PakfireCache cache = pakfire_repocache_cache(repo_cache);
+       int age = pakfire_cache_age(cache, cache_filename);
+       pakfire_free(cache_filename);
+
+       return age;
+}
+
+FILE* pakfire_repocache_open(PakfireRepoCache repo_cache, const char* filename, const char* flags) {
+       char* cache_filename = pakfire_repocache_get_cache_path(repo_cache, filename);
+
+       PakfireCache cache = pakfire_repocache_cache(repo_cache);
+       FILE* fp = pakfire_cache_open(cache, cache_filename, flags);
+       pakfire_free(cache_filename);
+
+       return fp;
+}
diff --git a/src/libpakfire/request.c b/src/libpakfire/request.c
new file mode 100644 (file)
index 0000000..e428117
--- /dev/null
@@ -0,0 +1,228 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2013 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 <solv/queue.h>
+#include <solv/solver.h>
+#include <solv/transaction.h>
+
+#ifdef DEBUG
+# include <solv/solverdebug.h>
+#endif
+
+#include <pakfire/package.h>
+#include <pakfire/request.h>
+#include <pakfire/selector.h>
+#include <pakfire/transaction.h>
+#include <pakfire/types.h>
+#include <pakfire/util.h>
+
+PakfireRequest pakfire_request_create(PakfirePool pool) {
+       PakfireRequest request = pakfire_calloc(1, sizeof(*request));
+       request->pool = pool;
+
+       queue_init(&request->queue);
+
+       return request;
+}
+
+void pakfire_request_free(PakfireRequest request) {
+       if (request->transaction)
+               transaction_free(request->transaction);
+
+       if (request->solver)
+               solver_free(request->solver);
+
+       queue_free(&request->queue);
+
+       pakfire_free(request);
+}
+
+PakfirePool pakfire_request_pool(PakfireRequest request) {
+       return request->pool;
+}
+
+static void init_solver(PakfireRequest request, int flags) {
+       PakfirePool pool = pakfire_request_pool(request);
+
+       Solver* solver = solver_create(pool->pool);
+
+       /* Free older solver */
+       if (request->solver) {
+               solver_free(request->solver);
+               request->solver = NULL;
+       }
+
+       request->solver = solver;
+
+       if (flags & PAKFIRE_SOLVER_ALLOW_UNINSTALL)
+               solver_set_flag(solver, SOLVER_FLAG_ALLOW_UNINSTALL, 1);
+
+       /* no vendor locking */
+       solver_set_flag(solver, SOLVER_FLAG_ALLOW_VENDORCHANGE, 1);
+
+       /* no arch change for forcebest */
+       solver_set_flag(solver, SOLVER_FLAG_BEST_OBEY_POLICY, 1);
+}
+
+static int solve(PakfireRequest request, Queue* queue) {
+       /* Remove any previous transactions */
+       if (request->transaction) {
+               transaction_free(request->transaction);
+               request->transaction = NULL;
+       }
+
+       pakfire_pool_make_provides_ready(request->pool);
+
+       if (solver_solve(request->solver, queue)) {
+#ifdef DEBUG
+               solver_printallsolutions(request->solver);
+#endif
+
+               return 1;
+       }
+
+       /* If the solving process was successful, we get the transaction
+        * from the solver. */
+       request->transaction = solver_create_transaction(request->solver);
+       transaction_order(request->transaction, 0);
+
+       return 0;
+}
+
+int pakfire_request_solve(PakfireRequest request, int flags) {
+       init_solver(request, flags);
+
+       Queue queue;
+       queue_init_clone(&queue, &request->queue);
+
+       /* Apply forcebest */
+       if (flags & PAKFIRE_SOLVER_FORCE_BEST) {
+               for (int i = 0; i < queue.count; i += 2) {
+                       queue.elements[i] |= SOLVER_FORCEBEST;
+               }
+       }
+
+       /* turn off implicit obsoletes for installonly packages */
+       PakfirePool pool = request->pool;
+       for (int i = 0; i < pool->installonly.count; i++)
+               queue_push2(&queue, SOLVER_MULTIVERSION|SOLVER_SOLVABLE_PROVIDES,
+                       pool->installonly.elements[i]);
+
+       // XXX EXCLUDES
+
+       int ret = solve(request, &queue);
+
+       queue_free(&queue);
+
+       return ret;
+}
+
+PakfireTransaction pakfire_request_get_transaction(PakfireRequest request) {
+       if (!request->transaction)
+               return NULL;
+
+       return pakfire_transaction_create(request->pool, request->transaction);
+}
+
+int pakfire_request_install(PakfireRequest request, PakfirePackage package) {
+       queue_push2(&request->queue, SOLVER_SOLVABLE|SOLVER_INSTALL, pakfire_package_id(package));
+
+       return 0;
+}
+
+int pakfire_request_install_relation(PakfireRequest request, PakfireRelation relation) {
+       return pakfire_relation2queue(relation, &request->queue, SOLVER_INSTALL);
+}
+
+int pakfire_request_install_selector(PakfireRequest request, PakfireSelector selector) {
+       return pakfire_selector2queue(selector, &request->queue, SOLVER_INSTALL);
+}
+
+static int erase_flags(int flags) {
+       int additional = 0;
+
+       if (flags & PAKFIRE_CLEAN_DEPS)
+               additional |= SOLVER_CLEANDEPS;
+
+       return additional;
+}
+
+int pakfire_request_erase(PakfireRequest request, PakfirePackage package, int flags) {
+       int additional = erase_flags(flags);
+       queue_push2(&request->queue, SOLVER_SOLVABLE|SOLVER_ERASE|additional, pakfire_package_id(package));
+
+       return 0;
+}
+
+int pakfire_request_erase_relation(PakfireRequest request, PakfireRelation relation, int flags) {
+       int additional = erase_flags(flags);
+
+       return pakfire_relation2queue(relation, &request->queue, SOLVER_ERASE|additional);
+}
+
+int pakfire_request_erase_selector(PakfireRequest request, PakfireSelector selector, int flags) {
+       int additional = erase_flags(flags);
+
+       return pakfire_selector2queue(selector, &request->queue, SOLVER_ERASE|additional);
+}
+
+int pakfire_request_upgrade(PakfireRequest request, PakfirePackage package) {
+       return pakfire_request_install(request, package);
+}
+
+int pakfire_request_upgrade_relation(PakfireRequest request, PakfireRelation relation) {
+       return pakfire_relation2queue(relation, &request->queue, SOLVER_UPDATE);
+}
+
+int pakfire_request_upgrade_selector(PakfireRequest request, PakfireSelector selector) {
+       return pakfire_selector2queue(selector, &request->queue, SOLVER_UPDATE);
+}
+
+int pakfire_request_upgrade_all(PakfireRequest request) {
+       queue_push2(&request->queue, SOLVER_UPDATE|SOLVER_SOLVABLE_ALL, 0);
+
+       return 0;
+}
+
+int pakfire_request_distupgrade(PakfireRequest request) {
+       queue_push2(&request->queue, SOLVER_DISTUPGRADE|SOLVER_SOLVABLE_ALL, 0);
+
+       return 0;
+}
+
+int pakfire_request_lock(PakfireRequest request, PakfirePackage package) {
+       queue_push2(&request->queue, SOLVER_SOLVABLE|SOLVER_LOCK, pakfire_package_id(package));
+
+       return 0;
+}
+
+int pakfire_request_lock_relation(PakfireRequest request, PakfireRelation relation) {
+       return pakfire_relation2queue(relation, &request->queue, SOLVER_LOCK);
+}
+
+int pakfire_request_lock_selector(PakfireRequest request, PakfireSelector selector) {
+       return pakfire_selector2queue(selector, &request->queue, SOLVER_LOCK);
+}
+
+int pakfire_request_verify(PakfireRequest request) {
+       queue_push2(&request->queue, SOLVER_VERIFY|SOLVER_SOLVABLE_ALL, 0);
+
+       return 0;
+}
diff --git a/src/libpakfire/selector.c b/src/libpakfire/selector.c
new file mode 100644 (file)
index 0000000..a2b0ff7
--- /dev/null
@@ -0,0 +1,305 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2013 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 <assert.h>
+
+#include <solv/pool.h>
+#include <solv/queue.h>
+#include <solv/solver.h>
+
+#include <pakfire/errno.h>
+#include <pakfire/filter.h>
+#include <pakfire/package.h>
+#include <pakfire/packagelist.h>
+#include <pakfire/pool.h>
+#include <pakfire/selector.h>
+#include <pakfire/types.h>
+#include <pakfire/util.h>
+
+PakfireSelector pakfire_selector_create(PakfirePool pool) {
+       PakfireSelector selector = pakfire_calloc(1, sizeof(*selector));
+       selector->pool = pool;
+
+       selector->f_arch = NULL;
+       selector->f_name = NULL;
+       selector->f_evr = NULL;
+       selector->f_provides = NULL;
+
+       return selector;
+}
+
+void pakfire_selector_free(PakfireSelector selector) {
+       pakfire_free(selector);
+}
+
+static int pakfire_selector_valid_setting(int keyname, int cmp_type) {
+       switch (keyname) {
+               case PAKFIRE_PKG_ARCH:
+               case PAKFIRE_PKG_EVR:
+               case PAKFIRE_PKG_VERSION:
+               case PAKFIRE_PKG_PROVIDES:
+                       return cmp_type == PAKFIRE_EQ;
+
+               case PAKFIRE_PKG_NAME:
+                       return (cmp_type == PAKFIRE_EQ || cmp_type == PAKFIRE_GLOB);
+
+               default:
+                       return 0;
+       }
+}
+
+static void pakfire_selector_replace_filter(PakfireFilter* filter, int keyname, int cmp_type, const char* match) {
+       if (*filter)
+               pakfire_filter_free(*filter);
+
+       PakfireFilter f = pakfire_filter_create();
+
+       f->keyname = keyname;
+       f->cmp_type = cmp_type;
+       f->match = pakfire_strdup(match);
+
+       *filter = f;
+}
+
+int pakfire_selector_set(PakfireSelector selector, int keyname, int cmp_type, const char* match) {
+       if (!pakfire_selector_valid_setting(keyname, cmp_type))
+               return PAKFIRE_E_SELECTOR;
+
+       PakfireFilter* filter = NULL;
+
+       switch (keyname) {
+               case PAKFIRE_PKG_ARCH:
+                       filter = &selector->f_arch;
+                       break;
+
+               case PAKFIRE_PKG_EVR:
+               case PAKFIRE_PKG_VERSION:
+                       filter = &selector->f_evr;
+                       break;
+
+               case PAKFIRE_PKG_NAME:
+                       if (selector->f_provides)
+                               return PAKFIRE_E_SELECTOR;
+
+                       filter = &selector->f_name;
+                       break;
+
+               case PAKFIRE_PKG_PROVIDES:
+                       if (selector->f_name)
+                               return PAKFIRE_E_SELECTOR;
+
+                       filter = &selector->f_provides;
+                       break;
+
+               default:
+                       return PAKFIRE_E_SELECTOR; 
+       }
+
+       assert(filter);
+
+       pakfire_selector_replace_filter(filter, keyname, cmp_type, match);
+
+       return 0;
+}
+
+PakfirePackageList pakfire_selector_providers(PakfireSelector selector) {
+       Queue q;
+       queue_init(&q);
+
+       pakfire_selector2queue(selector, &q, 0);
+
+       PakfirePackageList list = pakfire_packagelist_from_queue(selector->pool, &q);
+
+       queue_free(&q);
+
+       return list;
+}
+
+static int queue_has(Queue* queue, Id what, Id id) {
+       for (int i = 0; i < queue->count; i += 2) {
+               if (queue->elements[i] == what && queue->elements[i + 1] == id)
+                       return 1;
+       }
+
+       return 0;
+}
+
+static Id str2archid(Pool* pool, const char* arch) {
+       // originally from libsolv/examples/solv.c:str2archid()
+
+       if (!*arch)
+        return 0;
+
+    Id id = pool_str2id(pool, arch, 0);
+    if (id == ARCH_SRC || id == ARCH_NOSRC || id == ARCH_NOARCH)
+        return id;
+
+    if (pool->id2arch && (id > pool->lastarch || !pool->id2arch[id]))
+        return 0;
+
+    return id;
+}
+
+static int filter_arch2queue(PakfirePool pool, const PakfireFilter f, Queue* queue) {
+       if (f == NULL)
+               return 0;
+
+       assert(f->cmp_type == PAKFIRE_EQ);
+
+       Id archid = str2archid(pool->pool, f->match);
+       if (archid == 0)
+               return PAKFIRE_E_ARCH;
+
+       for (int i = 0; i < queue->count; i += 2) {
+               assert((queue->elements[i] & SOLVER_SELECTMASK) == SOLVER_SOLVABLE_NAME);
+
+               Id dep = queue->elements[i + 1];
+               queue->elements[i + 1] = pool_rel2id(pool->pool, dep, archid, REL_ARCH, 1);
+               queue->elements[i] |= SOLVER_SETARCH;
+       }
+
+       return 0;
+}
+
+static int filter_evr2queue(PakfirePool pool, const PakfireFilter f, Queue* queue) {
+       if (f == NULL)
+               return 0;
+
+       assert(f->cmp_type == PAKFIRE_EQ);
+
+       Id evr = pool_str2id(pool->pool, f->match, 1);
+
+       for (int i = 0; i < queue->count; i += 2) {
+               assert((queue->elements[i] & SOLVER_SELECTMASK) == SOLVER_SOLVABLE_NAME);
+
+               Id dep = queue->elements[i + 1];
+               queue->elements[i + 1] = pool_rel2id(pool->pool, dep, evr, REL_EQ, 1);
+               queue->elements[i] |= PAKFIRE_PKG_VERSION ? SOLVER_SETEV : SOLVER_SETEVR;
+       }
+
+       return 0;
+}
+
+static int filter_name2queue(PakfirePool pool, const PakfireFilter f, Queue* queue) {
+       if (f == NULL)
+               return 0;
+
+       const char* name = f->match;
+       Id id;
+       Dataiterator di;
+
+       switch (f->cmp_type) {
+               case PAKFIRE_EQ:
+                       id = pool_str2id(pool->pool, name, 0);
+                       if (id)
+                               queue_push2(queue, SOLVER_SOLVABLE_NAME, id);
+                       break;
+
+               case PAKFIRE_GLOB:
+                       dataiterator_init(&di, pool->pool, 0, 0, SOLVABLE_NAME, name, SEARCH_GLOB);
+
+                       while (dataiterator_step(&di)) {
+                               assert(di.idp);
+                               Id id = *di.idp;
+
+                               if (queue_has(queue, SOLVABLE_NAME, id))
+                                       continue;
+
+                               queue_push2(queue, SOLVER_SOLVABLE_NAME, id);
+                       }
+
+                       dataiterator_free(&di);
+                       break;
+
+               default:
+                       assert(0);
+                       return 1;
+       }
+
+       return 0;
+}
+
+static int filter_provides2queue(PakfirePool pool, const PakfireFilter f, Queue* queue) {
+       if (f == NULL)
+               return 0;
+
+       Id id;
+
+       switch (f->cmp_type) {
+               case PAKFIRE_EQ:
+                       id = pool_str2id(pool->pool, f->match, 0);
+                       if (id)
+                               queue_push2(queue, SOLVER_SOLVABLE_PROVIDES, id);
+                       break;
+
+               default:
+                       assert(0);
+                       return 1;
+       }
+
+       return 0;
+}
+
+int pakfire_selector2queue(const PakfireSelector selector, Queue* queue, int solver_action) {
+       PakfirePool pool = selector->pool;
+       int ret = 0;
+
+       Queue queue_selector;
+       queue_init(&queue_selector);
+
+       if (selector->f_name == NULL && selector->f_provides == NULL) {
+               // no name or provides in the selector is an erro
+               ret = PAKFIRE_E_SELECTOR;
+               goto finish;
+       }
+
+       pakfire_pool_make_provides_ready(pool);
+
+       ret = filter_name2queue(pool, selector->f_name, &queue_selector);
+       if (ret)
+               goto finish;
+
+       ret = filter_provides2queue(pool, selector->f_provides, &queue_selector);
+       if (ret)
+               goto finish;
+
+       ret = filter_arch2queue(pool, selector->f_arch, &queue_selector);
+       if (ret)
+               goto finish;
+
+       ret = filter_evr2queue(pool, selector->f_evr, &queue_selector);
+       if (ret)
+               goto finish;
+
+       for (int i = 0; i < queue_selector.count; i += 2) {
+               queue_push2(queue,
+                       queue_selector.elements[i] | solver_action,
+                       queue_selector.elements[i + 1]
+               );
+       }
+
+finish:
+       if (ret)
+               pakfire_errno = ret;
+
+       queue_free(&queue_selector);
+
+       return ret;
+}
diff --git a/src/libpakfire/solver.c b/src/libpakfire/solver.c
new file mode 100644 (file)
index 0000000..aeaf9dd
--- /dev/null
@@ -0,0 +1,19 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2013 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/>.       #
+#                                                                             #
+#############################################################################*/
diff --git a/src/libpakfire/step.c b/src/libpakfire/step.c
new file mode 100644 (file)
index 0000000..1480538
--- /dev/null
@@ -0,0 +1,208 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2013 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 <stdbool.h>
+
+#include <solv/pooltypes.h>
+#include <solv/transaction.h>
+
+#include <pakfire/cache.h>
+#include <pakfire/constants.h>
+#include <pakfire/package.h>
+#include <pakfire/repo.h>
+#include <pakfire/step.h>
+#include <pakfire/transaction.h>
+#include <pakfire/types.h>
+#include <pakfire/util.h>
+
+PakfireStep pakfire_step_create(PakfireTransaction transaction, Id id) {
+       PakfireStep step = pakfire_calloc(1, sizeof(*step));
+
+       step->pool = pakfire_transaction_pool(transaction);
+       step->transaction = transaction;
+       step->id = id;
+
+       return step;
+}
+
+void pakfire_step_free(PakfireStep step) {
+       pakfire_free(step);
+}
+
+PakfirePackage pakfire_step_get_package(PakfireStep step) {
+       return pakfire_package_create(step->pool, step->id);
+}
+
+int pakfire_step_get_type(PakfireStep step) {
+       Transaction* trans = step->transaction->transaction;
+
+       return transaction_type(trans, step->id,
+               SOLVER_TRANSACTION_SHOW_ACTIVE|SOLVER_TRANSACTION_CHANGE_IS_REINSTALL);
+}
+
+const char* pakfire_step_get_type_string(PakfireStep step) {
+       const char *type;
+
+       switch(pakfire_step_get_type(step)) {
+               case SOLVER_TRANSACTION_IGNORE:
+                       type = "ignore";
+                       break;
+
+               case SOLVER_TRANSACTION_ERASE:
+                       type = "erase";
+                       break;
+
+               case SOLVER_TRANSACTION_REINSTALLED:
+                       type = "reinstalled";
+                       break;
+
+               case SOLVER_TRANSACTION_DOWNGRADED:
+                       type = "downgraded";
+                       break;
+
+               case SOLVER_TRANSACTION_CHANGED:
+                       type = "changed";
+                       break;
+
+               case SOLVER_TRANSACTION_UPGRADED:
+                       type = "upgraded";
+                       break;
+
+               case SOLVER_TRANSACTION_OBSOLETED:
+                       type = "obsoleted";
+                       break;
+
+               case SOLVER_TRANSACTION_INSTALL:
+                       type = "install";
+                       break;
+
+               case SOLVER_TRANSACTION_REINSTALL:
+                       type = "reinstall";
+                       break;
+
+               case SOLVER_TRANSACTION_DOWNGRADE:
+                       type = "downgrade";
+                       break;
+
+               case SOLVER_TRANSACTION_CHANGE:
+                       type = "change";
+                       break;
+
+               case SOLVER_TRANSACTION_UPGRADE:
+                       type = "upgrade";
+                       break;
+
+               case SOLVER_TRANSACTION_OBSOLETES:
+                       type = "obsoletes";
+                       break;
+
+               case SOLVER_TRANSACTION_MULTIINSTALL:
+                       type = "multiinstall";
+                       break;
+
+               case SOLVER_TRANSACTION_MULTIREINSTALL:
+                       type = "multireinstall";
+                       break;
+
+               default:
+                       type = NULL;
+                       break;
+       }
+
+       return type;
+}
+
+static int pakfire_step_get_downloadtype(PakfireStep step) {
+       int type = pakfire_step_get_type(step);
+       switch (type) {
+               case SOLVER_TRANSACTION_DOWNGRADE:
+               //case SOLVER_TRANSACTION_IGNORE:
+               case SOLVER_TRANSACTION_INSTALL:
+               case SOLVER_TRANSACTION_MULTIINSTALL:
+               case SOLVER_TRANSACTION_MULTIREINSTALL:
+               case SOLVER_TRANSACTION_REINSTALL:
+               case SOLVER_TRANSACTION_UPGRADE:
+                       return 1;
+       }
+
+       return 0;
+}
+
+unsigned long long pakfire_step_get_downloadsize(PakfireStep step) {
+       PakfirePackage pkg = NULL;
+       int downloadsize = 0;
+
+       if (pakfire_step_get_downloadtype(step)) {
+               pkg = pakfire_step_get_package(step);
+               downloadsize = pakfire_package_get_downloadsize(pkg);
+       }
+
+       if (pkg)
+               pakfire_package_free(pkg);
+
+       return downloadsize;
+}
+
+long pakfire_step_get_installsizechange(PakfireStep step) {
+       PakfirePackage pkg = pakfire_step_get_package(step);
+       int installsize = pakfire_package_get_installsize(pkg);
+
+       int type = pakfire_step_get_type(step);
+       switch (type) {
+               case SOLVER_TRANSACTION_IGNORE:
+               case SOLVER_TRANSACTION_ERASE:
+                       installsize *= -1;
+                       break;
+       }
+
+       pakfire_package_free(pkg);
+
+       return installsize;
+}
+
+int pakfire_step_needs_download(PakfireStep step) {
+       PakfirePackage pkg = NULL;
+       int ret = true;
+
+       if (!pakfire_step_get_downloadtype(step))
+               return false;
+
+       /* Get the package object. */
+       pkg = pakfire_step_get_package(step);
+
+       PakfireRepo repo = pakfire_package_get_repo(pkg);
+       if (pakfire_repo_is_installed_repo(repo)) {
+               ret = false;
+               goto finish;
+       }
+
+       PakfireCache cache = pakfire_pool_get_cache(step->pool);
+       if (!cache)
+               goto finish;
+
+       // Return false if package is in cache.
+       ret = !pakfire_cache_has_package(cache, pkg);
+
+finish:
+       if (pkg)
+               pakfire_package_free(pkg);
+
+       return ret;
+}
diff --git a/src/libpakfire/transaction.c b/src/libpakfire/transaction.c
new file mode 100644 (file)
index 0000000..df15f80
--- /dev/null
@@ -0,0 +1,89 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2013 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 <solv/transaction.h>
+
+#include <pakfire/package.h>
+#include <pakfire/packagelist.h>
+#include <pakfire/step.h>
+#include <pakfire/transaction.h>
+#include <pakfire/types.h>
+#include <pakfire/util.h>
+
+PakfireTransaction pakfire_transaction_create(PakfirePool pool, Transaction* trans) {
+       PakfireTransaction transaction = pakfire_calloc(1, sizeof(*transaction));
+       transaction->pool = pool;
+
+       // Clone the transaction, so we get independent from what ever called this.
+       if (trans) {
+               transaction->transaction = transaction_create_clone(trans);
+               transaction_order(transaction->transaction, 0);
+       } else {
+               transaction->transaction = transaction_create(trans->pool);
+       }
+
+       return transaction;
+}
+
+void pakfire_transaction_free(PakfireTransaction transaction) {
+       transaction_free(transaction->transaction);
+       pakfire_free(transaction);
+}
+
+int pakfire_transaction_count(PakfireTransaction transaction) {
+       return transaction->transaction->steps.count;
+}
+
+int pakfire_transaction_installsizechange(PakfireTransaction transaction) {
+       int sizechange = transaction_calc_installsizechange(transaction->transaction);
+       printf("SIZECHANGE %d\n", sizechange);
+
+       // Convert from kbytes to bytes
+       return sizechange * 1024;
+}
+
+PakfireStep pakfire_transaction_get_step(PakfireTransaction transaction, int index) {
+       Transaction* trans = transaction->transaction;
+
+       if (index >= trans->steps.count)
+               return NULL;
+
+       return pakfire_step_create(transaction, trans->steps.elements[index]);
+}
+
+PakfirePackageList pakfire_transaction_get_packages(PakfireTransaction transaction, int type) {
+       PakfirePool pool = pakfire_transaction_pool(transaction);
+       Transaction* trans = transaction->transaction;
+
+       PakfirePackageList packagelist = pakfire_packagelist_create();
+
+       for (int i = 0; i < trans->steps.count; i++) {
+               Id p = trans->steps.elements[i];
+               Id t = transaction_type(trans, p,
+                       SOLVER_TRANSACTION_SHOW_ACTIVE|SOLVER_TRANSACTION_CHANGE_IS_REINSTALL);
+
+               if (t == type) {
+                       PakfirePackage package = pakfire_package_create(pool, p);
+                       pakfire_packagelist_push(packagelist, package);
+               }
+       }
+
+       return packagelist;
+}
diff --git a/src/libpakfire/util.c b/src/libpakfire/util.c
new file mode 100644 (file)
index 0000000..87490fb
--- /dev/null
@@ -0,0 +1,158 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2013 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 <libgen.h>
+#include <math.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <pakfire/constants.h>
+
+void pakfire_oom(size_t num, size_t len) {
+       if (num)
+               fprintf(stderr, "Out of memory allocating %zu*%zu bytes!\n", num, len);
+       else
+               fprintf(stderr, "Out of memory allocating %zu bytes!\n", len);
+
+       abort();
+       exit(1);
+}
+
+void* pakfire_malloc(size_t len) {
+       void* r = malloc(len ? len : 1);
+       if (!r)
+               pakfire_oom(0, len);
+
+       return r;
+}
+
+void* pakfire_calloc(size_t num, size_t len) {
+       void* r;
+
+       if (num == 0 || len == 0)
+               r = malloc(1);
+       else
+               r = calloc(num, len);
+
+       if (!r)
+               pakfire_oom(num, len);
+
+       return r;
+}
+
+void* pakfire_realloc(void* ptr, size_t size) {
+       ptr = realloc(ptr, size);
+       if (!ptr)
+               pakfire_oom(0, size);
+
+       return ptr;
+}
+
+void* pakfire_free(void* mem) {
+       if (mem)
+               free(mem);
+
+       return 0;
+}
+
+char* pakfire_strdup(const char* s) {
+       if (!s)
+               return 0;
+
+       char* r = strdup(s);
+       if (!r)
+               pakfire_oom(0, strlen(s));
+
+       return r;
+}
+
+char* pakfire_format_size(double size) {
+       char string[STRING_SIZE];
+       const char* units[] = {" ", "k", "M", "G", "T", NULL};
+       const char** unit = units;
+
+       while (*(unit + 1) && size >= 1024.0) {
+               size /= 1024.0;
+               unit++;
+       }
+
+       snprintf(string, STRING_SIZE, "%.0f%s", round(size), *unit);
+
+       return pakfire_strdup(string);
+}
+
+char* pakfire_path_join(const char* first, const char* second) {
+       char* buffer;
+
+       if (!second)
+               return pakfire_strdup(first);
+
+       if (*second == '/')
+               return pakfire_strdup(second);
+
+       asprintf(&buffer, "%s/%s", first, second);
+
+       return buffer;
+}
+
+char* pakfire_basename(const char* path) {
+       char* name = pakfire_strdup(path);
+
+       return basename(name);
+}
+
+char* pakfire_dirname(const char* path) {
+       char* parent = pakfire_strdup(path);
+
+       return dirname(parent);
+}
+
+char* pakfire_sgets(char* str, int num, char** input) {
+       char* next = *input;
+       int numread = 0;
+
+       while (numread + 1 < num && *next) {
+               int isnewline = (*next == '\n');
+
+               *str++ = *next++;
+               numread++;
+
+               if (isnewline)
+                       break;
+       }
+
+       // Terminate string
+       *str = '\0';
+
+       *input = next;
+
+       return str;
+}
+
+char* pakfire_remove_trailing_newline(char* str) {
+       ssize_t pos = strlen(str) - 1;
+
+       if (str[pos] == '\n')
+               str[pos] = '\0';
+
+       return str;
+}