Subject: [PATCH] nbcompat fgetln loses on missing newline
To: None <tech-pkg@NetBSD.org>
From: Eric Gillespie <epg@netbsd.org>
List: tech-pkg
Date: 05/15/2005 14:34:09
Run this program on a file with no trailing newline:

#include <nbcompat.h>

int
main(int argc, char *argv[])
{
    FILE *fp;
    size_t len;
    char *line;

    fp = fopen(argv[1], "r");
    while (line = fgetln(fp, &len)) {
        printf("%d ", len); fflush(stdout);
        write(1, line, len); write(1, "\n", 1);
    }

    return 0;
}

0 tmp% echo 'this file has no final newline' > test
0 tmp% echo -n 'oops' >> test
0 tmp% ./a.out test
31 this file has no final newline

8191 oopsfile has no final newline

The problem is the while loop looking for a newline doesn't
realize it may not be there.  Because it uses fgets, which
null-terminates, we can get the length with strlen when at eof:

=== fgetln.c
==================================================================
--- fgetln.c  (revision 343)
+++ fgetln.c  (local)
@@ -60,9 +60,16 @@
 	*len = 0;
 
 	while ((ptr = strchr(&buf[*len], '\n')) == NULL) {
-		size_t nbufsiz = bufsiz + BUFSIZ;
-		char *nbuf = realloc(buf, nbufsiz);
+		size_t nbufsiz;
+		char *nbuf;
 
+		if (feof(fp)) {
+			*len = strlen(buf);
+			return buf;
+		}
+
+		nbufsiz = bufsiz + BUFSIZ;
+		nbuf = realloc(buf, nbufsiz);
 		if (nbuf == NULL) {
 			int oerrno = errno;
 			free(buf);

Any objections?