19950eceeSBaptiste Daroussin /*- 29950eceeSBaptiste Daroussin * Copyright (c) 2013 Baptiste Daroussin <bapt@FreeBSD.org> 3f12db248SBryan Drewery * Copyright (c) 2013 Bryan Drewery <bdrewery@FreeBSD.org> 49950eceeSBaptiste Daroussin * All rights reserved. 59950eceeSBaptiste Daroussin * 69950eceeSBaptiste Daroussin * Redistribution and use in source and binary forms, with or without 79950eceeSBaptiste Daroussin * modification, are permitted provided that the following conditions 89950eceeSBaptiste Daroussin * are met: 99950eceeSBaptiste Daroussin * 1. Redistributions of source code must retain the above copyright 109950eceeSBaptiste Daroussin * notice, this list of conditions and the following disclaimer. 119950eceeSBaptiste Daroussin * 2. Redistributions in binary form must reproduce the above copyright 129950eceeSBaptiste Daroussin * notice, this list of conditions and the following disclaimer in the 139950eceeSBaptiste Daroussin * documentation and/or other materials provided with the distribution. 149950eceeSBaptiste Daroussin * 159950eceeSBaptiste Daroussin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 169950eceeSBaptiste Daroussin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 179950eceeSBaptiste Daroussin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 189950eceeSBaptiste Daroussin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 199950eceeSBaptiste Daroussin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 209950eceeSBaptiste Daroussin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 219950eceeSBaptiste Daroussin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 229950eceeSBaptiste Daroussin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 239950eceeSBaptiste Daroussin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 249950eceeSBaptiste Daroussin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 259950eceeSBaptiste Daroussin * SUCH DAMAGE. 269950eceeSBaptiste Daroussin */ 279950eceeSBaptiste Daroussin 289950eceeSBaptiste Daroussin #include <sys/cdefs.h> 299950eceeSBaptiste Daroussin __FBSDID("$FreeBSD$"); 309950eceeSBaptiste Daroussin 319950eceeSBaptiste Daroussin #include <sys/param.h> 32*a351c93dSBaptiste Daroussin #include <sys/queue.h> 339950eceeSBaptiste Daroussin #include <sys/sbuf.h> 349950eceeSBaptiste Daroussin #include <sys/elf_common.h> 359950eceeSBaptiste Daroussin #include <sys/endian.h> 36eb31a574SBryan Drewery #include <sys/types.h> 379950eceeSBaptiste Daroussin 3840274a2dSBaptiste Daroussin #include <assert.h> 39eb31a574SBryan Drewery #include <dirent.h> 40e3ededfaSBryan Drewery #include <yaml.h> 419950eceeSBaptiste Daroussin #include <ctype.h> 429950eceeSBaptiste Daroussin #include <err.h> 439950eceeSBaptiste Daroussin #include <errno.h> 449950eceeSBaptiste Daroussin #include <fcntl.h> 459950eceeSBaptiste Daroussin #include <gelf.h> 469950eceeSBaptiste Daroussin #include <inttypes.h> 479950eceeSBaptiste Daroussin #include <paths.h> 489950eceeSBaptiste Daroussin #include <stdbool.h> 499950eceeSBaptiste Daroussin #include <string.h> 509950eceeSBaptiste Daroussin #include <unistd.h> 519950eceeSBaptiste Daroussin 529950eceeSBaptiste Daroussin #include "elf_tables.h" 539950eceeSBaptiste Daroussin #include "config.h" 549950eceeSBaptiste Daroussin 559950eceeSBaptiste Daroussin #define roundup2(x, y) (((x)+((y)-1))&(~((y)-1))) /* if y is powers of two */ 569950eceeSBaptiste Daroussin 57eb31a574SBryan Drewery struct config_value { 58eb31a574SBryan Drewery char *value; 59eb31a574SBryan Drewery STAILQ_ENTRY(config_value) next; 60eb31a574SBryan Drewery }; 61eb31a574SBryan Drewery 629950eceeSBaptiste Daroussin struct config_entry { 639950eceeSBaptiste Daroussin uint8_t type; 649950eceeSBaptiste Daroussin const char *key; 659950eceeSBaptiste Daroussin const char *val; 669950eceeSBaptiste Daroussin char *value; 67eb31a574SBryan Drewery STAILQ_HEAD(, config_value) *list; 689950eceeSBaptiste Daroussin bool envset; 699950eceeSBaptiste Daroussin }; 709950eceeSBaptiste Daroussin 719950eceeSBaptiste Daroussin static struct config_entry c[] = { 729950eceeSBaptiste Daroussin [PACKAGESITE] = { 739950eceeSBaptiste Daroussin PKG_CONFIG_STRING, 749950eceeSBaptiste Daroussin "PACKAGESITE", 7562940ea9SBryan Drewery URL_SCHEME_PREFIX "http://pkg.FreeBSD.org/${ABI}/latest", 769950eceeSBaptiste Daroussin NULL, 77eb31a574SBryan Drewery NULL, 789950eceeSBaptiste Daroussin false, 799950eceeSBaptiste Daroussin }, 809950eceeSBaptiste Daroussin [ABI] = { 819950eceeSBaptiste Daroussin PKG_CONFIG_STRING, 829950eceeSBaptiste Daroussin "ABI", 839950eceeSBaptiste Daroussin NULL, 849950eceeSBaptiste Daroussin NULL, 85eb31a574SBryan Drewery NULL, 869950eceeSBaptiste Daroussin false, 879950eceeSBaptiste Daroussin }, 889950eceeSBaptiste Daroussin [MIRROR_TYPE] = { 899950eceeSBaptiste Daroussin PKG_CONFIG_STRING, 909950eceeSBaptiste Daroussin "MIRROR_TYPE", 919950eceeSBaptiste Daroussin "SRV", 929950eceeSBaptiste Daroussin NULL, 93eb31a574SBryan Drewery NULL, 949950eceeSBaptiste Daroussin false, 959950eceeSBaptiste Daroussin }, 969950eceeSBaptiste Daroussin [ASSUME_ALWAYS_YES] = { 979950eceeSBaptiste Daroussin PKG_CONFIG_BOOL, 989950eceeSBaptiste Daroussin "ASSUME_ALWAYS_YES", 999950eceeSBaptiste Daroussin "NO", 1009950eceeSBaptiste Daroussin NULL, 101eb31a574SBryan Drewery NULL, 1029950eceeSBaptiste Daroussin false, 103f12db248SBryan Drewery }, 104f12db248SBryan Drewery [SIGNATURE_TYPE] = { 105f12db248SBryan Drewery PKG_CONFIG_STRING, 106f12db248SBryan Drewery "SIGNATURE_TYPE", 107f12db248SBryan Drewery NULL, 108f12db248SBryan Drewery NULL, 109eb31a574SBryan Drewery NULL, 110f12db248SBryan Drewery false, 111f12db248SBryan Drewery }, 112f12db248SBryan Drewery [FINGERPRINTS] = { 113f12db248SBryan Drewery PKG_CONFIG_STRING, 114f12db248SBryan Drewery "FINGERPRINTS", 115f12db248SBryan Drewery NULL, 116f12db248SBryan Drewery NULL, 117eb31a574SBryan Drewery NULL, 118eb31a574SBryan Drewery false, 119eb31a574SBryan Drewery }, 120eb31a574SBryan Drewery [REPOS_DIR] = { 121eb31a574SBryan Drewery PKG_CONFIG_LIST, 122eb31a574SBryan Drewery "REPOS_DIR", 123eb31a574SBryan Drewery NULL, 124eb31a574SBryan Drewery NULL, 125eb31a574SBryan Drewery NULL, 126f12db248SBryan Drewery false, 127f12db248SBryan Drewery }, 1289950eceeSBaptiste Daroussin }; 1299950eceeSBaptiste Daroussin 1309950eceeSBaptiste Daroussin static const char * 1319950eceeSBaptiste Daroussin elf_corres_to_string(struct _elf_corres *m, int e) 1329950eceeSBaptiste Daroussin { 1339950eceeSBaptiste Daroussin int i; 1349950eceeSBaptiste Daroussin 1359950eceeSBaptiste Daroussin for (i = 0; m[i].string != NULL; i++) 1369950eceeSBaptiste Daroussin if (m[i].elf_nb == e) 1379950eceeSBaptiste Daroussin return (m[i].string); 1389950eceeSBaptiste Daroussin 1399950eceeSBaptiste Daroussin return ("unknown"); 1409950eceeSBaptiste Daroussin } 1419950eceeSBaptiste Daroussin 14240274a2dSBaptiste Daroussin static const char * 14340274a2dSBaptiste Daroussin aeabi_parse_arm_attributes(void *data, size_t length) 14440274a2dSBaptiste Daroussin { 14540274a2dSBaptiste Daroussin uint32_t sect_len; 14640274a2dSBaptiste Daroussin uint8_t *section = data; 14740274a2dSBaptiste Daroussin 14840274a2dSBaptiste Daroussin #define MOVE(len) do { \ 14940274a2dSBaptiste Daroussin assert(length >= (len)); \ 15040274a2dSBaptiste Daroussin section += (len); \ 15140274a2dSBaptiste Daroussin length -= (len); \ 15240274a2dSBaptiste Daroussin } while (0) 15340274a2dSBaptiste Daroussin 15440274a2dSBaptiste Daroussin if (length == 0 || *section != 'A') 15540274a2dSBaptiste Daroussin return (NULL); 15640274a2dSBaptiste Daroussin 15740274a2dSBaptiste Daroussin MOVE(1); 15840274a2dSBaptiste Daroussin 15940274a2dSBaptiste Daroussin /* Read the section length */ 16040274a2dSBaptiste Daroussin if (length < sizeof(sect_len)) 16140274a2dSBaptiste Daroussin return (NULL); 16240274a2dSBaptiste Daroussin 16340274a2dSBaptiste Daroussin memcpy(§_len, section, sizeof(sect_len)); 16440274a2dSBaptiste Daroussin 16540274a2dSBaptiste Daroussin /* 16640274a2dSBaptiste Daroussin * The section length should be no longer than the section it is within 16740274a2dSBaptiste Daroussin */ 16840274a2dSBaptiste Daroussin if (sect_len > length) 16940274a2dSBaptiste Daroussin return (NULL); 17040274a2dSBaptiste Daroussin 17140274a2dSBaptiste Daroussin MOVE(sizeof(sect_len)); 17240274a2dSBaptiste Daroussin 17340274a2dSBaptiste Daroussin /* Skip the vendor name */ 17440274a2dSBaptiste Daroussin while (length != 0) { 17540274a2dSBaptiste Daroussin if (*section == '\0') 17640274a2dSBaptiste Daroussin break; 17740274a2dSBaptiste Daroussin MOVE(1); 17840274a2dSBaptiste Daroussin } 17940274a2dSBaptiste Daroussin if (length == 0) 18040274a2dSBaptiste Daroussin return (NULL); 18140274a2dSBaptiste Daroussin MOVE(1); 18240274a2dSBaptiste Daroussin 18340274a2dSBaptiste Daroussin while (length != 0) { 18440274a2dSBaptiste Daroussin uint32_t tag_length; 18540274a2dSBaptiste Daroussin 18640274a2dSBaptiste Daroussin switch(*section) { 18740274a2dSBaptiste Daroussin case 1: /* Tag_File */ 18840274a2dSBaptiste Daroussin MOVE(1); 18940274a2dSBaptiste Daroussin if (length < sizeof(tag_length)) 19040274a2dSBaptiste Daroussin return (NULL); 19140274a2dSBaptiste Daroussin memcpy(&tag_length, section, sizeof(tag_length)); 19240274a2dSBaptiste Daroussin break; 19340274a2dSBaptiste Daroussin case 2: /* Tag_Section */ 19440274a2dSBaptiste Daroussin case 3: /* Tag_Symbol */ 19540274a2dSBaptiste Daroussin default: 19640274a2dSBaptiste Daroussin return (NULL); 19740274a2dSBaptiste Daroussin } 19840274a2dSBaptiste Daroussin /* At least space for the tag and size */ 19940274a2dSBaptiste Daroussin if (tag_length <= 5) 20040274a2dSBaptiste Daroussin return (NULL); 20140274a2dSBaptiste Daroussin tag_length--; 20240274a2dSBaptiste Daroussin /* Check the tag fits */ 20340274a2dSBaptiste Daroussin if (tag_length > length) 20440274a2dSBaptiste Daroussin return (NULL); 20540274a2dSBaptiste Daroussin 20640274a2dSBaptiste Daroussin #define MOVE_TAG(len) do { \ 20740274a2dSBaptiste Daroussin assert(tag_length >= (len)); \ 20840274a2dSBaptiste Daroussin MOVE(len); \ 20940274a2dSBaptiste Daroussin tag_length -= (len); \ 21040274a2dSBaptiste Daroussin } while(0) 21140274a2dSBaptiste Daroussin 21240274a2dSBaptiste Daroussin MOVE(sizeof(tag_length)); 21340274a2dSBaptiste Daroussin tag_length -= sizeof(tag_length); 21440274a2dSBaptiste Daroussin 21540274a2dSBaptiste Daroussin while (tag_length != 0) { 21640274a2dSBaptiste Daroussin uint8_t tag; 21740274a2dSBaptiste Daroussin 21840274a2dSBaptiste Daroussin assert(tag_length >= length); 21940274a2dSBaptiste Daroussin 22040274a2dSBaptiste Daroussin tag = *section; 22140274a2dSBaptiste Daroussin MOVE_TAG(1); 22240274a2dSBaptiste Daroussin 22340274a2dSBaptiste Daroussin /* 22440274a2dSBaptiste Daroussin * These tag values come from: 22540274a2dSBaptiste Daroussin * 22640274a2dSBaptiste Daroussin * Addenda to, and Errata in, the ABI for the 22740274a2dSBaptiste Daroussin * ARM Architecture. Release 2.08, section 2.3. 22840274a2dSBaptiste Daroussin */ 22940274a2dSBaptiste Daroussin if (tag == 6) { /* == Tag_CPU_arch */ 23040274a2dSBaptiste Daroussin uint8_t val; 23140274a2dSBaptiste Daroussin 23240274a2dSBaptiste Daroussin val = *section; 23340274a2dSBaptiste Daroussin /* 23440274a2dSBaptiste Daroussin * We don't support values that require 23540274a2dSBaptiste Daroussin * more than one byte. 23640274a2dSBaptiste Daroussin */ 23740274a2dSBaptiste Daroussin if (val & (1 << 7)) 23840274a2dSBaptiste Daroussin return (NULL); 23940274a2dSBaptiste Daroussin 24040274a2dSBaptiste Daroussin /* We have an ARMv4 or ARMv5 */ 24140274a2dSBaptiste Daroussin if (val <= 5) 24240274a2dSBaptiste Daroussin return ("arm"); 24340274a2dSBaptiste Daroussin else /* We have an ARMv6+ */ 24440274a2dSBaptiste Daroussin return ("armv6"); 24540274a2dSBaptiste Daroussin } else if (tag == 4 || tag == 5 || tag == 32 || 24640274a2dSBaptiste Daroussin tag == 65 || tag == 67) { 24740274a2dSBaptiste Daroussin while (*section != '\0' && length != 0) 24840274a2dSBaptiste Daroussin MOVE_TAG(1); 24940274a2dSBaptiste Daroussin if (tag_length == 0) 25040274a2dSBaptiste Daroussin return (NULL); 25140274a2dSBaptiste Daroussin /* Skip the last byte */ 25240274a2dSBaptiste Daroussin MOVE_TAG(1); 25340274a2dSBaptiste Daroussin } else if ((tag >= 7 && tag <= 31) || tag == 34 || 25440274a2dSBaptiste Daroussin tag == 36 || tag == 38 || tag == 42 || tag == 44 || 25540274a2dSBaptiste Daroussin tag == 64 || tag == 66 || tag == 68 || tag == 70) { 25640274a2dSBaptiste Daroussin /* Skip the uleb128 data */ 25740274a2dSBaptiste Daroussin while (*section & (1 << 7) && length != 0) 25840274a2dSBaptiste Daroussin MOVE_TAG(1); 25940274a2dSBaptiste Daroussin if (tag_length == 0) 26040274a2dSBaptiste Daroussin return (NULL); 26140274a2dSBaptiste Daroussin /* Skip the last byte */ 26240274a2dSBaptiste Daroussin MOVE_TAG(1); 26340274a2dSBaptiste Daroussin } else 26440274a2dSBaptiste Daroussin return (NULL); 26540274a2dSBaptiste Daroussin #undef MOVE_TAG 26640274a2dSBaptiste Daroussin } 26740274a2dSBaptiste Daroussin 26840274a2dSBaptiste Daroussin break; 26940274a2dSBaptiste Daroussin } 27040274a2dSBaptiste Daroussin return (NULL); 27140274a2dSBaptiste Daroussin #undef MOVE 27240274a2dSBaptiste Daroussin } 27340274a2dSBaptiste Daroussin 2749950eceeSBaptiste Daroussin static int 2759950eceeSBaptiste Daroussin pkg_get_myabi(char *dest, size_t sz) 2769950eceeSBaptiste Daroussin { 2779950eceeSBaptiste Daroussin Elf *elf; 2789950eceeSBaptiste Daroussin Elf_Data *data; 2799950eceeSBaptiste Daroussin Elf_Note note; 2809950eceeSBaptiste Daroussin Elf_Scn *scn; 2819950eceeSBaptiste Daroussin char *src, *osname; 28240274a2dSBaptiste Daroussin const char *arch, *abi, *fpu, *endian_corres_str; 28340274a2dSBaptiste Daroussin const char *wordsize_corres_str; 2849950eceeSBaptiste Daroussin GElf_Ehdr elfhdr; 2859950eceeSBaptiste Daroussin GElf_Shdr shdr; 2869950eceeSBaptiste Daroussin int fd, i, ret; 2879950eceeSBaptiste Daroussin uint32_t version; 2889950eceeSBaptiste Daroussin 2899950eceeSBaptiste Daroussin version = 0; 2909950eceeSBaptiste Daroussin ret = -1; 2919950eceeSBaptiste Daroussin scn = NULL; 2929950eceeSBaptiste Daroussin abi = NULL; 2939950eceeSBaptiste Daroussin 2949950eceeSBaptiste Daroussin if (elf_version(EV_CURRENT) == EV_NONE) { 2959950eceeSBaptiste Daroussin warnx("ELF library initialization failed: %s", 2969950eceeSBaptiste Daroussin elf_errmsg(-1)); 2979950eceeSBaptiste Daroussin return (-1); 2989950eceeSBaptiste Daroussin } 2999950eceeSBaptiste Daroussin 3009950eceeSBaptiste Daroussin if ((fd = open(_PATH_BSHELL, O_RDONLY)) < 0) { 3019950eceeSBaptiste Daroussin warn("open()"); 3029950eceeSBaptiste Daroussin return (-1); 3039950eceeSBaptiste Daroussin } 3049950eceeSBaptiste Daroussin 3059950eceeSBaptiste Daroussin if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) { 3069950eceeSBaptiste Daroussin ret = -1; 3079950eceeSBaptiste Daroussin warnx("elf_begin() failed: %s.", elf_errmsg(-1)); 3089950eceeSBaptiste Daroussin goto cleanup; 3099950eceeSBaptiste Daroussin } 3109950eceeSBaptiste Daroussin 3119950eceeSBaptiste Daroussin if (gelf_getehdr(elf, &elfhdr) == NULL) { 3129950eceeSBaptiste Daroussin ret = -1; 3139950eceeSBaptiste Daroussin warn("getehdr() failed: %s.", elf_errmsg(-1)); 3149950eceeSBaptiste Daroussin goto cleanup; 3159950eceeSBaptiste Daroussin } 3169950eceeSBaptiste Daroussin while ((scn = elf_nextscn(elf, scn)) != NULL) { 3179950eceeSBaptiste Daroussin if (gelf_getshdr(scn, &shdr) != &shdr) { 3189950eceeSBaptiste Daroussin ret = -1; 3199950eceeSBaptiste Daroussin warn("getshdr() failed: %s.", elf_errmsg(-1)); 3209950eceeSBaptiste Daroussin goto cleanup; 3219950eceeSBaptiste Daroussin } 3229950eceeSBaptiste Daroussin 3239950eceeSBaptiste Daroussin if (shdr.sh_type == SHT_NOTE) 3249950eceeSBaptiste Daroussin break; 3259950eceeSBaptiste Daroussin } 3269950eceeSBaptiste Daroussin 3279950eceeSBaptiste Daroussin if (scn == NULL) { 3289950eceeSBaptiste Daroussin ret = -1; 3299950eceeSBaptiste Daroussin warn("failed to get the note section"); 3309950eceeSBaptiste Daroussin goto cleanup; 3319950eceeSBaptiste Daroussin } 3329950eceeSBaptiste Daroussin 3339950eceeSBaptiste Daroussin data = elf_getdata(scn, NULL); 3349950eceeSBaptiste Daroussin src = data->d_buf; 3359950eceeSBaptiste Daroussin for (;;) { 3369950eceeSBaptiste Daroussin memcpy(¬e, src, sizeof(Elf_Note)); 3379950eceeSBaptiste Daroussin src += sizeof(Elf_Note); 3389950eceeSBaptiste Daroussin if (note.n_type == NT_VERSION) 3399950eceeSBaptiste Daroussin break; 3409950eceeSBaptiste Daroussin src += note.n_namesz + note.n_descsz; 3419950eceeSBaptiste Daroussin } 3429950eceeSBaptiste Daroussin osname = src; 3439950eceeSBaptiste Daroussin src += roundup2(note.n_namesz, 4); 3449950eceeSBaptiste Daroussin if (elfhdr.e_ident[EI_DATA] == ELFDATA2MSB) 3459950eceeSBaptiste Daroussin version = be32dec(src); 3469950eceeSBaptiste Daroussin else 3479950eceeSBaptiste Daroussin version = le32dec(src); 3489950eceeSBaptiste Daroussin 3499950eceeSBaptiste Daroussin for (i = 0; osname[i] != '\0'; i++) 3509950eceeSBaptiste Daroussin osname[i] = (char)tolower(osname[i]); 3519950eceeSBaptiste Daroussin 35240274a2dSBaptiste Daroussin wordsize_corres_str = elf_corres_to_string(wordsize_corres, 35340274a2dSBaptiste Daroussin (int)elfhdr.e_ident[EI_CLASS]); 35440274a2dSBaptiste Daroussin 35540274a2dSBaptiste Daroussin arch = elf_corres_to_string(mach_corres, (int) elfhdr.e_machine); 35640274a2dSBaptiste Daroussin 35740274a2dSBaptiste Daroussin snprintf(dest, sz, "%s:%d", 35840274a2dSBaptiste Daroussin osname, version / 100000); 3599950eceeSBaptiste Daroussin 3609950eceeSBaptiste Daroussin ret = 0; 3619950eceeSBaptiste Daroussin 3629950eceeSBaptiste Daroussin switch (elfhdr.e_machine) { 3639950eceeSBaptiste Daroussin case EM_ARM: 36440274a2dSBaptiste Daroussin endian_corres_str = elf_corres_to_string(endian_corres, 36540274a2dSBaptiste Daroussin (int)elfhdr.e_ident[EI_DATA]); 36640274a2dSBaptiste Daroussin 3674b5ef056SBaptiste Daroussin /* FreeBSD doesn't support the hard-float ABI yet */ 3684b5ef056SBaptiste Daroussin fpu = "softfp"; 3694b5ef056SBaptiste Daroussin if ((elfhdr.e_flags & 0xFF000000) != 0) { 37040274a2dSBaptiste Daroussin const char *sh_name = NULL; 37140274a2dSBaptiste Daroussin size_t shstrndx; 37240274a2dSBaptiste Daroussin 3734b5ef056SBaptiste Daroussin /* This is an EABI file, the conformance level is set */ 3744b5ef056SBaptiste Daroussin abi = "eabi"; 37540274a2dSBaptiste Daroussin /* Find which TARGET_ARCH we are building for. */ 37640274a2dSBaptiste Daroussin elf_getshdrstrndx(elf, &shstrndx); 37740274a2dSBaptiste Daroussin while ((scn = elf_nextscn(elf, scn)) != NULL) { 37840274a2dSBaptiste Daroussin sh_name = NULL; 37940274a2dSBaptiste Daroussin if (gelf_getshdr(scn, &shdr) != &shdr) { 38040274a2dSBaptiste Daroussin scn = NULL; 38140274a2dSBaptiste Daroussin break; 38240274a2dSBaptiste Daroussin } 38340274a2dSBaptiste Daroussin 38440274a2dSBaptiste Daroussin sh_name = elf_strptr(elf, shstrndx, 38540274a2dSBaptiste Daroussin shdr.sh_name); 38640274a2dSBaptiste Daroussin if (sh_name == NULL) 38740274a2dSBaptiste Daroussin continue; 38840274a2dSBaptiste Daroussin if (strcmp(".ARM.attributes", sh_name) == 0) 38940274a2dSBaptiste Daroussin break; 39040274a2dSBaptiste Daroussin } 39140274a2dSBaptiste Daroussin if (scn != NULL && sh_name != NULL) { 39240274a2dSBaptiste Daroussin data = elf_getdata(scn, NULL); 39340274a2dSBaptiste Daroussin /* 39440274a2dSBaptiste Daroussin * Prior to FreeBSD 10.0 libelf would return 39540274a2dSBaptiste Daroussin * NULL from elf_getdata on the .ARM.attributes 39640274a2dSBaptiste Daroussin * section. As this was the first release to 39740274a2dSBaptiste Daroussin * get armv6 support assume a NULL value means 39840274a2dSBaptiste Daroussin * arm. 39940274a2dSBaptiste Daroussin * 40040274a2dSBaptiste Daroussin * This assumption can be removed when 9.x 40140274a2dSBaptiste Daroussin * is unsupported. 40240274a2dSBaptiste Daroussin */ 40340274a2dSBaptiste Daroussin if (data != NULL) { 40440274a2dSBaptiste Daroussin arch = aeabi_parse_arm_attributes( 40540274a2dSBaptiste Daroussin data->d_buf, data->d_size); 40640274a2dSBaptiste Daroussin if (arch == NULL) { 40740274a2dSBaptiste Daroussin ret = 1; 40840274a2dSBaptiste Daroussin warn("unknown ARM ARCH"); 40940274a2dSBaptiste Daroussin goto cleanup; 41040274a2dSBaptiste Daroussin } 41140274a2dSBaptiste Daroussin } 41240274a2dSBaptiste Daroussin } else { 41340274a2dSBaptiste Daroussin ret = 1; 41440274a2dSBaptiste Daroussin warn("Unable to find the .ARM.attributes " 41540274a2dSBaptiste Daroussin "section"); 41640274a2dSBaptiste Daroussin goto cleanup; 41740274a2dSBaptiste Daroussin } 4184b5ef056SBaptiste Daroussin } else if (elfhdr.e_ident[EI_OSABI] != ELFOSABI_NONE) { 4194b5ef056SBaptiste Daroussin /* 4204b5ef056SBaptiste Daroussin * EABI executables all have this field set to 4214b5ef056SBaptiste Daroussin * ELFOSABI_NONE, therefore it must be an oabi file. 4224b5ef056SBaptiste Daroussin */ 4234b5ef056SBaptiste Daroussin abi = "oabi"; 4244b5ef056SBaptiste Daroussin } else { 4254b5ef056SBaptiste Daroussin ret = 1; 42640274a2dSBaptiste Daroussin warn("unknown ARM ABI"); 4274b5ef056SBaptiste Daroussin goto cleanup; 4284b5ef056SBaptiste Daroussin } 4299950eceeSBaptiste Daroussin snprintf(dest + strlen(dest), sz - strlen(dest), 43040274a2dSBaptiste Daroussin ":%s:%s:%s:%s:%s", arch, wordsize_corres_str, 43140274a2dSBaptiste Daroussin endian_corres_str, abi, fpu); 4329950eceeSBaptiste Daroussin break; 4339950eceeSBaptiste Daroussin case EM_MIPS: 4349950eceeSBaptiste Daroussin /* 4359950eceeSBaptiste Daroussin * this is taken from binutils sources: 4369950eceeSBaptiste Daroussin * include/elf/mips.h 4379950eceeSBaptiste Daroussin * mapping is figured out from binutils: 4389950eceeSBaptiste Daroussin * gas/config/tc-mips.c 4399950eceeSBaptiste Daroussin */ 4409950eceeSBaptiste Daroussin switch (elfhdr.e_flags & EF_MIPS_ABI) { 4419950eceeSBaptiste Daroussin case E_MIPS_ABI_O32: 4429950eceeSBaptiste Daroussin abi = "o32"; 4439950eceeSBaptiste Daroussin break; 4449950eceeSBaptiste Daroussin case E_MIPS_ABI_N32: 4459950eceeSBaptiste Daroussin abi = "n32"; 4469950eceeSBaptiste Daroussin break; 4479950eceeSBaptiste Daroussin default: 4489950eceeSBaptiste Daroussin if (elfhdr.e_ident[EI_DATA] == 4499950eceeSBaptiste Daroussin ELFCLASS32) 4509950eceeSBaptiste Daroussin abi = "o32"; 4519950eceeSBaptiste Daroussin else if (elfhdr.e_ident[EI_DATA] == 4529950eceeSBaptiste Daroussin ELFCLASS64) 4539950eceeSBaptiste Daroussin abi = "n64"; 4549950eceeSBaptiste Daroussin break; 4559950eceeSBaptiste Daroussin } 45640274a2dSBaptiste Daroussin endian_corres_str = elf_corres_to_string(endian_corres, 45740274a2dSBaptiste Daroussin (int)elfhdr.e_ident[EI_DATA]); 45840274a2dSBaptiste Daroussin 45940274a2dSBaptiste Daroussin snprintf(dest + strlen(dest), sz - strlen(dest), ":%s:%s:%s:%s", 46040274a2dSBaptiste Daroussin arch, wordsize_corres_str, endian_corres_str, abi); 4619950eceeSBaptiste Daroussin break; 46240274a2dSBaptiste Daroussin default: 46340274a2dSBaptiste Daroussin snprintf(dest + strlen(dest), sz - strlen(dest), ":%s:%s", 46440274a2dSBaptiste Daroussin arch, wordsize_corres_str); 4659950eceeSBaptiste Daroussin } 4669950eceeSBaptiste Daroussin 4679950eceeSBaptiste Daroussin cleanup: 4689950eceeSBaptiste Daroussin if (elf != NULL) 4699950eceeSBaptiste Daroussin elf_end(elf); 4709950eceeSBaptiste Daroussin 4719950eceeSBaptiste Daroussin close(fd); 4729950eceeSBaptiste Daroussin return (ret); 4739950eceeSBaptiste Daroussin } 4749950eceeSBaptiste Daroussin 4759950eceeSBaptiste Daroussin static void 4769950eceeSBaptiste Daroussin subst_packagesite(const char *abi) 4779950eceeSBaptiste Daroussin { 4789950eceeSBaptiste Daroussin struct sbuf *newval; 4799950eceeSBaptiste Daroussin const char *variable_string; 4809950eceeSBaptiste Daroussin const char *oldval; 4819950eceeSBaptiste Daroussin 4829950eceeSBaptiste Daroussin if (c[PACKAGESITE].value != NULL) 4839950eceeSBaptiste Daroussin oldval = c[PACKAGESITE].value; 4849950eceeSBaptiste Daroussin else 4859950eceeSBaptiste Daroussin oldval = c[PACKAGESITE].val; 4869950eceeSBaptiste Daroussin 4879950eceeSBaptiste Daroussin if ((variable_string = strstr(oldval, "${ABI}")) == NULL) 4889950eceeSBaptiste Daroussin return; 4899950eceeSBaptiste Daroussin 4909950eceeSBaptiste Daroussin newval = sbuf_new_auto(); 4919950eceeSBaptiste Daroussin sbuf_bcat(newval, oldval, variable_string - oldval); 4929950eceeSBaptiste Daroussin sbuf_cat(newval, abi); 4939950eceeSBaptiste Daroussin sbuf_cat(newval, variable_string + strlen("${ABI}")); 4949950eceeSBaptiste Daroussin sbuf_finish(newval); 4959950eceeSBaptiste Daroussin 4969950eceeSBaptiste Daroussin free(c[PACKAGESITE].value); 4979950eceeSBaptiste Daroussin c[PACKAGESITE].value = strdup(sbuf_data(newval)); 4989950eceeSBaptiste Daroussin } 4999950eceeSBaptiste Daroussin 500eb31a574SBryan Drewery static int 501eb31a574SBryan Drewery boolstr_to_bool(const char *str) 502eb31a574SBryan Drewery { 503eb31a574SBryan Drewery if (str != NULL && (strcasecmp(str, "true") == 0 || 504eb31a574SBryan Drewery strcasecmp(str, "yes") == 0 || strcasecmp(str, "on") == 0 || 505eb31a574SBryan Drewery str[0] == '1')) 506eb31a574SBryan Drewery return (true); 507eb31a574SBryan Drewery 508eb31a574SBryan Drewery return (false); 509eb31a574SBryan Drewery } 510eb31a574SBryan Drewery 5119950eceeSBaptiste Daroussin static void 512bc5e9ac0SBryan Drewery config_parse(yaml_document_t *doc, yaml_node_t *node, pkg_conf_file_t conftype) 5139950eceeSBaptiste Daroussin { 514eb31a574SBryan Drewery yaml_node_item_t *item; 5159950eceeSBaptiste Daroussin yaml_node_pair_t *pair; 516eb31a574SBryan Drewery yaml_node_t *key, *val, *item_val; 5179950eceeSBaptiste Daroussin struct sbuf *buf = sbuf_new_auto(); 518eb31a574SBryan Drewery struct config_entry *temp_config; 519eb31a574SBryan Drewery struct config_value *cv; 5209950eceeSBaptiste Daroussin int i; 5219950eceeSBaptiste Daroussin size_t j; 5229950eceeSBaptiste Daroussin 5239950eceeSBaptiste Daroussin pair = node->data.mapping.pairs.start; 5249950eceeSBaptiste Daroussin 525eb31a574SBryan Drewery /* Temporary config for configs that may be disabled. */ 526eb31a574SBryan Drewery temp_config = calloc(CONFIG_SIZE, sizeof(struct config_entry)); 527eb31a574SBryan Drewery 5289950eceeSBaptiste Daroussin while (pair < node->data.mapping.pairs.top) { 5299950eceeSBaptiste Daroussin key = yaml_document_get_node(doc, pair->key); 5309950eceeSBaptiste Daroussin val = yaml_document_get_node(doc, pair->value); 5319950eceeSBaptiste Daroussin 5329950eceeSBaptiste Daroussin /* 5339950eceeSBaptiste Daroussin * ignoring silently empty keys can be empty lines 5349950eceeSBaptiste Daroussin * or user mistakes 5359950eceeSBaptiste Daroussin */ 5369950eceeSBaptiste Daroussin if (key->data.scalar.length <= 0) { 5379950eceeSBaptiste Daroussin ++pair; 5389950eceeSBaptiste Daroussin continue; 5399950eceeSBaptiste Daroussin } 5409950eceeSBaptiste Daroussin 5419950eceeSBaptiste Daroussin /* 5429950eceeSBaptiste Daroussin * silently skip on purpose to allow user to leave 5439950eceeSBaptiste Daroussin * empty lines without complaining 5449950eceeSBaptiste Daroussin */ 5459950eceeSBaptiste Daroussin if (val->type == YAML_NO_NODE || 5469950eceeSBaptiste Daroussin (val->type == YAML_SCALAR_NODE && 5479950eceeSBaptiste Daroussin val->data.scalar.length <= 0)) { 5489950eceeSBaptiste Daroussin ++pair; 5499950eceeSBaptiste Daroussin continue; 5509950eceeSBaptiste Daroussin } 5519950eceeSBaptiste Daroussin 5529950eceeSBaptiste Daroussin sbuf_clear(buf); 5539950eceeSBaptiste Daroussin 554bc5e9ac0SBryan Drewery if (conftype == CONFFILE_PKG) { 555bc5e9ac0SBryan Drewery for (j = 0; j < strlen(key->data.scalar.value); ++j) 556bc5e9ac0SBryan Drewery sbuf_putc(buf, 557bc5e9ac0SBryan Drewery toupper(key->data.scalar.value[j])); 5589950eceeSBaptiste Daroussin sbuf_finish(buf); 559bc5e9ac0SBryan Drewery } else if (conftype == CONFFILE_REPO) { 560bc5e9ac0SBryan Drewery /* The CONFFILE_REPO type is more restrictive. Only 561bc5e9ac0SBryan Drewery parse known elements. */ 562bc5e9ac0SBryan Drewery if (strcasecmp(key->data.scalar.value, "url") == 0) 563bc5e9ac0SBryan Drewery sbuf_cpy(buf, "PACKAGESITE"); 564bc5e9ac0SBryan Drewery else if (strcasecmp(key->data.scalar.value, 565bc5e9ac0SBryan Drewery "mirror_type") == 0) 566bc5e9ac0SBryan Drewery sbuf_cpy(buf, "MIRROR_TYPE"); 567f12db248SBryan Drewery else if (strcasecmp(key->data.scalar.value, 568f12db248SBryan Drewery "signature_type") == 0) 569f12db248SBryan Drewery sbuf_cpy(buf, "SIGNATURE_TYPE"); 570f12db248SBryan Drewery else if (strcasecmp(key->data.scalar.value, 571f12db248SBryan Drewery "fingerprints") == 0) 572f12db248SBryan Drewery sbuf_cpy(buf, "FINGERPRINTS"); 573eb31a574SBryan Drewery else if (strcasecmp(key->data.scalar.value, 574eb31a574SBryan Drewery "enabled") == 0) { 575eb31a574SBryan Drewery /* Skip disabled repos. */ 576eb31a574SBryan Drewery if (!boolstr_to_bool(val->data.scalar.value)) 577eb31a574SBryan Drewery goto cleanup; 578eb31a574SBryan Drewery } else { /* Skip unknown entries for future use. */ 579bc5e9ac0SBryan Drewery ++pair; 580bc5e9ac0SBryan Drewery continue; 581bc5e9ac0SBryan Drewery } 582bc5e9ac0SBryan Drewery sbuf_finish(buf); 583bc5e9ac0SBryan Drewery } 584bc5e9ac0SBryan Drewery 5859950eceeSBaptiste Daroussin for (i = 0; i < CONFIG_SIZE; i++) { 5869950eceeSBaptiste Daroussin if (strcmp(sbuf_data(buf), c[i].key) == 0) 5879950eceeSBaptiste Daroussin break; 5889950eceeSBaptiste Daroussin } 5899950eceeSBaptiste Daroussin 590bc5e9ac0SBryan Drewery /* Silently skip unknown keys to be future compatible. */ 5919950eceeSBaptiste Daroussin if (i == CONFIG_SIZE) { 5929950eceeSBaptiste Daroussin ++pair; 5939950eceeSBaptiste Daroussin continue; 5949950eceeSBaptiste Daroussin } 5959950eceeSBaptiste Daroussin 5969950eceeSBaptiste Daroussin /* env has priority over config file */ 5979950eceeSBaptiste Daroussin if (c[i].envset) { 5989950eceeSBaptiste Daroussin ++pair; 5999950eceeSBaptiste Daroussin continue; 6009950eceeSBaptiste Daroussin } 6019950eceeSBaptiste Daroussin 602eb31a574SBryan Drewery /* Parse sequence value ["item1", "item2"] */ 603eb31a574SBryan Drewery switch (c[i].type) { 604eb31a574SBryan Drewery case PKG_CONFIG_LIST: 605eb31a574SBryan Drewery if (val->type != YAML_SEQUENCE_NODE) { 606eb31a574SBryan Drewery fprintf(stderr, "Skipping invalid array " 607eb31a574SBryan Drewery "value for %s.\n", c[i].key); 608eb31a574SBryan Drewery ++pair; 609eb31a574SBryan Drewery continue; 610eb31a574SBryan Drewery } 611eb31a574SBryan Drewery item = val->data.sequence.items.start; 612eb31a574SBryan Drewery temp_config[i].list = 613eb31a574SBryan Drewery malloc(sizeof(*temp_config[i].list)); 614eb31a574SBryan Drewery STAILQ_INIT(temp_config[i].list); 615eb31a574SBryan Drewery 616eb31a574SBryan Drewery while (item < val->data.sequence.items.top) { 617eb31a574SBryan Drewery item_val = yaml_document_get_node(doc, *item); 618eb31a574SBryan Drewery if (item_val->type != YAML_SCALAR_NODE) { 619eb31a574SBryan Drewery ++item; 620eb31a574SBryan Drewery continue; 621eb31a574SBryan Drewery } 622eb31a574SBryan Drewery cv = malloc(sizeof(struct config_value)); 623eb31a574SBryan Drewery cv->value = 624eb31a574SBryan Drewery strdup(item_val->data.scalar.value); 625eb31a574SBryan Drewery STAILQ_INSERT_TAIL(temp_config[i].list, cv, 626eb31a574SBryan Drewery next); 627eb31a574SBryan Drewery ++item; 628eb31a574SBryan Drewery } 629eb31a574SBryan Drewery break; 630eb31a574SBryan Drewery default: 631eb31a574SBryan Drewery /* Normal string value. */ 632eb31a574SBryan Drewery temp_config[i].value = strdup(val->data.scalar.value); 633eb31a574SBryan Drewery break; 634eb31a574SBryan Drewery } 6359950eceeSBaptiste Daroussin ++pair; 6369950eceeSBaptiste Daroussin } 6379950eceeSBaptiste Daroussin 638eb31a574SBryan Drewery /* Repo is enabled, copy over all settings from temp_config. */ 639eb31a574SBryan Drewery for (i = 0; i < CONFIG_SIZE; i++) { 640eb31a574SBryan Drewery if (c[i].envset) 641eb31a574SBryan Drewery continue; 642eb31a574SBryan Drewery switch (c[i].type) { 643eb31a574SBryan Drewery case PKG_CONFIG_LIST: 644eb31a574SBryan Drewery c[i].list = temp_config[i].list; 645eb31a574SBryan Drewery break; 646eb31a574SBryan Drewery default: 647eb31a574SBryan Drewery c[i].value = temp_config[i].value; 648eb31a574SBryan Drewery break; 649eb31a574SBryan Drewery } 650eb31a574SBryan Drewery } 651eb31a574SBryan Drewery 652eb31a574SBryan Drewery cleanup: 653eb31a574SBryan Drewery free(temp_config); 6549950eceeSBaptiste Daroussin sbuf_delete(buf); 6559950eceeSBaptiste Daroussin } 6569950eceeSBaptiste Daroussin 657bc5e9ac0SBryan Drewery /*- 658bc5e9ac0SBryan Drewery * Parse new repo style configs in style: 659bc5e9ac0SBryan Drewery * Name: 660bc5e9ac0SBryan Drewery * URL: 661bc5e9ac0SBryan Drewery * MIRROR_TYPE: 662bc5e9ac0SBryan Drewery * etc... 663bc5e9ac0SBryan Drewery */ 664bc5e9ac0SBryan Drewery static void 665bc5e9ac0SBryan Drewery parse_repo_file(yaml_document_t *doc, yaml_node_t *node) 666bc5e9ac0SBryan Drewery { 667bc5e9ac0SBryan Drewery yaml_node_pair_t *pair; 668bc5e9ac0SBryan Drewery 669bc5e9ac0SBryan Drewery pair = node->data.mapping.pairs.start; 670bc5e9ac0SBryan Drewery while (pair < node->data.mapping.pairs.top) { 671bc5e9ac0SBryan Drewery yaml_node_t *key = yaml_document_get_node(doc, pair->key); 672bc5e9ac0SBryan Drewery yaml_node_t *val = yaml_document_get_node(doc, pair->value); 673bc5e9ac0SBryan Drewery 674bc5e9ac0SBryan Drewery if (key->data.scalar.length <= 0) { 675bc5e9ac0SBryan Drewery ++pair; 676bc5e9ac0SBryan Drewery continue; 677bc5e9ac0SBryan Drewery } 678bc5e9ac0SBryan Drewery 679bc5e9ac0SBryan Drewery if (val->type != YAML_MAPPING_NODE) { 680bc5e9ac0SBryan Drewery ++pair; 681bc5e9ac0SBryan Drewery continue; 682bc5e9ac0SBryan Drewery } 683bc5e9ac0SBryan Drewery 684bc5e9ac0SBryan Drewery config_parse(doc, val, CONFFILE_REPO); 685bc5e9ac0SBryan Drewery ++pair; 686bc5e9ac0SBryan Drewery } 687bc5e9ac0SBryan Drewery } 688bc5e9ac0SBryan Drewery 689bc5e9ac0SBryan Drewery 690bc5e9ac0SBryan Drewery static int 691bc5e9ac0SBryan Drewery read_conf_file(const char *confpath, pkg_conf_file_t conftype) 6929950eceeSBaptiste Daroussin { 6939950eceeSBaptiste Daroussin FILE *fp; 6949950eceeSBaptiste Daroussin yaml_parser_t parser; 6959950eceeSBaptiste Daroussin yaml_document_t doc; 6969950eceeSBaptiste Daroussin yaml_node_t *node; 697bc5e9ac0SBryan Drewery 698bc5e9ac0SBryan Drewery if ((fp = fopen(confpath, "r")) == NULL) { 699bc5e9ac0SBryan Drewery if (errno != ENOENT) 700bc5e9ac0SBryan Drewery err(EXIT_FAILURE, "Unable to open configuration " 701bc5e9ac0SBryan Drewery "file %s", confpath); 702bc5e9ac0SBryan Drewery /* no configuration present */ 703bc5e9ac0SBryan Drewery return (1); 704bc5e9ac0SBryan Drewery } 705bc5e9ac0SBryan Drewery 706bc5e9ac0SBryan Drewery yaml_parser_initialize(&parser); 707bc5e9ac0SBryan Drewery yaml_parser_set_input_file(&parser, fp); 708bc5e9ac0SBryan Drewery yaml_parser_load(&parser, &doc); 709bc5e9ac0SBryan Drewery 710bc5e9ac0SBryan Drewery node = yaml_document_get_root_node(&doc); 711bc5e9ac0SBryan Drewery 712bc5e9ac0SBryan Drewery if (node == NULL || node->type != YAML_MAPPING_NODE) 713bc5e9ac0SBryan Drewery warnx("Invalid configuration format, ignoring the " 714bc5e9ac0SBryan Drewery "configuration file %s", confpath); 715bc5e9ac0SBryan Drewery else { 716bc5e9ac0SBryan Drewery if (conftype == CONFFILE_PKG) 717bc5e9ac0SBryan Drewery config_parse(&doc, node, conftype); 718bc5e9ac0SBryan Drewery else if (conftype == CONFFILE_REPO) 719bc5e9ac0SBryan Drewery parse_repo_file(&doc, node); 720bc5e9ac0SBryan Drewery } 721bc5e9ac0SBryan Drewery 722bc5e9ac0SBryan Drewery yaml_document_delete(&doc); 723bc5e9ac0SBryan Drewery yaml_parser_delete(&parser); 724bc5e9ac0SBryan Drewery 725bc5e9ac0SBryan Drewery return (0); 726bc5e9ac0SBryan Drewery } 727bc5e9ac0SBryan Drewery 728eb31a574SBryan Drewery static int 729eb31a574SBryan Drewery load_repositories(const char *repodir) 730eb31a574SBryan Drewery { 731eb31a574SBryan Drewery struct dirent *ent; 732eb31a574SBryan Drewery DIR *d; 733eb31a574SBryan Drewery char *p; 734eb31a574SBryan Drewery size_t n; 735eb31a574SBryan Drewery char path[MAXPATHLEN]; 736eb31a574SBryan Drewery int ret; 737eb31a574SBryan Drewery 738eb31a574SBryan Drewery ret = 0; 739eb31a574SBryan Drewery 740eb31a574SBryan Drewery if ((d = opendir(repodir)) == NULL) 741eb31a574SBryan Drewery return (1); 742eb31a574SBryan Drewery 743eb31a574SBryan Drewery while ((ent = readdir(d))) { 744eb31a574SBryan Drewery /* Trim out 'repos'. */ 745eb31a574SBryan Drewery if ((n = strlen(ent->d_name)) <= 5) 746eb31a574SBryan Drewery continue; 747eb31a574SBryan Drewery p = &ent->d_name[n - 5]; 748eb31a574SBryan Drewery if (strcmp(p, ".conf") == 0) { 749eb31a574SBryan Drewery snprintf(path, sizeof(path), "%s%s%s", 750eb31a574SBryan Drewery repodir, 751eb31a574SBryan Drewery repodir[strlen(repodir) - 1] == '/' ? "" : "/", 752eb31a574SBryan Drewery ent->d_name); 753eb31a574SBryan Drewery if (access(path, F_OK) == 0 && 754eb31a574SBryan Drewery read_conf_file(path, CONFFILE_REPO)) { 755eb31a574SBryan Drewery ret = 1; 756eb31a574SBryan Drewery goto cleanup; 757eb31a574SBryan Drewery } 758eb31a574SBryan Drewery } 759eb31a574SBryan Drewery } 760eb31a574SBryan Drewery 761eb31a574SBryan Drewery cleanup: 762eb31a574SBryan Drewery closedir(d); 763eb31a574SBryan Drewery 764eb31a574SBryan Drewery return (ret); 765eb31a574SBryan Drewery } 766eb31a574SBryan Drewery 767bc5e9ac0SBryan Drewery int 768bc5e9ac0SBryan Drewery config_init(void) 769bc5e9ac0SBryan Drewery { 770eb31a574SBryan Drewery char *val; 7719950eceeSBaptiste Daroussin int i; 7729950eceeSBaptiste Daroussin const char *localbase; 773eb31a574SBryan Drewery char *env_list_item; 7749950eceeSBaptiste Daroussin char confpath[MAXPATHLEN]; 775eb31a574SBryan Drewery struct config_value *cv; 7769950eceeSBaptiste Daroussin char abi[BUFSIZ]; 7779950eceeSBaptiste Daroussin 7789950eceeSBaptiste Daroussin for (i = 0; i < CONFIG_SIZE; i++) { 7799950eceeSBaptiste Daroussin val = getenv(c[i].key); 7809950eceeSBaptiste Daroussin if (val != NULL) { 7819950eceeSBaptiste Daroussin c[i].envset = true; 782eb31a574SBryan Drewery switch (c[i].type) { 783eb31a574SBryan Drewery case PKG_CONFIG_LIST: 784eb31a574SBryan Drewery /* Split up comma-separated items from env. */ 785eb31a574SBryan Drewery c[i].list = malloc(sizeof(*c[i].list)); 786eb31a574SBryan Drewery STAILQ_INIT(c[i].list); 787eb31a574SBryan Drewery for (env_list_item = strtok(val, ","); 788eb31a574SBryan Drewery env_list_item != NULL; 789eb31a574SBryan Drewery env_list_item = strtok(NULL, ",")) { 790eb31a574SBryan Drewery cv = 791eb31a574SBryan Drewery malloc(sizeof(struct config_value)); 792eb31a574SBryan Drewery cv->value = 793eb31a574SBryan Drewery strdup(env_list_item); 794eb31a574SBryan Drewery STAILQ_INSERT_TAIL(c[i].list, cv, 795eb31a574SBryan Drewery next); 796eb31a574SBryan Drewery } 797eb31a574SBryan Drewery break; 798eb31a574SBryan Drewery default: 799eb31a574SBryan Drewery c[i].val = val; 800eb31a574SBryan Drewery break; 801eb31a574SBryan Drewery } 8029950eceeSBaptiste Daroussin } 8039950eceeSBaptiste Daroussin } 8049950eceeSBaptiste Daroussin 805eb31a574SBryan Drewery /* Read LOCALBASE/etc/pkg.conf first. */ 8069950eceeSBaptiste Daroussin localbase = getenv("LOCALBASE") ? getenv("LOCALBASE") : _LOCALBASE; 807bc5e9ac0SBryan Drewery snprintf(confpath, sizeof(confpath), "%s/etc/pkg.conf", 808bc5e9ac0SBryan Drewery localbase); 8099950eceeSBaptiste Daroussin 810bc5e9ac0SBryan Drewery if (access(confpath, F_OK) == 0 && read_conf_file(confpath, 811bc5e9ac0SBryan Drewery CONFFILE_PKG)) 8129950eceeSBaptiste Daroussin goto finalize; 8139950eceeSBaptiste Daroussin 814eb31a574SBryan Drewery /* Then read in all repos from REPOS_DIR list of directories. */ 815eb31a574SBryan Drewery if (c[REPOS_DIR].list == NULL) { 816eb31a574SBryan Drewery c[REPOS_DIR].list = malloc(sizeof(*c[REPOS_DIR].list)); 817eb31a574SBryan Drewery STAILQ_INIT(c[REPOS_DIR].list); 818eb31a574SBryan Drewery cv = malloc(sizeof(struct config_value)); 819eb31a574SBryan Drewery cv->value = strdup("/etc/pkg"); 820eb31a574SBryan Drewery STAILQ_INSERT_TAIL(c[REPOS_DIR].list, cv, next); 821eb31a574SBryan Drewery cv = malloc(sizeof(struct config_value)); 822eb31a574SBryan Drewery if (asprintf(&cv->value, "%s/etc/pkg/repos", localbase) < 0) 823eb31a574SBryan Drewery goto finalize; 824eb31a574SBryan Drewery STAILQ_INSERT_TAIL(c[REPOS_DIR].list, cv, next); 825eb31a574SBryan Drewery } 826eb31a574SBryan Drewery 827eb31a574SBryan Drewery STAILQ_FOREACH(cv, c[REPOS_DIR].list, next) 828eb31a574SBryan Drewery if (load_repositories(cv->value)) 829bc5e9ac0SBryan Drewery goto finalize; 8309950eceeSBaptiste Daroussin 8319950eceeSBaptiste Daroussin finalize: 8329950eceeSBaptiste Daroussin if (c[ABI].val == NULL && c[ABI].value == NULL) { 8339950eceeSBaptiste Daroussin if (pkg_get_myabi(abi, BUFSIZ) != 0) 8344ff9a7efSBryan Drewery errx(EXIT_FAILURE, "Failed to determine the system " 8354ff9a7efSBryan Drewery "ABI"); 8369950eceeSBaptiste Daroussin c[ABI].val = abi; 8379950eceeSBaptiste Daroussin } 8389950eceeSBaptiste Daroussin 839d5bf8a8bSBaptiste Daroussin subst_packagesite(c[ABI].value != NULL ? c[ABI].value : c[ABI].val); 8409950eceeSBaptiste Daroussin 8419950eceeSBaptiste Daroussin return (0); 8429950eceeSBaptiste Daroussin } 8439950eceeSBaptiste Daroussin 8449950eceeSBaptiste Daroussin int 8459950eceeSBaptiste Daroussin config_string(pkg_config_key k, const char **val) 8469950eceeSBaptiste Daroussin { 8479950eceeSBaptiste Daroussin if (c[k].type != PKG_CONFIG_STRING) 8489950eceeSBaptiste Daroussin return (-1); 8499950eceeSBaptiste Daroussin 8509950eceeSBaptiste Daroussin if (c[k].value != NULL) 8519950eceeSBaptiste Daroussin *val = c[k].value; 8529950eceeSBaptiste Daroussin else 8539950eceeSBaptiste Daroussin *val = c[k].val; 8549950eceeSBaptiste Daroussin 8559950eceeSBaptiste Daroussin return (0); 8569950eceeSBaptiste Daroussin } 8579950eceeSBaptiste Daroussin 8589950eceeSBaptiste Daroussin int 8599950eceeSBaptiste Daroussin config_bool(pkg_config_key k, bool *val) 8609950eceeSBaptiste Daroussin { 8619950eceeSBaptiste Daroussin const char *value; 8629950eceeSBaptiste Daroussin 8639950eceeSBaptiste Daroussin if (c[k].type != PKG_CONFIG_BOOL) 8649950eceeSBaptiste Daroussin return (-1); 8659950eceeSBaptiste Daroussin 8669950eceeSBaptiste Daroussin *val = false; 8679950eceeSBaptiste Daroussin 8689950eceeSBaptiste Daroussin if (c[k].value != NULL) 8699950eceeSBaptiste Daroussin value = c[k].value; 8709950eceeSBaptiste Daroussin else 8719950eceeSBaptiste Daroussin value = c[k].val; 8729950eceeSBaptiste Daroussin 873eb31a574SBryan Drewery if (boolstr_to_bool(value)) 8749950eceeSBaptiste Daroussin *val = true; 8759950eceeSBaptiste Daroussin 8769950eceeSBaptiste Daroussin return (0); 8779950eceeSBaptiste Daroussin } 8789950eceeSBaptiste Daroussin 8799950eceeSBaptiste Daroussin void 8809950eceeSBaptiste Daroussin config_finish(void) { 8819950eceeSBaptiste Daroussin int i; 8829950eceeSBaptiste Daroussin 8839950eceeSBaptiste Daroussin for (i = 0; i < CONFIG_SIZE; i++) 8849950eceeSBaptiste Daroussin free(c[i].value); 8859950eceeSBaptiste Daroussin } 886