13aa4b42aSBaptiste Daroussin /*- 23aa4b42aSBaptiste Daroussin * Copyright (c) 2012 Baptiste Daroussin <bapt@FreeBSD.org> 33aa4b42aSBaptiste Daroussin * All rights reserved. 43aa4b42aSBaptiste Daroussin * 53aa4b42aSBaptiste Daroussin * Redistribution and use in source and binary forms, with or without 63aa4b42aSBaptiste Daroussin * modification, are permitted provided that the following conditions 73aa4b42aSBaptiste Daroussin * are met: 83aa4b42aSBaptiste Daroussin * 1. Redistributions of source code must retain the above copyright 93aa4b42aSBaptiste Daroussin * notice, this list of conditions and the following disclaimer. 103aa4b42aSBaptiste Daroussin * 2. Redistributions in binary form must reproduce the above copyright 113aa4b42aSBaptiste Daroussin * notice, this list of conditions and the following disclaimer in the 123aa4b42aSBaptiste Daroussin * documentation and/or other materials provided with the distribution. 133aa4b42aSBaptiste Daroussin * 143aa4b42aSBaptiste Daroussin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 153aa4b42aSBaptiste Daroussin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 163aa4b42aSBaptiste Daroussin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 173aa4b42aSBaptiste Daroussin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 183aa4b42aSBaptiste Daroussin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 193aa4b42aSBaptiste Daroussin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 203aa4b42aSBaptiste Daroussin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 213aa4b42aSBaptiste Daroussin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 223aa4b42aSBaptiste Daroussin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 233aa4b42aSBaptiste Daroussin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 243aa4b42aSBaptiste Daroussin * SUCH DAMAGE. 253aa4b42aSBaptiste Daroussin */ 263aa4b42aSBaptiste Daroussin 273aa4b42aSBaptiste Daroussin #include <sys/cdefs.h> 283aa4b42aSBaptiste Daroussin __FBSDID("$FreeBSD$"); 293aa4b42aSBaptiste Daroussin 303aa4b42aSBaptiste Daroussin #include <sys/param.h> 313aa4b42aSBaptiste Daroussin #include <sys/elf_common.h> 323aa4b42aSBaptiste Daroussin #include <sys/endian.h> 333b05c2a8SBaptiste Daroussin #include <sys/wait.h> 343aa4b42aSBaptiste Daroussin 353aa4b42aSBaptiste Daroussin #include <archive.h> 363aa4b42aSBaptiste Daroussin #include <archive_entry.h> 373aa4b42aSBaptiste Daroussin #include <ctype.h> 383aa4b42aSBaptiste Daroussin #include <err.h> 393aa4b42aSBaptiste Daroussin #include <errno.h> 403aa4b42aSBaptiste Daroussin #include <fcntl.h> 413b05c2a8SBaptiste Daroussin #include <fetch.h> 423aa4b42aSBaptiste Daroussin #include <gelf.h> 43a6454741SBaptiste Daroussin #include <paths.h> 443aa4b42aSBaptiste Daroussin #include <stdlib.h> 453aa4b42aSBaptiste Daroussin #include <stdio.h> 463aa4b42aSBaptiste Daroussin #include <string.h> 473aa4b42aSBaptiste Daroussin #include <time.h> 483aa4b42aSBaptiste Daroussin #include <unistd.h> 493aa4b42aSBaptiste Daroussin 503aa4b42aSBaptiste Daroussin #include "elf_tables.h" 5129aaa961SBaptiste Daroussin #include "dns_utils.h" 523aa4b42aSBaptiste Daroussin 533aa4b42aSBaptiste Daroussin #define _LOCALBASE "/usr/local" 5429aaa961SBaptiste Daroussin #define _PKGS_URL "http://pkg.FreeBSD.org" 553aa4b42aSBaptiste Daroussin 563aa4b42aSBaptiste Daroussin static const char * 573aa4b42aSBaptiste Daroussin elf_corres_to_string(struct _elf_corres *m, int e) 583aa4b42aSBaptiste Daroussin { 59ce36f45dSBaptiste Daroussin int i; 603aa4b42aSBaptiste Daroussin 613aa4b42aSBaptiste Daroussin for (i = 0; m[i].string != NULL; i++) 623aa4b42aSBaptiste Daroussin if (m[i].elf_nb == e) 633aa4b42aSBaptiste Daroussin return (m[i].string); 643aa4b42aSBaptiste Daroussin 653aa4b42aSBaptiste Daroussin return ("unknown"); 663aa4b42aSBaptiste Daroussin } 673aa4b42aSBaptiste Daroussin 683aa4b42aSBaptiste Daroussin static int 693aa4b42aSBaptiste Daroussin pkg_get_myabi(char *dest, size_t sz) 703aa4b42aSBaptiste Daroussin { 713aa4b42aSBaptiste Daroussin Elf *elf; 723aa4b42aSBaptiste Daroussin Elf_Data *data; 733aa4b42aSBaptiste Daroussin Elf_Note note; 743aa4b42aSBaptiste Daroussin Elf_Scn *scn; 753aa4b42aSBaptiste Daroussin char *src, *osname; 763aa4b42aSBaptiste Daroussin const char *abi; 77a6454741SBaptiste Daroussin GElf_Ehdr elfhdr; 78a6454741SBaptiste Daroussin GElf_Shdr shdr; 793aa4b42aSBaptiste Daroussin int fd, i, ret; 803aa4b42aSBaptiste Daroussin uint32_t version; 813aa4b42aSBaptiste Daroussin 823aa4b42aSBaptiste Daroussin version = 0; 83a6454741SBaptiste Daroussin ret = -1; 843aa4b42aSBaptiste Daroussin scn = NULL; 853aa4b42aSBaptiste Daroussin abi = NULL; 863aa4b42aSBaptiste Daroussin 873aa4b42aSBaptiste Daroussin if (elf_version(EV_CURRENT) == EV_NONE) { 883b05c2a8SBaptiste Daroussin warnx("ELF library initialization failed: %s", 893b05c2a8SBaptiste Daroussin elf_errmsg(-1)); 903b05c2a8SBaptiste Daroussin return (-1); 913aa4b42aSBaptiste Daroussin } 923aa4b42aSBaptiste Daroussin 933aa4b42aSBaptiste Daroussin if ((fd = open("/bin/sh", O_RDONLY)) < 0) { 943aa4b42aSBaptiste Daroussin warn("open()"); 953b05c2a8SBaptiste Daroussin return (-1); 963aa4b42aSBaptiste Daroussin } 973aa4b42aSBaptiste Daroussin 983aa4b42aSBaptiste Daroussin if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) { 993aa4b42aSBaptiste Daroussin ret = -1; 1003aa4b42aSBaptiste Daroussin warnx("elf_begin() failed: %s.", elf_errmsg(-1)); 1013aa4b42aSBaptiste Daroussin goto cleanup; 1023aa4b42aSBaptiste Daroussin } 1033aa4b42aSBaptiste Daroussin 1043aa4b42aSBaptiste Daroussin if (gelf_getehdr(elf, &elfhdr) == NULL) { 1053aa4b42aSBaptiste Daroussin ret = -1; 1063aa4b42aSBaptiste Daroussin warn("getehdr() failed: %s.", elf_errmsg(-1)); 1073aa4b42aSBaptiste Daroussin goto cleanup; 1083aa4b42aSBaptiste Daroussin } 1093aa4b42aSBaptiste Daroussin 1103aa4b42aSBaptiste Daroussin while ((scn = elf_nextscn(elf, scn)) != NULL) { 1113aa4b42aSBaptiste Daroussin if (gelf_getshdr(scn, &shdr) != &shdr) { 1123aa4b42aSBaptiste Daroussin ret = -1; 1133aa4b42aSBaptiste Daroussin warn("getshdr() failed: %s.", elf_errmsg(-1)); 1143aa4b42aSBaptiste Daroussin goto cleanup; 1153aa4b42aSBaptiste Daroussin } 1163aa4b42aSBaptiste Daroussin 1173aa4b42aSBaptiste Daroussin if (shdr.sh_type == SHT_NOTE) 1183aa4b42aSBaptiste Daroussin break; 1193aa4b42aSBaptiste Daroussin } 1203aa4b42aSBaptiste Daroussin 1213aa4b42aSBaptiste Daroussin if (scn == NULL) { 1223aa4b42aSBaptiste Daroussin ret = -1; 123a6454741SBaptiste Daroussin warn("failed to get the note section"); 1243aa4b42aSBaptiste Daroussin goto cleanup; 1253aa4b42aSBaptiste Daroussin } 1263aa4b42aSBaptiste Daroussin 1273aa4b42aSBaptiste Daroussin data = elf_getdata(scn, NULL); 1283aa4b42aSBaptiste Daroussin src = data->d_buf; 129ce36f45dSBaptiste Daroussin for (;;) { 1303aa4b42aSBaptiste Daroussin memcpy(¬e, src, sizeof(Elf_Note)); 1313aa4b42aSBaptiste Daroussin src += sizeof(Elf_Note); 1323aa4b42aSBaptiste Daroussin if (note.n_type == NT_VERSION) 1333aa4b42aSBaptiste Daroussin break; 1343aa4b42aSBaptiste Daroussin src += note.n_namesz + note.n_descsz; 1353aa4b42aSBaptiste Daroussin } 1363aa4b42aSBaptiste Daroussin osname = src; 1373aa4b42aSBaptiste Daroussin src += note.n_namesz; 1383aa4b42aSBaptiste Daroussin if (elfhdr.e_ident[EI_DATA] == ELFDATA2MSB) 1393aa4b42aSBaptiste Daroussin version = be32dec(src); 1403aa4b42aSBaptiste Daroussin else 1413aa4b42aSBaptiste Daroussin version = le32dec(src); 1423aa4b42aSBaptiste Daroussin 1433aa4b42aSBaptiste Daroussin for (i = 0; osname[i] != '\0'; i++) 1443aa4b42aSBaptiste Daroussin osname[i] = (char)tolower(osname[i]); 1453aa4b42aSBaptiste Daroussin 1463aa4b42aSBaptiste Daroussin snprintf(dest, sz, "%s:%d:%s:%s", 1473b05c2a8SBaptiste Daroussin osname, version / 100000, 1483aa4b42aSBaptiste Daroussin elf_corres_to_string(mach_corres, (int)elfhdr.e_machine), 1493aa4b42aSBaptiste Daroussin elf_corres_to_string(wordsize_corres, 1503aa4b42aSBaptiste Daroussin (int)elfhdr.e_ident[EI_CLASS])); 1513aa4b42aSBaptiste Daroussin 152a6454741SBaptiste Daroussin ret = 0; 153a6454741SBaptiste Daroussin 1543aa4b42aSBaptiste Daroussin switch (elfhdr.e_machine) { 1553aa4b42aSBaptiste Daroussin case EM_ARM: 1563aa4b42aSBaptiste Daroussin snprintf(dest + strlen(dest), sz - strlen(dest), 1573b05c2a8SBaptiste Daroussin ":%s:%s:%s", elf_corres_to_string(endian_corres, 1583aa4b42aSBaptiste Daroussin (int)elfhdr.e_ident[EI_DATA]), 1593aa4b42aSBaptiste Daroussin (elfhdr.e_flags & EF_ARM_NEW_ABI) > 0 ? 1603aa4b42aSBaptiste Daroussin "eabi" : "oabi", 1613aa4b42aSBaptiste Daroussin (elfhdr.e_flags & EF_ARM_VFP_FLOAT) > 0 ? 1623aa4b42aSBaptiste Daroussin "softfp" : "vfp"); 1633aa4b42aSBaptiste Daroussin break; 1643aa4b42aSBaptiste Daroussin case EM_MIPS: 1653aa4b42aSBaptiste Daroussin /* 1663aa4b42aSBaptiste Daroussin * this is taken from binutils sources: 1673aa4b42aSBaptiste Daroussin * include/elf/mips.h 1683aa4b42aSBaptiste Daroussin * mapping is figured out from binutils: 1693aa4b42aSBaptiste Daroussin * gas/config/tc-mips.c 1703aa4b42aSBaptiste Daroussin */ 1713aa4b42aSBaptiste Daroussin switch (elfhdr.e_flags & EF_MIPS_ABI) { 1723aa4b42aSBaptiste Daroussin case E_MIPS_ABI_O32: 1733aa4b42aSBaptiste Daroussin abi = "o32"; 1743aa4b42aSBaptiste Daroussin break; 1753aa4b42aSBaptiste Daroussin case E_MIPS_ABI_N32: 1763aa4b42aSBaptiste Daroussin abi = "n32"; 1773aa4b42aSBaptiste Daroussin break; 1783aa4b42aSBaptiste Daroussin default: 1793aa4b42aSBaptiste Daroussin if (elfhdr.e_ident[EI_DATA] == 1803aa4b42aSBaptiste Daroussin ELFCLASS32) 1813aa4b42aSBaptiste Daroussin abi = "o32"; 1823aa4b42aSBaptiste Daroussin else if (elfhdr.e_ident[EI_DATA] == 1833aa4b42aSBaptiste Daroussin ELFCLASS64) 1843aa4b42aSBaptiste Daroussin abi = "n64"; 1853aa4b42aSBaptiste Daroussin break; 1863aa4b42aSBaptiste Daroussin } 1873aa4b42aSBaptiste Daroussin snprintf(dest + strlen(dest), sz - strlen(dest), 1883b05c2a8SBaptiste Daroussin ":%s:%s", elf_corres_to_string(endian_corres, 1893b05c2a8SBaptiste Daroussin (int)elfhdr.e_ident[EI_DATA]), abi); 1903aa4b42aSBaptiste Daroussin break; 1913aa4b42aSBaptiste Daroussin } 1923aa4b42aSBaptiste Daroussin 1933aa4b42aSBaptiste Daroussin cleanup: 1943aa4b42aSBaptiste Daroussin if (elf != NULL) 1953aa4b42aSBaptiste Daroussin elf_end(elf); 1963aa4b42aSBaptiste Daroussin 1973aa4b42aSBaptiste Daroussin close(fd); 1983aa4b42aSBaptiste Daroussin return (ret); 1993aa4b42aSBaptiste Daroussin } 2003aa4b42aSBaptiste Daroussin 2013aa4b42aSBaptiste Daroussin static int 2023aa4b42aSBaptiste Daroussin extract_pkg_static(int fd, char *p, int sz) 2033aa4b42aSBaptiste Daroussin { 2043aa4b42aSBaptiste Daroussin struct archive *a; 2053aa4b42aSBaptiste Daroussin struct archive_entry *ae; 2063aa4b42aSBaptiste Daroussin char *end; 2073aa4b42aSBaptiste Daroussin int ret, r; 2083aa4b42aSBaptiste Daroussin 209a6454741SBaptiste Daroussin ret = -1; 2103aa4b42aSBaptiste Daroussin a = archive_read_new(); 211a6454741SBaptiste Daroussin if (a == NULL) { 212a6454741SBaptiste Daroussin warn("archive_read_new"); 213a6454741SBaptiste Daroussin return (ret); 214a6454741SBaptiste Daroussin } 2153aa4b42aSBaptiste Daroussin archive_read_support_compression_all(a); 2163aa4b42aSBaptiste Daroussin archive_read_support_format_tar(a); 2173aa4b42aSBaptiste Daroussin 218a6454741SBaptiste Daroussin if (lseek(fd, 0, 0) == -1) { 219a6454741SBaptiste Daroussin warn("lseek"); 220a6454741SBaptiste Daroussin goto cleanup; 221a6454741SBaptiste Daroussin } 2223aa4b42aSBaptiste Daroussin 2233aa4b42aSBaptiste Daroussin if (archive_read_open_fd(a, fd, 4096) != ARCHIVE_OK) { 224a6454741SBaptiste Daroussin warnx("archive_read_open_fd: %s", archive_error_string(a)); 2253aa4b42aSBaptiste Daroussin goto cleanup; 2263aa4b42aSBaptiste Daroussin } 2273aa4b42aSBaptiste Daroussin 2283aa4b42aSBaptiste Daroussin ae = NULL; 2293aa4b42aSBaptiste Daroussin while ((r = archive_read_next_header(a, &ae)) == ARCHIVE_OK) { 2303aa4b42aSBaptiste Daroussin end = strrchr(archive_entry_pathname(ae), '/'); 2313aa4b42aSBaptiste Daroussin if (end == NULL) 2323aa4b42aSBaptiste Daroussin continue; 2333aa4b42aSBaptiste Daroussin 2343aa4b42aSBaptiste Daroussin if (strcmp(end, "/pkg-static") == 0) { 2353aa4b42aSBaptiste Daroussin r = archive_read_extract(a, ae, 2363aa4b42aSBaptiste Daroussin ARCHIVE_EXTRACT_OWNER | ARCHIVE_EXTRACT_PERM | 2373aa4b42aSBaptiste Daroussin ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_ACL | 2383aa4b42aSBaptiste Daroussin ARCHIVE_EXTRACT_FFLAGS | ARCHIVE_EXTRACT_XATTR); 239a6454741SBaptiste Daroussin strlcpy(p, archive_entry_pathname(ae), sz); 2403aa4b42aSBaptiste Daroussin break; 2413aa4b42aSBaptiste Daroussin } 2423aa4b42aSBaptiste Daroussin } 2433aa4b42aSBaptiste Daroussin 244a6454741SBaptiste Daroussin if (r == ARCHIVE_OK) 245a6454741SBaptiste Daroussin ret = 0; 246a6454741SBaptiste Daroussin else 2473aa4b42aSBaptiste Daroussin warnx("fail to extract pkg-static"); 2483aa4b42aSBaptiste Daroussin 2493aa4b42aSBaptiste Daroussin cleanup: 2503aa4b42aSBaptiste Daroussin archive_read_finish(a); 2513b05c2a8SBaptiste Daroussin return (ret); 2523aa4b42aSBaptiste Daroussin 2533aa4b42aSBaptiste Daroussin } 2543aa4b42aSBaptiste Daroussin 2553aa4b42aSBaptiste Daroussin static int 2563aa4b42aSBaptiste Daroussin install_pkg_static(char *path, char *pkgpath) 2573aa4b42aSBaptiste Daroussin { 2583aa4b42aSBaptiste Daroussin int pstat; 2593aa4b42aSBaptiste Daroussin pid_t pid; 2603aa4b42aSBaptiste Daroussin 2613aa4b42aSBaptiste Daroussin switch ((pid = fork())) { 2623aa4b42aSBaptiste Daroussin case -1: 2633aa4b42aSBaptiste Daroussin return (-1); 2643aa4b42aSBaptiste Daroussin case 0: 265a6454741SBaptiste Daroussin execl(path, "pkg-static", "add", pkgpath, (char *)NULL); 2663b05c2a8SBaptiste Daroussin _exit(1); 2673aa4b42aSBaptiste Daroussin default: 2683aa4b42aSBaptiste Daroussin break; 2693aa4b42aSBaptiste Daroussin } 2703aa4b42aSBaptiste Daroussin 271a6454741SBaptiste Daroussin while (waitpid(pid, &pstat, 0) == -1) 2723aa4b42aSBaptiste Daroussin if (errno != EINTR) 2733aa4b42aSBaptiste Daroussin return (-1); 2743aa4b42aSBaptiste Daroussin 275a6454741SBaptiste Daroussin if (WEXITSTATUS(pstat)) 2763aa4b42aSBaptiste Daroussin return (WEXITSTATUS(pstat)); 277a6454741SBaptiste Daroussin else if (WIFSIGNALED(pstat)) 278a6454741SBaptiste Daroussin return (128 & (WTERMSIG(pstat))); 279a6454741SBaptiste Daroussin return (pstat); 2803aa4b42aSBaptiste Daroussin } 2813aa4b42aSBaptiste Daroussin 2823aa4b42aSBaptiste Daroussin static int 2833aa4b42aSBaptiste Daroussin bootstrap_pkg(void) 2843aa4b42aSBaptiste Daroussin { 28529aaa961SBaptiste Daroussin struct url *u; 2863aa4b42aSBaptiste Daroussin FILE *remote; 2872fe3761eSBaptiste Daroussin FILE *config; 2882fe3761eSBaptiste Daroussin char *site; 28929aaa961SBaptiste Daroussin struct dns_srvinfo *mirrors, *current; 29029aaa961SBaptiste Daroussin /* To store _https._tcp. + hostname + \0 */ 29129aaa961SBaptiste Daroussin char zone[MAXHOSTNAMELEN + 13]; 2923aa4b42aSBaptiste Daroussin char url[MAXPATHLEN]; 2932fe3761eSBaptiste Daroussin char conf[MAXPATHLEN]; 2943aa4b42aSBaptiste Daroussin char abi[BUFSIZ]; 2953aa4b42aSBaptiste Daroussin char tmppkg[MAXPATHLEN]; 2963aa4b42aSBaptiste Daroussin char buf[10240]; 2973aa4b42aSBaptiste Daroussin char pkgstatic[MAXPATHLEN]; 29829aaa961SBaptiste Daroussin int fd, retry, ret, max_retry; 299a6454741SBaptiste Daroussin struct url_stat st; 3003aa4b42aSBaptiste Daroussin off_t done, r; 301a6454741SBaptiste Daroussin time_t now; 302a6454741SBaptiste Daroussin time_t last; 3033aa4b42aSBaptiste Daroussin 3043aa4b42aSBaptiste Daroussin done = 0; 305a6454741SBaptiste Daroussin last = 0; 30629aaa961SBaptiste Daroussin max_retry = 3; 307a6454741SBaptiste Daroussin ret = -1; 3083aa4b42aSBaptiste Daroussin remote = NULL; 3092fe3761eSBaptiste Daroussin config = NULL; 31029aaa961SBaptiste Daroussin current = mirrors = NULL; 3113aa4b42aSBaptiste Daroussin 312a6454741SBaptiste Daroussin printf("Bootstrapping pkg please wait\n"); 3133aa4b42aSBaptiste Daroussin 3143aa4b42aSBaptiste Daroussin if (pkg_get_myabi(abi, MAXPATHLEN) != 0) { 315a6454741SBaptiste Daroussin warnx("failed to determine the system ABI"); 3163b05c2a8SBaptiste Daroussin return (-1); 3173aa4b42aSBaptiste Daroussin } 3183aa4b42aSBaptiste Daroussin 319a6454741SBaptiste Daroussin if (getenv("PACKAGESITE") != NULL) 3202fe3761eSBaptiste Daroussin snprintf(url, MAXPATHLEN, "%s/Latest/pkg.txz", getenv("PACKAGESITE")); 321a6454741SBaptiste Daroussin else 3223aa4b42aSBaptiste Daroussin snprintf(url, MAXPATHLEN, "%s/%s/latest/Latest/pkg.txz", 3233aa4b42aSBaptiste Daroussin getenv("PACKAGEROOT") ? getenv("PACKAGEROOT") : _PKGS_URL, 3243aa4b42aSBaptiste Daroussin getenv("ABI") ? getenv("ABI") : abi); 3253aa4b42aSBaptiste Daroussin 3263aa4b42aSBaptiste Daroussin snprintf(tmppkg, MAXPATHLEN, "%s/pkg.txz.XXXXXX", 327a6454741SBaptiste Daroussin getenv("TMPDIR") ? getenv("TMPDIR") : _PATH_TMP); 3283aa4b42aSBaptiste Daroussin 3293aa4b42aSBaptiste Daroussin if ((fd = mkstemp(tmppkg)) == -1) { 3303aa4b42aSBaptiste Daroussin warn("mkstemp()"); 3313b05c2a8SBaptiste Daroussin return (-1); 3323aa4b42aSBaptiste Daroussin } 3333aa4b42aSBaptiste Daroussin 33429aaa961SBaptiste Daroussin retry = max_retry; 33529aaa961SBaptiste Daroussin 33629aaa961SBaptiste Daroussin u = fetchParseURL(url); 33729aaa961SBaptiste Daroussin while (remote == NULL) { 33829aaa961SBaptiste Daroussin if (retry == max_retry) { 33929aaa961SBaptiste Daroussin if (strcmp(u->scheme, "file") != 0) { 34029aaa961SBaptiste Daroussin snprintf(zone, sizeof(zone), 34129aaa961SBaptiste Daroussin "_%s._tcp.%s", u->scheme, u->host); 34229aaa961SBaptiste Daroussin printf("%s\n", zone); 34329aaa961SBaptiste Daroussin mirrors = dns_getsrvinfo(zone); 34429aaa961SBaptiste Daroussin current = mirrors; 34529aaa961SBaptiste Daroussin } 34629aaa961SBaptiste Daroussin } 34729aaa961SBaptiste Daroussin 34829aaa961SBaptiste Daroussin if (mirrors != NULL) 34929aaa961SBaptiste Daroussin strlcpy(u->host, current->host, sizeof(u->host)); 35029aaa961SBaptiste Daroussin 35129aaa961SBaptiste Daroussin remote = fetchXGet(u, &st, ""); 35229aaa961SBaptiste Daroussin if (remote == NULL) { 35329aaa961SBaptiste Daroussin --retry; 35429aaa961SBaptiste Daroussin if (retry <= 0) 35529aaa961SBaptiste Daroussin goto fetchfail; 35629aaa961SBaptiste Daroussin if (mirrors == NULL) { 3573aa4b42aSBaptiste Daroussin sleep(1); 35829aaa961SBaptiste Daroussin } else { 35929aaa961SBaptiste Daroussin current = current->next; 36029aaa961SBaptiste Daroussin if (current == NULL) 36129aaa961SBaptiste Daroussin current = mirrors; 36229aaa961SBaptiste Daroussin } 36329aaa961SBaptiste Daroussin } 36429aaa961SBaptiste Daroussin } 365a6454741SBaptiste Daroussin 366a6454741SBaptiste Daroussin if (remote == NULL) 367a6454741SBaptiste Daroussin goto fetchfail; 3683aa4b42aSBaptiste Daroussin 3693aa4b42aSBaptiste Daroussin while (done < st.size) { 3703aa4b42aSBaptiste Daroussin if ((r = fread(buf, 1, sizeof(buf), remote)) < 1) 3713aa4b42aSBaptiste Daroussin break; 3723aa4b42aSBaptiste Daroussin 3733aa4b42aSBaptiste Daroussin if (write(fd, buf, r) != r) { 3743aa4b42aSBaptiste Daroussin warn("write()"); 3753aa4b42aSBaptiste Daroussin goto cleanup; 3763aa4b42aSBaptiste Daroussin } 3773aa4b42aSBaptiste Daroussin 3783aa4b42aSBaptiste Daroussin done += r; 3793aa4b42aSBaptiste Daroussin now = time(NULL); 380a6454741SBaptiste Daroussin if (now > last || done == st.size) 3813aa4b42aSBaptiste Daroussin last = now; 3823aa4b42aSBaptiste Daroussin } 3833aa4b42aSBaptiste Daroussin 384a6454741SBaptiste Daroussin if (ferror(remote)) 385a6454741SBaptiste Daroussin goto fetchfail; 3863aa4b42aSBaptiste Daroussin 3873aa4b42aSBaptiste Daroussin if ((ret = extract_pkg_static(fd, pkgstatic, MAXPATHLEN)) == 0) 3883aa4b42aSBaptiste Daroussin ret = install_pkg_static(pkgstatic, tmppkg); 3893aa4b42aSBaptiste Daroussin 3902fe3761eSBaptiste Daroussin snprintf(conf, MAXPATHLEN, "%s/etc/pkg.conf", 3912fe3761eSBaptiste Daroussin getenv("LOCALBASE") ? getenv("LOCALBASE") : _LOCALBASE); 3922fe3761eSBaptiste Daroussin 3932fe3761eSBaptiste Daroussin if (access(conf, R_OK) == -1) { 3942fe3761eSBaptiste Daroussin site = strrchr(url, '/'); 3952fe3761eSBaptiste Daroussin if (site == NULL) 3962fe3761eSBaptiste Daroussin goto cleanup; 3972fe3761eSBaptiste Daroussin site[0] = '\0'; 3982fe3761eSBaptiste Daroussin site = strrchr(url, '/'); 3992fe3761eSBaptiste Daroussin if (site == NULL) 4002fe3761eSBaptiste Daroussin goto cleanup; 4012fe3761eSBaptiste Daroussin site[0] = '\0'; 4022fe3761eSBaptiste Daroussin 4032fe3761eSBaptiste Daroussin config = fopen(conf, "w+"); 4042fe3761eSBaptiste Daroussin if (config == NULL) 4052fe3761eSBaptiste Daroussin goto cleanup; 406514ead92SBaptiste Daroussin fprintf(config, "packagesite: %s\n", url); 4072fe3761eSBaptiste Daroussin fclose(config); 4082fe3761eSBaptiste Daroussin } 4092fe3761eSBaptiste Daroussin 410a6454741SBaptiste Daroussin goto cleanup; 411a6454741SBaptiste Daroussin 412a6454741SBaptiste Daroussin fetchfail: 413a6454741SBaptiste Daroussin warnx("Error fetching %s: %s", url, fetchLastErrString); 414a6454741SBaptiste Daroussin 4153aa4b42aSBaptiste Daroussin cleanup: 4162fe3761eSBaptiste Daroussin if (remote != NULL) 4172fe3761eSBaptiste Daroussin fclose(remote); 4183aa4b42aSBaptiste Daroussin close(fd); 4193aa4b42aSBaptiste Daroussin unlink(tmppkg); 4203aa4b42aSBaptiste Daroussin 421a6454741SBaptiste Daroussin return (ret); 4223aa4b42aSBaptiste Daroussin } 4233aa4b42aSBaptiste Daroussin 424e18ad51cSAlexander Kabaev static const char confirmation_message[] = 425e18ad51cSAlexander Kabaev "The package management tool is not yet installed on your system.\n" 426e18ad51cSAlexander Kabaev "Do you want to fetch and install it now? [y/N]: "; 427e18ad51cSAlexander Kabaev 428e18ad51cSAlexander Kabaev static int 429e18ad51cSAlexander Kabaev pkg_query_yes_no(void) 430e18ad51cSAlexander Kabaev { 431e18ad51cSAlexander Kabaev int ret, c; 432e18ad51cSAlexander Kabaev 433e18ad51cSAlexander Kabaev c = getchar(); 434e18ad51cSAlexander Kabaev 435e18ad51cSAlexander Kabaev if (c == 'y' || c == 'Y') 436e18ad51cSAlexander Kabaev ret = 1; 437e18ad51cSAlexander Kabaev else 438e18ad51cSAlexander Kabaev ret = 0; 439e18ad51cSAlexander Kabaev 440e18ad51cSAlexander Kabaev while (c != '\n' && c != EOF) 441e18ad51cSAlexander Kabaev c = getchar(); 442e18ad51cSAlexander Kabaev 443e18ad51cSAlexander Kabaev return (ret); 444e18ad51cSAlexander Kabaev } 445e18ad51cSAlexander Kabaev 4463aa4b42aSBaptiste Daroussin int 4473aa4b42aSBaptiste Daroussin main(__unused int argc, char *argv[]) 4483aa4b42aSBaptiste Daroussin { 4493aa4b42aSBaptiste Daroussin char pkgpath[MAXPATHLEN]; 4503aa4b42aSBaptiste Daroussin 4513aa4b42aSBaptiste Daroussin snprintf(pkgpath, MAXPATHLEN, "%s/sbin/pkg", 4523aa4b42aSBaptiste Daroussin getenv("LOCALBASE") ? getenv("LOCALBASE") : _LOCALBASE); 4533aa4b42aSBaptiste Daroussin 454e18ad51cSAlexander Kabaev if (access(pkgpath, X_OK) == -1) { 455e18ad51cSAlexander Kabaev /* 456d482e1f4SMatthew Seaman * To allow 'pkg -N' to be used as a reliable test for whether 457ecfed9f2SMatthew Seaman * a system is configured to use pkg, don't bootstrap pkg 458ecfed9f2SMatthew Seaman * when that argument is given as argv[1]. 459ecfed9f2SMatthew Seaman */ 460d8f9490cSMatthew Seaman if (argv[1] != NULL && strcmp(argv[1], "-N") == 0) 461*e41b8acbSMatthew Seaman errx(EXIT_FAILURE, "pkg is not installed"); 462ecfed9f2SMatthew Seaman 463ecfed9f2SMatthew Seaman /* 464e18ad51cSAlexander Kabaev * Do not ask for confirmation if either of stdin or stdout is 465e18ad51cSAlexander Kabaev * not tty. Check the environment to see if user has answer 466e18ad51cSAlexander Kabaev * tucked in there already. 467e18ad51cSAlexander Kabaev */ 4683a480126SBaptiste Daroussin if (getenv("ASSUME_ALWAYS_YES") == NULL) { 469e18ad51cSAlexander Kabaev printf("%s", confirmation_message); 470204ea792SBaptiste Daroussin if (!isatty(fileno(stdin))) 4713a480126SBaptiste Daroussin exit(EXIT_FAILURE); 472204ea792SBaptiste Daroussin 473204ea792SBaptiste Daroussin if (pkg_query_yes_no() == 0) 474e18ad51cSAlexander Kabaev exit(EXIT_FAILURE); 475e18ad51cSAlexander Kabaev } 476a6454741SBaptiste Daroussin if (bootstrap_pkg() != 0) 477a6454741SBaptiste Daroussin exit(EXIT_FAILURE); 478e18ad51cSAlexander Kabaev } 4793aa4b42aSBaptiste Daroussin 4803aa4b42aSBaptiste Daroussin execv(pkgpath, argv); 4813aa4b42aSBaptiste Daroussin 482a6454741SBaptiste Daroussin /* NOT REACHED */ 4833b05c2a8SBaptiste Daroussin return (EXIT_FAILURE); 4843aa4b42aSBaptiste Daroussin } 485