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/