PERFORCE change 178862 for review
Garrett Cooper
gcooper at FreeBSD.org
Thu May 27 08:59:33 UTC 2010
http://p4web.freebsd.org/@@178862?ac=10
Change 178862 by gcooper at gcooper-bayonetta on 2010/05/27 08:58:57
Partially fix the linereading mechanism in read_plist I broke in @178293
when I removed the fgets invocation.
Affected files ...
.. //depot/projects/soc2007/gcooper-pkg_install-enhancements-simplified/lib/libpkg/plist.c#5 edit
Differences ...
==== //depot/projects/soc2007/gcooper-pkg_install-enhancements-simplified/lib/libpkg/plist.c#5 (text+ko) ====
@@ -22,10 +22,14 @@
__FBSDID("$FreeBSD: src/lib/libpkg/plist.c,v 1.1 2010/04/23 11:07:43 flz Exp $");
#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
#include <sys/uio.h>
+#include <assert.h>
#include <err.h>
#include <errno.h>
#include <md5.h>
+#include <string.h>
#include <unistd.h>
#include "pkg.h"
@@ -196,7 +200,7 @@
char *cp;
const char *sp;
- strcpy(cmd, s);
+ strlcpy(cmd, s, sizeof(cmd));
str_lowercase(cmd);
cp = cmd;
sp = s;
@@ -264,72 +268,163 @@
int
read_plist(Package *pkg, int fd)
{
- char *cp, pline[FILENAME_MAX];
- int cmd, major, minor, rc = 0;
+ struct stat sb;
+ char *cmd_buf = NULL;
+ char *contents_map = NULL;
+ char *cp;
+ char *end;
+ char *start;
+ int cmd;
+ int serrno;
+ int major;
+ int minor;
+ int rc = -1;
+ off_t off;
size_t len;
pkg->fmtver_maj = 1;
pkg->fmtver_mnr = 0;
pkg->origin = NULL;
- /*
- * XXX (gcooper): BAD BAD BAD -- this can be longer than
- * FILENAME_MAX
- */
- while (rc == 0 && 0 < read(fd, pline, FILENAME_MAX)) {
- len = strlen(pline);
+ errno = 0;
+
+ if (fstat(fd, &sb) == 0 &&
+ (contents_map = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd,
+ 0)) != NULL) {
+
+ off = sb.st_size;
+ rc = 0;
+ start = contents_map;
+
+ /*
+ * XXX (gcooper): BAD BAD BAD -- this can be longer than
+ * FILENAME_MAX
+ */
+ while (rc == 0 && 0 < off) {
+
+ end = strchr(start, '\n');
+ /* No trailing newlines -- look for '\0'. */
+ if (end == NULL)
+ end = strchr(start, '\0');
+ /* Don't forget we're eating newlines.. om nom nom... */
+ else
+ off--;
+ /*
+ * This is bad if this fails -- a non-NUL terminated
+ * string is in our midst!
+ */
+ assert (end != NULL);
+
+ cmd_buf = malloc(end-start+1);
+
+ if (cmd_buf == NULL)
+ rc = -1;
+ else {
+
+ strlcpy(cmd_buf, start, end-start+1);
+
+ warnx("cmd_buf: %s", cmd_buf);
+
+ len = strlen(cmd_buf);
+ off -= len;
+
+ /* Trim off trailing whitespace. */
+ while (0 < len && isspace(cmd_buf[len]))
+ cmd_buf[len--] = '\0';
+
+ /* Empty line. */
+ if (len == 0) {
+ errno = EINVAL;
+ rc = -1;
+ } else
+ cp = cmd_buf;
- while (len && isspace(pline[len - 1]))
- pline[--len] = '\0';
- if (!len)
- continue;
- cp = pline;
- if (pline[0] != CMD_CHAR) {
- cmd = PLIST_FILE;
- goto bottom;
- }
- cmd = plist_cmd(pline + 1, &cp);
- if (cmd == -1) {
- warnx("%s: unknown command '%s' (package tools out of "
- "date?)", __func__, pline);
- goto bottom;
- }
- if (*cp == '\0') {
- cp = NULL;
- if (cmd == PLIST_PKGDEP) {
- warnx("corrupted record (pkgdep line without "
- "argument), ignoring");
- cmd = -1;
}
- goto bottom;
- }
- if (cmd == PLIST_COMMENT &&
- sscanf(cp, "PKG_FORMAT_REVISION:%d.%d\n", &major, &minor) ==
- 2) {
+
+ /* A plist command directive */
+ if (rc == 0 && *start == CMD_CHAR) {
+
+ cmd = plist_cmd(start+1, &cp);
+
+ if (cmd == -1) {
+ warnx("%s: unknown command '%s' "
+ "(package tools out of date?)",
+ __func__, start);
+ rc = -1;
+ } else if (*cp == '\0') {
+
+ cp = NULL;
+ if (cmd == PLIST_PKGDEP) {
+ warnx("corrupted record (pkgdep line "
+ "without argument), ignoring");
+ cmd = rc = -1;
+ }
+
+ }
+ if (cp != NULL && cmd == PLIST_COMMENT &&
+ sscanf(cp, "PKG_FORMAT_REVISION:%d.%d\n",
+ &major, &minor) == 2) {
+
+ pkg->fmtver_maj = major;
+ pkg->fmtver_mnr = minor;
+
+ if (verscmp(pkg, PLIST_FMT_VER_MAJOR,
+ PLIST_FMT_VER_MINOR) > 0) {
+
+ warnx("plist format revision "
+ "(%d.%d) is higher than "
+ "supported format "
+ "reversion (%d.%d)",
+ pkg->fmtver_maj,
+ pkg->fmtver_mnr,
+ PLIST_FMT_VER_MAJOR,
+ PLIST_FMT_VER_MINOR);
+
+ if (pkg->fmtver_maj >
+ PLIST_FMT_VER_MAJOR) {
+ errno = EINVAL;
+ rc = -1;
+ }
+
+ }
+
+ }
- pkg->fmtver_maj = major;
- pkg->fmtver_mnr = minor;
+ }
+ /* A file manifest item */
+ else if (rc == 0)
+ cmd = PLIST_FILE;
+ if (rc == 0) {
- if (verscmp(pkg, PLIST_FMT_VER_MAJOR,
- PLIST_FMT_VER_MINOR) <= 0)
- goto bottom;
+ add_plist(pkg, cmd, cp);
+ start = end;
+ /* We aren't at the end of the line, yet.. */
+ if (start != '\0')
+ start++;
- warnx("plist format revision (%d.%d) is higher than "
- "supported (%d.%d)",
- pkg->fmtver_maj, pkg->fmtver_mnr,
- PLIST_FMT_VER_MAJOR, PLIST_FMT_VER_MINOR);
+ }
- if (pkg->fmtver_maj > PLIST_FMT_VER_MAJOR) {
- errno = EINVAL;
- rc = -1;
+ if (cmd_buf != NULL) {
+ free (cmd_buf);
+ cmd_buf = NULL;
}
}
-bottom:
- if (rc == 0)
- add_plist(pkg, cmd, cp);
+ }
+
+ if (contents_map != NULL) {
+ serrno = errno;
+ munmap(contents_map, sb.st_size);
+ if (serrno == 0)
+ errno = serrno;
+ }
+ if (rc == -1 && cmd_buf != NULL) {
+ serrno = errno;
+ free(cmd_buf);
+ if (serrno == 0)
+ errno = serrno;
}
return rc;
@@ -476,8 +571,9 @@
break;
case PLIST_CWD:
- if (!prefix)
+ if (prefix == NULL)
prefix = p->name;
+ warnx("prefix: %s", prefix);
Where = (p->name == NULL) ? prefix : p->name;
if (Verbose)
printf("Change working directory to %s\n", Where);
More information about the p4-projects
mailing list