git: 25696725b65b - main - patch: use getline() instead of fgetln()

From: Warner Losh <imp_at_FreeBSD.org>
Date: Fri, 19 Apr 2024 21:52:44 UTC
The branch main has been updated by imp:

URL: https://cgit.FreeBSD.org/src/commit/?id=25696725b65b651814799574fdfadb1b1a5e0b02

commit 25696725b65b651814799574fdfadb1b1a5e0b02
Author:     Martin Tournoij <martin@arp242.net>
AuthorDate: 2024-04-19 21:11:30 +0000
Commit:     Warner Losh <imp@FreeBSD.org>
CommitDate: 2024-04-19 21:52:22 +0000

    patch: use getline() instead of fgetln()
    
    This replaces fgetln() with getline(). The main reason for this is
    portability, making things easier for people who want to compile these
    tools on non-FreeBSD systems.
    
    I appreciate that's probably not the top concern for FreeBSD base tools,
    but fgetln() is impossible to port to most platforms, as concurrent
    access is essentially impossible to implement fully correct without the
    line buffer on the FILE struct. Other than this, many generic FreeBSD
    tools compile fairly cleanly on Linux with a few small changes.
    
    Most uses of fgetln() pre-date getline() support (added in 2009 with
    69099ba2ec8b), and there's been some previous patches (ee3ca711a898
    8c98e6b1a7f3 1a2a4fc8ce1b) for other tools.
    
    Obtained from:  https://github.com/dcantrell/bsdutils and
                    https://github.com/chimera-linux/chimerautils
    Signed-off-by: Martin Tournoij <martin@arp242.net>
    Reviewed by: imp
    Pull Request: https://github.com/freebsd/freebsd-src/pull/893
---
 usr.bin/patch/inp.c | 19 +++++++------------
 usr.bin/patch/pch.c | 17 ++++++++++-------
 2 files changed, 17 insertions(+), 19 deletions(-)

diff --git a/usr.bin/patch/inp.c b/usr.bin/patch/inp.c
index 24fdcac1b7c6..ccc9a39b117b 100644
--- a/usr.bin/patch/inp.c
+++ b/usr.bin/patch/inp.c
@@ -283,8 +283,9 @@ static void
 plan_b(const char *filename)
 {
 	FILE	*ifp;
-	size_t	i, j, len, maxlen;
-	char	*lbuf = NULL, *p;
+	size_t i = 0, j, blen = 0, maxlen = 1;
+	ssize_t len;
+	char *p = NULL;
 	bool	found_revision = (revision == NULL);
 
 	using_plan_a = false;
@@ -295,26 +296,20 @@ plan_b(const char *filename)
 		pfatal("can't open file %s", TMPINNAME);
 	len = 0;
 	maxlen = 1;
-	while ((p = fgetln(ifp, &len)) != NULL) {
+	while ((len = getline(&p, &blen, ifp)) >= 0) {
 		if (p[len - 1] == '\n')
 			p[len - 1] = '\0';
 		else {
-			/* EOF without EOL, copy and add the NUL */
-			if ((lbuf = malloc(len + 1)) == NULL)
-				fatal("out of memory\n");
-			memcpy(lbuf, p, len);
-			lbuf[len] = '\0';
-			p = lbuf;
-
+			/* EOF without EOL */
 			last_line_missing_eol = true;
 			len++;
 		}
 		if (revision != NULL && !found_revision && rev_in_string(p))
 			found_revision = true;
-		if (len > maxlen)
+		if ((size_t)len > maxlen)
 			maxlen = len;   /* find longest line */
 	}
-	free(lbuf);
+	free(p);
 	if (ferror(ifp))
 		pfatal("can't read file %s", filename);
 
diff --git a/usr.bin/patch/pch.c b/usr.bin/patch/pch.c
index fb53ff86f9ef..71f73125a8cb 100644
--- a/usr.bin/patch/pch.c
+++ b/usr.bin/patch/pch.c
@@ -1213,14 +1213,15 @@ hunk_done:
 size_t
 pgets(bool do_indent)
 {
-	char *line;
-	size_t len = 0;
+	char *line = NULL;
+	ssize_t len = 0;
+	size_t buflen = 0;
 	int indent = 0, skipped = 0;
 
-	line = fgetln(pfp, &len);
-	if (line != NULL) {
-		if (len + 1 > buf_size) {
-			while (len + 1 > buf_size)
+	if ((len = getline(&line, &buflen, pfp)) >= 0) {
+		char *linep = line;
+		if ((size_t)(len + 1) > buf_size) {
+			while ((size_t)(len + 1) > buf_size)
 				buf_size *= 2;
 			free(buf);
 			buf = malloc(buf_size);
@@ -1239,8 +1240,10 @@ pgets(bool do_indent)
 		}
 		memcpy(buf, line, len - skipped);
 		buf[len - skipped] = '\0';
+		line = linep;
 	}
-	return len;
+	free(line);
+	return (len > 0) ? len : 0;
 }