Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 95 additions & 25 deletions bin/xbps-create/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
Expand Down Expand Up @@ -100,7 +101,7 @@ usage(bool fail)
" e.g: '/usr/lib/foo /usr/bin/blah')\n"
" -m, --maintainer Maintainer\n"
" -n, --pkgver Package name/version tuple (e.g `foo-1.0_1')\n"
" -P, --provides Provides (blank separated list, e.g: 'foo-9999 blah-1.0')\n"
" -P, --provides Provides (blank separated list, e.g: 'foo-9999_1 blah-1.0_1')\n"
" -p, --preserve Enable package preserve boolean\n"
" -q, --quiet Work silently\n"
" -R, --replaces Replaces (blank separated list, e.g: 'foo>=1.0 blah<2.0')\n"
Expand All @@ -118,6 +119,8 @@ usage(bool fail)
" e.g 'libfoo.so.1 libblah.so.2')\n"
" --shlib-requires List of required shared libraries (blank separated list,\n"
" e.g 'libfoo.so.1 libblah.so.2')\n\n"
" --provides-priority Provides with explicit priority (blank separated list,\n"
" e.g: 'foo-9999_1,100 blah-1.0_1,0')\n"
"NOTE:\n"
" At least three flags are required: architecture, pkgver and desc.\n\n"
"EXAMPLE:\n"
Expand Down Expand Up @@ -231,69 +234,130 @@ process_array(const char *key, const char *val, bool (*validate)(const char *s))
}

