From owner-p4-projects@FreeBSD.ORG Sun Jul 25 12:52:21 2010 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 211551065687; Sun, 25 Jul 2010 12:52:21 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id D80C7106567C; Sun, 25 Jul 2010 12:52:20 +0000 (UTC) (envelope-from julien.laffaye@gmail.com) Received: from mail-bw0-f54.google.com (mail-bw0-f54.google.com [209.85.214.54]) by mx1.freebsd.org (Postfix) with ESMTP id 43CDF8FC25; Sun, 25 Jul 2010 12:52:19 +0000 (UTC) Received: by bwz12 with SMTP id 12so2748328bwz.13 for ; Sun, 25 Jul 2010 05:52:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:mime-version:received:sender:received :in-reply-to:references:date:x-google-sender-auth:message-id:subject :from:to:cc:content-type:content-transfer-encoding; bh=Leql3CYuzJNM7yuqvJbj8k8VElvX0KuTMH6QN0wC4fs=; b=Lt4BA2hcGRlqQxryARd/104rUQGkBgMUcleWbRs9nixErgnCU6qXEhyL/7Cq04YvND 0A1/ZlkSOfV07jf6uCSQGi87dwYAedTAUZvs+nK6Tk4TdveuXwap/IuTMpU+cSyqhhSO t6l9bowqrj3qDRtmEGuB+KgA1YP0bLL1tQzJ4= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:sender:in-reply-to:references:date :x-google-sender-auth:message-id:subject:from:to:cc:content-type :content-transfer-encoding; b=bRPp3lIefWKrf7+0H15Wwx5m+WQVqGrO/YMugYlfn7V4IHOSKmMc6f6nJ58n/EWBqS eIgZKoy6hGd8HXeM6QKQHOtkW23K31P+opJHPXxbT3r1/Ib5vKwUQ7CZq8mdK3n9D5nL nXCgRPD7OUY2xXZPEBa8ydfmgcU5formxn7RI= MIME-Version: 1.0 Received: by 10.204.126.205 with SMTP id d13mr4547031bks.126.1280062338874; Sun, 25 Jul 2010 05:52:18 -0700 (PDT) Sender: julien.laffaye@gmail.com Received: by 10.204.48.27 with HTTP; Sun, 25 Jul 2010 05:52:18 -0700 (PDT) In-Reply-To: References: <201007242051.o6OKpF5t030159@repoman.freebsd.org> Date: Sun, 25 Jul 2010 14:52:18 +0200 X-Google-Sender-Auth: SAxJRFmKuk0MGSoCdyy8DulSXFM Message-ID: From: Julien LAFFAYE To: Garrett Cooper Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Cc: Perforce Change Reviews Subject: Re: PERFORCE change 181439 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 25 Jul 2010 12:52:21 -0000 On Sun, Jul 25, 2010 at 1:09 PM, Garrett Cooper wrote= : > On Sat, Jul 24, 2010 at 1:51 PM, Julien Laffaye wr= ote: >> http://p4web.freebsd.org/@@181439?ac=3D10 >> >> Change 181439 by jlaffaye@jlaffaye-chulak on 2010/07/24 20:51:13 >> >> =A0 =A0 =A0 =A0Add support for fetching packages. Read them on the fly t= hanks >> =A0 =A0 =A0 =A0to libarchive(3) callbacks. >> =A0 =A0 =A0 =A0Fix 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? Actually, on a particular error I was trying to cleanup the plist, but it was not initialized yet. So pkg.head contained an arbitrary value (but not NULL), so plist_free() started to follow this memory address... which was indeed garbage. > >> 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/extrac= t.c#6 edit >> .. //depot/projects/soc2010/pkg_complete/usr.sbin/pkg_install/add/perfor= m.c#6 edit >> >> Differences ... >> >> =3D=3D=3D=3D //depot/projects/soc2010/pkg_complete/lib/libpkg/pkg.h#7 (t= ext+ko) =3D=3D=3D=3D >> >> @@ -33,6 +33,7 @@ >> =A0#include >> =A0#include >> =A0#include >> +#include > > 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)... >From style(9), I can read: "Leave a blank line before the next group, the /usr/include files, which should be sorted alphabetically by name". But that's right, fetch(3) uses FILE which is defined in So I guess the point here is 'standard' as in C standard or as in "shipped with base". Anyway, I must admit that the advised blank line is missing here ;p > >> =A0#include >> =A0#include >> =A0#include >> @@ -144,6 +145,12 @@ >> =A0}; >> =A0STAILQ_HEAD(reqr_by_head, reqr_by_entry); >> >> +struct fetch_data { >> + =A0 =A0 =A0 FILE *ftp; >> + =A0 =A0 =A0 int pkgfd; >> + =A0 =A0 =A0 char buf[8192]; >> +}; > > Using BUFSIZ might be a better idea. I am not sure that BUFSIZ is meant to be used in this case. On my system, its value is 1024 which is pretty low for net I/O IMHO. Furthermore, I've experienced something "strange" (I might ask Tim): on open, libarchive called ~50 times the read callback. Which means that libarchive stored ~409Kb somewhere in a buffer, while I did not called next_header() nor read_data()... Likewise, libarchive called like 10times the read callback, then extracted ~6files, and so on. I am confused cause it's advertised that it's a no-copy architecture. Anyway, it works and that's all that matters. > >> + >> =A0/* Prototypes */ >> =A0/* Misc */ >> =A0int =A0 =A0 =A0 =A0 =A0 =A0vsystem(const char *, ...); >> @@ -173,6 +180,8 @@ >> =A0Boolean =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0issymlink(const char *); >> =A0Boolean =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0isURL(const char *); >> =A0const char =A0 =A0 *fileGetURL(const char *, const char *, int); >> +int =A0 =A0 =A0 =A0 =A0 =A0fetch_archive(struct archive *, const char *= , const char *, >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 Boolean); >> =A0char =A0 =A0 =A0 =A0 =A0 *fileFindByPath(const char *, const char *); >> =A0char =A0 =A0 =A0 =A0 =A0 *fileGetContents(const char *); >> =A0ssize_t =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0write_file(const char *, const= char *); >> >> =3D=3D=3D=3D //depot/projects/soc2010/pkg_complete/lib/libpkg/url.c#3 (t= ext+ko) =3D=3D=3D=3D >> >> @@ -23,15 +23,23 @@ >> >> =A0#include >> =A0#include >> +#include >> =A0#include >> +#include >> =A0#include >> =A0#include >> =A0#include =A0 =A0 /* NOTE: stdio must come before fetch. */ >> =A0#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 *); >> + >> =A0/* >> =A0* Try and fetch a file by URL, returning the directory name for where >> =A0* it's unpacked, if successful. >> + * XXX (jlaffaye): to be removed when all call to fileGetURL() are conv= erted to >> + * fetch_archive() >> =A0*/ >> =A0const char * >> =A0fileGetURL(const char *base, const char *spec, int keep_package) >> @@ -113,11 +121,11 @@ >> =A0 =A0 =A0 =A0fetchDebug =3D (Verbose > 0); >> =A0 =A0 =A0 =A0if ((ftp =3D fetchGetURL(fname, Verbose ? "v" : NULL)) = =3D=3D NULL) { >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0warnx("Error: Unable to get %s: %s\n", fn= ame, >> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 fetchLastErrString); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 fetchLastErrString); >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* If the fetch fails, yank the package. = */ >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (keep_package && unlink(pkg) < 0) { >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0warnx("failed to remove p= artially fetched package: %s", >> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 pkg); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 pkg); >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0return (NULL); >> =A0 =A0 =A0 =A0} >> @@ -182,3 +190,170 @@ >> =A0 =A0 =A0 =A0return (rp); >> >> =A0} >> + >> +/* >> + * 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 th= e 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, >> + =A0 =A0 =A0 =A0 =A0 =A0 Boolean keep_package) >> +{ >> + =A0 =A0 =A0 struct fetch_data *data =3D NULL; >> + =A0 =A0 =A0 char *cp, *hint, *tmp; >> + =A0 =A0 =A0 char fname[FILENAME_MAX]; >> + =A0 =A0 =A0 char pkg[FILENAME_MAX]; >> + =A0 =A0 =A0 int retcode =3D 0; >> + >> + =A0 =A0 =A0 if ((data =3D malloc(sizeof(struct fetch_data))) =3D=3D NU= LL) >> + =A0 =A0 =A0 =A0 =A0 err(EXIT_FAILURE, "malloc()"); >> + >> + =A0 =A0 =A0 if (!isURL(spec)) { >> + =A0 =A0 =A0 =A0 =A0 /* >> + =A0 =A0 =A0 =A0 =A0 =A0* We've been given an existing URL (that's know= n-good) and now >> + =A0 =A0 =A0 =A0 =A0 =A0* we need to construct a composite one out of t= hat and the >> + =A0 =A0 =A0 =A0 =A0 =A0* basename we were handed as a dependency. >> + =A0 =A0 =A0 =A0 =A0 =A0*/ >> + =A0 =A0 =A0 =A0 =A0 if (base !=3D NULL) { >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 strcpy(fname, base); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* Advance back two slashes to get to th= e root of the >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* package hierarchy >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/ >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 cp =3D strrchr(fname, '/'); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (cp) { >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 *cp =3D '\0'; /* chop name */ >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 cp =3D strrchr(fname, '/'); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 } >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (cp !=3D NULL) { >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 *(cp + 1) =3D '\0'; >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 strcat(cp, "All/"); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 strcat(cp, spec); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 strcat(cp, ".tbz"); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 } else { >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 retcode =3D 1; >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto cleanup; >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 } >> + =A0 =A0 =A0 =A0 =A0 } >> + =A0 =A0 =A0 =A0 =A0 /* Special tip that sysinstall left for us */ >> + =A0 =A0 =A0 =A0 =A0 else if ((hint =3D getenv("PKG_ADD_BASE")) !=3D NU= LL) { >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* Otherwise, we've been given an enviro= nment variable >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* hinting at the right location from sy= sinstall >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/ >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 strcpy(fname, hint); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 strcat(fname, spec); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 strcat(fname, ".tbz"); >> + =A0 =A0 =A0 =A0 =A0 } >> + =A0 =A0 =A0 =A0 =A0 /* We dont have an url and are unable to guess one= */ >> + =A0 =A0 =A0 =A0 =A0 else { >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 retcode =3D 1; >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto cleanup; >> + =A0 =A0 =A0 =A0 =A0 } >> + =A0 =A0 =A0 } >> + =A0 =A0 =A0 else >> + =A0 =A0 =A0 =A0 =A0 strcpy(fname, spec); >> + >> + =A0 =A0 =A0 if (keep_package) { >> + =A0 =A0 =A0 =A0 =A0 tmp =3D getenv("PKGDIR"); >> + =A0 =A0 =A0 =A0 =A0 strlcpy(pkg, tmp ? tmp : ".", sizeof(pkg)); >> + =A0 =A0 =A0 =A0 =A0 tmp =3D basename(fname); >> + =A0 =A0 =A0 =A0 =A0 strlcat(pkg, "/", sizeof(pkg)); >> + =A0 =A0 =A0 =A0 =A0 strlcat(pkg, tmp, sizeof(pkg)); >> + >> + =A0 =A0 =A0 =A0 =A0 data->pkgfd =3D open(pkg, O_WRONLY|O_CREAT|O_TRUNC= , 0644); >> + =A0 =A0 =A0 =A0 =A0 if (data->pkgfd =3D=3D -1) { >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 warn("Error: Unable to open %s", pkg); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 retcode =3D 1; >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto cleanup; >> + =A0 =A0 =A0 =A0 =A0 } >> + =A0 =A0 =A0 } else >> + =A0 =A0 =A0 =A0 =A0 data->pkgfd =3D 0; >> + >> + =A0 =A0 =A0 fetchDebug =3D (Verbose > 0); >> + =A0 =A0 =A0 if ((data->ftp =3D fetchGetURL(fname, Verbose ? "v" : NULL= )) =3D=3D NULL) { >> + =A0 =A0 =A0 =A0 =A0 warnx("Error: Unable to get %s: %s\n", fname, fetc= hLastErrString); >> + =A0 =A0 =A0 =A0 =A0 /* If the fetch fails, yank the package. */ >> + =A0 =A0 =A0 =A0 =A0 if (keep_package && unlink(pkg) < 0) >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 warnx("failed to remove partially fetched = package: %s", pkg); >> + =A0 =A0 =A0 =A0 =A0 retcode =3D 1; >> + =A0 =A0 =A0 =A0 =A0 goto cleanup; >> + =A0 =A0 =A0 } >> + >> + =A0 =A0 =A0 if (isatty(0) || Verbose) { >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 printf("Fetching %s...", fname); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 fflush(stdout); >> + =A0 =A0 =A0 } >> + >> + =A0 =A0 =A0 if (archive_read_open(a, data, archive_open_cb, archive_re= ad_cb, >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 archive_close_= cb) !=3D ARCHIVE_OK) { >> + =A0 =A0 =A0 =A0 =A0 warnx("Can not open '%s': %s", pkg, archive_error_= string(a)); >> + =A0 =A0 =A0 =A0 =A0 retcode =3D 1; >> + =A0 =A0 =A0 =A0 =A0 goto cleanup; >> + =A0 =A0 =A0 } >> + >> + =A0 =A0 =A0 cleanup: >> + =A0 =A0 =A0 if (retcode =3D=3D 1 && data !=3D NULL) >> + =A0 =A0 =A0 =A0 =A0 free(data); >> + >> + =A0 =A0 =A0 return (retcode); >> +} >> + >> +/* >> + * Libarchive callback called when more data is needed. >> + * Read the data from the fetch(3) file descriptor and store it into bu= f. >> + * If `pkgfd' is a valid file descriptor, also write the data on disk. >> + * Returns the read size, 0 on EOF, -1 on error. >> + */ >> +static ssize_t >> +archive_read_cb(struct archive *a, void *client_data, const void **buf) >> +{ >> + =A0 =A0 =A0 ssize_t r; >> + =A0 =A0 =A0 struct fetch_data *data =3D client_data; >> + >> + =A0 =A0 =A0 *buf =3D data->buf; >> + =A0 =A0 =A0 if ((r =3D fread(data->buf, 1, sizeof(data->buf), data->ft= p)) < 1) >> + =A0 =A0 =A0 =A0 =A0 if (ferror(data->ftp)) { >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 archive_set_error(a, 0, "error while fetch= ing : %s", >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 fetchL= astErrString); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return (-1); >> + =A0 =A0 =A0 =A0 =A0 } >> + >> + =A0 =A0 =A0 if (data->pkgfd > 0 && r > 0) > > What if the pkgfd is <=3D 0 and r is > 0? If pkgfd is <=3D 0 then we did not open the file on disk cause KeepPackage was set to FALSE. So we do nothing. > >> + =A0 =A0 =A0 =A0 =A0 if (write(data->pkgfd, buf, r) !=3D r) { >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 archive_set_error(a, 0, "can not write to = package file: %s", >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 strerr= or(errno)); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return (-1); >> + =A0 =A0 =A0 =A0 =A0 } >> + >> + =A0 =A0 =A0 return (r); >> +} >> + >> +/* >> + * Libarchive callback called by archive_open() >> + * Since all the job is done in fetch_archive(), always return success. >> + */ >> +static int >> +archive_open_cb(struct archive *a, void *client_data) >> +{ >> + =A0 =A0 =A0 return (ARCHIVE_OK); >> +} >> + >> +/* >> + * Libarchive callback called by archive_close(). >> + * Release the file descriptors and free the structure. >> + */ >> +static int >> +archive_close_cb(struct archive *a, void *client_data) >> +{ >> + =A0 =A0 =A0 struct fetch_data *data =3D client_data; >> + >> + =A0 =A0 =A0 fclose(data->ftp); >> + =A0 =A0 =A0 if (data->pkgfd > 0) >> + =A0 =A0 =A0 =A0 =A0 close(data->pkgfd); >> + =A0 =A0 =A0 free(data); >> + >> + =A0 =A0 =A0 return (ARCHIVE_OK); >> +} >> >> =3D=3D=3D=3D //depot/projects/soc2010/pkg_complete/usr.sbin/pkg_install/= add/extract.c#6 (text+ko) =3D=3D=3D=3D >> >> @@ -43,7 +43,8 @@ >> =A0 =A0 =A0 =A0if ((plist_buf =3D malloc(s+1)) =3D=3D NULL) >> =A0 =A0 =A0 =A0 =A0 =A0err(EXIT_FAILURE, "malloc()"); >> =A0 =A0 =A0 =A0if (archive_read_data(a, plist_buf, s) !=3D s) { >> - =A0 =A0 =A0 =A0 =A0 warnx("Can not extract plist: %s", archive_error_s= tring(a)); >> + =A0 =A0 =A0 =A0 =A0 warnx("Can not extract %s: %s", CONTENTS_FNAME, >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 archive_error_string(a)); >> =A0 =A0 =A0 =A0 =A0 =A0return (1); >> =A0 =A0 =A0 =A0} >> =A0 =A0 =A0 =A0plist_buf[s] =3D '\0'; >> @@ -52,7 +53,7 @@ >> =A0 =A0 =A0 =A0retcode =3D read_plist_from_buffer(pkg, plist_buf, s); >> =A0 =A0 =A0 =A0free(plist_buf); >> =A0 =A0 =A0 =A0if (retcode !=3D 0) { >> - =A0 =A0 =A0 =A0 =A0 warnx("Unable to parse plist!"); >> + =A0 =A0 =A0 =A0 =A0 warnx("Unable to parse %s!", CONTENTS_FNAME); >> =A0 =A0 =A0 =A0 =A0 =A0return (1); >> =A0 =A0 =A0 =A0} >> >> >> =3D=3D=3D=3D //depot/projects/soc2010/pkg_complete/usr.sbin/pkg_install/= add/perform.c#6 (text+ko) =3D=3D=3D=3D >> >> @@ -73,20 +73,23 @@ >> >> =A0 =A0 =A0 =A0/* >> =A0 =A0 =A0 =A0 * TODO: >> - =A0 =A0 =A0 =A0* =A0 =A0 =A0dowload the package if it is an URL, read = from stdin if "-" >> =A0 =A0 =A0 =A0 * =A0 =A0 =A0Deal with master/slave modes. >> =A0 =A0 =A0 =A0 * =A0 =A0 =A0add support for complete packages >> =A0 =A0 =A0 =A0 */ >> =A0 =A0 =A0 =A0if (isURL(fname)) { >> - =A0 =A0 =A0 =A0 =A0 /* TODO: add support */ >> - =A0 =A0 =A0 =A0 =A0 return (1); >> + =A0 =A0 =A0 =A0 =A0 if (fetch_archive(a, NULL, fname, KeepPackage) != =3D 0) { >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 warnx("Can not fetch '%s' - aborting", fna= me); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 retcode =3D 1; >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto cleanup; >> + =A0 =A0 =A0 =A0 =A0 } >> =A0 =A0 =A0 =A0} else { >> =A0 =A0 =A0 =A0 =A0 =A0if (strcmp(fname, "-") =3D=3D 0) >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0fd =3D fileno(stdin); >> =A0 =A0 =A0 =A0 =A0 =A0else { >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if ((fd =3D open(fname, O_RDONLY)) =3D=3D= -1) { >> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 warn("open(%s)", fname); >> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return (1); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 warn("Can not open '%s' for readin= g", fname); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 retcode =3D 1; >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto cleanup; >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} >> =A0 =A0 =A0 =A0 =A0 =A0} >> >> @@ -102,11 +105,12 @@ >> =A0 =A0 =A0 =A0 =A0 =A0pathname =3D archive_entry_pathname(entry); >> =A0 =A0 =A0 =A0 =A0 =A0if (strcmp(pathname, CONTENTS_FNAME) =3D=3D 0) { >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (extract_plist(a, entry, &pkg) !=3D 0)= { >> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 warnx("Can not extract & parse " C= ONTENTS_FNAME); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 warnx("Can not proceed without pac= king list - aborting"); >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0retcode =3D 1; >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0goto cleanup; >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} >> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 extract_package(a, &pkg); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 retcode =3D extract_package(a, &pkg); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 free_plist(&pkg); >> =A0 =A0 =A0 =A0 =A0 =A0} else if (strcmp(pathname, "+PKG_COMPLETE") =3D= =3D 0) { >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (Verbose) >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0printf("'%s' is a complete packag= e...\n", fname); >> @@ -126,8 +130,6 @@ >> =A0 =A0 =A0 =A0cleanup: >> =A0 =A0 =A0 =A0if (a !=3D NULL) >> =A0 =A0 =A0 =A0 =A0 =A0archive_read_finish(a); >> - =A0 =A0 =A0 if (pkg.head !=3D NULL) >> - =A0 =A0 =A0 =A0 =A0 free_plist(&pkg); >> =A0 =A0 =A0 =A0return (retcode); >> >> =A0# if 0 >> >