]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
cut,fold,expand,unexpand: ensure we process all available characters
authorPádraig Brady <P@draigBrady.com>
Thu, 2 Apr 2026 19:19:07 +0000 (20:19 +0100)
committerPádraig Brady <P@draigBrady.com>
Mon, 6 Apr 2026 14:52:56 +0000 (15:52 +0100)
* gl/lib/mbbuf.h: Adjust mbbuf_fill() to process full characters
in the slop at the end of a read().  Previously valid characters
in the last MCEL_LEN_MAX bytes were ignored until the next read().
* src/cut.c (cut_fields_bytesearch): Adjust to the new naming.
* NEWS: Mention the fold(1) responsiveness fix, which was
improved with the change from fread() to read(),
and completed with this patch.

NEWS
gl/lib/mbbuf.h
src/cut.c

diff --git a/NEWS b/NEWS
index 98f0724e3623c93b15d898d76919f1f2d843e3fa..a2ff40ee4b155b722fc0b9e8c141fb428abf86f6 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -11,6 +11,10 @@ GNU coreutils NEWS                                    -*- outline -*-
   'fold' will no longer truncate output when encountering 0xFF bytes.
   [bug introduced in coreutils-9.8]
 
+  'fold' is again responsive to its input.  Previously it would have delayed
+  processing until 256KiB was read from the input.
+  [bug introduced in coreutils-9.8]
+
   'kill --help' now has links to valid anchors in the html manual.
   [bug introduced in coreutils-9.10]
 
index ed02a83d54e361a1929da0785f144bf8d6a02abe..715bec6c344b8f5762b1590cfa6269218393db81 100644 (file)
@@ -79,7 +79,7 @@ mbbuf_init (mbbuf_t *mbbuf, char *buffer, idx_t size, FILE *fp)
    At end of file, MBBUF.EOF is set, and zero will eventually be returned.
    Note feof() will _NOT_ be set on the MBBUF.FP.  */
 MBBUF_INLINE idx_t
-mbbuf_fill (mbbuf_t *mbbuf)
+mbbuf_topup (mbbuf_t *mbbuf)
 {
   idx_t available = mbbuf_avail (mbbuf);
 
@@ -114,6 +114,27 @@ mbbuf_fill (mbbuf_t *mbbuf)
   return available;
 }
 
+/* Fill the input buffer enough to scan the next character if possible.
+   Return the number of bytes available from the current offset.  */
+MBBUF_INLINE idx_t
+mbbuf_fill (mbbuf_t *mbbuf)
+{
+  idx_t available = mbbuf_avail (mbbuf);
+
+  if (available == 0)
+    return mbbuf_topup (mbbuf);
+
+  if (available < MCEL_LEN_MAX && ! mbbuf->eof)
+    {
+      mcel_t g = mcel_scan (mbbuf->buffer + mbbuf->offset,
+                            mbbuf->buffer + mbbuf->length);
+      if (g.err)
+        return mbbuf_topup (mbbuf);
+    }
+
+  return available;
+}
+
 /* Consume N bytes from the current buffer.  */
 MBBUF_INLINE void
 mbbuf_advance (mbbuf_t *mbbuf, idx_t n)
index 85b3287cd6c25651627e0be103bad30b031afab7..80e34cc0951a9a1577f003bb4e7bb593b22ec2ae 100644 (file)
--- a/src/cut.c
+++ b/src/cut.c
@@ -1042,7 +1042,7 @@ cut_fields_bytesearch (FILE *stream)
 
   while (true)
     {
-      idx_t n_avail = mbbuf_fill (&mbbuf);
+      idx_t n_avail = mbbuf_topup (&mbbuf);
       search.at_eof = mbbuf.eof;
       search.line_end_known = false;