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" 513aa4b42aSBaptiste Daroussin 523aa4b42aSBaptiste Daroussin #define _LOCALBASE "/usr/local" 533aa4b42aSBaptiste Daroussin #define _PKGS_URL "http://pkgbeta.FreeBSD.org" 543aa4b42aSBaptiste Daroussin 553aa4b42aSBaptiste Daroussin static const char * 563aa4b42aSBaptiste Daroussin elf_corres_to_string(struct _elf_corres *m, int e) 573aa4b42aSBaptiste Daroussin { 58ce36f45dSBaptiste Daroussin int i; 593aa4b42aSBaptiste Daroussin 603aa4b42aSBaptiste Daroussin for (i = 0; m[i].string != NULL; i++) 613aa4b42aSBaptiste Daroussin if (m[i].elf_nb == e) 623aa4b42aSBaptiste Daroussin return (m[i].string); 633aa4b42aSBaptiste Daroussin 643aa4b42aSBaptiste Daroussin return ("unknown"); 653aa4b42aSBaptiste Daroussin } 663aa4b42aSBaptiste Daroussin 673aa4b42aSBaptiste Daroussin static int 683aa4b42aSBaptiste Daroussin pkg_get_myabi(char *dest, size_t sz) 693aa4b42aSBaptiste Daroussin { 703aa4b42aSBaptiste Daroussin Elf *elf; 713aa4b42aSBaptiste Daroussin Elf_Data *data; 723aa4b42aSBaptiste Daroussin Elf_Note note; 733aa4b42aSBaptiste Daroussin Elf_Scn *scn; 743aa4b42aSBaptiste Daroussin char *src, *osname; 753aa4b42aSBaptiste Daroussin const char *abi; 76a6454741SBaptiste Daroussin GElf_Ehdr elfhdr; 77a6454741SBaptiste Daroussin GElf_Shdr shdr; 783aa4b42aSBaptiste Daroussin int fd, i, ret; 793aa4b42aSBaptiste Daroussin uint32_t version; 803aa4b42aSBaptiste Daroussin 813aa4b42aSBaptiste Daroussin version = 0; 82a6454741SBaptiste Daroussin ret = -1; 833aa4b42aSBaptiste Daroussin scn = NULL; 843aa4b42aSBaptiste Daroussin abi = NULL; 853aa4b42aSBaptiste Daroussin 863aa4b42aSBaptiste Daroussin if (elf_version(EV_CURRENT) == EV_NONE) { 873b05c2a8SBaptiste Daroussin warnx("ELF library initialization failed: %s", 883b05c2a8SBaptiste Daroussin elf_errmsg(-1)); 893b05c2a8SBaptiste Daroussin return (-1); 903aa4b42aSBaptiste Daroussin } 913aa4b42aSBaptiste Daroussin 923aa4b42aSBaptiste Daroussin if ((fd = open("/bin/sh", O_RDONLY)) < 0) { 933aa4b42aSBaptiste Daroussin warn("open()"); 943b05c2a8SBaptiste Daroussin return (-1); 953aa4b42aSBaptiste Daroussin } 963aa4b42aSBaptiste Daroussin 973aa4b42aSBaptiste Daroussin if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) { 983aa4b42aSBaptiste Daroussin ret = -1; 993aa4b42aSBaptiste Daroussin warnx("elf_begin() failed: %s.", elf_errmsg(-1)); 1003aa4b42aSBaptiste Daroussin goto cleanup; 1013aa4b42aSBaptiste Daroussin } 1023aa4b42aSBaptiste Daroussin 1033aa4b42aSBaptiste Daroussin if (gelf_getehdr(elf, &elfhdr) == NULL) { 1043aa4b42aSBaptiste Daroussin ret = -1; 1053aa4b42aSBaptiste Daroussin warn("getehdr() failed: %s.", elf_errmsg(-1)); 1063aa4b42aSBaptiste Daroussin goto cleanup; 1073aa4b42aSBaptiste Daroussin } 1083aa4b42aSBaptiste Daroussin 1093aa4b42aSBaptiste Daroussin while ((scn = elf_nextscn(elf, scn)) != NULL) { 1103aa4b42aSBaptiste Daroussin if (gelf_getshdr(scn, &shdr) != &shdr) { 1113aa4b42aSBaptiste Daroussin ret = -1; 1123aa4b42aSBaptiste Daroussin warn("getshdr() failed: %s.", elf_errmsg(-1)); 1133aa4b42aSBaptiste Daroussin goto cleanup; 1143aa4b42aSBaptiste Daroussin } 1153aa4b42aSBaptiste Daroussin 1163aa4b42aSBaptiste Daroussin if (shdr.sh_type == SHT_NOTE) 1173aa4b42aSBaptiste Daroussin break; 1183aa4b42aSBaptiste Daroussin } 1193aa4b42aSBaptiste Daroussin 1203aa4b42aSBaptiste Daroussin if (scn == NULL) { 1213aa4b42aSBaptiste Daroussin ret = -1; 122a6454741SBaptiste Daroussin warn("failed to get the note section"); 1233aa4b42aSBaptiste Daroussin goto cleanup; 1243aa4b42aSBaptiste Daroussin } 1253aa4b42aSBaptiste Daroussin 1263aa4b42aSBaptiste Daroussin data = elf_getdata(scn, NULL); 1273aa4b42aSBaptiste Daroussin src = data->d_buf; 128ce36f45dSBaptiste Daroussin for (;;) { 1293aa4b42aSBaptiste Daroussin memcpy(¬e, src, sizeof(Elf_Note)); 1303aa4b42aSBaptiste Daroussin src += sizeof(Elf_Note); 1313aa4b42aSBaptiste Daroussin if (note.n_type == NT_VERSION) 1323aa4b42aSBaptiste Daroussin break; 1333aa4b42aSBaptiste Daroussin src += note.n_namesz + note.n_descsz; 1343aa4b42aSBaptiste Daroussin } 1353aa4b42aSBaptiste Daroussin osname = src; 1363aa4b42aSBaptiste Daroussin src += note.n_namesz; 1373aa4b42aSBaptiste Daroussin if (elfhdr.e_ident[EI_DATA] == ELFDATA2MSB) 1383aa4b42aSBaptiste Daroussin version = be32dec(src); 1393aa4b42aSBaptiste Daroussin else 1403aa4b42aSBaptiste Daroussin version = le32dec(src); 1413aa4b42aSBaptiste Daroussin 1423aa4b42aSBaptiste Daroussin for (i = 0; osname[i] != '\0'; i++) 1433aa4b42aSBaptiste Daroussin osname[i] = (char)tolower(osname[i]); 1443aa4b42aSBaptiste Daroussin 1453aa4b42aSBaptiste Daroussin snprintf(dest, sz, "%s:%d:%s:%s", 1463b05c2a8SBaptiste Daroussin osname, version / 100000, 1473aa4b42aSBaptiste Daroussin elf_corres_to_string(mach_corres, (int)elfhdr.e_machine), 1483aa4b42aSBaptiste Daroussin elf_corres_to_string(wordsize_corres, 1493aa4b42aSBaptiste Daroussin (int)elfhdr.e_ident[EI_CLASS])); 1503aa4b42aSBaptiste Daroussin 151a6454741SBaptiste Daroussin ret = 0; 152a6454741SBaptiste Daroussin 1533aa4b42aSBaptiste Daroussin switch (elfhdr.e_machine) { 1543aa4b42aSBaptiste Daroussin case EM_ARM: 1553aa4b42aSBaptiste Daroussin snprintf(dest + strlen(dest), sz - strlen(dest), 1563b05c2a8SBaptiste Daroussin ":%s:%s:%s", elf_corres_to_string(endian_corres, 1573aa4b42aSBaptiste Daroussin (int)elfhdr.e_ident[EI_DATA]), 1583aa4b42aSBaptiste Daroussin (elfhdr.e_flags & EF_ARM_NEW_ABI) > 0 ? 1593aa4b42aSBaptiste Daroussin "eabi" : "oabi", 1603aa4b42aSBaptiste Daroussin (elfhdr.e_flags & EF_ARM_VFP_FLOAT) > 0 ? 1613aa4b42aSBaptiste Daroussin "softfp" : "vfp"); 1623aa4b42aSBaptiste Daroussin break; 1633aa4b42aSBaptiste Daroussin case EM_MIPS: 1643aa4b42aSBaptiste Daroussin /* 1653aa4b42aSBaptiste Daroussin * this is taken from binutils sources: 1663aa4b42aSBaptiste Daroussin * include/elf/mips.h 1673aa4b42aSBaptiste Daroussin * mapping is figured out from binutils: 1683aa4b42aSBaptiste Daroussin * gas/config/tc-mips.c 1693aa4b42aSBaptiste Daroussin */ 1703aa4b42aSBaptiste Daroussin switch (elfhdr.e_flags & EF_MIPS_ABI) { 1713aa4b42aSBaptiste Daroussin case E_MIPS_ABI_O32: 1723aa4b42aSBaptiste Daroussin abi = "o32"; 1733aa4b42aSBaptiste Daroussin break; 1743aa4b42aSBaptiste Daroussin case E_MIPS_ABI_N32: 1753aa4b42aSBaptiste Daroussin abi = "n32"; 1763aa4b42aSBaptiste Daroussin break; 1773aa4b42aSBaptiste Daroussin default: 1783aa4b42aSBaptiste Daroussin if (elfhdr.e_ident[EI_DATA] == 1793aa4b42aSBaptiste Daroussin ELFCLASS32) 1803aa4b42aSBaptiste Daroussin abi = "o32"; 1813aa4b42aSBaptiste Daroussin else if (elfhdr.e_ident[EI_DATA] == 1823aa4b42aSBaptiste Daroussin ELFCLASS64) 1833aa4b42aSBaptiste Daroussin abi = "n64"; 1843aa4b42aSBaptiste Daroussin break; 1853aa4b42aSBaptiste Daroussin } 1863aa4b42aSBaptiste Daroussin snprintf(dest + strlen(dest), sz - strlen(dest), 1873b05c2a8SBaptiste Daroussin ":%s:%s", elf_corres_to_string(endian_corres, 1883b05c2a8SBaptiste Daroussin (int)elfhdr.e_ident[EI_DATA]), abi); 1893aa4b42aSBaptiste Daroussin break; 1903aa4b42aSBaptiste Daroussin } 1913aa4b42aSBaptiste Daroussin 1923aa4b42aSBaptiste Daroussin cleanup: 1933aa4b42aSBaptiste Daroussin if (elf != NULL) 1943aa4b42aSBaptiste Daroussin elf_end(elf); 1953aa4b42aSBaptiste Daroussin 1963aa4b42aSBaptiste Daroussin close(fd); 1973aa4b42aSBaptiste Daroussin return (ret); 1983aa4b42aSBaptiste Daroussin } 1993aa4b42aSBaptiste Daroussin 2003aa4b42aSBaptiste Daroussin static int 2013aa4b42aSBaptiste Daroussin extract_pkg_static(int fd, char *p, int sz) 2023aa4b42aSBaptiste Daroussin { 2033aa4b42aSBaptiste Daroussin struct archive *a; 2043aa4b42aSBaptiste Daroussin struct archive_entry *ae; 2053aa4b42aSBaptiste Daroussin char *end; 2063aa4b42aSBaptiste Daroussin int ret, r; 2073aa4b42aSBaptiste Daroussin 208a6454741SBaptiste Daroussin ret = -1; 2093aa4b42aSBaptiste Daroussin a = archive_read_new(); 210a6454741SBaptiste Daroussin if (a == NULL) { 211a6454741SBaptiste Daroussin warn("archive_read_new"); 212a6454741SBaptiste Daroussin return (ret); 213a6454741SBaptiste Daroussin } 2143aa4b42aSBaptiste Daroussin archive_read_support_compression_all(a); 2153aa4b42aSBaptiste Daroussin archive_read_support_format_tar(a); 2163aa4b42aSBaptiste Daroussin 217a6454741SBaptiste Daroussin if (lseek(fd, 0, 0) == -1) { 218a6454741SBaptiste Daroussin warn("lseek"); 219a6454741SBaptiste Daroussin goto cleanup; 220a6454741SBaptiste Daroussin } 2213aa4b42aSBaptiste Daroussin 2223aa4b42aSBaptiste Daroussin if (archive_read_open_fd(a, fd, 4096) != ARCHIVE_OK) { 223a6454741SBaptiste Daroussin warnx("archive_read_open_fd: %s", archive_error_string(a)); 2243aa4b42aSBaptiste Daroussin goto cleanup; 2253aa4b42aSBaptiste Daroussin } 2263aa4b42aSBaptiste Daroussin 2273aa4b42aSBaptiste Daroussin ae = NULL; 2283aa4b42aSBaptiste Daroussin while ((r = archive_read_next_header(a, &ae)) == ARCHIVE_OK) { 2293aa4b42aSBaptiste Daroussin end = strrchr(archive_entry_pathname(ae), '/'); 2303aa4b42aSBaptiste Daroussin if (end == NULL) 2313aa4b42aSBaptiste Daroussin continue; 2323aa4b42aSBaptiste Daroussin 2333aa4b42aSBaptiste Daroussin if (strcmp(end, "/pkg-static") == 0) { 2343aa4b42aSBaptiste Daroussin r = archive_read_extract(a, ae, 2353aa4b42aSBaptiste Daroussin ARCHIVE_EXTRACT_OWNER | ARCHIVE_EXTRACT_PERM | 2363aa4b42aSBaptiste Daroussin ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_ACL | 2373aa4b42aSBaptiste Daroussin ARCHIVE_EXTRACT_FFLAGS | ARCHIVE_EXTRACT_XATTR); 238a6454741SBaptiste Daroussin strlcpy(p, archive_entry_pathname(ae), sz); 2393aa4b42aSBaptiste Daroussin break; 2403aa4b42aSBaptiste Daroussin } 2413aa4b42aSBaptiste Daroussin } 2423aa4b42aSBaptiste Daroussin 243a6454741SBaptiste Daroussin if (r == ARCHIVE_OK) 244a6454741SBaptiste Daroussin ret = 0; 245a6454741SBaptiste Daroussin else 2463aa4b42aSBaptiste Daroussin warnx("fail to extract pkg-static"); 2473aa4b42aSBaptiste Daroussin 2483aa4b42aSBaptiste Daroussin cleanup: 2493aa4b42aSBaptiste Daroussin archive_read_finish(a); 2503b05c2a8SBaptiste Daroussin return (ret); 2513aa4b42aSBaptiste Daroussin 2523aa4b42aSBaptiste Daroussin } 2533aa4b42aSBaptiste Daroussin 2543aa4b42aSBaptiste Daroussin static int 2553aa4b42aSBaptiste Daroussin install_pkg_static(char *path, char *pkgpath) 2563aa4b42aSBaptiste Daroussin { 2573aa4b42aSBaptiste Daroussin int pstat; 2583aa4b42aSBaptiste Daroussin pid_t pid; 2593aa4b42aSBaptiste Daroussin 2603aa4b42aSBaptiste Daroussin switch ((pid = fork())) { 2613aa4b42aSBaptiste Daroussin case -1: 2623aa4b42aSBaptiste Daroussin return (-1); 2633aa4b42aSBaptiste Daroussin case 0: 264a6454741SBaptiste Daroussin execl(path, "pkg-static", "add", pkgpath, (char *)NULL); 2653b05c2a8SBaptiste Daroussin _exit(1); 2663aa4b42aSBaptiste Daroussin default: 2673aa4b42aSBaptiste Daroussin break; 2683aa4b42aSBaptiste Daroussin } 2693aa4b42aSBaptiste Daroussin 270a6454741SBaptiste Daroussin while (waitpid(pid, &pstat, 0) == -1) 2713aa4b42aSBaptiste Daroussin if (errno != EINTR) 2723aa4b42aSBaptiste Daroussin return (-1); 2733aa4b42aSBaptiste Daroussin 274a6454741SBaptiste Daroussin if (WEXITSTATUS(pstat)) 2753aa4b42aSBaptiste Daroussin return (WEXITSTATUS(pstat)); 276a6454741SBaptiste Daroussin else if (WIFSIGNALED(pstat)) 277a6454741SBaptiste Daroussin return (128 & (WTERMSIG(pstat))); 278a6454741SBaptiste Daroussin return (pstat); 2793aa4b42aSBaptiste Daroussin } 2803aa4b42aSBaptiste Daroussin 2813aa4b42aSBaptiste Daroussin static int 2823aa4b42aSBaptiste Daroussin bootstrap_pkg(void) 2833aa4b42aSBaptiste Daroussin { 2843aa4b42aSBaptiste Daroussin FILE *remote; 2852fe3761eSBaptiste Daroussin FILE *config; 2862fe3761eSBaptiste Daroussin char *site; 2873aa4b42aSBaptiste Daroussin char url[MAXPATHLEN]; 2882fe3761eSBaptiste Daroussin char conf[MAXPATHLEN]; 2893aa4b42aSBaptiste Daroussin char abi[BUFSIZ]; 2903aa4b42aSBaptiste Daroussin char tmppkg[MAXPATHLEN]; 2913aa4b42aSBaptiste Daroussin char buf[10240]; 2923aa4b42aSBaptiste Daroussin char pkgstatic[MAXPATHLEN]; 2933aa4b42aSBaptiste Daroussin int fd, retry, ret; 294a6454741SBaptiste Daroussin struct url_stat st; 2953aa4b42aSBaptiste Daroussin off_t done, r; 296a6454741SBaptiste Daroussin time_t now; 297a6454741SBaptiste Daroussin time_t last; 2983aa4b42aSBaptiste Daroussin 2993aa4b42aSBaptiste Daroussin done = 0; 300a6454741SBaptiste Daroussin last = 0; 301a6454741SBaptiste Daroussin ret = -1; 3023aa4b42aSBaptiste Daroussin remote = NULL; 3032fe3761eSBaptiste Daroussin config = NULL; 3043aa4b42aSBaptiste Daroussin 305a6454741SBaptiste Daroussin printf("Bootstrapping pkg please wait\n"); 3063aa4b42aSBaptiste Daroussin 3073aa4b42aSBaptiste Daroussin if (pkg_get_myabi(abi, MAXPATHLEN) != 0) { 308a6454741SBaptiste Daroussin warnx("failed to determine the system ABI"); 3093b05c2a8SBaptiste Daroussin return (-1); 3103aa4b42aSBaptiste Daroussin } 3113aa4b42aSBaptiste Daroussin 312a6454741SBaptiste Daroussin if (getenv("PACKAGESITE") != NULL) 3132fe3761eSBaptiste Daroussin snprintf(url, MAXPATHLEN, "%s/Latest/pkg.txz", getenv("PACKAGESITE")); 314a6454741SBaptiste Daroussin else 3153aa4b42aSBaptiste Daroussin snprintf(url, MAXPATHLEN, "%s/%s/latest/Latest/pkg.txz", 3163aa4b42aSBaptiste Daroussin getenv("PACKAGEROOT") ? getenv("PACKAGEROOT") : _PKGS_URL, 3173aa4b42aSBaptiste Daroussin getenv("ABI") ? getenv("ABI") : abi); 3183aa4b42aSBaptiste Daroussin 3193aa4b42aSBaptiste Daroussin snprintf(tmppkg, MAXPATHLEN, "%s/pkg.txz.XXXXXX", 320a6454741SBaptiste Daroussin getenv("TMPDIR") ? getenv("TMPDIR") : _PATH_TMP); 3213aa4b42aSBaptiste Daroussin 3223aa4b42aSBaptiste Daroussin if ((fd = mkstemp(tmppkg)) == -1) { 3233aa4b42aSBaptiste Daroussin warn("mkstemp()"); 3243b05c2a8SBaptiste Daroussin return (-1); 3253aa4b42aSBaptiste Daroussin } 3263aa4b42aSBaptiste Daroussin 327a6454741SBaptiste Daroussin retry = 3; 328a6454741SBaptiste Daroussin do { 3293aa4b42aSBaptiste Daroussin remote = fetchXGetURL(url, &st, ""); 330a6454741SBaptiste Daroussin if (remote == NULL) 3313aa4b42aSBaptiste Daroussin sleep(1); 332a6454741SBaptiste Daroussin } while (remote == NULL && retry-- > 0); 333a6454741SBaptiste Daroussin 334a6454741SBaptiste Daroussin if (remote == NULL) 335a6454741SBaptiste Daroussin goto fetchfail; 3363aa4b42aSBaptiste Daroussin 3373aa4b42aSBaptiste Daroussin while (done < st.size) { 3383aa4b42aSBaptiste Daroussin if ((r = fread(buf, 1, sizeof(buf), remote)) < 1) 3393aa4b42aSBaptiste Daroussin break; 3403aa4b42aSBaptiste Daroussin 3413aa4b42aSBaptiste Daroussin if (write(fd, buf, r) != r) { 3423aa4b42aSBaptiste Daroussin warn("write()"); 3433aa4b42aSBaptiste Daroussin goto cleanup; 3443aa4b42aSBaptiste Daroussin } 3453aa4b42aSBaptiste Daroussin 3463aa4b42aSBaptiste Daroussin done += r; 3473aa4b42aSBaptiste Daroussin now = time(NULL); 348a6454741SBaptiste Daroussin if (now > last || done == st.size) 3493aa4b42aSBaptiste Daroussin last = now; 3503aa4b42aSBaptiste Daroussin } 3513aa4b42aSBaptiste Daroussin 352a6454741SBaptiste Daroussin if (ferror(remote)) 353a6454741SBaptiste Daroussin goto fetchfail; 3543aa4b42aSBaptiste Daroussin 3553aa4b42aSBaptiste Daroussin if ((ret = extract_pkg_static(fd, pkgstatic, MAXPATHLEN)) == 0) 3563aa4b42aSBaptiste Daroussin ret = install_pkg_static(pkgstatic, tmppkg); 3573aa4b42aSBaptiste Daroussin 3582fe3761eSBaptiste Daroussin snprintf(conf, MAXPATHLEN, "%s/etc/pkg.conf", 3592fe3761eSBaptiste Daroussin getenv("LOCALBASE") ? getenv("LOCALBASE") : _LOCALBASE); 3602fe3761eSBaptiste Daroussin 3612fe3761eSBaptiste Daroussin if (access(conf, R_OK) == -1) { 3622fe3761eSBaptiste Daroussin site = strrchr(url, '/'); 3632fe3761eSBaptiste Daroussin if (site == NULL) 3642fe3761eSBaptiste Daroussin goto cleanup; 3652fe3761eSBaptiste Daroussin site[0] = '\0'; 3662fe3761eSBaptiste Daroussin site = strrchr(url, '/'); 3672fe3761eSBaptiste Daroussin if (site == NULL) 3682fe3761eSBaptiste Daroussin goto cleanup; 3692fe3761eSBaptiste Daroussin site[0] = '\0'; 3702fe3761eSBaptiste Daroussin 3712fe3761eSBaptiste Daroussin config = fopen(conf, "w+"); 3722fe3761eSBaptiste Daroussin if (config == NULL) 3732fe3761eSBaptiste Daroussin goto cleanup; 374514ead92SBaptiste Daroussin fprintf(config, "packagesite: %s\n", url); 3752fe3761eSBaptiste Daroussin fclose(config); 3762fe3761eSBaptiste Daroussin } 3772fe3761eSBaptiste Daroussin 378a6454741SBaptiste Daroussin goto cleanup; 379a6454741SBaptiste Daroussin 380a6454741SBaptiste Daroussin fetchfail: 381a6454741SBaptiste Daroussin warnx("Error fetching %s: %s", url, fetchLastErrString); 382a6454741SBaptiste Daroussin 3833aa4b42aSBaptiste Daroussin cleanup: 3842fe3761eSBaptiste Daroussin if (remote != NULL) 3852fe3761eSBaptiste Daroussin fclose(remote); 3863aa4b42aSBaptiste Daroussin close(fd); 3873aa4b42aSBaptiste Daroussin unlink(tmppkg); 3883aa4b42aSBaptiste Daroussin 389a6454741SBaptiste Daroussin return (ret); 3903aa4b42aSBaptiste Daroussin } 3913aa4b42aSBaptiste Daroussin 392e18ad51cSAlexander Kabaev static const char confirmation_message[] = 393e18ad51cSAlexander Kabaev "The package management tool is not yet installed on your system.\n" 394e18ad51cSAlexander Kabaev "Do you want to fetch and install it now? [y/N]: "; 395e18ad51cSAlexander Kabaev 396e18ad51cSAlexander Kabaev static int 397e18ad51cSAlexander Kabaev pkg_query_yes_no(void) 398e18ad51cSAlexander Kabaev { 399e18ad51cSAlexander Kabaev int ret, c; 400e18ad51cSAlexander Kabaev 401e18ad51cSAlexander Kabaev c = getchar(); 402e18ad51cSAlexander Kabaev 403e18ad51cSAlexander Kabaev if (c == 'y' || c == 'Y') 404e18ad51cSAlexander Kabaev ret = 1; 405e18ad51cSAlexander Kabaev else 406e18ad51cSAlexander Kabaev ret = 0; 407e18ad51cSAlexander Kabaev 408e18ad51cSAlexander Kabaev while (c != '\n' && c != EOF) 409e18ad51cSAlexander Kabaev c = getchar(); 410e18ad51cSAlexander Kabaev 411e18ad51cSAlexander Kabaev return (ret); 412e18ad51cSAlexander Kabaev } 413e18ad51cSAlexander Kabaev 4143aa4b42aSBaptiste Daroussin int 4153aa4b42aSBaptiste Daroussin main(__unused int argc, char *argv[]) 4163aa4b42aSBaptiste Daroussin { 4173aa4b42aSBaptiste Daroussin char pkgpath[MAXPATHLEN]; 4183aa4b42aSBaptiste Daroussin 4193aa4b42aSBaptiste Daroussin snprintf(pkgpath, MAXPATHLEN, "%s/sbin/pkg", 4203aa4b42aSBaptiste Daroussin getenv("LOCALBASE") ? getenv("LOCALBASE") : _LOCALBASE); 4213aa4b42aSBaptiste Daroussin 422e18ad51cSAlexander Kabaev if (access(pkgpath, X_OK) == -1) { 423e18ad51cSAlexander Kabaev /* 424e18ad51cSAlexander Kabaev * Do not ask for confirmation if either of stdin or stdout is 425e18ad51cSAlexander Kabaev * not tty. Check the environment to see if user has answer 426e18ad51cSAlexander Kabaev * tucked in there already. 427e18ad51cSAlexander Kabaev */ 4283a480126SBaptiste Daroussin if (getenv("ASSUME_ALWAYS_YES") == NULL) { 429e18ad51cSAlexander Kabaev printf("%s", confirmation_message); 430*204ea792SBaptiste Daroussin if (!isatty(fileno(stdin))) 4313a480126SBaptiste Daroussin exit(EXIT_FAILURE); 432*204ea792SBaptiste Daroussin 433*204ea792SBaptiste Daroussin if (pkg_query_yes_no() == 0) 434e18ad51cSAlexander Kabaev exit(EXIT_FAILURE); 435e18ad51cSAlexander Kabaev } 436a6454741SBaptiste Daroussin if (bootstrap_pkg() != 0) 437a6454741SBaptiste Daroussin exit(EXIT_FAILURE); 438e18ad51cSAlexander Kabaev } 4393aa4b42aSBaptiste Daroussin 4403aa4b42aSBaptiste Daroussin execv(pkgpath, argv); 4413aa4b42aSBaptiste Daroussin 442a6454741SBaptiste Daroussin /* NOT REACHED */ 4433b05c2a8SBaptiste Daroussin return (EXIT_FAILURE); 4443aa4b42aSBaptiste Daroussin } 445