svn commit: r239563 - in stable/8/usr.sbin: . pkg
Baptiste Daroussin
bapt at FreeBSD.org
Wed Aug 22 08:27:37 UTC 2012
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(¬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);
}
More information about the svn-src-stable-8
mailing list