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