src/libpakfire/compress.c \
src/libpakfire/config.c \
src/libpakfire/db.c \
+ src/libpakfire/dependencies.c \
src/libpakfire/dist.c \
src/libpakfire/downloader.c \
src/libpakfire/file.c \
src/libpakfire/include/pakfire/config.h \
src/libpakfire/include/pakfire/constants.h \
src/libpakfire/include/pakfire/db.h \
+ src/libpakfire/include/pakfire/dependencies.h \
src/libpakfire/include/pakfire/dist.h \
src/libpakfire/include/pakfire/downloader.h \
src/libpakfire/include/pakfire/file.h \
#include <pakfire/archive.h>
#include <pakfire/compress.h>
+#include <pakfire/dependencies.h>
#include <pakfire/file.h>
#include <pakfire/filelist.h>
#include <pakfire/i18n.h>
#include <pakfire/build.h>
#include <pakfire/cgroup.h>
+#include <pakfire/dependencies.h>
#include <pakfire/dist.h>
#include <pakfire/file.h>
#include <pakfire/i18n.h>
#include <pakfire/archive.h>
#include <pakfire/db.h>
+#include <pakfire/dependencies.h>
#include <pakfire/file.h>
#include <pakfire/filelist.h>
#include <pakfire/logging.h>
--- /dev/null
+/*#############################################################################
+# #
+# Pakfire - The IPFire package management system #
+# Copyright (C) 2022 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 <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <solv/pool.h>
+
+#include <pakfire/dependencies.h>
+#include <pakfire/logging.h>
+#include <pakfire/package.h>
+#include <pakfire/pakfire.h>
+#include <pakfire/util.h>
+
+static const struct pakfire_rich_operation {
+ const char* keyword;
+ const int flags;
+} pakfire_rich_operations[] = {
+ { "and ", REL_AND },
+ { "or ", REL_OR },
+ { "if ", REL_COND },
+ { "unless ", REL_UNLESS },
+ { "else ", REL_ELSE },
+ { "with ", REL_WITH },
+ { "without ", REL_WITHOUT },
+ { NULL, 0 },
+};
+
+const char* pakfire_dep2str(struct pakfire* pakfire, Id id) {
+ Pool* pool = pakfire_get_solv_pool(pakfire);
+ if (!pool)
+ return NULL;
+
+ return pool_dep2str(pool, id);
+}
+
+/*
+ Reads the string until the next space is found.
+
+ This function considers opening and closing brackets.
+*/
+static size_t skip(const char** s, const char** n) {
+ const char* p = *s;
+
+ // Store p in n
+ *n = p;
+
+ int brackets = 0;
+
+ while (*p) {
+ switch (*p) {
+ // End on space or comma
+ case ' ':
+ case ',':
+ goto END;
+
+ // Increment counter on opening bracket
+ case '(':
+ brackets++;
+ break;
+
+ // End on the last closing bracket
+ case ')':
+ if (brackets-- <= 0)
+ goto END;
+ break;
+ }
+
+ // Move to next character
+ p++;
+ }
+
+END:
+ *s = p;
+
+ // Return the length of the skipped string
+ return p - *n;
+}
+
+/*
+ This function parses any namespaced dependencies
+*/
+static Id pakfire_parse_namespace(Pool* pool, const char* s) {
+ const char* p = strchr(s, '(');
+ if (!p)
+ return 0;
+
+ // Store the namespace ID
+ Id namespace = pool_strn2id(pool, s, p - s, 1);
+
+ // Find the end of the string
+ s = strrchr(p, ')');
+ if (!s)
+ return 0;
+
+ Id id = pool_strn2id(pool, p + 1, s - p - 1, 1);
+
+ // Bring it all together
+ return pool_rel2id(pool, namespace, id, REL_NAMESPACE, 1);
+}
+
+/*
+ This function parses a simple dependency like "foo = 1.2.3"
+*/
+static Id pakfire_parse_dep(struct pakfire* pakfire, const char** s) {
+ Id id = ID_NULL;
+
+ if (!s) {
+ errno = EINVAL;
+ return 0;
+ }
+
+ const char* p = *s;
+ const char* n = NULL;
+
+ // Ignore empty strings
+ if (!p)
+ return ID_NULL;
+
+ Pool* pool = pakfire_get_solv_pool(pakfire);
+
+ // Consume any leading space
+ if (isspace(*p))
+ p++;
+
+ // Find the first part
+ size_t l = skip(&p, &n);
+
+ // Add name to pool
+ if (pakfire_string_startswith(n, "pakfire("))
+ id = pakfire_parse_namespace(pool, n);
+ else
+ id = pool_strn2id(pool, n, l, 1);
+
+ // Consume any more space
+ if (isspace(*p))
+ p++;
+
+ if (*p == '<' || *p == '=' || *p == '>') {
+ int flags = 0;
+
+ while (1) {
+ if (*p == '<')
+ flags |= REL_LT;
+ else if (*p == '=')
+ flags |= REL_EQ;
+ else if (*p == '>')
+ flags |= REL_GT;
+ else
+ break;
+
+ p++;
+ }
+
+ // Consume any more space
+ if (isspace(*p))
+ p++;
+
+ // Find the length of EVR
+ l = skip(&p, &n);
+
+ // Strip zero epoch
+ if (pakfire_string_startswith(n, "0:"))
+ n += 2;
+
+ // Add EVR to pool
+ Id evr = pool_strn2id(pool, n, l, 1);
+
+ // Combine everything
+ id = pool_rel2id(pool, id, evr, flags, 1);
+ }
+
+ *s = p;
+
+ return id;
+}
+
+/*
+ This function parses any rich dependencies
+*/
+static Id pakfire_parse_rich_dep(struct pakfire* pakfire, const char** dep, int flags) {
+ const char* p = *dep;
+ Id id;
+
+ // Do not try parsing empty strings
+ if (!*p)
+ return ID_NULL;
+
+ // Must be starting with an opening bracket
+ if (!flags && *p++ != '(')
+ return ID_NULL;
+
+ switch (*p) {
+ // A new rich dependency
+ case '(':
+ id = pakfire_parse_rich_dep(pakfire, &p, 0);
+ if (!id)
+ return id;
+ break;
+
+ // End
+ case ')':
+ return ID_NULL;
+
+ // Parse a regular dependency
+ default:
+ id = pakfire_parse_dep(pakfire, &p);
+ if (!id)
+ return id;
+ break;
+ }
+
+ // Consume any space
+ if (isspace(*p))
+ p++;
+
+ // If we have successfully parsed something, we would expect a closing bracket
+ if (*p == ')') {
+ *dep = p + 1;
+ return id;
+ }
+
+ // Search for a keyword
+ for (const struct pakfire_rich_operation* op = pakfire_rich_operations; op->keyword; op++) {
+ if (pakfire_string_startswith(p, op->keyword)) {
+ // Skip the keyword
+ p += strlen(op->keyword);
+
+ // Store the flags
+ flags = op->flags;
+ break;
+ }
+ }
+
+ // If there was no keyword, we are done
+ if (!flags)
+ return ID_NULL;
+
+ // Parse the next bit
+ Id evr = pakfire_parse_rich_dep(pakfire, &p, flags);
+
+ // Abort if there was a problem
+ if (!evr)
+ return ID_NULL;
+
+ // Store until where we have parsed the string
+ *dep = p;
+
+ Pool* pool = pakfire_get_solv_pool(pakfire);
+
+ // Combine everything
+ return pool_rel2id(pool, id, evr, flags, 1);
+}
+
+Id pakfire_str2dep(struct pakfire* pakfire, const char* s) {
+ Id id = ID_NULL;
+
+ // Invalid input
+ if (!s) {
+ errno = EINVAL;
+ return id;
+ }
+
+ // Ignore empty strings
+ if (!*s)
+ return id;
+
+ // Consume any leading space
+ if (isspace(*s))
+ s++;
+
+ // Ignore any comments
+ if (*s == '#')
+ return id;
+
+ // Parse any rich dependencies
+ if (*s == '(')
+ id = pakfire_parse_rich_dep(pakfire, &s, 0);
+ else
+ id = pakfire_parse_dep(pakfire, &s);
+
+ // Return nothing if we could not parse the entire string
+ if (id && *s)
+ id = ID_NULL;
+
+ return id;
+}
+
+int pakfire_str2deps(struct pakfire* pakfire, struct pakfire_package* pkg,
+ void (callback)(struct pakfire_package* pkg, const char* dep), const char* deps) {
+ char* p = NULL;
+
+ // Check for valid inputs
+ if (!callback || !deps) {
+ errno = EINVAL;
+ return 1;
+ }
+
+ // Copy deps into a working buffer
+ char* buffer = strdup(deps);
+ if (!buffer)
+ return 1;
+
+ char* dep = strtok_r(buffer, "\n", &p);
+
+ // Walk through the buffer line by line
+ while (dep) {
+ DEBUG(pakfire, "Found dep '%s'\n", dep);
+
+ // Add the dependency
+ callback(pkg, dep);
+
+ // Move on to next token
+ dep = strtok_r(NULL, "\n", &p);
+ }
+
+ free(buffer);
+ return 0;
+}
--- /dev/null
+/*#############################################################################
+# #
+# Pakfire - The IPFire package management system #
+# Copyright (C) 2022 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_DEPENDENCIES_H
+#define PAKFIRE_DEPENDENCIES_H
+
+#include <solv/pool.h>
+
+#include <pakfire/package.h>
+#include <pakfire/pakfire.h>
+
+const char* pakfire_dep2str(struct pakfire* pakfire, Id id);
+Id pakfire_str2dep(struct pakfire* pakfire, const char* s);
+
+int pakfire_str2deps(struct pakfire* pakfire, struct pakfire_package* pkg,
+ void (callback)(struct pakfire_package* pkg, const char* dep), const char* deps);
+
+#endif /* PAKFIRE_DEPENDENCIES_H */
#include <archive.h>
-#include <pakfire/package.h>
-
-const char* pakfire_dep2str(struct pakfire* pakfire, Id id);
-Id pakfire_str2dep(struct pakfire* pakfire, const char* s);
-int pakfire_str2deps(struct pakfire* pakfire, struct pakfire_package* pkg,
- void (*callback)(struct pakfire_package* pkg, const char* dep), const char* deps);
+#include <pakfire/pakfire.h>
#define pakfire_string_format(s, fmt, ...) snprintf(s, sizeof(s) - 1, fmt, __VA_ARGS__)
#define pakfire_string_set(s, value) pakfire_string_format(s, "%s", value)
#include <pakfire/archive.h>
#include <pakfire/constants.h>
+#include <pakfire/dependencies.h>
#include <pakfire/file.h>
#include <pakfire/filelist.h>
#include <pakfire/i18n.h>
#include <pakfire/config.h>
#include <pakfire/constants.h>
#include <pakfire/db.h>
+#include <pakfire/dependencies.h>
#include <pakfire/keystore.h>
#include <pakfire/logging.h>
#include <pakfire/mount.h>
#define PCRE2_CODE_UNIT_WIDTH 8
#include <pcre2.h>
+#include <pakfire/dependencies.h>
#include <pakfire/jail.h>
#include <pakfire/logging.h>
#include <pakfire/package.h>
#include <stdlib.h>
#include <pakfire/constants.h>
+#include <pakfire/dependencies.h>
#include <pakfire/i18n.h>
#include <pakfire/logging.h>
#include <pakfire/pakfire.h>
#endif
#include <pakfire/archive.h>
+#include <pakfire/dependencies.h>
#include <pakfire/logging.h>
#include <pakfire/package.h>
#include <pakfire/pakfire.h>
# #
#############################################################################*/
-#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <ftw.h>
#include <archive.h>
#include <archive_entry.h>
#include <json.h>
-#include <solv/pool.h>
#include <uuid/uuid.h>
#include <pakfire/constants.h>
#define BUFFER_SIZE 64 * 1024
#define NSEC_PER_SEC 1000000000
-static const struct pakfire_rich_operation {
- const char* keyword;
- const int flags;
-} pakfire_rich_operations[] = {
- { "and ", REL_AND },
- { "or ", REL_OR },
- { "if ", REL_COND },
- { "unless ", REL_UNLESS },
- { "else ", REL_ELSE },
- { "with ", REL_WITH },
- { "without ", REL_WITHOUT },
- { NULL, 0 },
-};
-
-const char* pakfire_dep2str(struct pakfire* pakfire, Id id) {
- Pool* pool = pakfire_get_solv_pool(pakfire);
- if (!pool)
- return NULL;
-
- return pool_dep2str(pool, id);
-}
-
-/*
- Reads the string until the next space is found.
-
- This function considers opening and closing brackets.
-*/
-static size_t skip(const char** s, const char** n) {
- const char* p = *s;
-
- // Store p in n
- *n = p;
-
- int brackets = 0;
-
- while (*p) {
- switch (*p) {
- // End on space or comma
- case ' ':
- case ',':
- goto END;
-
- // Increment counter on opening bracket
- case '(':
- brackets++;
- break;
-
- // End on the last closing bracket
- case ')':
- if (brackets-- <= 0)
- goto END;
- break;
- }
-
- // Move to next character
- p++;
- }
-
-END:
- *s = p;
-
- // Return the length of the skipped string
- return p - *n;
-}
-
-/*
- This function parses any namespaced dependencies
-*/
-static Id pakfire_parse_namespace(Pool* pool, const char* s) {
- const char* p = strchr(s, '(');
- if (!p)
- return 0;
-
- // Store the namespace ID
- Id namespace = pool_strn2id(pool, s, p - s, 1);
-
- // Find the end of the string
- s = strrchr(p, ')');
- if (!s)
- return 0;
-
- Id id = pool_strn2id(pool, p + 1, s - p - 1, 1);
-
- // Bring it all together
- return pool_rel2id(pool, namespace, id, REL_NAMESPACE, 1);
-}
-
-/*
- This function parses a simple dependency like "foo = 1.2.3"
-*/
-static Id pakfire_parse_dep(struct pakfire* pakfire, const char** s) {
- Id id = ID_NULL;
-
- if (!s) {
- errno = EINVAL;
- return 0;
- }
-
- const char* p = *s;
- const char* n = NULL;
-
- // Ignore empty strings
- if (!p)
- return ID_NULL;
-
- Pool* pool = pakfire_get_solv_pool(pakfire);
-
- // Consume any leading space
- if (isspace(*p))
- p++;
-
- // Find the first part
- size_t l = skip(&p, &n);
-
- // Add name to pool
- if (pakfire_string_startswith(n, "pakfire("))
- id = pakfire_parse_namespace(pool, n);
- else
- id = pool_strn2id(pool, n, l, 1);
-
- // Consume any more space
- if (isspace(*p))
- p++;
-
- if (*p == '<' || *p == '=' || *p == '>') {
- int flags = 0;
-
- while (1) {
- if (*p == '<')
- flags |= REL_LT;
- else if (*p == '=')
- flags |= REL_EQ;
- else if (*p == '>')
- flags |= REL_GT;
- else
- break;
-
- p++;
- }
-
- // Consume any more space
- if (isspace(*p))
- p++;
-
- // Find the length of EVR
- l = skip(&p, &n);
-
- // Strip zero epoch
- if (pakfire_string_startswith(n, "0:"))
- n += 2;
-
- // Add EVR to pool
- Id evr = pool_strn2id(pool, n, l, 1);
-
- // Combine everything
- id = pool_rel2id(pool, id, evr, flags, 1);
- }
-
- *s = p;
-
- return id;
-}
-
-/*
- This function parses any rich dependencies
-*/
-static Id pakfire_parse_rich_dep(struct pakfire* pakfire, const char** dep, int flags) {
- const char* p = *dep;
- Id id;
-
- // Do not try parsing empty strings
- if (!*p)
- return ID_NULL;
-
- // Must be starting with an opening bracket
- if (!flags && *p++ != '(')
- return ID_NULL;
-
- switch (*p) {
- // A new rich dependency
- case '(':
- id = pakfire_parse_rich_dep(pakfire, &p, 0);
- if (!id)
- return id;
- break;
-
- // End
- case ')':
- return ID_NULL;
-
- // Parse a regular dependency
- default:
- id = pakfire_parse_dep(pakfire, &p);
- if (!id)
- return id;
- break;
- }
-
- // Consume any space
- if (isspace(*p))
- p++;
-
- // If we have successfully parsed something, we would expect a closing bracket
- if (*p == ')') {
- *dep = p + 1;
- return id;
- }
-
- // Search for a keyword
- for (const struct pakfire_rich_operation* op = pakfire_rich_operations; op->keyword; op++) {
- if (pakfire_string_startswith(p, op->keyword)) {
- // Skip the keyword
- p += strlen(op->keyword);
-
- // Store the flags
- flags = op->flags;
- break;
- }
- }
-
- // If there was no keyword, we are done
- if (!flags)
- return ID_NULL;
-
- // Parse the next bit
- Id evr = pakfire_parse_rich_dep(pakfire, &p, flags);
-
- // Abort if there was a problem
- if (!evr)
- return ID_NULL;
-
- // Store until where we have parsed the string
- *dep = p;
-
- Pool* pool = pakfire_get_solv_pool(pakfire);
-
- // Combine everything
- return pool_rel2id(pool, id, evr, flags, 1);
-}
-
-Id pakfire_str2dep(struct pakfire* pakfire, const char* s) {
- Id id = ID_NULL;
-
- // Invalid input
- if (!s) {
- errno = EINVAL;
- return id;
- }
-
- // Ignore empty strings
- if (!*s)
- return id;
-
- // Consume any leading space
- if (isspace(*s))
- s++;
-
- // Ignore any comments
- if (*s == '#')
- return id;
-
- // Parse any rich dependencies
- if (*s == '(')
- id = pakfire_parse_rich_dep(pakfire, &s, 0);
- else
- id = pakfire_parse_dep(pakfire, &s);
-
- // Return nothing if we could not parse the entire string
- if (id && *s)
- id = ID_NULL;
-
- return id;
-}
-
-int pakfire_str2deps(struct pakfire* pakfire, struct pakfire_package* pkg,
- void (callback)(struct pakfire_package* pkg, const char* dep), const char* deps) {
- char* p = NULL;
-
- // Check for valid inputs
- if (!callback || !deps) {
- errno = EINVAL;
- return 1;
- }
-
- // Copy deps into a working buffer
- char* buffer = strdup(deps);
- if (!buffer)
- return 1;
-
- char* dep = strtok_r(buffer, "\n", &p);
-
- // Walk through the buffer line by line
- while (dep) {
- DEBUG(pakfire, "Found dep '%s'\n", dep);
-
- // Add the dependency
- callback(pkg, dep);
-
- // Move on to next token
- dep = strtok_r(NULL, "\n", &p);
- }
-
- free(buffer);
- return 0;
-}
-
int pakfire_string_startswith(const char* s, const char* prefix) {
// Validate input
if (!s || !prefix) {
#include <stdlib.h>
#include <string.h>
+#include <pakfire/dependencies.h>
#include <pakfire/parser.h>
#include <pakfire/util.h>