static void
process_one_alternative(const char *altgrname, const char *val)
process_keyval_array(const char *prop, const char *keyval, const char delim,
bool (*validate_key)(const char *),
bool (*validate_val)(const char *))
{
xbps_dictionary_t d;
xbps_array_t a;
char *altfiles;
char *key, *valstr;
bool alloc = false;

if ((d = xbps_dictionary_get(pkg_propsd, "alternatives")) == NULL) {
if ((d = xbps_dictionary_get(pkg_propsd, prop)) == NULL) {
d = xbps_dictionary_create();
if (d == NULL)
die("xbps_dictionary_create");
alloc = true;
}
if ((a = xbps_dictionary_get(d, altgrname)) == NULL) {

key = strdup(keyval);
if (key == NULL)
die("strdup");
valstr = strchr(key, delim);
*valstr = '\0';
valstr = valstr + 1;
assert(valstr);

if (validate_key && !validate_key(key)) {
diex("%s: invalid key: %s", prop, key);
}

if ((a = xbps_dictionary_get(d, key)) == NULL) {
a = xbps_array_create();
if (a == NULL)
die("xbps_array_create");
}
altfiles = strchr(val, ':') + 1;
assert(altfiles);

xbps_array_add_cstring(a, altfiles);
xbps_dictionary_set(d, altgrname, a);
xbps_dictionary_set(pkg_propsd, "alternatives", d);
if (validate_val && !validate_val(valstr)) {
diex("%s: invalid value for key `%s': %s", prop, key, valstr);
}

xbps_array_add_cstring(a, valstr);
xbps_dictionary_set(d, key, a);
xbps_dictionary_set(pkg_propsd, prop, d);
if (alloc) {
xbps_object_release(a);
xbps_object_release(d);
}
}

static void
process_keyval_uint64(const char *prop, const char *keyval, const char delim,
bool (*validate_key)(const char *),
bool (*validate_val)(const char *))
{
xbps_dictionary_t d;
char *key, *valstr, *rem = NULL;
uint64_t val = 0;
bool alloc = false;

if ((d = xbps_dictionary_get(pkg_propsd, prop)) == NULL) {
d = xbps_dictionary_create();
if (d == NULL)
die("xbps_dictionary_create");
alloc = true;
}

key = strdup(keyval);
if (key == NULL)
die("strdup");
valstr = strchr(key, delim);
*valstr = '\0';
valstr = valstr + 1;
assert(valstr);

if (validate_key && !validate_key(key)) {
diex("%s: invalid key: %s", prop, key);
}

if (validate_val && !validate_val(valstr)) {
diex("%s: invalid value for key `%s': %s", prop, key, valstr);
}

val = strtoull(valstr, &rem, 10);
if (errno != 0)
die("%s: %s: invalid integer: %s", prop, key, valstr);
else if (valstr == rem || (valstr && *rem != 0))
diex("%s: %s: invalid integer: %s", prop, key, valstr);

xbps_dictionary_set_uint64(d, key, val);
xbps_dictionary_set(pkg_propsd, prop, d);
if (alloc) {
xbps_object_release(d);
}
}

static void
process_dict_of_arrays(const char *key UNUSED, const char *val)
process_dict(const char *key, const char *val, const char delim,
void (*process_item)(const char *, const char *, const char,
bool (*)(const char *), bool (*)(const char *)),
bool (*validate_key)(const char *), bool (*validate_val)(const char *))
{
char *altgrname, *args, *p, *saveptr;
char *args, *p = NULL, *saveptr = NULL;

assert(key);

if (val == NULL)
return;

args = strdup(val);
assert(args);
if (args == NULL)
die("strdup");

if (strchr(args, ' ') == NULL) {
altgrname = strtok(args, ":");
assert(altgrname);
process_one_alternative(altgrname, val);
process_item(key, args, delim, validate_key, validate_val);
goto out;
}

for ((p = strtok_r(args, " ", &saveptr)); p;
(p = strtok_r(NULL, " ", &saveptr))) {
char *b;

b = strdup(p);
assert(b);
altgrname = strtok(b, ":");
assert(altgrname);
process_one_alternative(altgrname, p);
free(b);
char *buf;
buf = strdup(p);
assert(buf);
process_item(key, buf, delim, validate_key, validate_val);
free(buf);
}

out:
free(args);
}
Expand Down Expand Up @@ -863,6 +927,7 @@ main(int argc, char **argv)
{ "pkgver", required_argument, NULL, 'n' },
{ "preserve", no_argument, NULL, 'p' },
{ "provides", required_argument, NULL, 'P' },
{ "provides-priority", required_argument, NULL, '6' },
{ "quiet", no_argument, NULL, 'q' },
{ "replaces", required_argument, NULL, 'R' },
{ "reverts", required_argument, NULL, 'r' },
Expand All @@ -883,6 +948,7 @@ main(int argc, char **argv)
const char *arch, *config_files, *mutable_files, *version, *changelog;
const char *buildopts, *shlib_provides, *shlib_requires, *alternatives;
const char *compression, *tags = NULL, *srcrevs = NULL, *sourcepkg = NULL;
const char *provides_priority = NULL;
char pkgname[XBPS_NAME_SIZE], *binpkg, *tname, *p, cwd[PATH_MAX-1];
bool quiet = false, preserve = false;
int c, pkg_fd;
Expand Down Expand Up @@ -982,6 +1048,9 @@ main(int argc, char **argv)
case '5':
sourcepkg = optarg;
break;
case '6':
provides_priority = optarg;
break;
case '?':
default:
usage(true);
Expand Down Expand Up @@ -1070,11 +1139,12 @@ main(int argc, char **argv)
process_array("conf_files", config_files, NULL);
process_array("conflicts", conflicts, NULL);
process_array("provides", provides, validate_pkgver);
process_dict("provides-priority", provides_priority, ',', process_keyval_uint64, validate_pkgver, NULL);
process_array("replaces", replaces, NULL);
process_array("reverts", reverts, NULL);
process_array("shlib-provides", shlib_provides, NULL);
process_array("shlib-requires", shlib_requires, NULL);
process_dict_of_arrays("alternatives", alternatives);
process_dict("alternatives", alternatives, ':', process_keyval_array, NULL, NULL);

/* save cwd */
memset(&cwd, 0, sizeof(cwd));
Expand Down