Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 22 Aug 2012 08:27:37 +0000 (UTC)
From:      Baptiste Daroussin <bapt@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org
Subject:   svn commit: r239563 - in stable/8/usr.sbin: . pkg
Message-ID:  <201208220827.q7M8RbPm096132@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 <bsd.prog.mk>

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 <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
-#include <sys/types.h>
-#include <sys/wait.h>
 #include <sys/param.h>
 #include <sys/elf_common.h>
 #include <sys/endian.h>
+#include <sys/wait.h>
 
 #include <archive.h>
 #include <archive_entry.h>
@@ -39,24 +38,24 @@ __FBSDID("$FreeBSD$");
 #include <err.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <fetch.h>
 #include <gelf.h>
+#include <paths.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 #include <time.h>
 #include <unistd.h>
-#include <fetch.h>
 
 #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(&note, 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);
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201208220827.q7M8RbPm096132>