summaryrefslogtreecommitdiffstats
path: root/usr.sbin/pkg
diff options
context:
space:
mode:
authorobrien <obrien@FreeBSD.org>2013-02-08 16:10:16 +0000
committerobrien <obrien@FreeBSD.org>2013-02-08 16:10:16 +0000
commit3028e3f8aba938dfd0bf9fda987b8a72140b8027 (patch)
treeb2f038222ff8a70f687652441df00d2b564c8abe /usr.sbin/pkg
parent952a6d5a7cd3d3f9007acfa06805262fc04a105f (diff)
parent1d08d5f677c1dfa810e381073590adbae19cc69f (diff)
downloadFreeBSD-src-3028e3f8aba938dfd0bf9fda987b8a72140b8027.zip
FreeBSD-src-3028e3f8aba938dfd0bf9fda987b8a72140b8027.tar.gz
Sync with HEAD.
Diffstat (limited to 'usr.sbin/pkg')
-rw-r--r--usr.sbin/pkg/Makefile2
-rw-r--r--usr.sbin/pkg/dns_utils.c135
-rw-r--r--usr.sbin/pkg/dns_utils.h45
-rw-r--r--usr.sbin/pkg/pkg.c56
4 files changed, 229 insertions, 9 deletions
diff --git a/usr.sbin/pkg/Makefile b/usr.sbin/pkg/Makefile
index 360e301..c2ca0a3 100644
--- a/usr.sbin/pkg/Makefile
+++ b/usr.sbin/pkg/Makefile
@@ -1,7 +1,7 @@
# $FreeBSD$
PROG= pkg
-SRC= pkg.c
+SRCS= pkg.c dns_utils.c
NO_MAN= yes
DPADD= ${LIBARCHIVE} ${LIBELF} ${LIBFETCH}
diff --git a/usr.sbin/pkg/dns_utils.c b/usr.sbin/pkg/dns_utils.c
new file mode 100644
index 0000000..239be90
--- /dev/null
+++ b/usr.sbin/pkg/dns_utils.c
@@ -0,0 +1,135 @@
+/*-
+ * Copyright (c) 2012 Baptiste Daroussin <bapt@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer,
+ * without modification, immediately at the beginning of the file.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdlib.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <resolv.h>
+
+#include "dns_utils.h"
+
+typedef union {
+ HEADER hdr;
+ unsigned char buf[1024];
+} dns_query;
+
+struct dns_srvinfo *
+dns_getsrvinfo(const char *zone)
+{
+ struct dns_srvinfo **res, *first;
+ unsigned char *end, *p;
+ char host[MAXHOSTNAMELEN];
+ dns_query q;
+ int len, qdcount, ancount, n, i;
+ unsigned int type, class, ttl, priority, weight, port;
+
+ if ((len = res_query(zone, C_IN, T_SRV, q.buf, sizeof(q.buf))) == -1 ||
+ len < (int)sizeof(HEADER))
+ return (NULL);
+
+ qdcount = ntohs(q.hdr.qdcount);
+ ancount = ntohs(q.hdr.ancount);
+
+ end = q.buf + len;
+ p = q.buf + sizeof(HEADER);
+
+ while(qdcount > 0 && p < end) {
+ qdcount--;
+ if((len = dn_expand(q.buf, end, p, host, MAXHOSTNAMELEN)) < 0)
+ return (NULL);
+ p += len + NS_QFIXEDSZ;
+ }
+
+ res = calloc(ancount, sizeof(struct dns_srvinfo));
+ if (res == NULL)
+ return (NULL);
+
+ n = 0;
+ while (ancount > 0 && p < end) {
+ ancount--;
+ len = dn_expand(q.buf, end, p, host, MAXHOSTNAMELEN);
+ if (len < 0) {
+ for (i = 0; i < n; i++)
+ free(res[i]);
+ free(res);
+ return NULL;
+ }
+
+ p += len;
+
+ NS_GET16(type, p);
+ NS_GET16(class, p);
+ NS_GET32(ttl, p);
+ NS_GET16(len, p);
+
+ if (type != T_SRV) {
+ p += len;
+ continue;
+ }
+
+ NS_GET16(priority, p);
+ NS_GET16(weight, p);
+ NS_GET16(port, p);
+
+ len = dn_expand(q.buf, end, p, host, MAXHOSTNAMELEN);
+ if (len < 0) {
+ for (i = 0; i < n; i++)
+ free(res[i]);
+ free(res);
+ return (NULL);
+ }
+
+ res[n] = malloc(sizeof(struct dns_srvinfo));
+ if (res[n] == NULL) {
+ for (i = 0; i < n; i++)
+ free(res[i]);
+ free(res);
+ return (NULL);
+ }
+ res[n]->type = type;
+ res[n]->class = class;
+ res[n]->ttl = ttl;
+ res[n]->priority = priority;
+ res[n]->weight = weight;
+ res[n]->port = port;
+ res[n]->next = NULL;
+ strlcpy(res[n]->host, host, MAXHOSTNAMELEN);
+
+ p += len;
+ n++;
+ }
+
+ for (i = 0; i < n - 1; i++)
+ res[i]->next = res[i + 1];
+
+ first = res[0];
+ free(res);
+
+ return (first);
+}
diff --git a/usr.sbin/pkg/dns_utils.h b/usr.sbin/pkg/dns_utils.h
new file mode 100644
index 0000000..0f3367b
--- /dev/null
+++ b/usr.sbin/pkg/dns_utils.h
@@ -0,0 +1,45 @@
+/*-
+ * Copyright (c) 2012 Baptiste Daroussin <bapt@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef DNS_UTILS_H
+#define DNS_UTILS_H
+struct dns_srvinfo {
+ unsigned int type;
+ unsigned int class;
+ unsigned int ttl;
+ unsigned int priority;
+ unsigned int weight;
+ unsigned int port;
+ char host[MAXHOSTNAMELEN];
+ struct dns_srvinfo *next;
+};
+
+struct dns_srvinfo *
+ dns_getsrvinfo(const char *zone);
+
+#endif
diff --git a/usr.sbin/pkg/pkg.c b/usr.sbin/pkg/pkg.c
index 8dc7bcf..1b3146b 100644
--- a/usr.sbin/pkg/pkg.c
+++ b/usr.sbin/pkg/pkg.c
@@ -48,9 +48,10 @@ __FBSDID("$FreeBSD$");
#include <unistd.h>
#include "elf_tables.h"
+#include "dns_utils.h"
#define _LOCALBASE "/usr/local"
-#define _PKGS_URL "http://pkgbeta.FreeBSD.org"
+#define _PKGS_URL "http://pkg.FreeBSD.org"
static const char *
elf_corres_to_string(struct _elf_corres *m, int e)
@@ -281,16 +282,20 @@ install_pkg_static(char *path, char *pkgpath)
static int
bootstrap_pkg(void)
{
+ struct url *u;
FILE *remote;
FILE *config;
char *site;
+ struct dns_srvinfo *mirrors, *current;
+ /* To store _https._tcp. + hostname + \0 */
+ char zone[MAXHOSTNAMELEN + 13];
char url[MAXPATHLEN];
char conf[MAXPATHLEN];
char abi[BUFSIZ];
char tmppkg[MAXPATHLEN];
char buf[10240];
char pkgstatic[MAXPATHLEN];
- int fd, retry, ret;
+ int fd, retry, ret, max_retry;
struct url_stat st;
off_t done, r;
time_t now;
@@ -298,9 +303,11 @@ bootstrap_pkg(void)
done = 0;
last = 0;
+ max_retry = 3;
ret = -1;
remote = NULL;
config = NULL;
+ current = mirrors = NULL;
printf("Bootstrapping pkg please wait\n");
@@ -324,12 +331,37 @@ bootstrap_pkg(void)
return (-1);
}
- retry = 3;
- do {
- remote = fetchXGetURL(url, &st, "");
- if (remote == NULL)
- sleep(1);
- } while (remote == NULL && retry-- > 0);
+ retry = max_retry;
+
+ u = fetchParseURL(url);
+ while (remote == NULL) {
+ if (retry == max_retry) {
+ if (strcmp(u->scheme, "file") != 0) {
+ snprintf(zone, sizeof(zone),
+ "_%s._tcp.%s", u->scheme, u->host);
+ printf("%s\n", zone);
+ mirrors = dns_getsrvinfo(zone);
+ current = mirrors;
+ }
+ }
+
+ if (mirrors != NULL)
+ strlcpy(u->host, current->host, sizeof(u->host));
+
+ remote = fetchXGet(u, &st, "");
+ if (remote == NULL) {
+ --retry;
+ if (retry <= 0)
+ goto fetchfail;
+ if (mirrors == NULL) {
+ sleep(1);
+ } else {
+ current = current->next;
+ if (current == NULL)
+ current = mirrors;
+ }
+ }
+ }
if (remote == NULL)
goto fetchfail;
@@ -420,6 +452,14 @@ main(__unused int argc, char *argv[])
getenv("LOCALBASE") ? getenv("LOCALBASE") : _LOCALBASE);
if (access(pkgpath, X_OK) == -1) {
+ /*
+ * To allow 'pkg -N' to be used as a reliable test for whether
+ * a system is configured to use pkg, don't bootstrap pkg
+ * when that argument is given as argv[1].
+ */
+ if (argv[1] != NULL && strcmp(argv[1], "-N") == 0)
+ errx(EXIT_FAILURE, "pkg is not installed");
+
/*
* Do not ask for confirmation if either of stdin or stdout is
* not tty. Check the environment to see if user has answer
OpenPOWER on IntegriCloud