mirror of
https://git.hardenedbsd.org/hardenedbsd/HardenedBSD.git
synced 2024-12-03 14:40:50 +01:00
Fix multi-repository support by properly respecting 'enabled' flag.
This will read the REPOS_DIR env/config setting (default is /etc/pkg and /usr/local/etc/pkg/repos) and use the last enabled repository. This can be changed in the environment using a comma-separated list, or in /usr/local/etc/pkg.conf with JSON array syntax of: REPOS_DIR: ["/etc/pkg", "/usr/local/etc/pkg/repos"] Approved by: bapt MFC after: 1 week
This commit is contained in:
parent
369f2ddcb8
commit
eb31a57474
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=259266
@ -32,8 +32,10 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include <sys/sbuf.h>
|
#include <sys/sbuf.h>
|
||||||
#include <sys/elf_common.h>
|
#include <sys/elf_common.h>
|
||||||
#include <sys/endian.h>
|
#include <sys/endian.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <dirent.h>
|
||||||
#include <yaml.h>
|
#include <yaml.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
@ -51,11 +53,17 @@ __FBSDID("$FreeBSD$");
|
|||||||
|
|
||||||
#define roundup2(x, y) (((x)+((y)-1))&(~((y)-1))) /* if y is powers of two */
|
#define roundup2(x, y) (((x)+((y)-1))&(~((y)-1))) /* if y is powers of two */
|
||||||
|
|
||||||
|
struct config_value {
|
||||||
|
char *value;
|
||||||
|
STAILQ_ENTRY(config_value) next;
|
||||||
|
};
|
||||||
|
|
||||||
struct config_entry {
|
struct config_entry {
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
const char *key;
|
const char *key;
|
||||||
const char *val;
|
const char *val;
|
||||||
char *value;
|
char *value;
|
||||||
|
STAILQ_HEAD(, config_value) *list;
|
||||||
bool envset;
|
bool envset;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -65,6 +73,7 @@ static struct config_entry c[] = {
|
|||||||
"PACKAGESITE",
|
"PACKAGESITE",
|
||||||
URL_SCHEME_PREFIX "http://pkg.FreeBSD.org/${ABI}/latest",
|
URL_SCHEME_PREFIX "http://pkg.FreeBSD.org/${ABI}/latest",
|
||||||
NULL,
|
NULL,
|
||||||
|
NULL,
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
[ABI] = {
|
[ABI] = {
|
||||||
@ -72,6 +81,7 @@ static struct config_entry c[] = {
|
|||||||
"ABI",
|
"ABI",
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
|
NULL,
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
[MIRROR_TYPE] = {
|
[MIRROR_TYPE] = {
|
||||||
@ -79,6 +89,7 @@ static struct config_entry c[] = {
|
|||||||
"MIRROR_TYPE",
|
"MIRROR_TYPE",
|
||||||
"SRV",
|
"SRV",
|
||||||
NULL,
|
NULL,
|
||||||
|
NULL,
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
[ASSUME_ALWAYS_YES] = {
|
[ASSUME_ALWAYS_YES] = {
|
||||||
@ -86,6 +97,7 @@ static struct config_entry c[] = {
|
|||||||
"ASSUME_ALWAYS_YES",
|
"ASSUME_ALWAYS_YES",
|
||||||
"NO",
|
"NO",
|
||||||
NULL,
|
NULL,
|
||||||
|
NULL,
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
[SIGNATURE_TYPE] = {
|
[SIGNATURE_TYPE] = {
|
||||||
@ -93,6 +105,7 @@ static struct config_entry c[] = {
|
|||||||
"SIGNATURE_TYPE",
|
"SIGNATURE_TYPE",
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
|
NULL,
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
[FINGERPRINTS] = {
|
[FINGERPRINTS] = {
|
||||||
@ -100,6 +113,15 @@ static struct config_entry c[] = {
|
|||||||
"FINGERPRINTS",
|
"FINGERPRINTS",
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
|
NULL,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
[REPOS_DIR] = {
|
||||||
|
PKG_CONFIG_LIST,
|
||||||
|
"REPOS_DIR",
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -474,17 +496,34 @@ subst_packagesite(const char *abi)
|
|||||||
c[PACKAGESITE].value = strdup(sbuf_data(newval));
|
c[PACKAGESITE].value = strdup(sbuf_data(newval));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
boolstr_to_bool(const char *str)
|
||||||
|
{
|
||||||
|
if (str != NULL && (strcasecmp(str, "true") == 0 ||
|
||||||
|
strcasecmp(str, "yes") == 0 || strcasecmp(str, "on") == 0 ||
|
||||||
|
str[0] == '1'))
|
||||||
|
return (true);
|
||||||
|
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
config_parse(yaml_document_t *doc, yaml_node_t *node, pkg_conf_file_t conftype)
|
config_parse(yaml_document_t *doc, yaml_node_t *node, pkg_conf_file_t conftype)
|
||||||
{
|
{
|
||||||
|
yaml_node_item_t *item;
|
||||||
yaml_node_pair_t *pair;
|
yaml_node_pair_t *pair;
|
||||||
yaml_node_t *key, *val;
|
yaml_node_t *key, *val, *item_val;
|
||||||
struct sbuf *buf = sbuf_new_auto();
|
struct sbuf *buf = sbuf_new_auto();
|
||||||
|
struct config_entry *temp_config;
|
||||||
|
struct config_value *cv;
|
||||||
int i;
|
int i;
|
||||||
size_t j;
|
size_t j;
|
||||||
|
|
||||||
pair = node->data.mapping.pairs.start;
|
pair = node->data.mapping.pairs.start;
|
||||||
|
|
||||||
|
/* Temporary config for configs that may be disabled. */
|
||||||
|
temp_config = calloc(CONFIG_SIZE, sizeof(struct config_entry));
|
||||||
|
|
||||||
while (pair < node->data.mapping.pairs.top) {
|
while (pair < node->data.mapping.pairs.top) {
|
||||||
key = yaml_document_get_node(doc, pair->key);
|
key = yaml_document_get_node(doc, pair->key);
|
||||||
val = yaml_document_get_node(doc, pair->value);
|
val = yaml_document_get_node(doc, pair->value);
|
||||||
@ -530,7 +569,12 @@ config_parse(yaml_document_t *doc, yaml_node_t *node, pkg_conf_file_t conftype)
|
|||||||
else if (strcasecmp(key->data.scalar.value,
|
else if (strcasecmp(key->data.scalar.value,
|
||||||
"fingerprints") == 0)
|
"fingerprints") == 0)
|
||||||
sbuf_cpy(buf, "FINGERPRINTS");
|
sbuf_cpy(buf, "FINGERPRINTS");
|
||||||
else { /* Skip unknown entries for future use. */
|
else if (strcasecmp(key->data.scalar.value,
|
||||||
|
"enabled") == 0) {
|
||||||
|
/* Skip disabled repos. */
|
||||||
|
if (!boolstr_to_bool(val->data.scalar.value))
|
||||||
|
goto cleanup;
|
||||||
|
} else { /* Skip unknown entries for future use. */
|
||||||
++pair;
|
++pair;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -554,10 +598,58 @@ config_parse(yaml_document_t *doc, yaml_node_t *node, pkg_conf_file_t conftype)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
c[i].value = strdup(val->data.scalar.value);
|
/* Parse sequence value ["item1", "item2"] */
|
||||||
|
switch (c[i].type) {
|
||||||
|
case PKG_CONFIG_LIST:
|
||||||
|
if (val->type != YAML_SEQUENCE_NODE) {
|
||||||
|
fprintf(stderr, "Skipping invalid array "
|
||||||
|
"value for %s.\n", c[i].key);
|
||||||
|
++pair;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
item = val->data.sequence.items.start;
|
||||||
|
temp_config[i].list =
|
||||||
|
malloc(sizeof(*temp_config[i].list));
|
||||||
|
STAILQ_INIT(temp_config[i].list);
|
||||||
|
|
||||||
|
while (item < val->data.sequence.items.top) {
|
||||||
|
item_val = yaml_document_get_node(doc, *item);
|
||||||
|
if (item_val->type != YAML_SCALAR_NODE) {
|
||||||
|
++item;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
cv = malloc(sizeof(struct config_value));
|
||||||
|
cv->value =
|
||||||
|
strdup(item_val->data.scalar.value);
|
||||||
|
STAILQ_INSERT_TAIL(temp_config[i].list, cv,
|
||||||
|
next);
|
||||||
|
++item;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Normal string value. */
|
||||||
|
temp_config[i].value = strdup(val->data.scalar.value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
++pair;
|
++pair;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Repo is enabled, copy over all settings from temp_config. */
|
||||||
|
for (i = 0; i < CONFIG_SIZE; i++) {
|
||||||
|
if (c[i].envset)
|
||||||
|
continue;
|
||||||
|
switch (c[i].type) {
|
||||||
|
case PKG_CONFIG_LIST:
|
||||||
|
c[i].list = temp_config[i].list;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
c[i].value = temp_config[i].value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
free(temp_config);
|
||||||
sbuf_delete(buf);
|
sbuf_delete(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -632,23 +724,84 @@ read_conf_file(const char *confpath, pkg_conf_file_t conftype)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
load_repositories(const char *repodir)
|
||||||
|
{
|
||||||
|
struct dirent *ent;
|
||||||
|
DIR *d;
|
||||||
|
char *p;
|
||||||
|
size_t n;
|
||||||
|
char path[MAXPATHLEN];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
if ((d = opendir(repodir)) == NULL)
|
||||||
|
return (1);
|
||||||
|
|
||||||
|
while ((ent = readdir(d))) {
|
||||||
|
/* Trim out 'repos'. */
|
||||||
|
if ((n = strlen(ent->d_name)) <= 5)
|
||||||
|
continue;
|
||||||
|
p = &ent->d_name[n - 5];
|
||||||
|
if (strcmp(p, ".conf") == 0) {
|
||||||
|
snprintf(path, sizeof(path), "%s%s%s",
|
||||||
|
repodir,
|
||||||
|
repodir[strlen(repodir) - 1] == '/' ? "" : "/",
|
||||||
|
ent->d_name);
|
||||||
|
if (access(path, F_OK) == 0 &&
|
||||||
|
read_conf_file(path, CONFFILE_REPO)) {
|
||||||
|
ret = 1;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
closedir(d);
|
||||||
|
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
config_init(void)
|
config_init(void)
|
||||||
{
|
{
|
||||||
const char *val;
|
char *val;
|
||||||
int i;
|
int i;
|
||||||
const char *localbase;
|
const char *localbase;
|
||||||
|
char *env_list_item;
|
||||||
char confpath[MAXPATHLEN];
|
char confpath[MAXPATHLEN];
|
||||||
|
struct config_value *cv;
|
||||||
char abi[BUFSIZ];
|
char abi[BUFSIZ];
|
||||||
|
|
||||||
for (i = 0; i < CONFIG_SIZE; i++) {
|
for (i = 0; i < CONFIG_SIZE; i++) {
|
||||||
val = getenv(c[i].key);
|
val = getenv(c[i].key);
|
||||||
if (val != NULL) {
|
if (val != NULL) {
|
||||||
c[i].val = val;
|
|
||||||
c[i].envset = true;
|
c[i].envset = true;
|
||||||
|
switch (c[i].type) {
|
||||||
|
case PKG_CONFIG_LIST:
|
||||||
|
/* Split up comma-separated items from env. */
|
||||||
|
c[i].list = malloc(sizeof(*c[i].list));
|
||||||
|
STAILQ_INIT(c[i].list);
|
||||||
|
for (env_list_item = strtok(val, ",");
|
||||||
|
env_list_item != NULL;
|
||||||
|
env_list_item = strtok(NULL, ",")) {
|
||||||
|
cv =
|
||||||
|
malloc(sizeof(struct config_value));
|
||||||
|
cv->value =
|
||||||
|
strdup(env_list_item);
|
||||||
|
STAILQ_INSERT_TAIL(c[i].list, cv,
|
||||||
|
next);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
c[i].val = val;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Read LOCALBASE/etc/pkg.conf first. */
|
||||||
localbase = getenv("LOCALBASE") ? getenv("LOCALBASE") : _LOCALBASE;
|
localbase = getenv("LOCALBASE") ? getenv("LOCALBASE") : _LOCALBASE;
|
||||||
snprintf(confpath, sizeof(confpath), "%s/etc/pkg.conf",
|
snprintf(confpath, sizeof(confpath), "%s/etc/pkg.conf",
|
||||||
localbase);
|
localbase);
|
||||||
@ -657,10 +810,22 @@ config_init(void)
|
|||||||
CONFFILE_PKG))
|
CONFFILE_PKG))
|
||||||
goto finalize;
|
goto finalize;
|
||||||
|
|
||||||
snprintf(confpath, sizeof(confpath), "/etc/pkg/FreeBSD.conf");
|
/* Then read in all repos from REPOS_DIR list of directories. */
|
||||||
if (access(confpath, F_OK) == 0 && read_conf_file(confpath,
|
if (c[REPOS_DIR].list == NULL) {
|
||||||
CONFFILE_REPO))
|
c[REPOS_DIR].list = malloc(sizeof(*c[REPOS_DIR].list));
|
||||||
goto finalize;
|
STAILQ_INIT(c[REPOS_DIR].list);
|
||||||
|
cv = malloc(sizeof(struct config_value));
|
||||||
|
cv->value = strdup("/etc/pkg");
|
||||||
|
STAILQ_INSERT_TAIL(c[REPOS_DIR].list, cv, next);
|
||||||
|
cv = malloc(sizeof(struct config_value));
|
||||||
|
if (asprintf(&cv->value, "%s/etc/pkg/repos", localbase) < 0)
|
||||||
|
goto finalize;
|
||||||
|
STAILQ_INSERT_TAIL(c[REPOS_DIR].list, cv, next);
|
||||||
|
}
|
||||||
|
|
||||||
|
STAILQ_FOREACH(cv, c[REPOS_DIR].list, next)
|
||||||
|
if (load_repositories(cv->value))
|
||||||
|
goto finalize;
|
||||||
|
|
||||||
finalize:
|
finalize:
|
||||||
if (c[ABI].val == NULL && c[ABI].value == NULL) {
|
if (c[ABI].val == NULL && c[ABI].value == NULL) {
|
||||||
@ -704,10 +869,7 @@ config_bool(pkg_config_key k, bool *val)
|
|||||||
else
|
else
|
||||||
value = c[k].val;
|
value = c[k].val;
|
||||||
|
|
||||||
if (strcasecmp(value, "true") == 0 ||
|
if (boolstr_to_bool(value))
|
||||||
strcasecmp(value, "yes") == 0 ||
|
|
||||||
strcasecmp(value, "on") == 0 ||
|
|
||||||
*value == '1')
|
|
||||||
*val = true;
|
*val = true;
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
|
@ -39,12 +39,14 @@ typedef enum {
|
|||||||
ASSUME_ALWAYS_YES,
|
ASSUME_ALWAYS_YES,
|
||||||
SIGNATURE_TYPE,
|
SIGNATURE_TYPE,
|
||||||
FINGERPRINTS,
|
FINGERPRINTS,
|
||||||
|
REPOS_DIR,
|
||||||
CONFIG_SIZE
|
CONFIG_SIZE
|
||||||
} pkg_config_key;
|
} pkg_config_key;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
PKG_CONFIG_STRING=0,
|
PKG_CONFIG_STRING=0,
|
||||||
PKG_CONFIG_BOOL,
|
PKG_CONFIG_BOOL,
|
||||||
|
PKG_CONFIG_LIST,
|
||||||
} pkg_config_t;
|
} pkg_config_t;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
.\"
|
.\"
|
||||||
.\" $FreeBSD$
|
.\" $FreeBSD$
|
||||||
.\"
|
.\"
|
||||||
.Dd November 19, 2013
|
.Dd December 12, 2013
|
||||||
.Dt PKG 7
|
.Dt PKG 7
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -152,6 +152,7 @@ MIRROR_TYPE: "srv",
|
|||||||
SIGNATURE_TYPE: "none",
|
SIGNATURE_TYPE: "none",
|
||||||
FINGERPRINTS: "/usr/share/keys/pkg",
|
FINGERPRINTS: "/usr/share/keys/pkg",
|
||||||
ASSUME_ALWAYS_YES: "yes"
|
ASSUME_ALWAYS_YES: "yes"
|
||||||
|
REPOS_DIR: ["/etc/pkg", "/usr/local/etc/pkg/repos"]
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
Reference
|
Reference
|
||||||
@ -194,14 +195,20 @@ The URL that
|
|||||||
.Xr pkg 8
|
.Xr pkg 8
|
||||||
and other packages
|
and other packages
|
||||||
will be fetched from.
|
will be fetched from.
|
||||||
|
.It Ev REPOS_DIR
|
||||||
|
Comma-separated list of directories that should be searched for repository
|
||||||
|
configuration files.
|
||||||
.El
|
.El
|
||||||
.Sh FILES
|
.Sh FILES
|
||||||
Configuration is read from the files in the listed order.
|
Configuration is read from the files in the listed order.
|
||||||
The first enabled repository is the one used for bootstrapping
|
This path can be changed by setting
|
||||||
|
.Sy REPOS_DIR .
|
||||||
|
The last enabled repository is the one used for bootstrapping
|
||||||
.Xr pkg 8 .
|
.Xr pkg 8 .
|
||||||
.Bl -tag -width "/usr/local/etc/pkg/repos/*.conf"
|
.Bl -tag -width "/usr/local/etc/pkg/repos/*.conf"
|
||||||
.It Pa /usr/local/etc/pkg.conf
|
.It Pa /usr/local/etc/pkg.conf
|
||||||
.It Pa /etc/pkg/FreeBSD.conf
|
.It Pa /etc/pkg/FreeBSD.conf
|
||||||
|
.It Pa /usr/local/etc/pkg/repos/*.conf
|
||||||
.El
|
.El
|
||||||
.Sh EXAMPLES
|
.Sh EXAMPLES
|
||||||
Some examples are listed here.
|
Some examples are listed here.
|
||||||
|
Loading…
Reference in New Issue
Block a user