Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT cygwin DOT com Mail-Followup-To: cygwin AT cygwin DOT com Delivered-To: mailing list cygwin AT cygwin DOT com Message-ID: <437013E8.8030101@cwilson.fastmail.fm> Date: Mon, 07 Nov 2005 21:56:40 -0500 From: Charles Wilson User-Agent: Mozilla Thunderbird 1.0.6 (Windows/20050716) MIME-Version: 1.0 To: cygwin AT cygwin DOT com Subject: Re: BUG: alternatives References: <436CF5E9 DOT 30106 AT cwilson DOT fastmail DOT fm> <001201c5e244$c9e50490$020aa8c0 AT DFW5RB41> <436D9993 DOT 7050100 AT cwilson DOT fastmail DOT fm> <20051106134339 DOT GA24549 AT trixie DOT casa DOT cgf DOT cx> <436E50DE DOT 3070405 AT cwilson DOT fastmail DOT fm> <20051107005502 DOT GA8754 AT trixie DOT casa DOT cgf DOT cx> In-Reply-To: <20051107005502.GA8754@trixie.casa.cgf.cx> Content-Type: multipart/mixed; boundary="------------070000070704000008060702" --------------070000070704000008060702 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit 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 --------------070000070704000008060702 Content-Type: text/plain; name="alternatives-textmode-3.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="alternatives-textmode-3.patch" 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++) { --------------070000070704000008060702 Content-Type: text/plain; charset=us-ascii -- 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/ --------------070000070704000008060702--