From owner-svn-src-stable-8@FreeBSD.ORG Wed Aug 22 08:27:37 2012 Return-Path: Delivered-To: svn-src-stable-8@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id C73D4106564A; Wed, 22 Aug 2012 08:27:37 +0000 (UTC) (envelope-from bapt@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id A7FC48FC14; Wed, 22 Aug 2012 08:27:37 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q7M8Rb5a096137; Wed, 22 Aug 2012 08:27:37 GMT (envelope-from bapt@svn.freebsd.org) Received: (from bapt@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q7M8RbPm096132; Wed, 22 Aug 2012 08:27:37 GMT (envelope-from bapt@svn.freebsd.org) Message-Id: <201208220827.q7M8RbPm096132@svn.freebsd.org> From: Baptiste Daroussin Date: Wed, 22 Aug 2012 08:27:37 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org X-SVN-Group: stable-8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r239563 - in stable/8/usr.sbin: . pkg X-BeenThere: svn-src-stable-8@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for only the 8-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 22 Aug 2012 08:27:37 -0000 Author: bapt Date: Wed Aug 22 08:27:37 2012 New Revision: 239563 URL: http://svn.freebsd.org/changeset/base/239563 Log: MFC: r234313,234315,234322,234351,234870,235726,238461 add usr.sbin/pkg which is a bootstrap tool for pkgng. it respects PACKAGESITE, PACKAGEROOT, and a new environment variable ABI (if a user want to use a different API from the base one for its packages) it has no man page on purpose to avoid hidding the pkg(8) man page from the pkgng package. for now uses pkgbeta.FreeBSD.org as default mirror to find its package it respects MK_PKGTOOLS Added: - copied from r234313, head/usr.sbin/pkg/ Directory Properties: stable/8/usr.sbin/pkg/ (props changed) Modified: stable/8/usr.sbin/Makefile (contents, props changed) stable/8/usr.sbin/pkg/Makefile stable/8/usr.sbin/pkg/pkg.c Directory Properties: stable/8/usr.sbin/ (props changed) Modified: stable/8/usr.sbin/Makefile ============================================================================== --- stable/8/usr.sbin/Makefile Wed Aug 22 06:37:30 2012 (r239562) +++ stable/8/usr.sbin/Makefile Wed Aug 22 08:27:37 2012 (r239563) @@ -364,6 +364,7 @@ _ftp-proxy= ftp-proxy .if ${MK_PKGTOOLS} != "no" _pkg_install= pkg_install +SUBDIR+= pkg .endif # XXX MK_TOOLCHAIN? Modified: stable/8/usr.sbin/pkg/Makefile ============================================================================== --- head/usr.sbin/pkg/Makefile Sun Apr 15 15:13:36 2012 (r234313) +++ stable/8/usr.sbin/pkg/Makefile Wed Aug 22 08:27:37 2012 (r239563) @@ -4,6 +4,7 @@ PROG= pkg SRC= pkg.c NO_MAN= yes +DPADD= ${LIBARCHIVE} ${LIBELF} ${LIBFETCH} LDADD= -larchive -lelf -lfetch .include Modified: stable/8/usr.sbin/pkg/pkg.c ============================================================================== --- head/usr.sbin/pkg/pkg.c Sun Apr 15 15:13:36 2012 (r234313) +++ stable/8/usr.sbin/pkg/pkg.c Wed Aug 22 08:27:37 2012 (r239563) @@ -27,11 +27,10 @@ #include __FBSDID("$FreeBSD$"); -#include -#include #include #include #include +#include #include #include @@ -39,24 +38,24 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include +#include #include #include #include #include #include -#include #include "elf_tables.h" #define _LOCALBASE "/usr/local" #define _PKGS_URL "http://pkgbeta.FreeBSD.org" -#define _DEFAULT_TMP "/tmp" static const char * -elf_corres_to_string(struct _elf_corres* m, int e) +elf_corres_to_string(struct _elf_corres *m, int e) { - int i = 0; + int i; for (i = 0; m[i].string != NULL; i++) if (m[i].elf_nb == e) @@ -69,29 +68,30 @@ static int pkg_get_myabi(char *dest, size_t sz) { Elf *elf; - GElf_Ehdr elfhdr; - GElf_Shdr shdr; Elf_Data *data; Elf_Note note; Elf_Scn *scn; char *src, *osname; const char *abi; + GElf_Ehdr elfhdr; + GElf_Shdr shdr; int fd, i, ret; uint32_t version; version = 0; - ret = 0; + ret = -1; scn = NULL; abi = NULL; if (elf_version(EV_CURRENT) == EV_NONE) { - warnx("ELF library initialization failed: %s", elf_errmsg(-1)); - return -1; + warnx("ELF library initialization failed: %s", + elf_errmsg(-1)); + return (-1); } if ((fd = open("/bin/sh", O_RDONLY)) < 0) { warn("open()"); - return -1; + return (-1); } if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) { @@ -119,13 +119,13 @@ pkg_get_myabi(char *dest, size_t sz) if (scn == NULL) { ret = -1; - warn("fail to get the note section"); + warn("failed to get the note section"); goto cleanup; } data = elf_getdata(scn, NULL); src = data->d_buf; - while (1) { + for (;;) { memcpy(¬e, src, sizeof(Elf_Note)); src += sizeof(Elf_Note); if (note.n_type == NT_VERSION) @@ -143,52 +143,50 @@ pkg_get_myabi(char *dest, size_t sz) osname[i] = (char)tolower(osname[i]); snprintf(dest, sz, "%s:%d:%s:%s", - osname, - version / 100000, - elf_corres_to_string(mach_corres, (int) elfhdr.e_machine), + osname, version / 100000, + elf_corres_to_string(mach_corres, (int)elfhdr.e_machine), elf_corres_to_string(wordsize_corres, - (int)elfhdr.e_ident[EI_CLASS])); + (int)elfhdr.e_ident[EI_CLASS])); + + ret = 0; switch (elfhdr.e_machine) { - case EM_ARM: - snprintf(dest + strlen(dest), sz - strlen(dest), - ":%s:%s:%s", - elf_corres_to_string(endian_corres, - (int) elfhdr.e_ident[EI_DATA]), - (elfhdr.e_flags & EF_ARM_NEW_ABI) > 0 ? - "eabi" : "oabi", - (elfhdr.e_flags & EF_ARM_VFP_FLOAT) > 0 ? - "softfp" : "vfp"); + case EM_ARM: + snprintf(dest + strlen(dest), sz - strlen(dest), + ":%s:%s:%s", elf_corres_to_string(endian_corres, + (int)elfhdr.e_ident[EI_DATA]), + (elfhdr.e_flags & EF_ARM_NEW_ABI) > 0 ? + "eabi" : "oabi", + (elfhdr.e_flags & EF_ARM_VFP_FLOAT) > 0 ? + "softfp" : "vfp"); + break; + case EM_MIPS: + /* + * this is taken from binutils sources: + * include/elf/mips.h + * mapping is figured out from binutils: + * gas/config/tc-mips.c + */ + switch (elfhdr.e_flags & EF_MIPS_ABI) { + case E_MIPS_ABI_O32: + abi = "o32"; break; - case EM_MIPS: - /* - * this is taken from binutils sources: - * include/elf/mips.h - * mapping is figured out from binutils: - * gas/config/tc-mips.c - */ - switch (elfhdr.e_flags & EF_MIPS_ABI) { - case E_MIPS_ABI_O32: - abi = "o32"; - break; - case E_MIPS_ABI_N32: - abi = "n32"; - break; - default: - if (elfhdr.e_ident[EI_DATA] == - ELFCLASS32) - abi = "o32"; - else if (elfhdr.e_ident[EI_DATA] == - ELFCLASS64) - abi = "n64"; - break; - } - snprintf(dest + strlen(dest), sz - strlen(dest), - ":%s:%s", - elf_corres_to_string(endian_corres, - (int) elfhdr.e_ident[EI_DATA]), - abi); + case E_MIPS_ABI_N32: + abi = "n32"; + break; + default: + if (elfhdr.e_ident[EI_DATA] == + ELFCLASS32) + abi = "o32"; + else if (elfhdr.e_ident[EI_DATA] == + ELFCLASS64) + abi = "n64"; break; + } + snprintf(dest + strlen(dest), sz - strlen(dest), + ":%s:%s", elf_corres_to_string(endian_corres, + (int)elfhdr.e_ident[EI_DATA]), abi); + break; } cleanup: @@ -207,17 +205,22 @@ extract_pkg_static(int fd, char *p, int char *end; int ret, r; - ret = 0; + ret = -1; a = archive_read_new(); + if (a == NULL) { + warn("archive_read_new"); + return (ret); + } archive_read_support_compression_all(a); archive_read_support_format_tar(a); - lseek(fd, 0, 0); + if (lseek(fd, 0, 0) == -1) { + warn("lseek"); + goto cleanup; + } if (archive_read_open_fd(a, fd, 4096) != ARCHIVE_OK) { - warnx("archive_read_open_fd: %s", - archive_error_string(a)); - ret = -1; + warnx("archive_read_open_fd: %s", archive_error_string(a)); goto cleanup; } @@ -229,22 +232,22 @@ extract_pkg_static(int fd, char *p, int if (strcmp(end, "/pkg-static") == 0) { r = archive_read_extract(a, ae, - ARCHIVE_EXTRACT_OWNER |ARCHIVE_EXTRACT_PERM| - ARCHIVE_EXTRACT_TIME |ARCHIVE_EXTRACT_ACL | - ARCHIVE_EXTRACT_FFLAGS|ARCHIVE_EXTRACT_XATTR); - snprintf(p, sz, archive_entry_pathname(ae)); + ARCHIVE_EXTRACT_OWNER | ARCHIVE_EXTRACT_PERM | + ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_ACL | + ARCHIVE_EXTRACT_FFLAGS | ARCHIVE_EXTRACT_XATTR); + strlcpy(p, archive_entry_pathname(ae), sz); break; } } - if (r != ARCHIVE_OK) { + if (r == ARCHIVE_OK) + ret = 0; + else warnx("fail to extract pkg-static"); - ret = -1; - } cleanup: archive_read_finish(a); - return ret; + return (ret); } @@ -255,129 +258,185 @@ install_pkg_static(char *path, char *pkg pid_t pid; switch ((pid = fork())) { - case -1: - return (-1); - case 0: - execl(path, "pkg-static", "add", pkgpath, (char *)NULL); - _exit(1); /* NOT REACHED */ - default: - break; + case -1: + return (-1); + case 0: + execl(path, "pkg-static", "add", pkgpath, (char *)NULL); + _exit(1); + default: + break; } - while (waitpid(pid, &pstat, 0) == -1) { + while (waitpid(pid, &pstat, 0) == -1) if (errno != EINTR) return (-1); - } - return (WEXITSTATUS(pstat)); + if (WEXITSTATUS(pstat)) + return (WEXITSTATUS(pstat)); + else if (WIFSIGNALED(pstat)) + return (128 & (WTERMSIG(pstat))); + return (pstat); } static int bootstrap_pkg(void) { - struct url_stat st; FILE *remote; - time_t begin_dl; - time_t now; - time_t last = 0; + FILE *config; + char *site; char url[MAXPATHLEN]; + char conf[MAXPATHLEN]; char abi[BUFSIZ]; char tmppkg[MAXPATHLEN]; char buf[10240]; char pkgstatic[MAXPATHLEN]; int fd, retry, ret; + struct url_stat st; off_t done, r; + time_t now; + time_t last; done = 0; - ret = 0; - retry = 3; + last = 0; + ret = -1; remote = NULL; + config = NULL; - printf("Bootstraping pkg please wait\n"); + printf("Bootstrapping pkg please wait\n"); if (pkg_get_myabi(abi, MAXPATHLEN) != 0) { - warnx("fail to determine my abi"); - return -1; + warnx("failed to determine the system ABI"); + return (-1); } - if (getenv("PACKAGESITE") != NULL) { - snprintf(url, MAXPATHLEN, "%s/pkg.txz", - getenv("PACKAGESITE")); - } else { + if (getenv("PACKAGESITE") != NULL) + snprintf(url, MAXPATHLEN, "%s/Latest/pkg.txz", getenv("PACKAGESITE")); + else snprintf(url, MAXPATHLEN, "%s/%s/latest/Latest/pkg.txz", getenv("PACKAGEROOT") ? getenv("PACKAGEROOT") : _PKGS_URL, getenv("ABI") ? getenv("ABI") : abi); - } snprintf(tmppkg, MAXPATHLEN, "%s/pkg.txz.XXXXXX", - getenv("TMPDIR") ? getenv("TMPDIR") : "/tmp"); + getenv("TMPDIR") ? getenv("TMPDIR") : _PATH_TMP); if ((fd = mkstemp(tmppkg)) == -1) { warn("mkstemp()"); - return -1; + return (-1); } - while (remote == NULL) { + retry = 3; + do { remote = fetchXGetURL(url, &st, ""); - if (remote == NULL) { - --retry; - if (retry == 0) { - warnx("Error fetching %s: %s", url, - fetchLastErrString); - ret = 1; - goto cleanup; - } + if (remote == NULL) sleep(1); - } - } + } while (remote == NULL && retry-- > 0); + + if (remote == NULL) + goto fetchfail; - begin_dl = time(NULL); while (done < st.size) { if ((r = fread(buf, 1, sizeof(buf), remote)) < 1) break; if (write(fd, buf, r) != r) { warn("write()"); - ret = -1; goto cleanup; } done += r; now = time(NULL); - if (now > last || done == st.size) { + if (now > last || done == st.size) last = now; - } } - if (ferror(remote)) { - warnx("Error fetching %s: %s", url, - fetchLastErrString); - ret = 1; - goto cleanup; - } + if (ferror(remote)) + goto fetchfail; if ((ret = extract_pkg_static(fd, pkgstatic, MAXPATHLEN)) == 0) ret = install_pkg_static(pkgstatic, tmppkg); + snprintf(conf, MAXPATHLEN, "%s/etc/pkg.conf", + getenv("LOCALBASE") ? getenv("LOCALBASE") : _LOCALBASE); + + if (access(conf, R_OK) == -1) { + site = strrchr(url, '/'); + if (site == NULL) + goto cleanup; + site[0] = '\0'; + site = strrchr(url, '/'); + if (site == NULL) + goto cleanup; + site[0] = '\0'; + + config = fopen(conf, "w+"); + if (config == NULL) + goto cleanup; + fprintf(config, "packagesite: %s\n", url); + fclose(config); + } + + goto cleanup; + +fetchfail: + warnx("Error fetching %s: %s", url, fetchLastErrString); + cleanup: + if (remote != NULL) + fclose(remote); close(fd); unlink(tmppkg); - return 0; + return (ret); +} + +static const char confirmation_message[] = +"The package management tool is not yet installed on your system.\n" +"Do you want to fetch and install it now? [y/N]: "; + +static int +pkg_query_yes_no(void) +{ + int ret, c; + + c = getchar(); + + if (c == 'y' || c == 'Y') + ret = 1; + else + ret = 0; + + while (c != '\n' && c != EOF) + c = getchar(); + + return (ret); } int -main(__unused int argc, char * argv[]) +main(__unused int argc, char *argv[]) { char pkgpath[MAXPATHLEN]; snprintf(pkgpath, MAXPATHLEN, "%s/sbin/pkg", - getenv("LOCALBASE") ? getenv("LOCALBASE"): _LOCALBASE); + getenv("LOCALBASE") ? getenv("LOCALBASE") : _LOCALBASE); - if (access(pkgpath, X_OK) == -1) - bootstrap_pkg(); + if (access(pkgpath, X_OK) == -1) { + /* + * Do not ask for confirmation if either of stdin or stdout is + * not tty. Check the environment to see if user has answer + * tucked in there already. + */ + if (getenv("ALWAYS_ASSUME_YES") == NULL && + isatty(fileno(stdin))) { + printf("%s", confirmation_message); + if (pkg_query_yes_no() == 0) + exit(EXIT_FAILURE); + } + if (bootstrap_pkg() != 0) + exit(EXIT_FAILURE); + } execv(pkgpath, argv); - return (EXIT_SUCCESS); + /* NOT REACHED */ + return (EXIT_FAILURE); }