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