This is the mail archive of the cygwin mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: BUG: alternatives


Christopher Faylor wrote:

I have mixed feelings about alloca, personally.  I use it all of the time but
it is always with some trepidation because, AFAIK, the failure condition for
alloca is a SEGV.  OTOH, it is very convenient.

In this case, however, I think you really want to use realloc.  You could even
rely on the fact that realloc(NULL, n) is equivalent to malloc(n).

Okay, revised patch attached if anybody cares to comment. But more importantly, a test release (1.3.20a-2) should be up on the mirrors soon.


--
Chuck

diff -urN -x .build -x .inst -x .sinst -x .gmo -x .mo alternatives-1.3.20a-orig/alternatives.c alternatives-1.3.20a/alternatives.c
--- alternatives-1.3.20a-orig/alternatives.c	2005-06-25 21:55:02.000000000 -0400
+++ alternatives-1.3.20a/alternatives.c	2005-11-07 21:31:01.939142400 -0500
@@ -17,6 +17,23 @@
 #define	FLAGS_TEST	(1 << 0)
 #define	FLAGS_VERBOSE	(1 << 1)
 
+#if defined(O_BINARY)
+# define _O_BINARY		O_BINARY
+# define FOPEN_WRITE_MODE	"wb"
+# define FOPEN_READ_MODE	"rb"
+#else
+# define _O_BINARY		0
+# define FOPEN_WRITE_MODE	"w"
+# define FOPEN_READ_MODE	"r"
+#endif
+
+#define PARANOID_FREE(stale) do { \
+  if (stale) { free ((void *) stale); stale = 0; } \
+} while (0)
+#define READCONFIG_BUF_INITIALSZ	16
+#define READCONFIG_BUF_BEHAVIOR_THRESH	4096
+
+
 #define FL_TEST(flags)	    ((flags) & FLAGS_TEST)
 #define FL_VERBOSE(flags)   ((flags) & FLAGS_VERBOSE)
 
