PERFORCE change 181439 for review
Garrett Cooper
gcooper at FreeBSD.org
Sun Jul 25 11:09:38 UTC 2010
On Sat, Jul 24, 2010 at 1:51 PM, Julien Laffaye <jlaffaye at freebsd.org> wrote:
> http://p4web.freebsd.org/@@181439?ac=10
>
> Change 181439 by jlaffaye at jlaffaye-chulak on 2010/07/24 20:51:13
>
> Add support for fetching packages. Read them on the fly thanks
> to libarchive(3) callbacks.
> Fix segfault by not plist_free'ing an unitialised plist.
Was this perhaps a problem with the structure not being NULL'ed out
after it was free'd?
> Affected files ...
>
> .. //depot/projects/soc2010/pkg_complete/lib/libpkg/pkg.h#7 edit
> .. //depot/projects/soc2010/pkg_complete/lib/libpkg/url.c#3 edit
> .. //depot/projects/soc2010/pkg_complete/usr.sbin/pkg_install/add/extract.c#6 edit
> .. //depot/projects/soc2010/pkg_complete/usr.sbin/pkg_install/add/perform.c#6 edit
>
> Differences ...
>
> ==== //depot/projects/soc2010/pkg_complete/lib/libpkg/pkg.h#7 (text+ko) ====
>
> @@ -33,6 +33,7 @@
> #include <sys/stat.h>
> #include <sys/queue.h>
> #include <sys/utsname.h>
> +#include <archive.h>
This should be moved down below all of the standard system headers
(libarchive might require some of the headers above.. fetch.h has
similar requirements)...
> #include <ctype.h>
> #include <dirent.h>
> #include <stdarg.h>
> @@ -144,6 +145,12 @@
> };
> STAILQ_HEAD(reqr_by_head, reqr_by_entry);
>
> +struct fetch_data {
> + FILE *ftp;
> + int pkgfd;
> + char buf[8192];
> +};
Using BUFSIZ might be a better idea.
> +
> /* Prototypes */
> /* Misc */
> int vsystem(const char *, ...);
> @@ -173,6 +180,8 @@
> Boolean issymlink(const char *);
> Boolean isURL(const char *);
> const char *fileGetURL(const char *, const char *, int);
> +int fetch_archive(struct archive *, const char *, const char *,
> + Boolean);
> char *fileFindByPath(const char *, const char *);
> char *fileGetContents(const char *);
> ssize_t write_file(const char *, const char *);
>
> ==== //depot/projects/soc2010/pkg_complete/lib/libpkg/url.c#3 (text+ko) ====
>
> @@ -23,15 +23,23 @@
>
> #include <sys/param.h>
> #include <sys/wait.h>
> +#include <archive.h>
> #include <err.h>
> +#include <errno.h>
> #include <libgen.h>
> #include <stdio.h>
> #include <fetch.h> /* NOTE: stdio must come before fetch. */
> #include "pkg.h"
>
> +static ssize_t archive_read_cb(struct archive *, void *, const void **);
> +static int archive_open_cb(struct archive *a, void *);
> +static int archive_close_cb(struct archive *, void *);
> +
> /*
> * Try and fetch a file by URL, returning the directory name for where
> * it's unpacked, if successful.
> + * XXX (jlaffaye): to be removed when all call to fileGetURL() are converted to
> + * fetch_archive()
> */
> const char *
> fileGetURL(const char *base, const char *spec, int keep_package)
> @@ -113,11 +121,11 @@
> fetchDebug = (Verbose > 0);
> if ((ftp = fetchGetURL(fname, Verbose ? "v" : NULL)) == NULL) {
> warnx("Error: Unable to get %s: %s\n", fname,
> - fetchLastErrString);
> + fetchLastErrString);
> /* If the fetch fails, yank the package. */
> if (keep_package && unlink(pkg) < 0) {
> warnx("failed to remove partially fetched package: %s",
> - pkg);
> + pkg);
> }
> return (NULL);
> }
> @@ -182,3 +190,170 @@
> return (rp);
>
> }
> +
> +/*
> + * Setup the archive `a' callbacks to read data from an URL `spec' via fetch(3).
> + * If `spec' is not an URL, the function try to find the location of the file
> + * via `base' or via the environment variable `PKG_ADD_BASE'.
> + * Returns 0 on success, 1 otherwise.
> + */
> +int
> +fetch_archive(struct archive *a, const char *base, const char *spec,
> + Boolean keep_package)
> +{
> + struct fetch_data *data = NULL;
> + char *cp, *hint, *tmp;
> + char fname[FILENAME_MAX];
> + char pkg[FILENAME_MAX];
> + int retcode = 0;
> +
> + if ((data = malloc(sizeof(struct fetch_data))) == NULL)
> + err(EXIT_FAILURE, "malloc()");
> +
> + if (!isURL(spec)) {
> + /*
> + * We've been given an existing URL (that's known-good) and now
> + * we need to construct a composite one out of that and the
> + * basename we were handed as a dependency.
> + */
> + if (base != NULL) {
> + strcpy(fname, base);
> + /*
> + * Advance back two slashes to get to the root of the
> + * package hierarchy
> + */
> + cp = strrchr(fname, '/');
> + if (cp) {
> + *cp = '\0'; /* chop name */
> + cp = strrchr(fname, '/');
> + }
> + if (cp != NULL) {
> + *(cp + 1) = '\0';
> + strcat(cp, "All/");
> + strcat(cp, spec);
> + strcat(cp, ".tbz");
> + } else {
> + retcode = 1;
> + goto cleanup;
> + }
> + }
> + /* Special tip that sysinstall left for us */
> + else if ((hint = getenv("PKG_ADD_BASE")) != NULL) {
> + /*
> + * Otherwise, we've been given an environment variable
> + * hinting at the right location from sysinstall
> + */
> + strcpy(fname, hint);
> + strcat(fname, spec);
> + strcat(fname, ".tbz");
> + }
> + /* We dont have an url and are unable to guess one */
> + else {
> + retcode = 1;
> + goto cleanup;
> + }
> + }
> + else
> + strcpy(fname, spec);
> +
> + if (keep_package) {
> + tmp = getenv("PKGDIR");
> + strlcpy(pkg, tmp ? tmp : ".", sizeof(pkg));
> + tmp = basename(fname);
> + strlcat(pkg, "/", sizeof(pkg));
> + strlcat(pkg, tmp, sizeof(pkg));
> +
> + data->pkgfd = open(pkg, O_WRONLY|O_CREAT|O_TRUNC, 0644);
> + if (data->pkgfd == -1) {
> + warn("Error: Unable to open %s", pkg);
> + retcode = 1;
> + goto cleanup;
> + }
> + } else
> + data->pkgfd = 0;
> +
> + fetchDebug = (Verbose > 0);
> + if ((data->ftp = fetchGetURL(fname, Verbose ? "v" : NULL)) == NULL) {
> + warnx("Error: Unable to get %s: %s\n", fname, fetchLastErrString);
> + /* If the fetch fails, yank the package. */
> + if (keep_package && unlink(pkg) < 0)
> + warnx("failed to remove partially fetched package: %s", pkg);
> + retcode = 1;
> + goto cleanup;
> + }
> +
> + if (isatty(0) || Verbose) {
> + printf("Fetching %s...", fname);
> + fflush(stdout);
> + }
> +
> + if (archive_read_open(a, data, archive_open_cb, archive_read_cb,
> + archive_close_cb) != ARCHIVE_OK) {
> + warnx("Can not open '%s': %s", pkg, archive_error_string(a));
> + retcode = 1;
> + goto cleanup;
> + }
> +
> + cleanup:
> + if (retcode == 1 && data != NULL)
> + free(data);
> +
> + return (retcode);
> +}
> +
> +/*
> + * Libarchive callback called when more data is needed.
> + * Read the data from the fetch(3) file descriptor and store it into buf
More information about the p4-projects
mailing list