From owner-p4-projects@FreeBSD.ORG Mon Jun 21 00:45:43 2010 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id D614A1065672; Mon, 21 Jun 2010 00:45:42 +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 99E24106564A for ; Mon, 21 Jun 2010 00:45:42 +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 85C0C8FC15 for ; Mon, 21 Jun 2010 00:45:42 +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 o5L0jgdi009140 for ; Mon, 21 Jun 2010 00:45:42 GMT (envelope-from ivoras@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id o5L0jgZ3009138 for perforce@freebsd.org; Mon, 21 Jun 2010 00:45:42 GMT (envelope-from ivoras@FreeBSD.org) Date: Mon, 21 Jun 2010 00:45:42 GMT Message-Id: <201006210045.o5L0jgZ3009138@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 180026 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: Mon, 21 Jun 2010 00:45:43 -0000 http://p4web.freebsd.org/@@180026?ac=10 Change 180026 by ivoras@betelgeuse on 2010/06/21 00:45:03 Finished most of +CONTENTS reading code, still a few things to go and certainly edge-cases resulting from the uglyness and adhockery of the format. Affected files ... .. //depot/projects/soc2010/pkg_patch/src/patch/Makefile#15 edit .. //depot/projects/soc2010/pkg_patch/src/patch/applypatch.c#5 edit .. //depot/projects/soc2010/pkg_patch/src/patch/applypatch.h#5 edit .. //depot/projects/soc2010/pkg_patch/src/patch/hashjob.c#14 edit .. //depot/projects/soc2010/pkg_patch/src/patch/hashjob.h#14 edit .. //depot/projects/soc2010/pkg_patch/src/patch/main.c#15 edit .. //depot/projects/soc2010/pkg_patch/src/patch/mkpatch.c#13 edit .. //depot/projects/soc2010/pkg_patch/src/patch/mkpatch.h#13 edit .. //depot/projects/soc2010/pkg_patch/src/patch/pkg_patch.h#13 edit .. //depot/projects/soc2010/pkg_patch/src/patch/support.c#12 edit Differences ... ==== //depot/projects/soc2010/pkg_patch/src/patch/Makefile#15 (text+ko) ==== ==== //depot/projects/soc2010/pkg_patch/src/patch/applypatch.c#5 (text+ko) ==== @@ -47,7 +47,7 @@ }; -struct pkgpatch { +struct pkg_patch { short int version_major; short int version_minor; char source[PATH_MAX]; @@ -60,7 +60,7 @@ static void -read_pkgpatch_file(char *filename, struct pkgpatch *pp) +read_pkgpatch_file(char *filename, struct pkg_patch *pp) { FILE *fp; char line[PATH_MAX], *p, *p2, *p3, *cmd; @@ -166,7 +166,8 @@ { char fpatch[PATH_MAX], dpatch[PATH_MAX], tmp[PATH_MAX]; struct pkgxjob xpatch; - struct pkgpatch pp; + struct pkg_patch pp; + struct pkg_metadata pkg_live; if (argc < 1) errx(1, "Expecting argument: patch filename"); @@ -180,7 +181,7 @@ if (mkdir(dpatch, 0700) != 0) err(1, "Cannot create directory: %s", dpatch); if (pkgxjob_start(&xpatch, dpatch, fpatch) != 0) - err(1, "Canot extract package %s to %s (start)", fpatch, + err(1, "Cannot extract package %s to %s (start)", fpatch, dpatch); if (pkgxjob_finish(&xpatch) != 0) err(1, "Cannot extract package %s to %s (finish)", fpatch, @@ -201,5 +202,9 @@ pp.version_major, pp.version_minor, pp.source, pp.target); /* Step 2 - read the existing (live system) package data */ + if (read_package_by_name(pp.source, &pkg_live) != 0) + err(1, "Cannot read package information for %s", pp.source); + + dump_package_info(&pkg_live); } ==== //depot/projects/soc2010/pkg_patch/src/patch/applypatch.h#5 (text+ko) ==== ==== //depot/projects/soc2010/pkg_patch/src/patch/hashjob.c#14 (text+ko) ==== ==== //depot/projects/soc2010/pkg_patch/src/patch/hashjob.h#14 (text+ko) ==== ==== //depot/projects/soc2010/pkg_patch/src/patch/main.c#15 (text+ko) ==== ==== //depot/projects/soc2010/pkg_patch/src/patch/mkpatch.c#13 (text+ko) ==== ==== //depot/projects/soc2010/pkg_patch/src/patch/mkpatch.h#13 (text+ko) ==== ==== //depot/projects/soc2010/pkg_patch/src/patch/pkg_patch.h#13 (text+ko) ==== @@ -32,10 +32,6 @@ #define PKGPATCH_VERSION_MINOR 0 #define PKGPATCH_VERSION "1.0" -#ifndef PKG_DBDIR -/* So much cruft... */ -#define PKG_DBDIR LOG_DIR -#endif enum PP_OP { PP_NONE, PP_MKPATCH, PP_APPLY }; @@ -51,19 +47,37 @@ SLIST_ENTRY(filelist) linkage; }; + +SLIST_HEAD(pathlist_head, pathlist); +struct pathlist { + char path[PATH_MAX]; + SLIST_ENTRY(pathlist) linkage; +}; + + 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; }; +#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; }; @@ -91,6 +105,8 @@ 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(char *name, struct pkg_metadata *pkg); +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); #endif ==== //depot/projects/soc2010/pkg_patch/src/patch/support.c#12 (text+ko) ==== @@ -340,28 +340,122 @@ /* - * 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. + * Parse the comment as if it were stand-alone, adding to package metadata. + * Destructive on cmt. + */ +static void +parse_pkg_comment(struct pkg_metadata *pkg, char *cmt) +{ + char *v; + struct pathlist *plcmt; + + 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); +} + + +/* + * Parse the comment and assign it to plist (if possible). Destructive on cmt. */ +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(char *name, struct pkg_metadata *pkg) +read_package_by_name(char *name, struct pkg_metadata *pkg) { - char pfilename[PATH_MAX], line[PATH_MAX]; + char pfilename[PATH_MAX]; FILE *fp; - struct pkg_plist *pl; - int llen, rval; + int rval; - snprintf(pfilename, PATH_MAX, "%s/%s/%s", PKG_DBDIR, name, + 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); + warn("Cannot access %s for reading", pfilename); return (-errno); } fp = fopen(pfilename, "r"); - if (fp == NULL) + 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); rval = 0; while (fgets(line, PATH_MAX, fp) != NULL) { @@ -374,27 +468,93 @@ } if (line[0] == '\0') continue; + /*printf("%s\n", line);*/ if (line[0] == CMD_CHAR) { cmd = line + 1; p = strchr(line, ' '); - if (p == NULL) { - rval = -1; - goto error; - } + 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) { + /* + * Apparently, "ignore" is similar to + * "comment" in that it can apply to + * the preceeding item. + */ + 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); } } - return (0); -error: - if (fp != NULL) - fclose(fp); - return (rval); } + +/* + * 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); + } +}