@@ -115,16 +132,30 @@
 
 char * parseLine(char ** buf) {
     char * start = *buf;
-    char * end;
+    char * end1 = *buf;
+    char * end2;
 
     if (!*buf || !**buf) return NULL;
 
-    end = strchr(start, '\n');
-    if (!end) {
-	*buf = start + strlen(start);
-    } else {
-	*buf = end + 1;
-	*end = '\0';
+    while (*end1 && (*end1 != '\n') && (*end1 != '\r'))
+       end1++;
+
+    end2 = end1;
+    while (*end2 && (*end2 == '\r')) /* only walk past '\r', NOT '\n' */
+    {
+       *end2 = '\0';
+       end2++;
+    }
+
+    /* ensures this parseLine() only consumes ONE '\n' */
+    if (*end2 == '\n')
+    {
+       *buf = end2 + 1;
+       *end2 = '\0';
+    }
+    else
+    {
+       *buf = end2;
     }
 
     while (isspace(*start) && *start) start++;
@@ -139,6 +170,7 @@
     int i;
     struct stat sb;
     char * buf;
+    char * bufp;
     char * end;
     char * line;
     struct {
@@ -147,6 +179,9 @@
     } * groups = NULL;
     int numGroups = 0;
     char linkBuf[1024];
+    size_t curBufSz;
+    size_t totalBytesRead;
+    size_t numBytesRead;
 
     set->alts = NULL;
     set->numAlts = 0;
@@ -160,26 +195,50 @@
     if (FL_VERBOSE(flags))
 	printf(_("reading %s\n"), path);
 
-    if ((fd = open(path, O_RDONLY)) < 0) {
+    if ((fd = open(path, O_RDONLY | _O_BINARY)) < 0) {
 	if (errno == ENOENT) return 3;
 	fprintf(stderr, _("failed to open %s: %s\n"), path,
 	        strerror(errno));
 	return 1;
     }
 
-    fstat(fd, &sb);
-    buf = alloca(sb.st_size + 1);
-    if (read(fd, buf, sb.st_size) != sb.st_size) {
-	close(fd);
+    curBufSz = READCONFIG_BUF_INITIALSZ;
+    totalBytesRead = 0;
+    numBytesRead = 0;
+    buf = NULL;
+    do
+    {
+       if (curBufSz < READCONFIG_BUF_BEHAVIOR_THRESH)
+          curBufSz *= 2;
+       else
+          curBufSz += READCONFIG_BUF_BEHAVIOR_THRESH;
+
+       buf = realloc(buf, curBufSz + 1);
+
+       bufp = buf + totalBytesRead;
+       numBytesRead = read(fd, bufp, curBufSz - totalBytesRead);
+
+       /* don't add '-1' ! */
+       if (numBytesRead > 0)
+           totalBytesRead += numBytesRead;
+    }
+    while (numBytesRead > 0);
+
+    if (numBytesRead < 0)
+    {
+        close(fd);
+        PARANOID_FREE(buf);
 	fprintf(stderr, _("failed to read %s: %s\n"), path,
 	        strerror(errno));
 	return 1;
     }
     close(fd);
-    buf[sb.st_size] = '\0';
+    buf[curBufSz] = '\0';
+    bufp = buf;
 
-    line = parseLine(&buf);
+    line = parseLine(&bufp);
     if (!line) {
+        PARANOID_FREE(buf);
 	fprintf(stderr, _("%s empty!\n"), path);
 	return 1;
     }
@@ -189,13 +248,15 @@
     } else if (!strcmp(line, "manual")) {
 	set->mode = MANUAL;
     } else {
+        PARANOID_FREE(buf);
 	fprintf(stderr, _("bad mode on line 1 of %s\n"), path);
 	return 1;
     }
     free(line);
 
-    line = parseLine(&buf);
+    line = parseLine(&bufp);
     if (!line || *line != '/') {
+        PARANOID_FREE(buf);
 	fprintf(stderr, _("bad primary link in %s\n"), path);
 	return 1;
     }
@@ -205,9 +266,10 @@
     groups[0].facility = line;
     numGroups = 1;
 
-    line = parseLine(&buf);
+    line = parseLine(&bufp);
     while (line && *line) {
 	if (*line == '/') {
+            PARANOID_FREE(buf);
 	    fprintf(stderr, _("path %s unexpected in %s\n"), line, path);
 	    return 1;
 	}
@@ -215,27 +277,30 @@
 	groups = realloc(groups, sizeof(*groups) * (numGroups + 1));
 	groups[numGroups].title = line;
 
-	line = parseLine(&buf);
+	line = parseLine(&bufp);
 	if (!line || !*line) {
+            PARANOID_FREE(buf);
 	    fprintf(stderr, _("missing path for slave %s in %s\n"), line, path);
 	    return 1;
 	}
 
 	groups[numGroups++].facility = line;
 
-	line = parseLine(&buf);
+	line = parseLine(&bufp);
     }
 
     if (!line) {
+        PARANOID_FREE(buf);
 	fprintf(stderr, _("unexpected end of file in %s\n"), path);
 	return 1;
     }
 
-    line = parseLine(&buf);
+    line = parseLine(&bufp);
     while (line && *line) {
 	set->alts = realloc(set->alts, (set->numAlts + 1) * sizeof(*set->alts));
 
 	if (*line != '/') {
+            PARANOID_FREE(buf);
 	    fprintf(stderr, _("path to alternate expected in %s\n"), path);
 	    return 1;
 	}
@@ -251,11 +316,12 @@
 	else
 	    set->alts[set->numAlts].slaves = NULL;
 
-	line = parseLine(&buf);
+	line = parseLine(&bufp);
 	set->alts[set->numAlts].priority = -1;
 	set->alts[set->numAlts].priority = strtol(line, &end, 0);
 	set->alts[set->numAlts].initscript = NULL;
 	if (!end || (end == line)) {
+            PARANOID_FREE(buf);
 	    fprintf(stderr, _("numeric priority expected in %s\n"), path);
 	    return 1;
 	}
@@ -276,8 +342,9 @@
 	    set->best = set->numAlts;
 
 	for (i = 1; i < numGroups; i++) {
-	    line = parseLine(&buf);
+	    line = parseLine(&bufp);
 	    if (line && strlen(line) && *line != '/') {
+                PARANOID_FREE(buf);
 		fprintf(stderr, _("slave path expected in %s\n"), path);
 		return 1;
 	    }
@@ -291,12 +358,13 @@
 
 	set->numAlts++;
 
-	line = parseLine(&buf);
+	line = parseLine(&bufp);
     }
 
     while (line) {
-	line = parseLine(&buf);
+	line = parseLine(&bufp);
 	if (line && *line) {
+            PARANOID_FREE(buf);
 	    fprintf(stderr, _("unexpected line in %s: %s\n"), path, line);
 	    return 1;
 	}
@@ -305,6 +373,7 @@
     sprintf(path, "%s/%s", altDir, set->alts[0].master.title);
 
     if (((i = readlink(path, linkBuf, sizeof(linkBuf) - 1)) < 0)) {
+        PARANOID_FREE(buf);
 	fprintf(stderr, _("failed to read link %s: %s\n"),
 		set->alts[0].master.facility, strerror(errno));
 	return 2;
@@ -331,6 +400,7 @@
 
     set->currentLink = strdup(linkBuf);
 
+    PARANOID_FREE(buf);
     return 0;
 }
 
@@ -414,7 +484,7 @@
     if (FL_TEST(flags))
 	fd = dup(1);
     else
-	fd = open(path, O_RDWR | O_CREAT | O_EXCL, 0644);
+	fd = open(path, O_RDWR | O_CREAT | O_EXCL | _O_BINARY, 0644);
 
     if (fd < 0) {
 	if (errno == EEXIST) 
@@ -425,7 +495,7 @@
 	return 1;
     }
 
-    f = fdopen(fd, "w");
+    f = fdopen(fd, FOPEN_WRITE_MODE); 
     fprintf(f, "%s\n", set->mode == AUTO ? "auto" : "manual");
     fprintf(f, "%s\n", set->alts[0].master.facility);
     for (i = 0; i < set->alts[0].numSlaves; i++) {

--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Problem reports:       http://cygwin.com/problems.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]