Radish alpha
H
HardenedBSD Package Manager
Radicle
Git (anonymous pull)
Log in to clone via SSH
New update subcommand which fetches repo.txz found in PACKAGESITE env var
Baptiste Daroussin committed 15 years ago
commit 533f51f9a69285bd82e1f2363a696494058f7bf6
parent ea2c22d39c6070823eb91bc2bc46f02a359b6f5b
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
+