2 * Copyright (c) 2013 Baptiste Daroussin <bapt@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
30 #include <sys/param.h>
32 #include <sys/elf_common.h>
33 #include <sys/endian.h>
47 #include "elf_tables.h"
50 #define roundup2(x, y) (((x)+((y)-1))&(~((y)-1))) /* if y is powers of two */
60 static struct config_entry c[] = {
64 "http://pkg.FreeBSD.org/${ABI}/latest",
82 [ASSUME_ALWAYS_YES] = {
92 elf_corres_to_string(struct _elf_corres *m, int e)
96 for (i = 0; m[i].string != NULL; i++)
104 pkg_get_myabi(char *dest, size_t sz)
122 if (elf_version(EV_CURRENT) == EV_NONE) {
123 warnx("ELF library initialization failed: %s",
128 if ((fd = open(_PATH_BSHELL, O_RDONLY)) < 0) {
133 if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
135 warnx("elf_begin() failed: %s.", elf_errmsg(-1));
139 if (gelf_getehdr(elf, &elfhdr) == NULL) {
141 warn("getehdr() failed: %s.", elf_errmsg(-1));
144 while ((scn = elf_nextscn(elf, scn)) != NULL) {
145 if (gelf_getshdr(scn, &shdr) != &shdr) {
147 warn("getshdr() failed: %s.", elf_errmsg(-1));
151 if (shdr.sh_type == SHT_NOTE)
157 warn("failed to get the note section");
161 data = elf_getdata(scn, NULL);
164 memcpy(¬e, src, sizeof(Elf_Note));
165 src += sizeof(Elf_Note);
166 if (note.n_type == NT_VERSION)
168 src += note.n_namesz + note.n_descsz;
171 src += roundup2(note.n_namesz, 4);
172 if (elfhdr.e_ident[EI_DATA] == ELFDATA2MSB)
173 version = be32dec(src);
175 version = le32dec(src);
177 for (i = 0; osname[i] != '\0'; i++)
178 osname[i] = (char)tolower(osname[i]);
180 snprintf(dest, sz, "%s:%d:%s:%s",
181 osname, version / 100000,
182 elf_corres_to_string(mach_corres, (int)elfhdr.e_machine),
183 elf_corres_to_string(wordsize_corres,
184 (int)elfhdr.e_ident[EI_CLASS]));
188 switch (elfhdr.e_machine) {
190 snprintf(dest + strlen(dest), sz - strlen(dest),
191 ":%s:%s:%s", elf_corres_to_string(endian_corres,
192 (int)elfhdr.e_ident[EI_DATA]),
193 (elfhdr.e_flags & EF_ARM_NEW_ABI) > 0 ?
195 (elfhdr.e_flags & EF_ARM_VFP_FLOAT) > 0 ?
200 * this is taken from binutils sources:
202 * mapping is figured out from binutils:
203 * gas/config/tc-mips.c
205 switch (elfhdr.e_flags & EF_MIPS_ABI) {
213 if (elfhdr.e_ident[EI_DATA] ==
216 else if (elfhdr.e_ident[EI_DATA] ==
221 snprintf(dest + strlen(dest), sz - strlen(dest),
222 ":%s:%s", elf_corres_to_string(endian_corres,
223 (int)elfhdr.e_ident[EI_DATA]), abi);
236 subst_packagesite(const char *abi)
239 const char *variable_string;
242 if (c[PACKAGESITE].value != NULL)
243 oldval = c[PACKAGESITE].value;
245 oldval = c[PACKAGESITE].val;
247 if ((variable_string = strstr(oldval, "${ABI}")) == NULL)
250 newval = sbuf_new_auto();
251 sbuf_bcat(newval, oldval, variable_string - oldval);
252 sbuf_cat(newval, abi);
253 sbuf_cat(newval, variable_string + strlen("${ABI}"));
256 free(c[PACKAGESITE].value);
257 c[PACKAGESITE].value = strdup(sbuf_data(newval));
261 config_parse(yaml_document_t *doc, yaml_node_t *node)
263 yaml_node_pair_t *pair;
264 yaml_node_t *key, *val;
265 struct sbuf *buf = sbuf_new_auto();
269 pair = node->data.mapping.pairs.start;
271 while (pair < node->data.mapping.pairs.top) {
272 key = yaml_document_get_node(doc, pair->key);
273 val = yaml_document_get_node(doc, pair->value);
276 * ignoring silently empty keys can be empty lines
279 if (key->data.scalar.length <= 0) {
285 * silently skip on purpose to allow user to leave
286 * empty lines without complaining
288 if (val->type == YAML_NO_NODE ||
289 (val->type == YAML_SCALAR_NODE &&
290 val->data.scalar.length <= 0)) {
296 for (j = 0; j < strlen(key->data.scalar.value); ++j)
297 sbuf_putc(buf, toupper(key->data.scalar.value[j]));
300 for (i = 0; i < CONFIG_SIZE; i++) {
301 if (strcmp(sbuf_data(buf), c[i].key) == 0)
305 if (i == CONFIG_SIZE) {
310 /* env has priority over config file */
316 c[i].value = strdup(val->data.scalar.value);
327 yaml_parser_t parser;
332 const char *localbase;
333 char confpath[MAXPATHLEN];
336 for (i = 0; i < CONFIG_SIZE; i++) {
337 val = getenv(c[i].key);
344 localbase = getenv("LOCALBASE") ? getenv("LOCALBASE") : _LOCALBASE;
345 snprintf(confpath, sizeof(confpath), "%s/etc/pkg.conf", localbase);
347 if ((fp = fopen(confpath, "r")) == NULL) {
349 err(EXIT_FAILURE, "Unable to open configuration file %s", confpath);
350 /* no configuration present */
354 yaml_parser_initialize(&parser);
355 yaml_parser_set_input_file(&parser, fp);
356 yaml_parser_load(&parser, &doc);
358 node = yaml_document_get_root_node(&doc);
361 if (node->type != YAML_MAPPING_NODE)
362 warnx("Invalid configuration format, ignoring the configuration file");
364 config_parse(&doc, node);
366 warnx("Invalid configuration format, ignoring the configuration file");
369 yaml_document_delete(&doc);
370 yaml_parser_delete(&parser);
373 if (c[ABI].val == NULL && c[ABI].value == NULL) {
374 if (pkg_get_myabi(abi, BUFSIZ) != 0)
375 errx(EXIT_FAILURE, "Failed to determine the system ABI");
379 subst_packagesite(c[ABI].value != NULL ? c[ABI].value : c[ABI].val);
385 config_string(pkg_config_key k, const char **val)
387 if (c[k].type != PKG_CONFIG_STRING)
390 if (c[k].value != NULL)
399 config_bool(pkg_config_key k, bool *val)
403 if (c[k].type != PKG_CONFIG_BOOL)
408 if (c[k].value != NULL)
413 if (strcasecmp(value, "true") == 0 ||
414 strcasecmp(value, "yes") == 0 ||
415 strcasecmp(value, "on") == 0 ||
423 config_finish(void) {
426 for (i = 0; i < CONFIG_SIZE; i++)