Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
New update subcommand which fetches repo.txz found in PACKAGESITE env var
Baptiste Daroussin committed 15 years ago
commit 533f51f9a69285bd82e1f2363a696494058f7bf6
parent ea2c22d
6 files changed +173 -1
modified libpkg/fetch.c
@@ -7,6 +7,7 @@
#include <string.h>
#include <time.h>
#include <unistd.h>
+
#include <stdlib.h>
#include <fetch.h>

#include "pkg.h"
@@ -84,3 +85,59 @@ pkg_fetch_file(const char *url, const char *dest, void *data, fetch_cb cb)

	return (retcode);
}
+

+
int
+
pkg_fetch_buffer(const char *url, char **buffer, void *data, fetch_cb cb)
+
{
+
	FILE *remote = NULL;
+
	struct url_stat st;
+
	off_t done = 0;
+
	off_t r;
+
	int retry = 3;
+
	time_t begin_dl;
+
	time_t now;
+
	time_t last = 0;
+
	int retcode = EPKG_OK;
+

+
	while (remote == NULL) {
+
		remote = fetchXGetURL(url, &st, "");
+
		if (remote == NULL) {
+
			--retry;
+
			if (retry == 0) {
+
				pkg_error_set(EPKG_FATAL, "%s", fetchLastErrString);
+
				goto cleanup;
+
			}
+
			sleep(1);
+
		}
+
	}
+

+
	*buffer = malloc(st.size + 1);
+

+
	begin_dl = time(NULL);
+
	while (done < st.size) {
+
		if ((r = fread(*buffer + done, 1, 10240, remote)) < 1)
+
			break;
+

+
		done += r;
+

+
		now = time(NULL);
+
		/* Only call the callback every second */
+

+
		if (cb != NULL && (now > last || done == st.size)) {
+
			cb(data, url, st.size, done, (now - begin_dl));
+
			last = now;
+
		}
+
	}
+

+
	if (ferror(remote)) {
+
		retcode = pkg_error_set(EPKG_FATAL, "%s", fetchLastErrString);
+
		goto cleanup;
+
	}
+

+
	cleanup:
+

+
	if (remote != NULL)
+
		fclose(remote);
+

+
	return (retcode);
+
}
modified libpkg/pkg.h
@@ -477,6 +477,11 @@ typedef void (*fetch_cb)(void *data, const char *url, off_t total, off_t done,
 * @return An error code.
 */
int pkg_fetch_file(const char *url, const char *dest, void *data, fetch_cb cb);
+
/**
+
 * Fetch to a given buffer
+
 * @return An error code
+
 */
+
int pkg_fetch_buffer(const char *url, char **buf, void *data, fetch_cb cb);

/* glue to deal with ports */
int ports_parse_plist(struct pkg *, char *);
modified pkg/Makefile
@@ -6,6 +6,7 @@ SRCS= add.c \
		main.c \
		register.c \
		repo.c \
+
		update.c \
		version.c \
		which.c
BINDIR=		/usr/sbin
modified pkg/main.c
@@ -11,6 +11,7 @@
#include "which.h"
#include "add.h"
#include "version.h"
+
#include "update.h"
#include "register.h"
#include "repo.h"

@@ -30,7 +31,7 @@ static struct commands {
	{ "info", exec_info, usage_info},
	{ "register", exec_register, usage_register},
	{ "repo", exec_repo, usage_repo},
-
	{ "update", NULL, NULL},
+
	{ "update", exec_update, usage_update},
	{ "upgrade", NULL, NULL},
	{ "version", exec_version, usage_version},
	{ "which", exec_which, usage_which},
added pkg/update.c
@@ -0,0 +1,101 @@
+
#include <sys/param.h>
+
#include <sys/types.h>
+

+
#include <err.h>
+
#include <stdlib.h>
+
#include <stdio.h>
+
#include <sysexits.h>
+
#include <unistd.h>
+
#include <string.h>
+
#include <fcntl.h>
+

+
#include <archive.h>
+
#include <archive_entry.h>
+

+
#include <pkg.h>
+

+
#include "update.h"
+

+
#define EXTRACT_ARCHIVE_FLAGS  (ARCHIVE_EXTRACT_OWNER |ARCHIVE_EXTRACT_PERM| \
+
		ARCHIVE_EXTRACT_TIME  |ARCHIVE_EXTRACT_ACL | \
+
		ARCHIVE_EXTRACT_FFLAGS|ARCHIVE_EXTRACT_XATTR)
+

+
static void
+
fetch_status(void *data, const char *url, off_t total, off_t done, time_t elapsed)
+
{
+
	unsigned int percent;
+

+
	elapsed = 0;
+

+
	int *size = (int *)data;
+
	*size = total;
+
	percent = ((float)done / (float)total) * 100;
+
	printf("\rFetching %s... %d%%", url, percent);
+

+
	if (done == total)
+
		printf("\n");
+

+
	fflush(stdout);
+
}
+

+
void
+
usage_update(void)
+
{
+
	fprintf(stderr, "usage pkg update\n\n");
+
	fprintf(stderr, "For more information see 'pkg help update'.\n");
+
}
+

+
int
+
exec_update(int argc, char **argv)
+
{
+
	char url[MAXPATHLEN];
+
	char *packagesite = NULL;
+
	int retcode = 0;
+
	int size = 0;
+
	char *repo;
+
	struct archive *a;
+
	struct archive_entry *ae;
+

+
	(void)argv;
+
	if (argc != 1) {
+
		usage_update();
+
		return (-1);
+
	}
+

+
	if (geteuid() != 0) {
+
		warnx("updating the remote database can only be done as root");
+
		return (EX_NOPERM);
+
	}
+

+
	packagesite = getenv("PACKAGESITE");
+

+
	if (packagesite == NULL)
+
		return (-2);
+

+
	if (packagesite[strlen(packagesite) - 1] == '/')
+
		snprintf(url, MAXPATHLEN, "%srepo.txz", packagesite);
+
	else
+
		snprintf(url, MAXPATHLEN, "%s/repo.txz", packagesite);
+

+
	if (pkg_fetch_buffer(url, &repo, &size, &fetch_status) != EPKG_OK) {
+
		pkg_error_warn("can not fetch %s", url);
+
		retcode = 1;
+
	}
+

+
	a = archive_read_new();
+
	archive_read_support_compression_all(a);
+
	archive_read_support_format_tar(a);
+

+
	archive_read_open_memory(a, repo, size);
+

+
	while (archive_read_next_header(a, &ae) == ARCHIVE_OK) {
+
		if (strcmp(archive_entry_pathname(ae), "repo.sqlite") == 0) {
+
			archive_entry_set_pathname(ae, "/var/db/pkg/repo.sqlite");
+
			archive_read_extract(a, ae, EXTRACT_ARCHIVE_FLAGS);
+
			break;
+
		}
+
	}
+

+
	archive_read_finish(a);
+
	return (retcode);
+
}
added pkg/update.h
@@ -0,0 +1,7 @@
+
#ifndef _UPDATE_H
+
#define _UPDATE_H
+

+
int exec_update(int, char **);
+
void usage_update(void);
+
#endif
+