From owner-p4-projects@FreeBSD.ORG Tue Jun 22 16:12:16 2010 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 165291065675; Tue, 22 Jun 2010 16:12:16 +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 CE1F91065673 for ; Tue, 22 Jun 2010 16:12:15 +0000 (UTC) (envelope-from ivoras@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id BA3BF8FC1A for ; Tue, 22 Jun 2010 16:12:15 +0000 (UTC) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.3/8.14.3) with ESMTP id o5MGCF1t034867 for ; Tue, 22 Jun 2010 16:12:15 GMT (envelope-from ivoras@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id o5MGCFxW034865 for perforce@freebsd.org; Tue, 22 Jun 2010 16:12:15 GMT (envelope-from ivoras@FreeBSD.org) Date: Tue, 22 Jun 2010 16:12:15 GMT Message-Id: <201006221612.o5MGCFxW034865@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to ivoras@FreeBSD.org using -f From: Ivan Voras To: Perforce Change Reviews Precedence: bulk Cc: Subject: PERFORCE change 180110 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 22 Jun 2010 16:12:16 -0000 http://p4web.freebsd.org/@@180110?ac=10 Change 180110 by ivoras@betelgeuse on 2010/06/22 16:12:02 Remove custom parsing of +CONTENTS, start working on applying the patch Affected files ... .. //depot/projects/soc2010/pkg_patch/src/patch/Makefile#16 edit .. //depot/projects/soc2010/pkg_patch/src/patch/applypatch.c#6 edit .. //depot/projects/soc2010/pkg_patch/src/patch/applypatch.h#6 edit .. //depot/projects/soc2010/pkg_patch/src/patch/hashjob.c#15 edit .. //depot/projects/soc2010/pkg_patch/src/patch/hashjob.h#15 edit .. //depot/projects/soc2010/pkg_patch/src/patch/main.c#16 edit .. //depot/projects/soc2010/pkg_patch/src/patch/mkpatch.c#14 edit .. //depot/projects/soc2010/pkg_patch/src/patch/mkpatch.h#14 edit .. //depot/projects/soc2010/pkg_patch/src/patch/pkg_patch.h#14 edit .. //depot/projects/soc2010/pkg_patch/src/patch/support.c#13 edit Differences ... ==== //depot/projects/soc2010/pkg_patch/src/patch/Makefile#16 (text+ko) ==== ==== //depot/projects/soc2010/pkg_patch/src/patch/applypatch.c#6 (text+ko) ==== @@ -36,128 +36,67 @@ #include "hashjob.h" -enum PPMETHOD { PPMETHOD_UNKNOWN, PPMETHOD_CP, PPMETHOD_BSDIFF }; +/* + * Create a backup package (pkg_create -b) for the given package (identified + * by its full name, e.g. "apache-2.2.13"). + */ +static int +pkg_backup(char *name) +{ + char pkg_file[PATH_MAX]; + + if (!isinstalledpkg(name)) { + warnx("Package not installed: %s", name); + return (-1); + } + if (access(PKGPATCH_BACKUP_DIR, F_OK) != 0) { + if (mkdir(PKGPATCH_BACKUP_DIR, 0644) != 0) { + warnx("Cannot mkdir: %s", PKGPATCH_BACKUP_DIR); + return (-1); + } + } + snprintf(pkg_file, PATH_MAX, "%s/%s.%s", PKGPATCH_BACKUP_DIR, name, + PKG_FORMAT_EXT); + if (vsystem("%s -b %s %s", _PATH_PKG_CREATE, name, pkg_file) != 0) { + warnx("pkg_create -b %s %s failed", name, pkg_file); + return (-1); + } + if (Verbose) + printf("Created backup package: %s\n", pkg_file); + return (0); +} -STAILQ_HEAD(pplist_head, pplist); -struct pplist { - char filename[PATH_MAX]; - enum PPMETHOD method; - STAILQ_ENTRY(pplist) linkage; -}; +/* + * Read the given +CONTENTS file. + */ +static int +read_package_contents_file(char *pfilename, Package *pkg) +{ + FILE *fp; + + fp = fopen(pfilename, "r"); + if (fp == NULL) { + warnx("Cannot open file: %s", pfilename); + return (-1); + } + read_plist(pkg, fp); + return (0); +} -struct pkg_patch { - short int version_major; - short int version_minor; - char source[PATH_MAX]; - char target[PATH_MAX]; - struct pplist_head pp_add; - struct pplist_head pp_remove; - struct pplist_head pp_rmdir; - struct pplist_head pp_patch; -}; - - -static void -read_pkgpatch_file(char *filename, struct pkg_patch *pp) +/* + * Read live/installed package metadata. The package is identified by its full + * name (e.g. "apache-2.2.13"). + */ +static int +read_package_by_name(char *name, Package *pkg) { - FILE *fp; - char line[PATH_MAX], *p, *p2, *p3, *cmd; - int llen; - struct pplist *pl; + char pfilename[PATH_MAX]; - fp = fopen(filename, "r"); - if (fp == NULL) - err(1, "Cannot open file: %s", filename); - memset(pp, 0, sizeof(*pp)); - STAILQ_INIT(&pp->pp_add); - STAILQ_INIT(&pp->pp_remove); - STAILQ_INIT(&pp->pp_rmdir); - STAILQ_INIT(&pp->pp_patch); - - while (fgets(line, PATH_MAX, fp) != NULL) { - llen = strlen(line); - if (line[llen-1] == '\n') { - line[llen-1] = '\0'; /* strip newline */ - llen--; - } - p = strchr(line, '#'); /* skip comments */ - if (p != NULL) - *p = '\0'; - if (line[0] == '\0') /* skip empty lines */ - continue; - cmd = line; - p = strchr(line, ' '); - if (p == NULL) - errx(1, "Invalid command format in %s", PKGPATCH_FNAME); - *p++ = '\0'; - if (strcmp(cmd, "@version") == 0) { - p2 = strchr(p, '.'); - if (p2 == NULL) - errx(1, "Invalid version format in %s", - PKGPATCH_FNAME); - *p2++ = '\0'; - pp->version_major = atoi(p); - pp->version_minor = atoi(p2); - } else if (strcmp(cmd, "@source") == 0) { - strlcpy(pp->source, p, PATH_MAX); - } else if (strcmp(cmd, "@target") == 0) { - strlcpy(pp->target, p, PATH_MAX); - } else if (strcmp(cmd, "@add") == 0) { - pl = calloc(1, sizeof(*pl)); - strlcpy(pl->filename, p, PATH_MAX); - STAILQ_INSERT_TAIL(&pp->pp_add, pl, linkage); - } else if (strcmp(cmd, "@remove") == 0) { - pl = calloc(1, sizeof(*pl)); - strlcpy(pl->filename, p, PATH_MAX); - STAILQ_INSERT_TAIL(&pp->pp_remove, pl, linkage); - } else if (strcmp(cmd, "@rmdir") == 0) { - pl = calloc(1, sizeof(*pl)); - strlcpy(pl->filename, p, PATH_MAX); - STAILQ_INSERT_TAIL(&pp->pp_rmdir, pl, linkage); - } else if (strcmp(cmd, "@patch") == 0) { - pl = calloc(1, sizeof(*pl)); - p2 = strchr(p, '['); - if (p2 != NULL) { - /* - * Parse options block of the form - * \[name=value[,name=value...]\] - */ - char m[100], *pm, *p4, *p5; - - pm = m; - p3 = strchr(p2, ']'); - assert(p3-p2 < (int)sizeof(m)); - strlcpy(m, p2 + 1, p3 - p2); - p3++; - while (*p3 == ' ') - p3++; - strlcpy(pl->filename, p3, PATH_MAX); - while ((p4 = strsep(&pm, ",")) != NULL) { - p5 = strchr(p4, '='); - if (p5 != NULL) - *p5++ = '\0'; - if (strcmp(p4, "method") == 0) { - if (p5 == NULL) - errx(1, "patch option " - "error"); - if (strcmp(p5, "bsdiff") == 0) - pl->method = - PPMETHOD_BSDIFF; - } - } - } else { - /* Default options */ - strlcpy(pl->filename, p, PATH_MAX); - pl->method = PPMETHOD_CP; - } - STAILQ_INSERT_TAIL(&pp->pp_patch, pl, linkage); - } else - errx(1, "Unknown command: %s", cmd); - - } - fclose(fp); + snprintf(pfilename, PATH_MAX, "%s/%s/%s", LOG_DIR, name, + CONTENTS_FNAME); + return (read_package_contents_file(pfilename, pkg)); } @@ -167,7 +106,9 @@ char fpatch[PATH_MAX], dpatch[PATH_MAX], tmp[PATH_MAX]; struct pkgxjob xpatch; struct pkg_patch pp; - struct pkg_metadata pkg_live; + Package pkg_live, pkg_new; + struct pplist *pl; + unsigned int err_count = 0; if (argc < 1) errx(1, "Expecting argument: patch filename"); @@ -198,13 +139,43 @@ errx(1, "Invalid patch data format minor version number: %d\n", pp.version_minor); if (Verbose) - printf("Read patch data, version %d.%d for '%s' to '%s'\n", + printf("Parsed patch version %d.%d for '%s' to '%s'\n", pp.version_major, pp.version_minor, pp.source, pp.target); - /* Step 2 - read the existing (live system) package data */ + if (Verbose > 1) + printf("New files: %u, removed: %u, changed: %u, rmdirs: %u\n", + pplist_count(&pp.pp_add), pplist_count(&pp.pp_remove), + pplist_count(&pp.pp_patch), pplist_count(&pp.pp_rmdir)); + + if (!isinstalledpkg(pp.source)) + errx(1, "The patch file applies to package '%s' which doesn't " + "appear to be installed.", pp.source); + + /* + * Step 2 - read the existing (live system) package data and the new + * package data. + */ if (read_package_by_name(pp.source, &pkg_live) != 0) err(1, "Cannot read package information for %s", pp.source); + snprintf(tmp, PATH_MAX, "%s/%s", dpatch, CONTENTS_FNAME); + if (read_package_contents_file(tmp, &pkg_new) != 0) + err(1, "Cannot read package information from %s", tmp); - dump_package_info(&pkg_live); + /* Step 3 - verify that the live system and the patch file agree */ + if (Verbose > 1) + printf("Verifying live system and patch data consistency...\n"); + /* Check that files to be added don't exist already. */ + STAILQ_FOREACH(pl, &pp.pp_add, linkage) { + snprintf(tmp, PATH_MAX, "%s/%s", PREFIX, pl->filename); + if (access(tmp, F_OK) == 0) { + warnx("File exists but shouldn't: %s", tmp); + err_count++; + } + } + if (err_count != 0) + errx(1, "Found %u errors. Cannot continue.", err_count); + /* Step 4 - backup the existing package */ + if (pkg_backup(pp.source) != 0) + err(1, "Cannot backup package: %s", pp.source); } ==== //depot/projects/soc2010/pkg_patch/src/patch/applypatch.h#6 (text+ko) ==== ==== //depot/projects/soc2010/pkg_patch/src/patch/hashjob.c#15 (text+ko) ==== ==== //depot/projects/soc2010/pkg_patch/src/patch/hashjob.h#15 (text+ko) ==== ==== //depot/projects/soc2010/pkg_patch/src/patch/main.c#16 (text+ko) ==== ==== //depot/projects/soc2010/pkg_patch/src/patch/mkpatch.c#14 (text+ko) ==== @@ -178,7 +178,8 @@ time(&tm); fprintf(fp, "# FreeBSD package patch archive created on %s\n", ctime(&tm)); - fprintf(fp, "@version %s\n", PKGPATCH_VERSION); + fprintf(fp, "@version %d.%d\n", PKGPATCH_VERSION_MAJOR, + PKGPATCH_VERSION_MINOR); parse_package_name(fold, tmp, tmp2, NULL); fprintf(fp, "@source %s-%s\n", tmp, tmp2); parse_package_name(fnew, tmp, tmp2, NULL); ==== //depot/projects/soc2010/pkg_patch/src/patch/mkpatch.h#14 (text+ko) ==== ==== //depot/projects/soc2010/pkg_patch/src/patch/pkg_patch.h#14 (text+ko) ==== @@ -26,12 +26,26 @@ #ifndef _PATH_BSDIFF #define _PATH_BSDIFF "/usr/bin/bsdiff" #endif +#ifndef _PATH_PKG_CREATE +#define _PATH_PKG_CREATE "/usr/sbin/pkg_create" +#endif + +#ifndef PKG_FORMAT_EXT +#define PKG_FORMAT_EXT "tbz" +#endif #define PKGPATCH_FNAME "+PKGPATCH" #define PKGPATCH_VERSION_MAJOR 1 #define PKGPATCH_VERSION_MINOR 0 -#define PKGPATCH_VERSION "1.0" + +#define PKGPATCH_BACKUP_DIR_ENV "PKG_BACKUPDIR" +#define PKGPATCH_BACKUP_DIR_DEFAULT "/var/backups/pkg" +#define PKGPATCH_BACKUP_DIR (getenv(PKGPATCH_BACKUP_DIR_ENV) ? \ + getenv(PKGPATCH_BACKUP_DIR_ENV) : PKGPATCH_BACKUP_DIR_DEFAULT) +#define PREFIX_ENV "PREFIX" +#define PREFIX_DEFAULT "/usr/local" +#define PREFIX (getenv(PREFIX_ENV) ? getenv(PREFIX_ENV) : PREFIX_DEFAULT) enum PP_OP { PP_NONE, PP_MKPATCH, PP_APPLY }; @@ -47,37 +61,30 @@ SLIST_ENTRY(filelist) linkage; }; - SLIST_HEAD(pathlist_head, pathlist); struct pathlist { char path[PATH_MAX]; SLIST_ENTRY(pathlist) linkage; }; +enum PPMETHOD { PPMETHOD_UNKNOWN, PPMETHOD_CP, PPMETHOD_BSDIFF }; -STAILQ_HEAD(pkg_plist_head, pkg_plist); -struct pkg_plist { - char name[PATH_MAX]; - union { - char md5[33]; - char deporigin[PATH_MAX]; - } param; - plist_t type; - unsigned flags; - STAILQ_ENTRY(pkg_plist) linkage; +STAILQ_HEAD(pplist_head, pplist); +struct pplist { + char filename[PATH_MAX]; + enum PPMETHOD method; + STAILQ_ENTRY(pplist) linkage; }; -#define PLIST_FLAG_IGNORE 1 -struct pkg_metadata { - char name[PATH_MAX]; - char origin[PATH_MAX]; - char pkg_format_revision[16]; - char prefix[PATH_MAX]; - char display[PATH_MAX]; - char mtree[PATH_MAX]; - struct pkg_plist_head plist; - struct pathlist_head conflicts; - struct pathlist_head unknown_comments; +struct pkg_patch { + short int version_major; + short int version_minor; + char source[PATH_MAX]; + char target[PATH_MAX]; + struct pplist_head pp_add; + struct pplist_head pp_remove; + struct pplist_head pp_rmdir; + struct pplist_head pp_patch; }; @@ -91,6 +98,7 @@ #endif + int rm_rf(char *dir); int pkgxjob_start(struct pkgxjob *job, char *dir, char *filename); int pkgxjob_finish(struct pkgxjob *job); @@ -105,8 +113,7 @@ int copy_file_absolute(char *from, char *to); int copy_file_attrs(char *from, struct stat *st_from, char *to); int replicate_dirtree(char *from, char *to); -int read_package(FILE *fp, struct pkg_metadata *pkg); -int read_package_by_name(char *name, struct pkg_metadata *pkg); -void dump_package_info(struct pkg_metadata *pkg); +void read_pkgpatch_file(char *filename, struct pkg_patch *pp); +unsigned int pplist_count(struct pplist_head *ppl); #endif ==== //depot/projects/soc2010/pkg_patch/src/patch/support.c#13 (text+ko) ==== @@ -340,221 +340,122 @@ /* - * Parse the comment as if it were stand-alone, adding to package metadata. - * Destructive on cmt. + * Counts the elements in the given pplist. */ -static void -parse_pkg_comment(struct pkg_metadata *pkg, char *cmt) +unsigned int +pplist_count(struct pplist_head *ppl) { - char *v; - struct pathlist *plcmt; + unsigned int count = 0; + struct pplist *pl; - if ((v = strchr(cmt, ':')) == NULL) - goto unknown_comment; - *v++ = '\0'; - if (strcmp(cmt, "PKG_FORMAT_REVISION") == 0) - strncpy(pkg->pkg_format_revision, v, - sizeof(pkg->pkg_format_revision)); - else if (strcmp(cmt, "ORIGIN") == 0) - strncpy(pkg->origin, v, sizeof(pkg->origin)); - else { - *(--v) = ':'; - goto unknown_comment; - } - return; -unknown_comment: - plcmt = calloc(1, sizeof(*plcmt)); - strncpy(plcmt->path, cmt, sizeof(plcmt->path)); - SLIST_INSERT_HEAD(&pkg->unknown_comments, plcmt, linkage); + STAILQ_FOREACH(pl, ppl, linkage) + count++; + return (count); } /* - * Parse the comment and assign it to plist (if possible). Destructive on cmt. + * Reads the given file into struct pkg_patch. */ -static void -parse_plist_comment(struct pkg_metadata *pkg, struct pkg_plist *pl, char *cmt) -{ - char *v; - struct pathlist *plcmt; - - if ((v = strchr(cmt, ':')) == NULL) - goto unknown_comment; - *v++ = '\0'; - if (strcmp(cmt, "MD5") == 0) - strncpy(pl->param.md5, v, sizeof(pl->param.md5)); - else if (strcmp(cmt, "DEPORIGIN") == 0) { - if (pl->type != PLIST_PKGDEP) { - warnx("DEPORIGIN not set on @pkgdep? (%s:%s)", cmt, v); - return; - } - strncpy(pl->param.deporigin, v, sizeof(pl->param.deporigin)); - } else { - *(--v) = ':'; - goto unknown_comment; - } - return; -unknown_comment: - plcmt = calloc(1, sizeof(*plcmt)); - strncpy(plcmt->path, cmt, sizeof(plcmt->path)); - SLIST_INSERT_HEAD(&pkg->unknown_comments, plcmt, linkage); -} - - -/* Parse @conflicts */ -static void -parse_pkg_conflicts(struct pkg_metadata *pkg, char *cfl) -{ - struct pathlist *pcfl; - - pcfl = calloc(1, sizeof(*pcfl)); - strncpy(pcfl->path, cfl, sizeof(pcfl->path)); - SLIST_INSERT_HEAD(&pkg->conflicts, pcfl, linkage); -} - - -/* - * Reads the package +CONTENTS file into the struct pkg_metadata. - */ -int -read_package_by_name(char *name, struct pkg_metadata *pkg) +void +read_pkgpatch_file(char *filename, struct pkg_patch *pp) { - char pfilename[PATH_MAX]; FILE *fp; - int rval; + char line[PATH_MAX], *p, *p2, *p3, *cmd; + int llen; + struct pplist *pl; - snprintf(pfilename, PATH_MAX, "%s/%s/%s", LOG_DIR, name, - CONTENTS_FNAME); - if (access(pfilename, R_OK) != 0) { - warn("Cannot access %s for reading", pfilename); - return (-errno); - } - fp = fopen(pfilename, "r"); - if (fp == NULL) { - warn("Cannot open filename: %s", pfilename); - return (-errno); - } - rval = read_package(fp, pkg); - fclose(fp); - return (rval); -} - - -/* - * Reads the package metadata for the given package name in the package database - * structure. The name is a full package name, e.g. "sqlite3-3.6.19". - * Hopefully, one day, someone will make a canonical way to do this instead - * of reinwenting the wheel. The actual format of +CONTENTS is very lame. - */ -int -read_package(FILE *fp, struct pkg_metadata *pkg) -{ - char line[PATH_MAX]; - struct pkg_plist *pl = NULL; - int llen, rval; - - STAILQ_INIT(&pkg->plist); - SLIST_INIT(&pkg->conflicts); - SLIST_INIT(&pkg->unknown_comments); + fp = fopen(filename, "r"); + if (fp == NULL) + err(1, "Cannot open file: %s", filename); + memset(pp, 0, sizeof(*pp)); + STAILQ_INIT(&pp->pp_add); + STAILQ_INIT(&pp->pp_remove); + STAILQ_INIT(&pp->pp_rmdir); + STAILQ_INIT(&pp->pp_patch); - rval = 0; while (fgets(line, PATH_MAX, fp) != NULL) { - char *p, *cmd; - llen = strlen(line); if (line[llen-1] == '\n') { line[llen-1] = '\0'; /* strip newline */ llen--; } - if (line[0] == '\0') + p = strchr(line, '#'); /* skip comments */ + if (p != NULL) + *p = '\0'; + if (line[0] == '\0') /* skip empty lines */ continue; - /*printf("%s\n", line);*/ - if (line[0] == CMD_CHAR) { - cmd = line + 1; - p = strchr(line, ' '); - if (p == NULL) - p = line + llen; - *p++ = '\0'; - if (strcmp(cmd, "comment") == 0) { - if (pl != NULL) - /* Comment on a plist entry? */ - parse_plist_comment(pkg, pl, p); - else - /* Comment on the package? */ - parse_pkg_comment(pkg, p); - } else if (strcmp(cmd, "name") == 0) { - strncpy(pkg->name, p, sizeof(pkg->name)); - pl = NULL; - } else if (strcmp(cmd, "cwd") == 0) { - if (strcmp(p, ".") != 0) { - strncpy(pkg->prefix, p, sizeof(pkg->prefix)); - pl = NULL; - } - } else if (strcmp(cmd, "display") == 0) { - strncpy(pkg->display, p, sizeof(pkg->display)); - /*pl = NULL;*/ - } else if (strcmp(cmd, "mtree") == 0) { - strncpy(pkg->mtree, p, sizeof(pkg->mtree)); - /*pl = NULL;*/ - } else if (strcmp(cmd, "pkgdep") == 0) { - pl = calloc(1, sizeof(*pl)); - pl->type = PLIST_PKGDEP; - strncpy(pl->name, p, sizeof(pl->name)); - STAILQ_INSERT_TAIL(&pkg->plist, pl, linkage); - } else if (strcmp(cmd, "conflicts") == 0) { - parse_pkg_conflicts(pkg, p); - pl = NULL; - } else if (strcmp(cmd, "exec") == 0) { - pl = calloc(1, sizeof(*pl)); - pl->type = PLIST_CMD; - strncpy(pl->name, p, sizeof(pl->name)); - STAILQ_INSERT_TAIL(&pkg->plist, pl, linkage); - } else if (strcmp(cmd, "unexec") == 0) { - pl = calloc(1, sizeof(*pl)); - pl->type = PLIST_UNEXEC; - strncpy(pl->name, p, sizeof(pl->name)); - STAILQ_INSERT_TAIL(&pkg->plist, pl, linkage); - } else if (strcmp(cmd, "dirrm") == 0) { - pl = calloc(1, sizeof(*pl)); - pl->type = PLIST_DIR_RM; - strncpy(pl->name, p, sizeof(pl->name)); - STAILQ_INSERT_TAIL(&pkg->plist, pl, linkage); - } else if (strcmp(cmd, "ignore") == 0) { + cmd = line; + p = strchr(line, ' '); + if (p == NULL) + errx(1, "Invalid command format in %s", PKGPATCH_FNAME); + *p++ = '\0'; + if (strcmp(cmd, "@version") == 0) { + p2 = strchr(p, '.'); + if (p2 == NULL) + errx(1, "Invalid version format in %s", + PKGPATCH_FNAME); + *p2++ = '\0'; + pp->version_major = atoi(p); + pp->version_minor = atoi(p2); + } else if (strcmp(cmd, "@source") == 0) { + strlcpy(pp->source, p, PATH_MAX); + } else if (strcmp(cmd, "@target") == 0) { + strlcpy(pp->target, p, PATH_MAX); + } else if (strcmp(cmd, "@add") == 0) { + pl = calloc(1, sizeof(*pl)); + strlcpy(pl->filename, p, PATH_MAX); + STAILQ_INSERT_TAIL(&pp->pp_add, pl, linkage); + } else if (strcmp(cmd, "@remove") == 0) { + pl = calloc(1, sizeof(*pl)); + strlcpy(pl->filename, p, PATH_MAX); + STAILQ_INSERT_TAIL(&pp->pp_remove, pl, linkage); + } else if (strcmp(cmd, "@rmdir") == 0) { + pl = calloc(1, sizeof(*pl)); + strlcpy(pl->filename, p, PATH_MAX); + STAILQ_INSERT_TAIL(&pp->pp_rmdir, pl, linkage); + } else if (strcmp(cmd, "@patch") == 0) { + pl = calloc(1, sizeof(*pl)); + p2 = strchr(p, '['); + if (p2 != NULL) { /* - * Apparently, "ignore" is similar to - * "comment" in that it can apply to - * the preceeding item. + * Parse options block of the form + * \[name=value[,name=value...]\] */ - if (pl == NULL) - errx(1, "@ignore on non-plist"); - pl->flags |= PLIST_FLAG_IGNORE; - } else - warnx("Unknown command: '%s'", cmd); - } else { - pl = calloc(1, sizeof(*pl)); - pl->type = PLIST_FILE; - strncpy(pl->name, line, sizeof(pl->name)); - STAILQ_INSERT_TAIL(&pkg->plist, pl, linkage); - } + char m[100], *pm, *p4, *p5; + + pm = m; + p3 = strchr(p2, ']'); + assert(p3-p2 < (int)sizeof(m)); + strlcpy(m, p2 + 1, p3 - p2); + p3++; + while (*p3 == ' ') + p3++; + strlcpy(pl->filename, p3, PATH_MAX); + while ((p4 = strsep(&pm, ",")) != NULL) { + p5 = strchr(p4, '='); + if (p5 != NULL) + *p5++ = '\0'; + if (strcmp(p4, "method") == 0) { + if (p5 == NULL) + errx(1, "patch option " + "error"); + if (strcmp(p5, "bsdiff") == 0) + pl->method = + PPMETHOD_BSDIFF; + } + } + } else { + /* Default options */ + strlcpy(pl->filename, p, PATH_MAX); + pl->method = PPMETHOD_CP; + } + STAILQ_INSERT_TAIL(&pp->pp_patch, pl, linkage); + } else + errx(1, "Unknown command: %s", cmd); + } - return (0); + fclose(fp); } -/* - * Debugging function - dump human-readable info on the given - * package. - */ -void -dump_package_info(struct pkg_metadata *pkg) -{ - struct pkg_plist *pl; - - printf("name:\t%s\n", pkg->name); - printf("origin:\t%s\n", pkg->origin); - printf("format:\t%s\n", pkg->pkg_format_revision); - printf("prefix:\t%s\n", pkg->prefix); - STAILQ_FOREACH(pl, &pkg->plist, linkage) { - printf("plist:\t%s\n", pl->name); - } -}