[{"id":1761886,"web_url":"http://patchwork.ozlabs.org/comment/1761886/","msgid":"<4694e740-6bdb-ef22-a945-21359367c788@redhat.com>","list_archive_url":null,"date":"2017-09-01T18:00:02","subject":"Re: [PATCH] libio: Implement internal function\n\t__libc_readline_unlocked","submitter":{"id":14312,"url":"http://patchwork.ozlabs.org/api/people/14312/","name":"Florian Weimer","email":"fweimer@redhat.com"},"content":"On 09/01/2017 05:43 PM, Florian Weimer wrote:\n> +      int ch = __uflow (fp);\n> +      if (ch == EOF)\n> +        {\n> +          if (_IO_ferror_unlocked (fp))\n> +            /* If the EOF was caused by a read error, report it.  */\n> +            return fail_no_erange ();\n> +          *buffer = '\\0';\n> +          /* Do not include the NULL terminator.  */\n> +          return buffer - start;\n> +        }\n> +\n> +      /* Save the character just read.  */\n> +      *buffer = ch;\n> +      ++buffer;\n> +\n> +      if (ch == '\\n')\n> +        {\n> +          if (buffer == buffer_end)\n> +            /* Not enough room in the caller-supplied buffer.  */\n> +            break;\n> +          *buffer = '\\0';\n> +          /* Do not include the NULL terminator.  */\n> +          return buffer - start;\n> +        }\n\nThis should use __underflow instead of __uflow, so that the need for the\nspecial handling for '\\n' goes away.\n\nHowever, it turns out that this does not actually solve anything on the\nNSS, so I'm not going to commit this.\n\nFlorian","headers":{"Return-Path":"<libc-alpha-return-84044-incoming=patchwork.ozlabs.org@sourceware.org>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":["patchwork-incoming@bilbo.ozlabs.org","mailing list libc-alpha@sourceware.org"],"Authentication-Results":["ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=sourceware.org\n\t(client-ip=209.132.180.131; helo=sourceware.org;\n\tenvelope-from=libc-alpha-return-84044-incoming=patchwork.ozlabs.org@sourceware.org;\n\treceiver=<UNKNOWN>)","ozlabs.org; dkim=pass (1024-bit key;\n\tsecure) header.d=sourceware.org header.i=@sourceware.org\n\theader.b=\"leEAIzCE\"; dkim-atps=neutral","sourceware.org; auth=none","ext-mx03.extmail.prod.ext.phx2.redhat.com;\n\tdmarc=none (p=none dis=none) header.from=redhat.com","ext-mx03.extmail.prod.ext.phx2.redhat.com;\n\tspf=fail smtp.mailfrom=fweimer@redhat.com"],"Received":["from sourceware.org (server1.sourceware.org [209.132.180.131])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256\n\tbits)) (No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3xkRqq1pyFz9s7M\n\tfor <incoming@patchwork.ozlabs.org>;\n\tSat,  2 Sep 2017 04:00:55 +1000 (AEST)","(qmail 82814 invoked by alias); 1 Sep 2017 18:00:37 -0000","(qmail 82169 invoked by uid 89); 1 Sep 2017 18:00:15 -0000"],"DomainKey-Signature":"a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id\n\t:list-unsubscribe:list-subscribe:list-archive:list-post\n\t:list-help:sender:subject:from:to:references:message-id:date\n\t:mime-version:in-reply-to:content-type\n\t:content-transfer-encoding; q=dns; s=default; b=hJ225jGwxklUKxeW\n\tw6t7yh5x9b+VIaCatcj0Xy1rOjkP4ofYAf2hvHcraGfbH3ZERPwLS+q3UXLgz/sk\n\t656xq3ekH7fZxmbaBN+flU9GYkJUbHj6mYRHonNuJX8/w+rLRk2H4SBxuxB3YhXi\n\tU8NHAl60/L7rBkskaAIyhk4NiWc=","DKIM-Signature":"v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id\n\t:list-unsubscribe:list-subscribe:list-archive:list-post\n\t:list-help:sender:subject:from:to:references:message-id:date\n\t:mime-version:in-reply-to:content-type\n\t:content-transfer-encoding; s=default; bh=zOFTNRhW5zjTd2GsOdJmiG\n\tNlnlQ=; b=leEAIzCEnb2hcTucDv1Q+4RoBD/k8MvGgr82GzNbulyPZRqEnFEOOl\n\tP0c+OC+e4jNNPocuhT2o9IM+PhkIZ6a1F2UGDTt32XXFoIqnpY3Ga3ZIgaoVbtyi\n\tp4I/dmhyUuwdBmNyF4UsI+0EPvr73XUsolakQGVUaOT2NGHO5DmLQ=","Mailing-List":"contact libc-alpha-help@sourceware.org; run by ezmlm","Precedence":"bulk","List-Id":"<libc-alpha.sourceware.org>","List-Unsubscribe":"<mailto:libc-alpha-unsubscribe-incoming=patchwork.ozlabs.org@sourceware.org>","List-Subscribe":"<mailto:libc-alpha-subscribe@sourceware.org>","List-Archive":"<http://sourceware.org/ml/libc-alpha/>","List-Post":"<mailto:libc-alpha@sourceware.org>","List-Help":"<mailto:libc-alpha-help@sourceware.org>,\n\t<http://sourceware.org/ml/#faqs>","Sender":"libc-alpha-owner@sourceware.org","X-Virus-Found":"No","X-Spam-SWARE-Status":"No, score=-0.9 required=5.0 tests=BAYES_00,\n\tKAM_LAZY_DOMAIN_SECURITY, RP_MATCHES_RCVD,\n\tSPF_HELO_PASS autolearn=no version=3.3.2 spammy=","X-HELO":"mx1.redhat.com","DMARC-Filter":"OpenDMARC Filter v1.3.2 mx1.redhat.com 4145F7E454","Subject":"Re: [PATCH] libio: Implement internal function\n\t__libc_readline_unlocked","From":"Florian Weimer <fweimer@redhat.com>","To":"libc-alpha@sourceware.org","References":"<20170901154335.E5819439942E3@oldenburg.str.redhat.com>","Message-ID":"<4694e740-6bdb-ef22-a945-21359367c788@redhat.com>","Date":"Fri, 1 Sep 2017 20:00:02 +0200","User-Agent":"Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101\n\tThunderbird/52.2.1","MIME-Version":"1.0","In-Reply-To":"<20170901154335.E5819439942E3@oldenburg.str.redhat.com>","Content-Type":"text/plain; charset=utf-8","Content-Transfer-Encoding":"7bit"}},{"id":1762176,"web_url":"http://patchwork.ozlabs.org/comment/1762176/","msgid":"<ab9faefa-7875-4380-fca0-87767bf271f0@redhat.com>","list_archive_url":null,"date":"2017-09-02T19:10:04","subject":"Re: [PATCH] libio: Implement internal function\n\t__libc_readline_unlocked","submitter":{"id":14312,"url":"http://patchwork.ozlabs.org/api/people/14312/","name":"Florian Weimer","email":"fweimer@redhat.com"},"content":"On 09/01/2017 08:00 PM, Florian Weimer wrote:\n> This should use __underflow instead of __uflow, so that the need for the\n> special handling for '\\n' goes away.\n\nHere is the version based on __underflow.  I changed the way the\n__ftello64 and __fseeko64 aliases are handled because the other patch\nneeds to call __fseko64 from a DSO, so the hidden symbol no longer works.\n\nThanks,\nFlorian\nlibio: Implement internal function __libc_readline_unlocked\n\nThis is a variant of fgets which fails with ERANGE if the\nbuffer is too small, and the buffer length is given as an\nargument of type size_t.\n\nThis function will be useful for implementing NSS file reading\noperations.  Compared to a direct implementation using the public API,\nit avoids an lseek system call in case the line terminator can be\nfound in the internal read buffer.\n\n2017-09-02  Florian Weimer  <fweimer@redhat.com>\n\n\t* include/stdio.h (__libc_readline_unlocked): Declare.\n\t(__ftello64, __fseeko64): Declare aliases.\n\t* libio/readline.c: New file.\n\t* libio/tst-readline.c: Likewise.\n\t(routines): Add readline.\n\t(tests-internal): Add tst-readlime.\n\t* libio/Versions (GLIBC_PRIVATE): Export __fseeko64, __ftello64,\n\t__libc_readline_unlocked.\n\t* libio/fseeko.c (__fseeko): Rename from fseeko.\n\t(fseeko): Add alias.\n\t[__OFF_T_MATCHES_OFF64_T] (fseeko64, __fseeko64): Likewise.\n\t* libio/fseeko64.c (__fseeko64): Rename from fseeko64.\n\t(fseeko64): Add alias.\n\t* libio/ftello.c [__OFF_T_MATCHES_OFF64_T] (__ftello64): Add alias.\n\t* libio/ftello64.c (__ftello64): Rename from ftello64.\n\t(ftello64): Add alias.\n\ndiff --git a/include/stdio.h b/include/stdio.h\nindex 509447c528..50b4191279 100644\n--- a/include/stdio.h\n+++ b/include/stdio.h\n@@ -122,6 +122,18 @@ extern int __fxprintf (FILE *__fp, const char *__fmt, ...)\n extern int __fxprintf_nocancel (FILE *__fp, const char *__fmt, ...)\n      __attribute__ ((__format__ (__printf__, 2, 3)));\n \n+/* Read the next line from FP into BUFFER, of LENGTH bytes.  LINE will\n+   include the line terminator and a NUL terminator.  On success,\n+   return the length of the line, including the line terminator, but\n+   excluding the NUL termintor.  On EOF, return zero and write a NUL\n+   terminator.  On error, return -1 and set errno.  If the total byte\n+   count (line and both terminators) exceeds LENGTH, return -1 and set\n+   errno to ERANGE (but do not mark the stream as failed).\n+\n+   The behavior is undefined if FP is not seekable.  */\n+ssize_t __libc_readline_unlocked (_IO_FILE *fp, char *buffer, size_t length);\n+libc_hidden_proto (__libc_readline_unlocked);\n+\n extern const char *const _sys_errlist_internal[] attribute_hidden;\n extern int _sys_nerr_internal attribute_hidden;\n \n@@ -161,6 +173,10 @@ libc_hidden_proto (fwrite)\n libc_hidden_proto (fseek)\n extern __typeof (ftello) __ftello;\n libc_hidden_proto (__ftello)\n+extern __typeof (fseeko64) __fseeko64;\n+libc_hidden_proto (__fseeko64)\n+extern __typeof (ftello64) __ftello64;\n+libc_hidden_proto (__ftello64)\n libc_hidden_proto (fflush)\n libc_hidden_proto (fflush_unlocked)\n extern __typeof (fflush_unlocked) __fflush_unlocked;\ndiff --git a/libio/Makefile b/libio/Makefile\nindex 9d09bd8b6a..85da7dc42f 100644\n--- a/libio/Makefile\n+++ b/libio/Makefile\n@@ -47,7 +47,7 @@ routines\t:=\t\t\t\t\t\t\t      \\\n \t__fbufsize __freading __fwriting __freadable __fwritable __flbf\t      \\\n \t__fpurge __fpending __fsetlocking\t\t\t\t      \\\n \t\t\t\t\t\t\t\t\t      \\\n-\tlibc_fatal fmemopen oldfmemopen vtables\n+\tlibc_fatal fmemopen oldfmemopen vtables readline\n \n tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc   \\\n \ttst_wprintf2 tst-widetext test-fmemopen tst-ext tst-ext2 \\\n@@ -63,6 +63,9 @@ tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc   \\\n \ttst-setvbuf1 tst-popen1 tst-fgetwc bug-wsetpos tst-fseek \\\n \ttst-fwrite-error tst-ftell-partial-wide tst-ftell-active-handler \\\n \ttst-ftell-append tst-fputws\n+\n+tests-internal = tst-readline\n+\n ifeq (yes,$(build-shared))\n # Add test-fopenloc only if shared library is enabled since it depends on\n # shared localedata objects.\ndiff --git a/libio/Versions b/libio/Versions\nindex 77123347e3..acb896afa9 100644\n--- a/libio/Versions\n+++ b/libio/Versions\n@@ -158,5 +158,9 @@ libc {\n \n     # Used by NPTL\n     _IO_enable_locks;\n+\n+    __fseeko64;\n+    __ftello64;\n+    __libc_readline_unlocked;\n   }\n }\ndiff --git a/libio/fseeko.c b/libio/fseeko.c\nindex b77d4be18f..606a30366f 100644\n--- a/libio/fseeko.c\n+++ b/libio/fseeko.c\n@@ -28,7 +28,7 @@\n #include \"stdio.h\"\n \n int\n-fseeko (_IO_FILE *fp, off_t offset, int whence)\n+__fseeko (_IO_FILE *fp, off_t offset, int whence)\n {\n   int result;\n   CHECK_FILE (fp, -1);\n@@ -38,6 +38,10 @@ fseeko (_IO_FILE *fp, off_t offset, int whence)\n   return result;\n }\n \n+weak_alias (__fseeko, fseeko)\n+\n #ifdef __OFF_T_MATCHES_OFF64_T\n-weak_alias (fseeko, fseeko64)\n+weak_alias (__fseeko, fseeko64)\n+strong_alias (__fseeko, __fseeko64)\n+libc_hidden_ver (__fseeko, __fseeko64)\n #endif\ndiff --git a/libio/fseeko64.c b/libio/fseeko64.c\nindex 12221d585e..fd612f4ed8 100644\n--- a/libio/fseeko64.c\n+++ b/libio/fseeko64.c\n@@ -32,7 +32,7 @@\n #ifndef __OFF_T_MATCHES_OFF64_T\n \n int\n-fseeko64 (_IO_FILE *fp, __off64_t offset, int whence)\n+__fseeko64 (_IO_FILE *fp, __off64_t offset, int whence)\n {\n   int result;\n   CHECK_FILE (fp, -1);\n@@ -42,4 +42,8 @@ fseeko64 (_IO_FILE *fp, __off64_t offset, int whence)\n   return result;\n }\n \n+libc_hidden_def (__fseeko64)\n+\n+weak_alias (__fseeko64, fseeko64)\n+\n #endif\ndiff --git a/libio/ftello.c b/libio/ftello.c\nindex 9791e835c6..a11c54d63c 100644\n--- a/libio/ftello.c\n+++ b/libio/ftello.c\n@@ -61,4 +61,6 @@ weak_alias (__ftello, ftello)\n \n #ifdef __OFF_T_MATCHES_OFF64_T\n weak_alias (__ftello, ftello64)\n+strong_alias (__ftello, __ftello64)\n+libc_hidden_ver (__ftello, __ftello64)\n #endif\ndiff --git a/libio/ftello64.c b/libio/ftello64.c\nindex 15518af7a6..afa0703f2e 100644\n--- a/libio/ftello64.c\n+++ b/libio/ftello64.c\n@@ -32,7 +32,7 @@\n #ifndef __OFF_T_MATCHES_OFF64_T\n \n off64_t\n-ftello64 (_IO_FILE *fp)\n+__ftello64 (_IO_FILE *fp)\n {\n   _IO_off64_t pos;\n   CHECK_FILE (fp, -1L);\n@@ -53,4 +53,8 @@ ftello64 (_IO_FILE *fp)\n   return pos;\n }\n \n+libc_hidden_def (__ftello64)\n+\n+weak_alias (__ftello64, ftello64)\n+\n #endif\ndiff --git a/libio/readline.c b/libio/readline.c\nnew file mode 100644\nindex 0000000000..0d46844c1a\n--- /dev/null\n+++ b/libio/readline.c\n@@ -0,0 +1,169 @@\n+/* fgets with ERANGE error reporting and size_t buffer length.\n+   Copyright (C) 2017 Free Software Foundation, Inc.\n+   This file is part of the GNU C Library.\n+\n+   The GNU C Library is free software; you can redistribute it and/or\n+   modify it under the terms of the GNU Lesser General Public\n+   License as published by the Free Software Foundation; either\n+   version 2.1 of the License, or (at your option) any later version.\n+\n+   The GNU C Library is distributed in the hope that it will be useful,\n+   but WITHOUT ANY WARRANTY; without even the implied warranty of\n+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n+   Lesser General Public License for more details.\n+\n+   You should have received a copy of the GNU Lesser General Public\n+   License along with the GNU C Library; if not, see\n+   <http://www.gnu.org/licenses/>.  */\n+\n+#include <assert.h>\n+#include <errno.h>\n+#include <stdio.h>\n+#include <string.h>\n+\n+#include \"libioP.h\"\n+\n+/* Return -1 and set errno to EINVAL if it is ERANGE.  */\n+static ssize_t\n+fail_no_erange (void)\n+{\n+  if (errno == ERANGE)\n+    __set_errno (EINVAL);\n+  return -1;\n+}\n+\n+/* Slow path for reading the line.  Called with no data in the stream\n+   read buffer.  Write data to [BUFFER, BUFFER_END).  */\n+static ssize_t\n+readline_slow (_IO_FILE *fp, char *buffer, char *buffer_end)\n+{\n+  char *start = buffer;\n+\n+  while (buffer < buffer_end)\n+    {\n+      if (__underflow (fp) == EOF)\n+        {\n+          if (_IO_ferror_unlocked (fp))\n+            /* If the EOF was caused by a read error, report it.  */\n+            return fail_no_erange ();\n+          *buffer = '\\0';\n+          /* Do not include the NULL terminator.  */\n+          return buffer - start;\n+        }\n+\n+      /* __underflow has filled the buffer.  */\n+      char *readptr = fp->_IO_read_ptr;\n+      ssize_t readlen = fp->_IO_read_end - readptr;\n+      assert (readlen > 0);\n+      char *pnl = memchr (readptr, '\\n', readlen);\n+      if (pnl != NULL)\n+        {\n+          /* We found the terminator.  */\n+          size_t line_length = pnl - readptr;\n+          if (line_length + 2 > buffer_end - buffer)\n+            /* Not enough room in the caller-supplied buffer.  */\n+            break;\n+          memcpy (buffer, readptr, line_length + 1);\n+          buffer[line_length + 1] = '\\0';\n+          fp->_IO_read_ptr = pnl + 1;\n+          /* Do not include the NULL terminator.  */\n+          return buffer - start + line_length + 1;\n+        }\n+\n+      if (readlen >= buffer_end - buffer)\n+        /* Not enough room in the caller-supplied buffer.  */\n+        break;\n+\n+      /* Save and consume the stream buffer.  */\n+      memcpy (buffer, readptr, readlen);\n+      fp->_IO_read_ptr = fp->_IO_read_end;\n+      buffer += readlen;\n+    }\n+\n+  /* The line does not fit into the buffer.  */\n+  __set_errno (ERANGE);\n+  return -1;\n+}\n+\n+ssize_t\n+__libc_readline_unlocked (_IO_FILE *fp, char *buffer, size_t buffer_length)\n+{\n+  char *buffer_end = buffer + buffer_length;\n+\n+  /* Orient the stream.  */\n+  if (__builtin_expect (fp->_mode, -1) == 0)\n+    _IO_fwide (fp, -1);\n+\n+  /* Fast path: The line terminator is found in the buffer.  */\n+  char *readptr = fp->_IO_read_ptr;\n+  ssize_t readlen = fp->_IO_read_end - readptr;\n+  off64_t start_offset;         /* File offset before reading anything.  */\n+  if (readlen > 0)\n+    {\n+      char *pnl = memchr (readptr, '\\n', readlen);\n+      if (pnl != NULL)\n+        {\n+          size_t line_length = pnl - readptr;\n+          /* Account for line and NULL terminators.  */\n+          if (line_length + 2 > buffer_length)\n+            {\n+              __set_errno (ERANGE);\n+              return -1;\n+            }\n+          memcpy (buffer, readptr, line_length + 1);\n+          buffer[line_length + 1] = '\\0';\n+          /* Consume the entire line.  */\n+          fp->_IO_read_ptr = pnl + 1;\n+          return line_length + 1;\n+        }\n+\n+      /* If the buffer does not have enough space for what is pending\n+         in the stream (plus a NUL terminator), the buffer is too\n+         small.  */\n+      if (readlen + 1 > buffer_length)\n+        {\n+          __set_errno (ERANGE);\n+          return -1;\n+        }\n+\n+      /* End of line not found.  We need all the buffered data.  Fall\n+         through to the slow path.  */\n+      memcpy (buffer, readptr, readlen);\n+      buffer += readlen;\n+      /* The original length is invalid after this point.  Use\n+         buffer_end instead.  */\n+#pragma GCC poison buffer_length\n+      /* Read the old offset before updating the read pointer.  */\n+      start_offset = __ftello64 (fp);\n+      fp->_IO_read_ptr = fp->_IO_read_end;\n+    }\n+  else\n+    {\n+      readlen = 0;\n+      start_offset = __ftello64 (fp);\n+    }\n+\n+  /* Slow path: Read more data from the underlying file.  We need to\n+     restore the file pointer if the buffer is too small.  First,\n+     check if the __ftello64 call above failed.  */\n+  if (start_offset < 0)\n+    return fail_no_erange ();\n+\n+  ssize_t result = readline_slow (fp, buffer, buffer_end);\n+  if (result < 0)\n+    {\n+      if (errno == ERANGE)\n+        {\n+          /* Restore the file pointer so that the caller may read the\n+             same line again.  */\n+          if (__fseeko64 (fp, start_offset, SEEK_SET) < 0)\n+            return fail_no_erange ();\n+          __set_errno (ERANGE);\n+        }\n+      /* Do not restore the file position on other errors; it is\n+         likely that the __fseeko64 call would fail, too.  */\n+      return -1;\n+    }\n+  return readlen + result;\n+}\n+libc_hidden_def (__libc_readline_unlocked)\ndiff --git a/libio/tst-readline.c b/libio/tst-readline.c\nnew file mode 100644\nindex 0000000000..79ed6ea699\n--- /dev/null\n+++ b/libio/tst-readline.c\n@@ -0,0 +1,235 @@\n+/* Test the __libc_readline_unlocked function.\n+   Copyright (C) 2017 Free Software Foundation, Inc.\n+   This file is part of the GNU C Library.\n+\n+   The GNU C Library is free software; you can redistribute it and/or\n+   modify it under the terms of the GNU Lesser General Public\n+   License as published by the Free Software Foundation; either\n+   version 2.1 of the License, or (at your option) any later version.\n+\n+   The GNU C Library is distributed in the hope that it will be useful,\n+   but WITHOUT ANY WARRANTY; without even the implied warranty of\n+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n+   Lesser General Public License for more details.\n+\n+   You should have received a copy of the GNU Lesser General Public\n+   License along with the GNU C Library; if not, see\n+   <http://www.gnu.org/licenses/>.  */\n+\n+/* Exercise __libc_readline_unlocked with various combinations of line\n+   lengths, stdio buffer sizes, and line read buffer sizes.  */\n+\n+#include <errno.h>\n+#include <stdbool.h>\n+#include <stdio.h>\n+#include <support/check.h>\n+#include <support/test-driver.h>\n+#include <support/support.h>\n+#include <support/xstdio.h>\n+#include <support/xmemstream.h>\n+#include <support/temp_file.h>\n+#include <support/xunistd.h>\n+\n+enum\n+  {\n+    maximum_line_length = 7,\n+    number_of_lines = 3,\n+  };\n+\n+/* -1: Do not set buffer size.  0: unbuffered.  Otherwise, use this as\n+   the size of the buffer.  */\n+static int buffer_size;\n+\n+/* These size of the buffer used for reading.  Must be at least 2.  */\n+static int read_size;\n+\n+/* If a read files with ERANGE, increase the buffer size by this\n+   amount.  Must be positive.  */\n+static int read_size_increment;\n+\n+/* If non-zero, do not reset the read size after an ERANGE error.  */\n+static int read_size_preserve;\n+\n+/* If non-zero, no '\\n' at the end of the file.  */\n+static int no_newline_at_eof;\n+\n+/* Length of the line, or -1 if the line is not present.  */\n+static int line_lengths[number_of_lines];\n+\n+/* The name of the test file.  */\n+static char *test_file_path;\n+\n+/* The contents of the test file.  */\n+static char expected_contents[(maximum_line_length + 2) * number_of_lines + 1];\n+static size_t expected_length;\n+\n+/* Returns a random byte which is not zero or the line terminator.  */\n+static char\n+random_char (void)\n+{\n+  static unsigned int rand_state = 1;\n+  while (true)\n+    {\n+      char result = rand_r (&rand_state) >> 16;\n+      if (result != 0 && result != '\\n')\n+        return result;\n+    }\n+}\n+\n+/* Create the test file.  */\n+static void\n+prepare (int argc, char **argv)\n+{\n+  int fd = create_temp_file (\"tst-readline-\", &test_file_path);\n+  TEST_VERIFY_EXIT (fd >= 0);\n+  xclose (fd);\n+}\n+\n+/* Prepare the test file.  Return false if the test parameters are\n+   incongruent and the test should be skipped.  */\n+static bool\n+write_test_file (void)\n+{\n+  expected_length = 0;\n+  char *p = expected_contents;\n+  for (int lineno = 0; lineno < number_of_lines; ++lineno)\n+    for (int i = 0; i < line_lengths[lineno]; ++i)\n+      *p++ = random_char ();\n+  expected_length = p - &expected_contents[0];\n+  if (no_newline_at_eof)\n+    {\n+      if (expected_length == 0)\n+        return false;\n+      --expected_length;\n+      --p;\n+    }\n+  if (test_verbose > 0)\n+    {\n+      printf (\"info: writing test file of %zu bytes:\\n\", expected_length);\n+      for (int i = 0; i < number_of_lines; ++i)\n+        printf (\" line %d: %d\\n\", i, line_lengths[i]);\n+      if (no_newline_at_eof)\n+        puts (\"  (no newline at EOF)\");\n+    }\n+  TEST_VERIFY_EXIT (expected_length < sizeof (expected_contents));\n+  *p++ = '\\0';\n+  support_write_file_string (test_file_path, expected_contents);\n+  return true;\n+}\n+\n+/* Run a single test (a combination of a test file and read\n+   parameters).  */\n+static void\n+run_test (void)\n+{\n+  TEST_VERIFY_EXIT (read_size_increment > 0);\n+  if (test_verbose > 0)\n+    {\n+      printf (\"info: running test: buffer_size=%d read_size=%d\\n\"\n+              \"  read_size_increment=%d read_size_preserve=%d\\n\",\n+              buffer_size, read_size, read_size_increment, read_size_preserve);\n+    }\n+\n+  struct xmemstream result;\n+  xopen_memstream (&result);\n+\n+  FILE *fp = xfopen (test_file_path, \"rce\");\n+  char *fp_buffer = NULL;\n+  if (buffer_size == 0)\n+    TEST_VERIFY_EXIT (setvbuf (fp, NULL, _IONBF, 0) == 0);\n+  if (buffer_size > 0)\n+    {\n+      fp_buffer = xmalloc (buffer_size);\n+      TEST_VERIFY_EXIT (setvbuf (fp, fp_buffer, _IOFBF, buffer_size) == 0);\n+    }\n+\n+  char *line_buffer = xmalloc (read_size);\n+  size_t line_buffer_size = read_size;\n+\n+  while (true)\n+    {\n+      ssize_t ret = __libc_readline_unlocked\n+        (fp, line_buffer, line_buffer_size);\n+      if (ret < 0)\n+        {\n+          TEST_VERIFY (ret == -1);\n+          if (errno != ERANGE)\n+            FAIL_EXIT1 (\"__libc_readline_unlocked: %m\");\n+          line_buffer_size += read_size_increment;\n+          free (line_buffer);\n+          line_buffer = xmalloc (line_buffer_size);\n+          /* Try reading this line again.  */\n+        }\n+      else if (ret == 0)\n+        break;\n+      else\n+        {\n+          /* A line has been read.  Save it.  */\n+          TEST_VERIFY (ret == strlen (line_buffer));\n+          const char *pnl = strchr (line_buffer, '\\n');\n+          /* If there is a \\n, it must be at the end.  */\n+          TEST_VERIFY (pnl == NULL || pnl == line_buffer + ret - 1);\n+          fputs (line_buffer, result.out);\n+\n+          /* Restore the original read size if required.  */\n+          if (line_buffer_size > read_size && !read_size_preserve)\n+            {\n+              line_buffer_size = read_size;\n+              free (line_buffer);\n+              line_buffer = xmalloc (line_buffer_size);\n+            }\n+        }\n+    }\n+\n+  xfclose (fp);\n+  free (fp_buffer);\n+  free (line_buffer);\n+\n+  xfclose_memstream (&result);\n+  TEST_VERIFY (result.length == expected_length);\n+  TEST_VERIFY (strcmp (result.buffer, expected_contents) == 0);\n+  if (test_verbose > 0)\n+    {\n+      printf (\"info: expected (%zu): [[%s]]\\n\",\n+              expected_length, expected_contents);\n+      printf (\"info:   actual (%zu): [[%s]]\\n\", result.length, result.buffer);\n+    }\n+  free (result.buffer);\n+}\n+\n+/* Test one test file with multiple read parameters.  */\n+static void\n+test_one_file (void)\n+{\n+  for (buffer_size = -1; buffer_size <= maximum_line_length + 1; ++buffer_size)\n+    for (read_size = 2; read_size <= maximum_line_length + 2; ++read_size)\n+      for (read_size_increment = 1; read_size_increment <= 4;\n+           ++read_size_increment)\n+        for (read_size_preserve = 0; read_size_preserve < 2;\n+             ++read_size_preserve)\n+          run_test ();\n+}\n+\n+\n+static int\n+do_test (void)\n+{\n+  /* Set up the test file contents.  */\n+  for (line_lengths[0] = -1; line_lengths[0] <= maximum_line_length;\n+       ++line_lengths[0])\n+    for (line_lengths[1] = -1; line_lengths[1] <= maximum_line_length;\n+         ++line_lengths[1])\n+      for (line_lengths[2] = -1; line_lengths[2] <= maximum_line_length;\n+           ++line_lengths[2])\n+        for (no_newline_at_eof = 0; no_newline_at_eof < 2; ++no_newline_at_eof)\n+          {\n+            if (!write_test_file ())\n+              continue;\n+            test_one_file ();\n+          }\n+  free (test_file_path);\n+  return 0;\n+}\n+\n+#define PREPARE prepare\n+#include <support/test-driver.c>","headers":{"Return-Path":"<libc-alpha-return-84123-incoming=patchwork.ozlabs.org@sourceware.org>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":["patchwork-incoming@bilbo.ozlabs.org","mailing list libc-alpha@sourceware.org"],"Authentication-Results":["ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=sourceware.org\n\t(client-ip=209.132.180.131; helo=sourceware.org;\n\tenvelope-from=libc-alpha-return-84123-incoming=patchwork.ozlabs.org@sourceware.org;\n\treceiver=<UNKNOWN>)","ozlabs.org; dkim=pass (1024-bit key;\n\tsecure) header.d=sourceware.org header.i=@sourceware.org\n\theader.b=\"vs7Q1Xux\"; dkim-atps=neutral","sourceware.org; auth=none","ext-mx01.extmail.prod.ext.phx2.redhat.com;\n\tdmarc=none (p=none dis=none) header.from=redhat.com","ext-mx01.extmail.prod.ext.phx2.redhat.com;\n\tspf=fail smtp.mailfrom=fweimer@redhat.com"],"Received":["from sourceware.org (server1.sourceware.org [209.132.180.131])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256\n\tbits)) (No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3xl5KZ2kWvz9sPs\n\tfor <incoming@patchwork.ozlabs.org>;\n\tSun,  3 Sep 2017 05:10:22 +1000 (AEST)","(qmail 116267 invoked by alias); 2 Sep 2017 19:10:15 -0000","(qmail 116249 invoked by uid 89); 2 Sep 2017 19:10:14 -0000"],"DomainKey-Signature":"a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id\n\t:list-unsubscribe:list-subscribe:list-archive:list-post\n\t:list-help:sender:subject:to:references:from:message-id:date\n\t:mime-version:in-reply-to:content-type; q=dns; s=default; b=oo0e\n\twT3MGh1G8PpsbdgPiYl4TDmQjx9/sDH0u6xkwCdEsJp+9NPDttV6hftzSVojn6xl\n\tkcpuYQjpWrJW81OIlMnkw+/NZm/l7NPQ8KkcQwkW0KueBLfab8EuDDf4CTwkzLb2\n\tS7y6Xs1byq1nypthINQX11fqyNdCpQ87ShrD9to=","DKIM-Signature":"v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id\n\t:list-unsubscribe:list-subscribe:list-archive:list-post\n\t:list-help:sender:subject:to:references:from:message-id:date\n\t:mime-version:in-reply-to:content-type; s=default; bh=jJk1Qb4LOM\n\tthYylNeyuxZtwFsHM=; b=vs7Q1Xuxg/t5g4abpkJgcTIo3l4KbM/2hrl5JinRmh\n\tKaxC65ng5TNFDhTkHMwrkJueiF/O3XuFRZY36q3NlsoDptrRmm1ZcahO4aaJFn5I\n\tv09DW0z/9u0I53/I0f5ZI3zq8ZMriE/Ws/CdqMrPHpNeGPSQumAXxZFwCVbTDteC\n\tU=","Mailing-List":"contact libc-alpha-help@sourceware.org; run by ezmlm","Precedence":"bulk","List-Id":"<libc-alpha.sourceware.org>","List-Unsubscribe":"<mailto:libc-alpha-unsubscribe-incoming=patchwork.ozlabs.org@sourceware.org>","List-Subscribe":"<mailto:libc-alpha-subscribe@sourceware.org>","List-Archive":"<http://sourceware.org/ml/libc-alpha/>","List-Post":"<mailto:libc-alpha@sourceware.org>","List-Help":"<mailto:libc-alpha-help@sourceware.org>,\n\t<http://sourceware.org/ml/#faqs>","Sender":"libc-alpha-owner@sourceware.org","X-Virus-Found":"No","X-Spam-SWARE-Status":"No, score=-26.9 required=5.0 tests=BAYES_00, GIT_PATCH_0,\n\tGIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RP_MATCHES_RCVD,\n\tSPF_HELO_PASS autolearn=ham version=3.3.2 spammy=","X-HELO":"mx1.redhat.com","DMARC-Filter":"OpenDMARC Filter v1.3.2 mx1.redhat.com 4B0C281E12","Subject":"Re: [PATCH] libio: Implement internal function\n\t__libc_readline_unlocked","To":"libc-alpha@sourceware.org","References":"<20170901154335.E5819439942E3@oldenburg.str.redhat.com>\n\t<4694e740-6bdb-ef22-a945-21359367c788@redhat.com>","From":"Florian Weimer <fweimer@redhat.com>","Message-ID":"<ab9faefa-7875-4380-fca0-87767bf271f0@redhat.com>","Date":"Sat, 2 Sep 2017 21:10:04 +0200","User-Agent":"Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101\n\tThunderbird/52.2.1","MIME-Version":"1.0","In-Reply-To":"<4694e740-6bdb-ef22-a945-21359367c788@redhat.com>","Content-Type":"multipart/mixed;\n\tboundary=\"------------D59664ECD7F097108D5143BE\""}},{"id":1768370,"web_url":"http://patchwork.ozlabs.org/comment/1768370/","msgid":"<c6c7fade-c111-7d20-a9dd-cfd34014f9f7@redhat.com>","list_archive_url":null,"date":"2017-09-14T06:56:21","subject":"Re: [PATCH] libio: Implement internal function\n\t__libc_readline_unlocked","submitter":{"id":14312,"url":"http://patchwork.ozlabs.org/api/people/14312/","name":"Florian Weimer","email":"fweimer@redhat.com"},"content":"On 09/02/2017 09:10 PM, Florian Weimer wrote:\n> On 09/01/2017 08:00 PM, Florian Weimer wrote:\n>> This should use __underflow instead of __uflow, so that the need for the\n>> special handling for '\\n' goes away.\n> \n> Here is the version based on __underflow.  I changed the way the\n> __ftello64 and __fseeko64 aliases are handled because the other patch\n> needs to call __fseko64 from a DSO, so the hidden symbol no longer works.\n\nPing?\n\n  <https://sourceware.org/ml/libc-alpha/2017-09/msg00121.html>\n\nThanks,\nFlorian","headers":{"Return-Path":"<libc-alpha-return-84592-incoming=patchwork.ozlabs.org@sourceware.org>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":["patchwork-incoming@bilbo.ozlabs.org","mailing list libc-alpha@sourceware.org"],"Authentication-Results":["ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=sourceware.org\n\t(client-ip=209.132.180.131; helo=sourceware.org;\n\tenvelope-from=libc-alpha-return-84592-incoming=patchwork.ozlabs.org@sourceware.org;\n\treceiver=<UNKNOWN>)","ozlabs.org; dkim=pass (1024-bit key;\n\tsecure) header.d=sourceware.org header.i=@sourceware.org\n\theader.b=\"ZI5LSsc8\"; dkim-atps=neutral","sourceware.org; auth=none","ext-mx10.extmail.prod.ext.phx2.redhat.com;\n\tdmarc=none (p=none dis=none) header.from=redhat.com","ext-mx10.extmail.prod.ext.phx2.redhat.com;\n\tspf=fail smtp.mailfrom=fweimer@redhat.com"],"Received":["from sourceware.org (server1.sourceware.org [209.132.180.131])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256\n\tbits)) (No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3xt8TJ753mz9sRg\n\tfor <incoming@patchwork.ozlabs.org>;\n\tThu, 14 Sep 2017 16:56:36 +1000 (AEST)","(qmail 114915 invoked by alias); 14 Sep 2017 06:56:26 -0000","(qmail 114903 invoked by uid 89); 14 Sep 2017 06:56:26 -0000"],"DomainKey-Signature":"a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id\n\t:list-unsubscribe:list-subscribe:list-archive:list-post\n\t:list-help:sender:subject:from:to:references:message-id:date\n\t:mime-version:in-reply-to:content-type\n\t:content-transfer-encoding; q=dns; s=default; b=kAgbfTCV2lJIYSPZ\n\t5hXTc4EBInEAbSWxEThCf04eGEV1zFnDCUnt2MJSLOdUO52fwDjbzV7WijLEF+8i\n\tNVghC0EqvTSr6vQMT+mYQp7qjuwKphbxpkpBP+HPVYXR9vcB7OLZCXA6EQqRJ733\n\t6NyTBeti/CJI7OOiUgS0a0zFlvw=","DKIM-Signature":"v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id\n\t:list-unsubscribe:list-subscribe:list-archive:list-post\n\t:list-help:sender:subject:from:to:references:message-id:date\n\t:mime-version:in-reply-to:content-type\n\t:content-transfer-encoding; s=default; bh=Hhz3jAEiqZk3z9IStSLb/7\n\tj2drE=; b=ZI5LSsc8/jY7lQf9hzaf8LLyW4at8cxzjJHa9s8NMBGE7kG2R28hwm\n\t8sFBXTcdgi1eSDxnHzuu9RIiTvdtTGDhHzPI93dGQE35yN85x77v2Skl7WNuoDvr\n\tPJR+zgv0wRGV3ebL93fqD3gtf9hmqQ27XL1+0i28DJ3/BlodaybHw=","Mailing-List":"contact libc-alpha-help@sourceware.org; run by ezmlm","Precedence":"bulk","List-Id":"<libc-alpha.sourceware.org>","List-Unsubscribe":"<mailto:libc-alpha-unsubscribe-incoming=patchwork.ozlabs.org@sourceware.org>","List-Subscribe":"<mailto:libc-alpha-subscribe@sourceware.org>","List-Archive":"<http://sourceware.org/ml/libc-alpha/>","List-Post":"<mailto:libc-alpha@sourceware.org>","List-Help":"<mailto:libc-alpha-help@sourceware.org>,\n\t<http://sourceware.org/ml/#faqs>","Sender":"libc-alpha-owner@sourceware.org","X-Virus-Found":"No","X-Spam-SWARE-Status":"No, score=-0.9 required=5.0 tests=BAYES_00,\n\tKAM_LAZY_DOMAIN_SECURITY, RP_MATCHES_RCVD,\n\tSPF_HELO_PASS autolearn=no version=3.3.2 spammy=","X-HELO":"mx1.redhat.com","DMARC-Filter":"OpenDMARC Filter v1.3.2 mx1.redhat.com 2C2A45AFED","Subject":"Re: [PATCH] libio: Implement internal function\n\t__libc_readline_unlocked","From":"Florian Weimer <fweimer@redhat.com>","To":"libc-alpha@sourceware.org","References":"<20170901154335.E5819439942E3@oldenburg.str.redhat.com>\n\t<4694e740-6bdb-ef22-a945-21359367c788@redhat.com>\n\t<ab9faefa-7875-4380-fca0-87767bf271f0@redhat.com>","Message-ID":"<c6c7fade-c111-7d20-a9dd-cfd34014f9f7@redhat.com>","Date":"Thu, 14 Sep 2017 08:56:21 +0200","User-Agent":"Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101\n\tThunderbird/52.3.0","MIME-Version":"1.0","In-Reply-To":"<ab9faefa-7875-4380-fca0-87767bf271f0@redhat.com>","Content-Type":"text/plain; charset=utf-8","Content-Transfer-Encoding":"7bit"}},{"id":1780799,"web_url":"http://patchwork.ozlabs.org/comment/1780799/","msgid":"<2c1e372c-c573-a9d6-6a60-7e9c46fd16b9@redhat.com>","list_archive_url":null,"date":"2017-10-05T16:44:28","subject":"Re: [PATCH] libio: Implement internal function\n\t__libc_readline_unlocked","submitter":{"id":14312,"url":"http://patchwork.ozlabs.org/api/people/14312/","name":"Florian Weimer","email":"fweimer@redhat.com"},"content":"On 09/14/2017 08:56 AM, Florian Weimer wrote:\n> On 09/02/2017 09:10 PM, Florian Weimer wrote:\n>> On 09/01/2017 08:00 PM, Florian Weimer wrote:\n>>> This should use __underflow instead of __uflow, so that the need for the\n>>> special handling for '\\n' goes away.\n>>\n>> Here is the version based on __underflow.  I changed the way the\n>> __ftello64 and __fseeko64 aliases are handled because the other patch\n>> needs to call __fseko64 from a DSO, so the hidden symbol no longer works.\n\n>    <https://sourceware.org/ml/libc-alpha/2017-09/msg00121.html>\n\nPing?\n\nThanks,\nFlorian","headers":{"Return-Path":"<libc-alpha-return-85468-incoming=patchwork.ozlabs.org@sourceware.org>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":["patchwork-incoming@bilbo.ozlabs.org","mailing list libc-alpha@sourceware.org"],"Authentication-Results":["ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=sourceware.org\n\t(client-ip=209.132.180.131; helo=sourceware.org;\n\tenvelope-from=libc-alpha-return-85468-incoming=patchwork.ozlabs.org@sourceware.org;\n\treceiver=<UNKNOWN>)","ozlabs.org; dkim=pass (1024-bit key;\n\tsecure) header.d=sourceware.org header.i=@sourceware.org\n\theader.b=\"TFjJoAT1\"; dkim-atps=neutral","sourceware.org; auth=none","ext-mx07.extmail.prod.ext.phx2.redhat.com;\n\tdmarc=none (p=none dis=none) header.from=redhat.com","ext-mx07.extmail.prod.ext.phx2.redhat.com;\n\tspf=fail smtp.mailfrom=fweimer@redhat.com"],"Received":["from sourceware.org (server1.sourceware.org [209.132.180.131])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256\n\tbits)) (No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3y7JX737qsz9t16\n\tfor <incoming@patchwork.ozlabs.org>;\n\tFri,  6 Oct 2017 03:44:39 +1100 (AEDT)","(qmail 49775 invoked by alias); 5 Oct 2017 16:44:33 -0000","(qmail 49761 invoked by uid 89); 5 Oct 2017 16:44:32 -0000"],"DomainKey-Signature":"a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id\n\t:list-unsubscribe:list-subscribe:list-archive:list-post\n\t:list-help:sender:subject:from:to:references:message-id:date\n\t:mime-version:in-reply-to:content-type\n\t:content-transfer-encoding; q=dns; s=default; b=Ej7Y4EPC2qsKN+yl\n\tczVrZLsLE2SCwSCIaNKDzDO6ZAdZQ/Bp4FEDs7U/LkvGa0HDfdUTX5UG0KOXxNOe\n\tVyvXocVtPp1SFnarlPjzU/iB1FyxU9lRWONkq7/0PR5/c1Km13WACa7RF8YTV2O2\n\tYxJGFXrjF4SsubUOqUPsZp7N6bo=","DKIM-Signature":"v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id\n\t:list-unsubscribe:list-subscribe:list-archive:list-post\n\t:list-help:sender:subject:from:to:references:message-id:date\n\t:mime-version:in-reply-to:content-type\n\t:content-transfer-encoding; s=default; bh=22YlPlWMoC0pcv9gcnQMKW\n\tYuNMU=; b=TFjJoAT1gK2tBPcW9025NTUI4pJ2I6QNaqYPGON6nH756j0DITITYT\n\tLxBZHWD7pfWzNrvlDwdgf4IPAihJZHXVwBlN/k4wcvOFm2amykkj29Y6/+7rdkgh\n\t58L17slXMdQ/D4RtdWqrE3smTqsSotYonP7N6O1KxwG7BtcJpdUiQ=","Mailing-List":"contact libc-alpha-help@sourceware.org; run by ezmlm","Precedence":"bulk","List-Id":"<libc-alpha.sourceware.org>","List-Unsubscribe":"<mailto:libc-alpha-unsubscribe-incoming=patchwork.ozlabs.org@sourceware.org>","List-Subscribe":"<mailto:libc-alpha-subscribe@sourceware.org>","List-Archive":"<http://sourceware.org/ml/libc-alpha/>","List-Post":"<mailto:libc-alpha@sourceware.org>","List-Help":"<mailto:libc-alpha-help@sourceware.org>,\n\t<http://sourceware.org/ml/#faqs>","Sender":"libc-alpha-owner@sourceware.org","X-Virus-Found":"No","X-Spam-SWARE-Status":"No, score=-0.9 required=5.0 tests=BAYES_00,\n\tKAM_LAZY_DOMAIN_SECURITY, RP_MATCHES_RCVD,\n\tSPF_HELO_PASS autolearn=no version=3.3.2\n\tspammy=Hx-languages-length:642","X-HELO":"mx1.redhat.com","DMARC-Filter":"OpenDMARC Filter v1.3.2 mx1.redhat.com 9DB79C047B66","Subject":"Re: [PATCH] libio: Implement internal function\n\t__libc_readline_unlocked","From":"Florian Weimer <fweimer@redhat.com>","To":"libc-alpha@sourceware.org","References":"<20170901154335.E5819439942E3@oldenburg.str.redhat.com>\n\t<4694e740-6bdb-ef22-a945-21359367c788@redhat.com>\n\t<ab9faefa-7875-4380-fca0-87767bf271f0@redhat.com>\n\t<c6c7fade-c111-7d20-a9dd-cfd34014f9f7@redhat.com>","Message-ID":"<2c1e372c-c573-a9d6-6a60-7e9c46fd16b9@redhat.com>","Date":"Thu, 5 Oct 2017 18:44:28 +0200","User-Agent":"Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101\n\tThunderbird/52.3.0","MIME-Version":"1.0","In-Reply-To":"<c6c7fade-c111-7d20-a9dd-cfd34014f9f7@redhat.com>","Content-Type":"text/plain; charset=utf-8; format=flowed","Content-Transfer-Encoding":"7bit"}},{"id":1808512,"web_url":"http://patchwork.ozlabs.org/comment/1808512/","msgid":"<20171122055001.GC7625@aiede.mtv.corp.google.com>","list_archive_url":null,"date":"2017-11-22T05:50:01","subject":"Re: [PATCH] libio: Implement internal function\n\t__libc_readline_unlocked","submitter":{"id":8008,"url":"http://patchwork.ozlabs.org/api/people/8008/","name":"Jonathan Nieder","email":"jrnieder@gmail.com"},"content":"Florian Weimer wrote:\n\n> --- a/libio/ftello.c\n> +++ b/libio/ftello.c\n> @@ -61,4 +61,6 @@ weak_alias (__ftello, ftello)\n> \n>  #ifdef __OFF_T_MATCHES_OFF64_T\n>  weak_alias (__ftello, ftello64)\n> +strong_alias (__ftello, __ftello64)\n\nWhat does this part do?\n\n[...]\n> +++ b/libio/readline.c\n> @@ -0,0 +1,169 @@\n[...]\n> +/* Slow path for reading the line.  Called with no data in the stream\n> +   read buffer.  Write data to [BUFFER, BUFFER_END).  */\n> +static ssize_t\n> +readline_slow (_IO_FILE *fp, char *buffer, char *buffer_end)\n> +{\n> +  char *start = buffer;\n> +\n> +  while (buffer < buffer_end)\n> +    {\n> +      if (__underflow (fp) == EOF)\n> +        {\n> +          if (_IO_ferror_unlocked (fp))\n> +            /* If the EOF was caused by a read error, report it.  */\n> +            return fail_no_erange ();\n\nIs readline_slow's caller responsible for ensuring !ferror(fp) before\nthe __underflow call?  Otherwise it's possible for this to return -1\nwithout setting errno.\n\n> +          *buffer = '\\0';\n> +          /* Do not include the NULL terminator.  */\n\nnit: s/NULL/NUL/ or s/NULL/null/ (NULL is a pointer, NUL an ascii code\npoint).\n\n> +          return buffer - start;\n> +        }\n[...]\n> +      char *pnl = memchr (readptr, '\\n', readlen);\n> +      if (pnl != NULL)\n> +        {\n> +          /* We found the terminator.  */\n> +          size_t line_length = pnl - readptr;\n> +          if (line_length + 2 > buffer_end - buffer)\n> +            /* Not enough room in the caller-supplied buffer.  */\n> +            break;\n> +          memcpy (buffer, readptr, line_length + 1);\n> +          buffer[line_length + 1] = '\\0';\n> +          fp->_IO_read_ptr = pnl + 1;\n> +          /* Do not include the NULL terminator.  */\n\nSame nit about \\0 vs NULL.\n\n> +          return buffer - start + line_length + 1;\n> +        }\n[...]\n> +ssize_t\n> +__libc_readline_unlocked (_IO_FILE *fp, char *buffer, size_t buffer_length)\n> +{\n> +  char *buffer_end = buffer + buffer_length;\n> +\n> +  /* Orient the stream.  */\n> +  if (__builtin_expect (fp->_mode, -1) == 0)\n> +    _IO_fwide (fp, -1);\n> +\n> +  /* Fast path: The line terminator is found in the buffer.  */\n> +  char *readptr = fp->_IO_read_ptr;\n> +  ssize_t readlen = fp->_IO_read_end - readptr;\n> +  off64_t start_offset;         /* File offset before reading anything.  */\n> +  if (readlen > 0)\n> +    {\n\noptional: could handle the !readlen case first to avoid leaving the\nreader in suspense.\n\n> +      char *pnl = memchr (readptr, '\\n', readlen);\n[...]\n> +      buffer += readlen;\n> +      /* The original length is invalid after this point.  Use\n> +         buffer_end instead.  */\n> +#pragma GCC poison buffer_length\n\nNeat!  I hadn't seen this trick before.\n\n[...]\n> +  /* Slow path: Read more data from the underlying file.  We need to\n> +     restore the file pointer if the buffer is too small.  First,\n> +     check if the __ftello64 call above failed.  */\n> +  if (start_offset < 0)\n> +    return fail_no_erange ();\n> +\n> +  ssize_t result = readline_slow (fp, buffer, buffer_end);\n> +  if (result < 0)\n> +    {\n> +      if (errno == ERANGE)\n> +        {\n> +          /* Restore the file pointer so that the caller may read the\n> +             same line again.  */\n> +          if (__fseeko64 (fp, start_offset, SEEK_SET) < 0)\n> +            return fail_no_erange ();\n\nWhat happens if the file is unseekable?  Is this function not meant to\nbe used for such files, or is this seeking to reset the file pointer a\nbest-effort kind of thing?\n\n[...]\n> +  return readlen + result;\n> +}\n\nLooks good.  The test also looks good.\n\nThe only part that worries me is the value of errno if ferror(fp) was\nalready true.  The rest of my observations are cosmetic.\n\nThanks and hope that helps,\nJonathan","headers":{"Return-Path":"<libc-alpha-return-87407-incoming=patchwork.ozlabs.org@sourceware.org>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":["patchwork-incoming@bilbo.ozlabs.org","mailing list libc-alpha@sourceware.org"],"Authentication-Results":["ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=sourceware.org\n\t(client-ip=209.132.180.131; helo=sourceware.org;\n\tenvelope-from=libc-alpha-return-87407-incoming=patchwork.ozlabs.org@sourceware.org;\n\treceiver=<UNKNOWN>)","ozlabs.org; dkim=pass (1024-bit key;\n\tsecure) header.d=sourceware.org header.i=@sourceware.org\n\theader.b=\"eAE5e975\"; dkim-atps=neutral","sourceware.org; auth=none"],"Received":["from sourceware.org (server1.sourceware.org [209.132.180.131])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256\n\tbits)) (No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3yhWlT3Vmhz9s76\n\tfor <incoming@patchwork.ozlabs.org>;\n\tWed, 22 Nov 2017 16:50:45 +1100 (AEDT)","(qmail 83676 invoked by alias); 22 Nov 2017 05:50:38 -0000","(qmail 76620 invoked by uid 89); 22 Nov 2017 05:50:13 -0000"],"DomainKey-Signature":"a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id\n\t:list-unsubscribe:list-subscribe:list-archive:list-post\n\t:list-help:sender:date:from:to:cc:subject:message-id:references\n\t:mime-version:content-type:in-reply-to; q=dns; s=default; b=izDi\n\tMxOqpp+Ajkd2hoDd55Cg7lbMN5CG1TXODTwTBnQHUC4ZLctyLy4ghGZkhelWeJEk\n\tHZdg9E66HknBbbuDEvN6c2Xof5aEFJguHj53F3U7jN1YRen2uhO4/6f8r56mHZZT\n\tw9p2Yw88kNZ0Ttu76o0yhvciimPHnADp9HJ/vsM=","DKIM-Signature":"v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id\n\t:list-unsubscribe:list-subscribe:list-archive:list-post\n\t:list-help:sender:date:from:to:cc:subject:message-id:references\n\t:mime-version:content-type:in-reply-to; s=default; bh=q46LTtYyc8\n\t/Ap3qaaEbhKZmW6Yw=; b=eAE5e975flXbtCgRKZEjsyb9Im9mHVqurUzV3zsSvU\n\tc32DyEXpvHFS+sxg+fHmKKroxCCHpN2jxQlFjNPqKVmW2m2vWQnoRrI3qb6bFX+/\n\tydejp4wEZAm5vz2l8Dvn0BYGwv4Z90sNxUuhfEx4Mn6lk+I47djGB94aJNXMpV12\n\tM=","Mailing-List":"contact libc-alpha-help@sourceware.org; run by ezmlm","Precedence":"bulk","List-Id":"<libc-alpha.sourceware.org>","List-Unsubscribe":"<mailto:libc-alpha-unsubscribe-incoming=patchwork.ozlabs.org@sourceware.org>","List-Subscribe":"<mailto:libc-alpha-subscribe@sourceware.org>","List-Archive":"<http://sourceware.org/ml/libc-alpha/>","List-Post":"<mailto:libc-alpha@sourceware.org>","List-Help":"<mailto:libc-alpha-help@sourceware.org>,\n\t<http://sourceware.org/ml/#faqs>","Sender":"libc-alpha-owner@sourceware.org","X-Virus-Found":"No","X-Spam-SWARE-Status":"No, score=-11.7 required=5.0 tests=BAYES_00,\n\tFREEMAIL_FROM, GIT_PATCH_2, GIT_PATCH_3,\n\tKB_WAM_FROM_NAME_SINGLEWORD, RCVD_IN_DNSWL_NONE,\n\tSPF_PASS autolearn=ham version=3.3.2 spammy=suspense, pnl,\n\tobservations, seeking","X-HELO":"mail-it0-f67.google.com","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:date:from:to:cc:subject:message-id:references\n\t:mime-version:content-disposition:in-reply-to:user-agent;\n\tbh=/mMsUSd3wl4+DRVFROfprdO7wlOw1qWFOtdBrWLMSQ4=;\n\tb=KiF4IiSHnX2lJvoZAUhanFeck8+BdFytY54OKgB/iIMCx83osRlDTq7M5QuHIiUFFV\n\tB6JmFEfVg1aZElHcSzS8CPFnYjOuyQD7yDtGMy0rTcF5od2/4R194f+iT5RXWcbEd2Bx\n\tjPCAjz2uWrAohNyIYwE+j4FrNcpwHLjJrXPgb+a4vSaagOT0D/BscY7S4uZ47Cpze05Y\n\tACLwYK9KWJYy91V2ZFed2lbiHBOys6plx/Oe1wtIm7yjcf4XI1x9fmJx7P5Hzkhu8z32\n\tGnLQjpqA4CCsN19tGmdGEorCQj07xC6qIletRNDoDR+ZgA6M6BfkB9tEL1Cdixc65FGE\n\tZp9w==","X-Gm-Message-State":"AJaThX5Y67P69yQrXSW2M9EDe0W2h9LhSviXdDEXDXBZhJINtW4DgAQZ\n\t6I6gIMRX8UAVsvYQ6nNCwhM=","X-Google-Smtp-Source":"AGs4zMYLJ9RHlWUbNClc/imJE3OEeuh6FRkQIvORI/8FblrZ1vjwbTLny6tkK16URfO4I2wcsXPcXw==","X-Received":"by 10.36.246.136 with SMTP id u130mr5239937ith.129.1511329803471;\n\tTue, 21 Nov 2017 21:50:03 -0800 (PST)","Date":"Tue, 21 Nov 2017 21:50:01 -0800","From":"Jonathan Nieder <jrnieder@gmail.com>","To":"Florian Weimer <fweimer@redhat.com>","Cc":"libc-alpha@sourceware.org","Subject":"Re: [PATCH] libio: Implement internal function\n\t__libc_readline_unlocked","Message-ID":"<20171122055001.GC7625@aiede.mtv.corp.google.com>","References":"<20170901154335.E5819439942E3@oldenburg.str.redhat.com>\n\t<4694e740-6bdb-ef22-a945-21359367c788@redhat.com>\n\t<ab9faefa-7875-4380-fca0-87767bf271f0@redhat.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=us-ascii","Content-Disposition":"inline","In-Reply-To":"<ab9faefa-7875-4380-fca0-87767bf271f0@redhat.com>","User-Agent":"Mutt/1.9.1 (2017-09-22)"}},{"id":1808592,"web_url":"http://patchwork.ozlabs.org/comment/1808592/","msgid":"<mvm4lpm39nh.fsf@suse.de>","list_archive_url":null,"date":"2017-11-22T10:11:46","subject":"Re: [PATCH] libio: Implement internal function\n\t__libc_readline_unlocked","submitter":{"id":37,"url":"http://patchwork.ozlabs.org/api/people/37/","name":"Andreas Schwab","email":"schwab@suse.de"},"content":"On Nov 21 2017, Jonathan Nieder <jrnieder@gmail.com> wrote:\n\n> nit: s/NULL/NUL/ or s/NULL/null/ (NULL is a pointer, NUL an ascii code\n> point).\n\nNULL is the official name of the Unicode character U+0000, though most\npresentations use the abbreviation.\n\nAndreas.","headers":{"Return-Path":"<libc-alpha-return-87410-incoming=patchwork.ozlabs.org@sourceware.org>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":["patchwork-incoming@bilbo.ozlabs.org","mailing list libc-alpha@sourceware.org"],"Authentication-Results":["ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=sourceware.org\n\t(client-ip=209.132.180.131; helo=sourceware.org;\n\tenvelope-from=libc-alpha-return-87410-incoming=patchwork.ozlabs.org@sourceware.org;\n\treceiver=<UNKNOWN>)","ozlabs.org; dkim=pass (1024-bit key;\n\tsecure) header.d=sourceware.org header.i=@sourceware.org\n\theader.b=\"Wy/cFmsI\"; dkim-atps=neutral","sourceware.org; auth=none"],"Received":["from sourceware.org (server1.sourceware.org [209.132.180.131])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256\n\tbits)) (No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3yhdXx2ysLz9s76\n\tfor <incoming@patchwork.ozlabs.org>;\n\tWed, 22 Nov 2017 21:12:01 +1100 (AEDT)","(qmail 38891 invoked by alias); 22 Nov 2017 10:11:55 -0000","(qmail 38861 invoked by uid 89); 22 Nov 2017 10:11:54 -0000"],"DomainKey-Signature":"a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id\n\t:list-unsubscribe:list-subscribe:list-archive:list-post\n\t:list-help:sender:from:to:cc:subject:references:date:in-reply-to\n\t:message-id:mime-version:content-type; q=dns; s=default; b=FycSV\n\tyoObx6lf9uCNFPlycFBCyIFX7Cv0A69y57Zf+SOAq/aqJVeSks/Ww3HrrgDvnM9G\n\tXFiBqjwKD5dEFq4FSF0xwFGF/9LO9jdKaL/qEOcfdzZ53al3GWMmGZyIUt85Yx92\n\tnMJICvJDIUA2SbxGruEwrawKTvYhZoHIvIlaLI=","DKIM-Signature":"v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id\n\t:list-unsubscribe:list-subscribe:list-archive:list-post\n\t:list-help:sender:from:to:cc:subject:references:date:in-reply-to\n\t:message-id:mime-version:content-type; s=default; bh=XFma4DLkLNu\n\tOGmUk/x7HflowgsE=; b=Wy/cFmsIOUHozH+/3Sqib8+5SXQo4joP/Wdg8SpG3It\n\t7/cUKTs5IXpsOnfq1NFD24K9o2ODmqbLpbM2AMg7faU4hImXBqaoZn8Q766YFInE\n\t2/6D74mWXufENzPG5ZX3yiv+nkneFc7rqU4PoZeTmoHUpGbmnP4OEOq4FAJGx9SI\n\t=","Mailing-List":"contact libc-alpha-help@sourceware.org; run by ezmlm","Precedence":"bulk","List-Id":"<libc-alpha.sourceware.org>","List-Unsubscribe":"<mailto:libc-alpha-unsubscribe-incoming=patchwork.ozlabs.org@sourceware.org>","List-Subscribe":"<mailto:libc-alpha-subscribe@sourceware.org>","List-Archive":"<http://sourceware.org/ml/libc-alpha/>","List-Post":"<mailto:libc-alpha@sourceware.org>","List-Help":"<mailto:libc-alpha-help@sourceware.org>,\n\t<http://sourceware.org/ml/#faqs>","Sender":"libc-alpha-owner@sourceware.org","X-Virus-Found":"No","X-Spam-SWARE-Status":"No, score=-1.7 required=5.0 tests=BAYES_00,\n\tKB_WAM_FROM_NAME_SINGLEWORD, SPF_PASS,\n\tT_RP_MATCHES_RCVD autolearn=no version=3.3.2 spammy=presentations,\n\tunicode","X-HELO":"mx2.suse.de","From":"Andreas Schwab <schwab@suse.de>","To":"Jonathan Nieder <jrnieder@gmail.com>","Cc":"Florian Weimer <fweimer@redhat.com>,  libc-alpha@sourceware.org","Subject":"Re: [PATCH] libio: Implement internal function\n\t__libc_readline_unlocked","References":"<20170901154335.E5819439942E3@oldenburg.str.redhat.com>\n\t<4694e740-6bdb-ef22-a945-21359367c788@redhat.com>\n\t<ab9faefa-7875-4380-fca0-87767bf271f0@redhat.com>\n\t<20171122055001.GC7625@aiede.mtv.corp.google.com>","X-Yow":"Then, it's off to RED CHINA!!","Date":"Wed, 22 Nov 2017 11:11:46 +0100","In-Reply-To":"<20171122055001.GC7625@aiede.mtv.corp.google.com> (Jonathan\n\tNieder's message of \"Tue, 21 Nov 2017 21:50:01 -0800\")","Message-ID":"<mvm4lpm39nh.fsf@suse.de>","User-Agent":"Gnus/5.13 (Gnus v5.13) Emacs/25.3 (gnu/linux)","MIME-Version":"1.0","Content-Type":"text/plain"}},{"id":1948662,"web_url":"http://patchwork.ozlabs.org/comment/1948662/","msgid":"<33d730f8-4ad2-4055-fdcc-98117ecc3f45@redhat.com>","list_archive_url":null,"date":"2018-07-06T12:31:25","subject":"Re: [PATCH] libio: Implement internal function\n\t__libc_readline_unlocked","submitter":{"id":14312,"url":"http://patchwork.ozlabs.org/api/people/14312/","name":"Florian Weimer","email":"fweimer@redhat.com"},"content":"On 11/22/2017 06:50 AM, Jonathan Nieder wrote:\n> Florian Weimer wrote:\n> \n>> --- a/libio/ftello.c\n>> +++ b/libio/ftello.c\n>> @@ -61,4 +61,6 @@ weak_alias (__ftello, ftello)\n>>\n>>   #ifdef __OFF_T_MATCHES_OFF64_T\n>>   weak_alias (__ftello, ftello64)\n>> +strong_alias (__ftello, __ftello64)\n> \n> What does this part do?\n\nIf off_t and off64_t are the same type, __ftello and __ftello64 are the \nsame function (at the same address).\n\n> [...]\n>> +++ b/libio/readline.c\n>> @@ -0,0 +1,169 @@\n> [...]\n>> +/* Slow path for reading the line.  Called with no data in the stream\n>> +   read buffer.  Write data to [BUFFER, BUFFER_END).  */\n>> +static ssize_t\n>> +readline_slow (_IO_FILE *fp, char *buffer, char *buffer_end)\n>> +{\n>> +  char *start = buffer;\n>> +\n>> +  while (buffer < buffer_end)\n>> +    {\n>> +      if (__underflow (fp) == EOF)\n>> +        {\n>> +          if (_IO_ferror_unlocked (fp))\n>> +            /* If the EOF was caused by a read error, report it.  */\n>> +            return fail_no_erange ();\n> \n> Is readline_slow's caller responsible for ensuring !ferror(fp) before\n> the __underflow call?  Otherwise it's possible for this to return -1\n> without setting errno.\n\nThe caller should not call the function if the stream is in an error \ncondition I added a comment to the header file.\n\n> \n>> +          *buffer = '\\0';\n>> +          /* Do not include the NULL terminator.  */\n> \n> nit: s/NULL/NUL/ or s/NULL/null/ (NULL is a pointer, NUL an ascii code\n> point).\n\nThanks, fixed.\n\n> [...]\n>> +  /* Slow path: Read more data from the underlying file.  We need to\n>> +     restore the file pointer if the buffer is too small.  First,\n>> +     check if the __ftello64 call above failed.  */\n>> +  if (start_offset < 0)\n>> +    return fail_no_erange ();\n>> +\n>> +  ssize_t result = readline_slow (fp, buffer, buffer_end);\n>> +  if (result < 0)\n>> +    {\n>> +      if (errno == ERANGE)\n>> +        {\n>> +          /* Restore the file pointer so that the caller may read the\n>> +             same line again.  */\n>> +          if (__fseeko64 (fp, start_offset, SEEK_SET) < 0)\n>> +            return fail_no_erange ();\n> \n> What happens if the file is unseekable?  Is this function not meant to\n> be used for such files, or is this seeking to reset the file pointer a\n> best-effort kind of thing?\n\nThe function is not meant to be used for such files.\n\nI've rebased the patch and fixed the internal alias generation logic.\n\nCarlos, is this and the fix for bug 18991 (which has already been \nreviewed by DJ) still acceptable during the freeze?\n\nThanks,\nFlorian","headers":{"Return-Path":"<libc-alpha-return-94063-incoming=patchwork.ozlabs.org@sourceware.org>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":["patchwork-incoming@bilbo.ozlabs.org","mailing list libc-alpha@sourceware.org"],"Authentication-Results":["ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=sourceware.org\n\t(client-ip=209.132.180.131; helo=sourceware.org;\n\tenvelope-from=libc-alpha-return-94063-incoming=patchwork.ozlabs.org@sourceware.org;\n\treceiver=<UNKNOWN>)","ozlabs.org;\n\tdmarc=fail (p=none dis=none) header.from=redhat.com","ozlabs.org; dkim=pass (1024-bit key;\n\tsecure) header.d=sourceware.org header.i=@sourceware.org\n\theader.b=\"aGLHVrk3\"; dkim-atps=neutral","sourceware.org; auth=none"],"Received":["from sourceware.org (server1.sourceware.org [209.132.180.131])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256\n\tbits)) (No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 41MYxh1yxTz9s1B\n\tfor <incoming@patchwork.ozlabs.org>;\n\tFri,  6 Jul 2018 22:31:36 +1000 (AEST)","(qmail 100519 invoked by alias); 6 Jul 2018 12:31:30 -0000","(qmail 100501 invoked by uid 89); 6 Jul 2018 12:31:29 -0000"],"DomainKey-Signature":"a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id\n\t:list-unsubscribe:list-subscribe:list-archive:list-post\n\t:list-help:sender:subject:to:cc:references:from:message-id:date\n\t:mime-version:in-reply-to:content-type\n\t:content-transfer-encoding; q=dns; s=default; b=vsTU87hdGxGASiEW\n\t6xdh2Bcm83x8GBEbDxMkdGUQHzPNDZrgsTOYGIcwfWC4iExaJjxeoPcLZsEcLSDi\n\tCpB0sfqUWWCbYHnKeviZOTYGIRH3llDjhRaBjks5/3bUL+ZOYUZY5XtbWdSu6gW+\n\thdIxdkBu/YvCCsIxi76sQd45Uq8=","DKIM-Signature":"v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id\n\t:list-unsubscribe:list-subscribe:list-archive:list-post\n\t:list-help:sender:subject:to:cc:references:from:message-id:date\n\t:mime-version:in-reply-to:content-type\n\t:content-transfer-encoding; s=default; bh=BN0nAKFKUTwR+oiow+jcZa\n\tP2kT4=; b=aGLHVrk3KHww1XXh3t8miekC0v85JhnUJ0/NDP/LHHjn9oGfj2pI/Q\n\t5uOxDIRHnQ4g/D2pWmgUG+ZJTzDfOs161Y2YesvtXQiByMDfwNQdWuZlSs5giqXe\n\thZCoAqdduyuud5Up+f81Njat4zwKqJu7DgiTJLUVfQxmIyeD+XFCI=","Mailing-List":"contact libc-alpha-help@sourceware.org; run by ezmlm","Precedence":"bulk","List-Id":"<libc-alpha.sourceware.org>","List-Unsubscribe":"<mailto:libc-alpha-unsubscribe-incoming=patchwork.ozlabs.org@sourceware.org>","List-Subscribe":"<mailto:libc-alpha-subscribe@sourceware.org>","List-Archive":"<http://sourceware.org/ml/libc-alpha/>","List-Post":"<mailto:libc-alpha@sourceware.org>","List-Help":"<mailto:libc-alpha-help@sourceware.org>,\n\t<http://sourceware.org/ml/#faqs>","Sender":"libc-alpha-owner@sourceware.org","X-Spam-SWARE-Status":"No, score=-11.3 required=5.0 tests=AWL, BAYES_00,\n\tGIT_PATCH_2, GIT_PATCH_3,\n\tSPF_HELO_PASS autolearn=ham version=3.3.2 spammy=","X-HELO":"mx1.redhat.com","Subject":"Re: [PATCH] libio: Implement internal function\n\t__libc_readline_unlocked","To":"Jonathan Nieder <jrnieder@gmail.com>","Cc":"libc-alpha@sourceware.org, Carlos O'Donell <carlos@redhat.com>","References":"<20170901154335.E5819439942E3@oldenburg.str.redhat.com>\n\t<4694e740-6bdb-ef22-a945-21359367c788@redhat.com>\n\t<ab9faefa-7875-4380-fca0-87767bf271f0@redhat.com>\n\t<20171122055001.GC7625@aiede.mtv.corp.google.com>","From":"Florian Weimer <fweimer@redhat.com>","Message-ID":"<33d730f8-4ad2-4055-fdcc-98117ecc3f45@redhat.com>","Date":"Fri, 6 Jul 2018 14:31:25 +0200","User-Agent":"Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101\n\tThunderbird/52.8.0","MIME-Version":"1.0","In-Reply-To":"<20171122055001.GC7625@aiede.mtv.corp.google.com>","Content-Type":"text/plain; charset=utf-8; format=flowed","Content-Transfer-Encoding":"7bit"}},{"id":1948665,"web_url":"http://patchwork.ozlabs.org/comment/1948665/","msgid":"<50086f64-2ea0-18ae-60f4-7b149493a79b@redhat.com>","list_archive_url":null,"date":"2018-07-06T12:31:58","subject":"Re: [PATCH] libio: Implement internal function\n\t__libc_readline_unlocked","submitter":{"id":14312,"url":"http://patchwork.ozlabs.org/api/people/14312/","name":"Florian Weimer","email":"fweimer@redhat.com"},"content":"On 07/06/2018 02:31 PM, Florian Weimer wrote:\n> On 11/22/2017 06:50 AM, Jonathan Nieder wrote:\n>> Florian Weimer wrote:\n>>\n>>> --- a/libio/ftello.c\n>>> +++ b/libio/ftello.c\n>>> @@ -61,4 +61,6 @@ weak_alias (__ftello, ftello)\n>>>\n>>>   #ifdef __OFF_T_MATCHES_OFF64_T\n>>>   weak_alias (__ftello, ftello64)\n>>> +strong_alias (__ftello, __ftello64)\n>>\n>> What does this part do?\n> \n> If off_t and off64_t are the same type, __ftello and __ftello64 are the \n> same function (at the same address).\n> \n>> [...]\n>>> +++ b/libio/readline.c\n>>> @@ -0,0 +1,169 @@\n>> [...]\n>>> +/* Slow path for reading the line.  Called with no data in the stream\n>>> +   read buffer.  Write data to [BUFFER, BUFFER_END).  */\n>>> +static ssize_t\n>>> +readline_slow (_IO_FILE *fp, char *buffer, char *buffer_end)\n>>> +{\n>>> +  char *start = buffer;\n>>> +\n>>> +  while (buffer < buffer_end)\n>>> +    {\n>>> +      if (__underflow (fp) == EOF)\n>>> +        {\n>>> +          if (_IO_ferror_unlocked (fp))\n>>> +            /* If the EOF was caused by a read error, report it.  */\n>>> +            return fail_no_erange ();\n>>\n>> Is readline_slow's caller responsible for ensuring !ferror(fp) before\n>> the __underflow call?  Otherwise it's possible for this to return -1\n>> without setting errno.\n> \n> The caller should not call the function if the stream is in an error \n> condition I added a comment to the header file.\n> \n>>\n>>> +          *buffer = '\\0';\n>>> +          /* Do not include the NULL terminator.  */\n>>\n>> nit: s/NULL/NUL/ or s/NULL/null/ (NULL is a pointer, NUL an ascii code\n>> point).\n> \n> Thanks, fixed.\n> \n>> [...]\n>>> +  /* Slow path: Read more data from the underlying file.  We need to\n>>> +     restore the file pointer if the buffer is too small.  First,\n>>> +     check if the __ftello64 call above failed.  */\n>>> +  if (start_offset < 0)\n>>> +    return fail_no_erange ();\n>>> +\n>>> +  ssize_t result = readline_slow (fp, buffer, buffer_end);\n>>> +  if (result < 0)\n>>> +    {\n>>> +      if (errno == ERANGE)\n>>> +        {\n>>> +          /* Restore the file pointer so that the caller may read the\n>>> +             same line again.  */\n>>> +          if (__fseeko64 (fp, start_offset, SEEK_SET) < 0)\n>>> +            return fail_no_erange ();\n>>\n>> What happens if the file is unseekable?  Is this function not meant to\n>> be used for such files, or is this seeking to reset the file pointer a\n>> best-effort kind of thing?\n> \n> The function is not meant to be used for such files.\n> \n> I've rebased the patch and fixed the internal alias generation logic.\n> \n> Carlos, is this and the fix for bug 18991 (which has already been \n> reviewed by DJ) still acceptable during the freeze?\n> \n> Thanks,\n> Florian\n\nAnd now with the patch attached.\nSubject: [PATCH] libio: Implement internal function __libc_readline_unlocked\nTo: libc-alpha@sourceware.org\n\nThis is a variant of fgets which fails with ERANGE if the\nbuffer is too small, and the buffer length is given as an\nargument of type size_t.\n\nThis function will be useful for implementing NSS file reading\noperations.  Compared to a direct implementation using the public API,\nit avoids an lseek system call in case the line terminator can be\nfound in the internal read buffer.\n\n2018-07-06  Florian Weimer  <fweimer@redhat.com>\n\n\t* include/stdio.h (__libc_readline_unlocked): Declare.\n\t(__ftello64, __fseeko64): Declare aliases.\n\t* libio/readline.c: New file.\n\t* libio/tst-readline.c: Likewise.\n\t(routines): Add readline.\n\t(tests-internal): Add tst-readlime.\n\t* libio/Versions (GLIBC_PRIVATE): Export __fseeko64, __ftello64,\n\t__libc_readline_unlocked.\n\t* libio/fseeko.c (__fseeko): Rename from fseeko.\n\t(fseeko): Add alias.\n\t[__OFF_T_MATCHES_OFF64_T] (fseeko64, __fseeko64): Likewise.\n\t* libio/fseeko64.c (__fseeko64): Rename from fseeko64.\n\t(fseeko64): Add alias.\n\t* libio/ftello.c [__OFF_T_MATCHES_OFF64_T] (__ftello64): Add alias.\n\t* libio/ftello64.c (__ftello64): Rename from ftello64.\n\t(ftello64): Add alias.\n\ndiff --git a/include/stdio.h b/include/stdio.h\nindex 3ba0edc924..9162d4e247 100644\n--- a/include/stdio.h\n+++ b/include/stdio.h\n@@ -127,6 +127,19 @@ extern int __fxprintf (FILE *__fp, const char *__fmt, ...)\n extern int __fxprintf_nocancel (FILE *__fp, const char *__fmt, ...)\n      __attribute__ ((__format__ (__printf__, 2, 3))) attribute_hidden;\n \n+/* Read the next line from FP into BUFFER, of LENGTH bytes.  LINE will\n+   include the line terminator and a NUL terminator.  On success,\n+   return the length of the line, including the line terminator, but\n+   excluding the NUL termintor.  On EOF, return zero and write a NUL\n+   terminator.  On error, return -1 and set errno.  If the total byte\n+   count (line and both terminators) exceeds LENGTH, return -1 and set\n+   errno to ERANGE (but do not mark the stream as failed).\n+\n+   The behavior is undefined if FP is not seekable, or if the stream\n+   is already in an error state.  */\n+ssize_t __libc_readline_unlocked (FILE *fp, char *buffer, size_t length);\n+libc_hidden_proto (__libc_readline_unlocked);\n+\n extern const char *const _sys_errlist_internal[] attribute_hidden;\n extern int _sys_nerr_internal attribute_hidden;\n \n@@ -170,6 +183,10 @@ libc_hidden_proto (fwrite)\n libc_hidden_proto (fseek)\n extern __typeof (ftello) __ftello;\n libc_hidden_proto (__ftello)\n+extern __typeof (fseeko64) __fseeko64;\n+libc_hidden_proto (__fseeko64)\n+extern __typeof (ftello64) __ftello64;\n+libc_hidden_proto (__ftello64)\n libc_hidden_proto (fflush)\n libc_hidden_proto (fflush_unlocked)\n extern __typeof (fflush_unlocked) __fflush_unlocked;\ndiff --git a/libio/Makefile b/libio/Makefile\nindex 64d283e512..cab0eae946 100644\n--- a/libio/Makefile\n+++ b/libio/Makefile\n@@ -49,7 +49,7 @@ routines\t:=\t\t\t\t\t\t\t      \\\n \t__fbufsize __freading __fwriting __freadable __fwritable __flbf\t      \\\n \t__fpurge __fpending __fsetlocking\t\t\t\t      \\\n \t\t\t\t\t\t\t\t\t      \\\n-\tlibc_fatal fmemopen oldfmemopen vtables\n+\tlibc_fatal fmemopen oldfmemopen vtables readline\n \n tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc   \\\n \ttst_wprintf2 tst-widetext test-fmemopen tst-ext tst-ext2 \\\n@@ -66,7 +66,7 @@ tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc   \\\n \ttst-fwrite-error tst-ftell-partial-wide tst-ftell-active-handler \\\n \ttst-ftell-append tst-fputws tst-bz22415 tst-fgetc-after-eof\n \n-tests-internal = tst-vtables tst-vtables-interposed\n+tests-internal = tst-vtables tst-vtables-interposed tst-readline\n \n ifeq (yes,$(build-shared))\n # Add test-fopenloc only if shared library is enabled since it depends on\ndiff --git a/libio/Versions b/libio/Versions\nindex 77123347e3..acb896afa9 100644\n--- a/libio/Versions\n+++ b/libio/Versions\n@@ -158,5 +158,9 @@ libc {\n \n     # Used by NPTL\n     _IO_enable_locks;\n+\n+    __fseeko64;\n+    __ftello64;\n+    __libc_readline_unlocked;\n   }\n }\ndiff --git a/libio/fseeko.c b/libio/fseeko.c\nindex 2df0453d35..4d086c15d8 100644\n--- a/libio/fseeko.c\n+++ b/libio/fseeko.c\n@@ -24,11 +24,15 @@\n    This exception applies to code released by its copyright holders\n    in files containing the exception.  */\n \n+/* We need to disable the redirect for __fseeko64 for the alias\n+   definitions below to work.  */\n+#define __fseeko64 __fseeko64_disable\n+\n #include \"libioP.h\"\n #include \"stdio.h\"\n \n int\n-fseeko (FILE *fp, off_t offset, int whence)\n+__fseeko (FILE *fp, off_t offset, int whence)\n {\n   int result;\n   CHECK_FILE (fp, -1);\n@@ -37,7 +41,11 @@ fseeko (FILE *fp, off_t offset, int whence)\n   _IO_release_lock (fp);\n   return result;\n }\n+weak_alias (__fseeko, fseeko)\n \n #ifdef __OFF_T_MATCHES_OFF64_T\n-weak_alias (fseeko, fseeko64)\n+weak_alias (__fseeko, fseeko64)\n+# undef __fseeko64\n+strong_alias (__fseeko, __fseeko64)\n+libc_hidden_ver (__fseeko, __fseeko64)\n #endif\ndiff --git a/libio/fseeko64.c b/libio/fseeko64.c\nindex eea6455bc3..1d9bb190a6 100644\n--- a/libio/fseeko64.c\n+++ b/libio/fseeko64.c\n@@ -32,7 +32,7 @@\n #ifndef __OFF_T_MATCHES_OFF64_T\n \n int\n-fseeko64 (FILE *fp, off64_t offset, int whence)\n+__fseeko64 (FILE *fp, off64_t offset, int whence)\n {\n   int result;\n   CHECK_FILE (fp, -1);\n@@ -41,5 +41,6 @@ fseeko64 (FILE *fp, off64_t offset, int whence)\n   _IO_release_lock (fp);\n   return result;\n }\n-\n+libc_hidden_def (__fseeko64)\n+weak_alias (__fseeko64, fseeko64)\n #endif\ndiff --git a/libio/ftello.c b/libio/ftello.c\nindex 5405821b45..5a3caf4ad9 100644\n--- a/libio/ftello.c\n+++ b/libio/ftello.c\n@@ -24,12 +24,15 @@\n    This exception applies to code released by its copyright holders\n    in files containing the exception.  */\n \n+/* We need to disable the redirect for __ftello64 for the alias\n+   definitions below to work.  */\n+#define __ftello64 __ftello64_disable\n+\n #include <stdio.h>\n #include <stdlib.h>\n #include <libioP.h>\n #include <errno.h>\n \n-\n off_t\n __ftello (FILE *fp)\n {\n@@ -61,4 +64,7 @@ weak_alias (__ftello, ftello)\n \n #ifdef __OFF_T_MATCHES_OFF64_T\n weak_alias (__ftello, ftello64)\n+# undef __ftello64\n+strong_alias (__ftello, __ftello64)\n+libc_hidden_ver (__ftello, __ftello64)\n #endif\ndiff --git a/libio/ftello64.c b/libio/ftello64.c\nindex 281667fee2..d5546e1fb0 100644\n--- a/libio/ftello64.c\n+++ b/libio/ftello64.c\n@@ -32,7 +32,7 @@\n #ifndef __OFF_T_MATCHES_OFF64_T\n \n off64_t\n-ftello64 (FILE *fp)\n+__ftello64 (FILE *fp)\n {\n   off64_t pos;\n   CHECK_FILE (fp, -1L);\n@@ -52,5 +52,6 @@ ftello64 (FILE *fp)\n     }\n   return pos;\n }\n-\n+libc_hidden_def (__ftello64)\n+weak_alias (__ftello64, ftello64)\n #endif\ndiff --git a/libio/readline.c b/libio/readline.c\nnew file mode 100644\nindex 0000000000..d5424b1c27\n--- /dev/null\n+++ b/libio/readline.c\n@@ -0,0 +1,169 @@\n+/* fgets with ERANGE error reporting and size_t buffer length.\n+   Copyright (C) 2017 Free Software Foundation, Inc.\n+   This file is part of the GNU C Library.\n+\n+   The GNU C Library is free software; you can redistribute it and/or\n+   modify it under the terms of the GNU Lesser General Public\n+   License as published by the Free Software Foundation; either\n+   version 2.1 of the License, or (at your option) any later version.\n+\n+   The GNU C Library is distributed in the hope that it will be useful,\n+   but WITHOUT ANY WARRANTY; without even the implied warranty of\n+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n+   Lesser General Public License for more details.\n+\n+   You should have received a copy of the GNU Lesser General Public\n+   License along with the GNU C Library; if not, see\n+   <http://www.gnu.org/licenses/>.  */\n+\n+#include <assert.h>\n+#include <errno.h>\n+#include <stdio.h>\n+#include <string.h>\n+\n+#include \"libioP.h\"\n+\n+/* Return -1 and set errno to EINVAL if it is ERANGE.  */\n+static ssize_t\n+fail_no_erange (void)\n+{\n+  if (errno == ERANGE)\n+    __set_errno (EINVAL);\n+  return -1;\n+}\n+\n+/* Slow path for reading the line.  Called with no data in the stream\n+   read buffer.  Write data to [BUFFER, BUFFER_END).  */\n+static ssize_t\n+readline_slow (FILE *fp, char *buffer, char *buffer_end)\n+{\n+  char *start = buffer;\n+\n+  while (buffer < buffer_end)\n+    {\n+      if (__underflow (fp) == EOF)\n+        {\n+          if (_IO_ferror_unlocked (fp))\n+            /* If the EOF was caused by a read error, report it.  */\n+            return fail_no_erange ();\n+          *buffer = '\\0';\n+          /* Do not include the null terminator.  */\n+          return buffer - start;\n+        }\n+\n+      /* __underflow has filled the buffer.  */\n+      char *readptr = fp->_IO_read_ptr;\n+      ssize_t readlen = fp->_IO_read_end - readptr;\n+      assert (readlen > 0);\n+      char *pnl = memchr (readptr, '\\n', readlen);\n+      if (pnl != NULL)\n+        {\n+          /* We found the terminator.  */\n+          size_t line_length = pnl - readptr;\n+          if (line_length + 2 > buffer_end - buffer)\n+            /* Not enough room in the caller-supplied buffer.  */\n+            break;\n+          memcpy (buffer, readptr, line_length + 1);\n+          buffer[line_length + 1] = '\\0';\n+          fp->_IO_read_ptr = pnl + 1;\n+          /* Do not include the null terminator.  */\n+          return buffer - start + line_length + 1;\n+        }\n+\n+      if (readlen >= buffer_end - buffer)\n+        /* Not enough room in the caller-supplied buffer.  */\n+        break;\n+\n+      /* Save and consume the stream buffer.  */\n+      memcpy (buffer, readptr, readlen);\n+      fp->_IO_read_ptr = fp->_IO_read_end;\n+      buffer += readlen;\n+    }\n+\n+  /* The line does not fit into the buffer.  */\n+  __set_errno (ERANGE);\n+  return -1;\n+}\n+\n+ssize_t\n+__libc_readline_unlocked (FILE *fp, char *buffer, size_t buffer_length)\n+{\n+  char *buffer_end = buffer + buffer_length;\n+\n+  /* Orient the stream.  */\n+  if (__builtin_expect (fp->_mode, -1) == 0)\n+    _IO_fwide (fp, -1);\n+\n+  /* Fast path: The line terminator is found in the buffer.  */\n+  char *readptr = fp->_IO_read_ptr;\n+  ssize_t readlen = fp->_IO_read_end - readptr;\n+  off64_t start_offset;         /* File offset before reading anything.  */\n+  if (readlen > 0)\n+    {\n+      char *pnl = memchr (readptr, '\\n', readlen);\n+      if (pnl != NULL)\n+        {\n+          size_t line_length = pnl - readptr;\n+          /* Account for line and null terminators.  */\n+          if (line_length + 2 > buffer_length)\n+            {\n+              __set_errno (ERANGE);\n+              return -1;\n+            }\n+          memcpy (buffer, readptr, line_length + 1);\n+          buffer[line_length + 1] = '\\0';\n+          /* Consume the entire line.  */\n+          fp->_IO_read_ptr = pnl + 1;\n+          return line_length + 1;\n+        }\n+\n+      /* If the buffer does not have enough space for what is pending\n+         in the stream (plus a NUL terminator), the buffer is too\n+         small.  */\n+      if (readlen + 1 > buffer_length)\n+        {\n+          __set_errno (ERANGE);\n+          return -1;\n+        }\n+\n+      /* End of line not found.  We need all the buffered data.  Fall\n+         through to the slow path.  */\n+      memcpy (buffer, readptr, readlen);\n+      buffer += readlen;\n+      /* The original length is invalid after this point.  Use\n+         buffer_end instead.  */\n+#pragma GCC poison buffer_length\n+      /* Read the old offset before updating the read pointer.  */\n+      start_offset = __ftello64 (fp);\n+      fp->_IO_read_ptr = fp->_IO_read_end;\n+    }\n+  else\n+    {\n+      readlen = 0;\n+      start_offset = __ftello64 (fp);\n+    }\n+\n+  /* Slow path: Read more data from the underlying file.  We need to\n+     restore the file pointer if the buffer is too small.  First,\n+     check if the __ftello64 call above failed.  */\n+  if (start_offset < 0)\n+    return fail_no_erange ();\n+\n+  ssize_t result = readline_slow (fp, buffer, buffer_end);\n+  if (result < 0)\n+    {\n+      if (errno == ERANGE)\n+        {\n+          /* Restore the file pointer so that the caller may read the\n+             same line again.  */\n+          if (__fseeko64 (fp, start_offset, SEEK_SET) < 0)\n+            return fail_no_erange ();\n+          __set_errno (ERANGE);\n+        }\n+      /* Do not restore the file position on other errors; it is\n+         likely that the __fseeko64 call would fail, too.  */\n+      return -1;\n+    }\n+  return readlen + result;\n+}\n+libc_hidden_def (__libc_readline_unlocked)\ndiff --git a/libio/tst-readline.c b/libio/tst-readline.c\nnew file mode 100644\nindex 0000000000..79ed6ea699\n--- /dev/null\n+++ b/libio/tst-readline.c\n@@ -0,0 +1,235 @@\n+/* Test the __libc_readline_unlocked function.\n+   Copyright (C) 2017 Free Software Foundation, Inc.\n+   This file is part of the GNU C Library.\n+\n+   The GNU C Library is free software; you can redistribute it and/or\n+   modify it under the terms of the GNU Lesser General Public\n+   License as published by the Free Software Foundation; either\n+   version 2.1 of the License, or (at your option) any later version.\n+\n+   The GNU C Library is distributed in the hope that it will be useful,\n+   but WITHOUT ANY WARRANTY; without even the implied warranty of\n+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n+   Lesser General Public License for more details.\n+\n+   You should have received a copy of the GNU Lesser General Public\n+   License along with the GNU C Library; if not, see\n+   <http://www.gnu.org/licenses/>.  */\n+\n+/* Exercise __libc_readline_unlocked with various combinations of line\n+   lengths, stdio buffer sizes, and line read buffer sizes.  */\n+\n+#include <errno.h>\n+#include <stdbool.h>\n+#include <stdio.h>\n+#include <support/check.h>\n+#include <support/test-driver.h>\n+#include <support/support.h>\n+#include <support/xstdio.h>\n+#include <support/xmemstream.h>\n+#include <support/temp_file.h>\n+#include <support/xunistd.h>\n+\n+enum\n+  {\n+    maximum_line_length = 7,\n+    number_of_lines = 3,\n+  };\n+\n+/* -1: Do not set buffer size.  0: unbuffered.  Otherwise, use this as\n+   the size of the buffer.  */\n+static int buffer_size;\n+\n+/* These size of the buffer used for reading.  Must be at least 2.  */\n+static int read_size;\n+\n+/* If a read files with ERANGE, increase the buffer size by this\n+   amount.  Must be positive.  */\n+static int read_size_increment;\n+\n+/* If non-zero, do not reset the read size after an ERANGE error.  */\n+static int read_size_preserve;\n+\n+/* If non-zero, no '\\n' at the end of the file.  */\n+static int no_newline_at_eof;\n+\n+/* Length of the line, or -1 if the line is not present.  */\n+static int line_lengths[number_of_lines];\n+\n+/* The name of the test file.  */\n+static char *test_file_path;\n+\n+/* The contents of the test file.  */\n+static char expected_contents[(maximum_line_length + 2) * number_of_lines + 1];\n+static size_t expected_length;\n+\n+/* Returns a random byte which is not zero or the line terminator.  */\n+static char\n+random_char (void)\n+{\n+  static unsigned int rand_state = 1;\n+  while (true)\n+    {\n+      char result = rand_r (&rand_state) >> 16;\n+      if (result != 0 && result != '\\n')\n+        return result;\n+    }\n+}\n+\n+/* Create the test file.  */\n+static void\n+prepare (int argc, char **argv)\n+{\n+  int fd = create_temp_file (\"tst-readline-\", &test_file_path);\n+  TEST_VERIFY_EXIT (fd >= 0);\n+  xclose (fd);\n+}\n+\n+/* Prepare the test file.  Return false if the test parameters are\n+   incongruent and the test should be skipped.  */\n+static bool\n+write_test_file (void)\n+{\n+  expected_length = 0;\n+  char *p = expected_contents;\n+  for (int lineno = 0; lineno < number_of_lines; ++lineno)\n+    for (int i = 0; i < line_lengths[lineno]; ++i)\n+      *p++ = random_char ();\n+  expected_length = p - &expected_contents[0];\n+  if (no_newline_at_eof)\n+    {\n+      if (expected_length == 0)\n+        return false;\n+      --expected_length;\n+      --p;\n+    }\n+  if (test_verbose > 0)\n+    {\n+      printf (\"info: writing test file of %zu bytes:\\n\", expected_length);\n+      for (int i = 0; i < number_of_lines; ++i)\n+        printf (\" line %d: %d\\n\", i, line_lengths[i]);\n+      if (no_newline_at_eof)\n+        puts (\"  (no newline at EOF)\");\n+    }\n+  TEST_VERIFY_EXIT (expected_length < sizeof (expected_contents));\n+  *p++ = '\\0';\n+  support_write_file_string (test_file_path, expected_contents);\n+  return true;\n+}\n+\n+/* Run a single test (a combination of a test file and read\n+   parameters).  */\n+static void\n+run_test (void)\n+{\n+  TEST_VERIFY_EXIT (read_size_increment > 0);\n+  if (test_verbose > 0)\n+    {\n+      printf (\"info: running test: buffer_size=%d read_size=%d\\n\"\n+              \"  read_size_increment=%d read_size_preserve=%d\\n\",\n+              buffer_size, read_size, read_size_increment, read_size_preserve);\n+    }\n+\n+  struct xmemstream result;\n+  xopen_memstream (&result);\n+\n+  FILE *fp = xfopen (test_file_path, \"rce\");\n+  char *fp_buffer = NULL;\n+  if (buffer_size == 0)\n+    TEST_VERIFY_EXIT (setvbuf (fp, NULL, _IONBF, 0) == 0);\n+  if (buffer_size > 0)\n+    {\n+      fp_buffer = xmalloc (buffer_size);\n+      TEST_VERIFY_EXIT (setvbuf (fp, fp_buffer, _IOFBF, buffer_size) == 0);\n+    }\n+\n+  char *line_buffer = xmalloc (read_size);\n+  size_t line_buffer_size = read_size;\n+\n+  while (true)\n+    {\n+      ssize_t ret = __libc_readline_unlocked\n+        (fp, line_buffer, line_buffer_size);\n+      if (ret < 0)\n+        {\n+          TEST_VERIFY (ret == -1);\n+          if (errno != ERANGE)\n+            FAIL_EXIT1 (\"__libc_readline_unlocked: %m\");\n+          line_buffer_size += read_size_increment;\n+          free (line_buffer);\n+          line_buffer = xmalloc (line_buffer_size);\n+          /* Try reading this line again.  */\n+        }\n+      else if (ret == 0)\n+        break;\n+      else\n+        {\n+          /* A line has been read.  Save it.  */\n+          TEST_VERIFY (ret == strlen (line_buffer));\n+          const char *pnl = strchr (line_buffer, '\\n');\n+          /* If there is a \\n, it must be at the end.  */\n+          TEST_VERIFY (pnl == NULL || pnl == line_buffer + ret - 1);\n+          fputs (line_buffer, result.out);\n+\n+          /* Restore the original read size if required.  */\n+          if (line_buffer_size > read_size && !read_size_preserve)\n+            {\n+              line_buffer_size = read_size;\n+              free (line_buffer);\n+              line_buffer = xmalloc (line_buffer_size);\n+            }\n+        }\n+    }\n+\n+  xfclose (fp);\n+  free (fp_buffer);\n+  free (line_buffer);\n+\n+  xfclose_memstream (&result);\n+  TEST_VERIFY (result.length == expected_length);\n+  TEST_VERIFY (strcmp (result.buffer, expected_contents) == 0);\n+  if (test_verbose > 0)\n+    {\n+      printf (\"info: expected (%zu): [[%s]]\\n\",\n+              expected_length, expected_contents);\n+      printf (\"info:   actual (%zu): [[%s]]\\n\", result.length, result.buffer);\n+    }\n+  free (result.buffer);\n+}\n+\n+/* Test one test file with multiple read parameters.  */\n+static void\n+test_one_file (void)\n+{\n+  for (buffer_size = -1; buffer_size <= maximum_line_length + 1; ++buffer_size)\n+    for (read_size = 2; read_size <= maximum_line_length + 2; ++read_size)\n+      for (read_size_increment = 1; read_size_increment <= 4;\n+           ++read_size_increment)\n+        for (read_size_preserve = 0; read_size_preserve < 2;\n+             ++read_size_preserve)\n+          run_test ();\n+}\n+\n+\n+static int\n+do_test (void)\n+{\n+  /* Set up the test file contents.  */\n+  for (line_lengths[0] = -1; line_lengths[0] <= maximum_line_length;\n+       ++line_lengths[0])\n+    for (line_lengths[1] = -1; line_lengths[1] <= maximum_line_length;\n+         ++line_lengths[1])\n+      for (line_lengths[2] = -1; line_lengths[2] <= maximum_line_length;\n+           ++line_lengths[2])\n+        for (no_newline_at_eof = 0; no_newline_at_eof < 2; ++no_newline_at_eof)\n+          {\n+            if (!write_test_file ())\n+              continue;\n+            test_one_file ();\n+          }\n+  free (test_file_path);\n+  return 0;\n+}\n+\n+#define PREPARE prepare\n+#include <support/test-driver.c>","headers":{"Return-Path":"<libc-alpha-return-94064-incoming=patchwork.ozlabs.org@sourceware.org>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":["patchwork-incoming@bilbo.ozlabs.org","mailing list libc-alpha@sourceware.org"],"Authentication-Results":["ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=sourceware.org\n\t(client-ip=209.132.180.131; helo=sourceware.org;\n\tenvelope-from=libc-alpha-return-94064-incoming=patchwork.ozlabs.org@sourceware.org;\n\treceiver=<UNKNOWN>)","ozlabs.org;\n\tdmarc=fail (p=none dis=none) header.from=redhat.com","ozlabs.org; dkim=pass (1024-bit key;\n\tsecure) header.d=sourceware.org header.i=@sourceware.org\n\theader.b=\"aIZElEw1\"; dkim-atps=neutral","sourceware.org; auth=none"],"Received":["from sourceware.org (server1.sourceware.org [209.132.180.131])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256\n\tbits)) (No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 41MYyP50gDz9s1B\n\tfor <incoming@patchwork.ozlabs.org>;\n\tFri,  6 Jul 2018 22:32:13 +1000 (AEST)","(qmail 101855 invoked by alias); 6 Jul 2018 12:32:06 -0000","(qmail 101832 invoked by uid 89); 6 Jul 2018 12:32:05 -0000"],"DomainKey-Signature":"a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id\n\t:list-unsubscribe:list-subscribe:list-archive:list-post\n\t:list-help:sender:subject:from:to:cc:references:message-id:date\n\t:mime-version:in-reply-to:content-type; q=dns; s=default; b=t18f\n\tI4eg+pmzdDsHJocemSCxxOz7dTn3rpuBqD8rlxpnbEpVXJPj/1LJE7xM3fSxNSQV\n\tgBNdJl8dlynbWShKzEftbZsZK23Z1dGEBOfBxqCDzNK2EZDQYOT2g8+D6gKo0LL2\n\tAjQt5ZnYmRNT+odlb8o0AmH8JFisBRKWORi2Uyg=","DKIM-Signature":"v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id\n\t:list-unsubscribe:list-subscribe:list-archive:list-post\n\t:list-help:sender:subject:from:to:cc:references:message-id:date\n\t:mime-version:in-reply-to:content-type; s=default; bh=BCf4bcl3Iw\n\tsJNODBsahpR0buut4=; b=aIZElEw1myhiYZAlU2OY+oha/yOsaAfGtUjPaQfb/Z\n\tzsBZdx7nFudoI/ZsizhM8QDTkSUicplcTjoDvqbY2+dH5UlidBVq6BEK7uM7rG/f\n\thnuo11eRprnbgDi34hhuyrS6WhX5VPZMJd9k6kCBluHK+Q7ehF3R+nRW+0Rb+kRY\n\tE=","Mailing-List":"contact libc-alpha-help@sourceware.org; run by ezmlm","Precedence":"bulk","List-Id":"<libc-alpha.sourceware.org>","List-Unsubscribe":"<mailto:libc-alpha-unsubscribe-incoming=patchwork.ozlabs.org@sourceware.org>","List-Subscribe":"<mailto:libc-alpha-subscribe@sourceware.org>","List-Archive":"<http://sourceware.org/ml/libc-alpha/>","List-Post":"<mailto:libc-alpha@sourceware.org>","List-Help":"<mailto:libc-alpha-help@sourceware.org>,\n\t<http://sourceware.org/ml/#faqs>","Sender":"libc-alpha-owner@sourceware.org","X-Spam-SWARE-Status":"No, score=-24.8 required=5.0 tests=AWL, BAYES_00,\n\tGIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_SHORT,\n\tSPF_HELO_PASS autolearn=ham version=3.3.2 spammy=","X-HELO":"mx1.redhat.com","Subject":"Re: [PATCH] libio: Implement internal function\n\t__libc_readline_unlocked","From":"Florian Weimer <fweimer@redhat.com>","To":"Jonathan Nieder <jrnieder@gmail.com>","Cc":"libc-alpha@sourceware.org, Carlos O'Donell <carlos@redhat.com>","References":"<20170901154335.E5819439942E3@oldenburg.str.redhat.com>\n\t<4694e740-6bdb-ef22-a945-21359367c788@redhat.com>\n\t<ab9faefa-7875-4380-fca0-87767bf271f0@redhat.com>\n\t<20171122055001.GC7625@aiede.mtv.corp.google.com>\n\t<33d730f8-4ad2-4055-fdcc-98117ecc3f45@redhat.com>","Message-ID":"<50086f64-2ea0-18ae-60f4-7b149493a79b@redhat.com>","Date":"Fri, 6 Jul 2018 14:31:58 +0200","User-Agent":"Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101\n\tThunderbird/52.8.0","MIME-Version":"1.0","In-Reply-To":"<33d730f8-4ad2-4055-fdcc-98117ecc3f45@redhat.com>","Content-Type":"multipart/mixed;\n\tboundary=\"------------E1D110E95DFBCAB391CE6D70\""}},{"id":1948698,"web_url":"http://patchwork.ozlabs.org/comment/1948698/","msgid":"<61d534c7-0d53-a1d2-dc1f-b99ea1fae92f@redhat.com>","list_archive_url":null,"date":"2018-07-06T13:07:49","subject":"Re: [PATCH] libio: Implement internal function\n\t__libc_readline_unlocked","submitter":{"id":22438,"url":"http://patchwork.ozlabs.org/api/people/22438/","name":"Carlos O'Donell","email":"carlos@redhat.com"},"content":"On 07/06/2018 08:31 AM, Florian Weimer wrote:\n> On 07/06/2018 02:31 PM, Florian Weimer wrote:\n>> On 11/22/2017 06:50 AM, Jonathan Nieder wrote:\n>>> Florian Weimer wrote:\n>>>\n>>>> --- a/libio/ftello.c\n>>>> +++ b/libio/ftello.c\n>>>> @@ -61,4 +61,6 @@ weak_alias (__ftello, ftello)\n>>>>\n>>>>   #ifdef __OFF_T_MATCHES_OFF64_T\n>>>>   weak_alias (__ftello, ftello64)\n>>>> +strong_alias (__ftello, __ftello64)\n>>>\n>>> What does this part do?\n>>\n>> If off_t and off64_t are the same type, __ftello and __ftello64 are the same function (at the same address).\n>>\n>>> [...]\n>>>> +++ b/libio/readline.c\n>>>> @@ -0,0 +1,169 @@\n>>> [...]\n>>>> +/* Slow path for reading the line.  Called with no data in the stream\n>>>> +   read buffer.  Write data to [BUFFER, BUFFER_END).  */\n>>>> +static ssize_t\n>>>> +readline_slow (_IO_FILE *fp, char *buffer, char *buffer_end)\n>>>> +{\n>>>> +  char *start = buffer;\n>>>> +\n>>>> +  while (buffer < buffer_end)\n>>>> +    {\n>>>> +      if (__underflow (fp) == EOF)\n>>>> +        {\n>>>> +          if (_IO_ferror_unlocked (fp))\n>>>> +            /* If the EOF was caused by a read error, report it.  */\n>>>> +            return fail_no_erange ();\n>>>\n>>> Is readline_slow's caller responsible for ensuring !ferror(fp) before\n>>> the __underflow call?  Otherwise it's possible for this to return -1\n>>> without setting errno.\n>>\n>> The caller should not call the function if the stream is in an error condition I added a comment to the header file.\n>>\n>>>\n>>>> +          *buffer = '\\0';\n>>>> +          /* Do not include the NULL terminator.  */\n>>>\n>>> nit: s/NULL/NUL/ or s/NULL/null/ (NULL is a pointer, NUL an ascii code\n>>> point).\n>>\n>> Thanks, fixed.\n>>\n>>> [...]\n>>>> +  /* Slow path: Read more data from the underlying file.  We need to\n>>>> +     restore the file pointer if the buffer is too small.  First,\n>>>> +     check if the __ftello64 call above failed.  */\n>>>> +  if (start_offset < 0)\n>>>> +    return fail_no_erange ();\n>>>> +\n>>>> +  ssize_t result = readline_slow (fp, buffer, buffer_end);\n>>>> +  if (result < 0)\n>>>> +    {\n>>>> +      if (errno == ERANGE)\n>>>> +        {\n>>>> +          /* Restore the file pointer so that the caller may read the\n>>>> +             same line again.  */\n>>>> +          if (__fseeko64 (fp, start_offset, SEEK_SET) < 0)\n>>>> +            return fail_no_erange ();\n>>>\n>>> What happens if the file is unseekable?  Is this function not meant to\n>>> be used for such files, or is this seeking to reset the file pointer a\n>>> best-effort kind of thing?\n>>\n>> The function is not meant to be used for such files.\n>>\n>> I've rebased the patch and fixed the internal alias generation logic.\n>>\n>> Carlos, is this and the fix for bug 18991 (which has already been\n>> reviewed by DJ) still acceptable during the freeze?\n\nYes, they are still OK during the freeze. They are technically bug fixes\nfor a known issue, and the functions implemented are GLIBC_PRIVATE. I see little\nrisk in these functions causing a release regression.\n\n>>\n>> Thanks,\n>> Florian\n> \n> And now with the patch attached.\n> \n> readline.patch\n> \n> \n> Subject: [PATCH] libio: Implement internal function __libc_readline_unlocked\n> To: libc-alpha@sourceware.org\n> \n> This is a variant of fgets which fails with ERANGE if the\n> buffer is too small, and the buffer length is given as an\n> argument of type size_t.\n> \n> This function will be useful for implementing NSS file reading\n> operations.  Compared to a direct implementation using the public API,\n> it avoids an lseek system call in case the line terminator can be\n> found in the internal read buffer.\n> \n> 2018-07-06  Florian Weimer  <fweimer@redhat.com>\n> \n> \t* include/stdio.h (__libc_readline_unlocked): Declare.\n> \t(__ftello64, __fseeko64): Declare aliases.\n> \t* libio/readline.c: New file.\n> \t* libio/tst-readline.c: Likewise.\n> \t(routines): Add readline.\n> \t(tests-internal): Add tst-readlime.\n> \t* libio/Versions (GLIBC_PRIVATE): Export __fseeko64, __ftello64,\n> \t__libc_readline_unlocked.\n> \t* libio/fseeko.c (__fseeko): Rename from fseeko.\n> \t(fseeko): Add alias.\n> \t[__OFF_T_MATCHES_OFF64_T] (fseeko64, __fseeko64): Likewise.\n> \t* libio/fseeko64.c (__fseeko64): Rename from fseeko64.\n> \t(fseeko64): Add alias.\n> \t* libio/ftello.c [__OFF_T_MATCHES_OFF64_T] (__ftello64): Add alias.\n> \t* libio/ftello64.c (__ftello64): Rename from ftello64.\n> \t(ftello64): Add alias.\n> \n\nOK with comment tweak in readline_slow for assert.\n\nReviewed-by: Carlos O'Donell <carlos@redhat.com>\n\n> diff --git a/include/stdio.h b/include/stdio.h\n> index 3ba0edc924..9162d4e247 100644\n> --- a/include/stdio.h\n> +++ b/include/stdio.h\n> @@ -127,6 +127,19 @@ extern int __fxprintf (FILE *__fp, const char *__fmt, ...)\n>  extern int __fxprintf_nocancel (FILE *__fp, const char *__fmt, ...)\n>       __attribute__ ((__format__ (__printf__, 2, 3))) attribute_hidden;\n>  \n> +/* Read the next line from FP into BUFFER, of LENGTH bytes.  LINE will\n> +   include the line terminator and a NUL terminator.  On success,\n> +   return the length of the line, including the line terminator, but\n> +   excluding the NUL termintor.  On EOF, return zero and write a NUL\n> +   terminator.  On error, return -1 and set errno.  If the total byte\n> +   count (line and both terminators) exceeds LENGTH, return -1 and set\n> +   errno to ERANGE (but do not mark the stream as failed).\n\nOK.\n\n> +\n> +   The behavior is undefined if FP is not seekable, or if the stream\n> +   is already in an error state.  */\n\nOK.\n\n> +ssize_t __libc_readline_unlocked (FILE *fp, char *buffer, size_t length);\n> +libc_hidden_proto (__libc_readline_unlocked);\n> +\n>  extern const char *const _sys_errlist_internal[] attribute_hidden;\n>  extern int _sys_nerr_internal attribute_hidden;\n>  \n> @@ -170,6 +183,10 @@ libc_hidden_proto (fwrite)\n>  libc_hidden_proto (fseek)\n>  extern __typeof (ftello) __ftello;\n>  libc_hidden_proto (__ftello)\n> +extern __typeof (fseeko64) __fseeko64;\n> +libc_hidden_proto (__fseeko64)\n> +extern __typeof (ftello64) __ftello64;\n> +libc_hidden_proto (__ftello64)\n\nOK.\n\n>  libc_hidden_proto (fflush)\n>  libc_hidden_proto (fflush_unlocked)\n>  extern __typeof (fflush_unlocked) __fflush_unlocked;\n> diff --git a/libio/Makefile b/libio/Makefile\n> index 64d283e512..cab0eae946 100644\n> --- a/libio/Makefile\n> +++ b/libio/Makefile\n> @@ -49,7 +49,7 @@ routines\t:=\t\t\t\t\t\t\t      \\\n>  \t__fbufsize __freading __fwriting __freadable __fwritable __flbf\t      \\\n>  \t__fpurge __fpending __fsetlocking\t\t\t\t      \\\n>  \t\t\t\t\t\t\t\t\t      \\\n> -\tlibc_fatal fmemopen oldfmemopen vtables\n> +\tlibc_fatal fmemopen oldfmemopen vtables readline\n\nOK.\n\n>  \n>  tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc   \\\n>  \ttst_wprintf2 tst-widetext test-fmemopen tst-ext tst-ext2 \\\n> @@ -66,7 +66,7 @@ tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc   \\\n>  \ttst-fwrite-error tst-ftell-partial-wide tst-ftell-active-handler \\\n>  \ttst-ftell-append tst-fputws tst-bz22415 tst-fgetc-after-eof\n>  \n> -tests-internal = tst-vtables tst-vtables-interposed\n> +tests-internal = tst-vtables tst-vtables-interposed tst-readline\n\nOK.\n\n>  \n>  ifeq (yes,$(build-shared))\n>  # Add test-fopenloc only if shared library is enabled since it depends on\n> diff --git a/libio/Versions b/libio/Versions\n> index 77123347e3..acb896afa9 100644\n> --- a/libio/Versions\n> +++ b/libio/Versions\n> @@ -158,5 +158,9 @@ libc {\n>  \n>      # Used by NPTL\n>      _IO_enable_locks;\n> +\n> +    __fseeko64;\n> +    __ftello64;\n> +    __libc_readline_unlocked;\n\nOK.\n\n>    }\n>  }\n> diff --git a/libio/fseeko.c b/libio/fseeko.c\n> index 2df0453d35..4d086c15d8 100644\n> --- a/libio/fseeko.c\n> +++ b/libio/fseeko.c\n> @@ -24,11 +24,15 @@\n>     This exception applies to code released by its copyright holders\n>     in files containing the exception.  */\n>  \n> +/* We need to disable the redirect for __fseeko64 for the alias\n> +   definitions below to work.  */\n> +#define __fseeko64 __fseeko64_disable\n> +\n>  #include \"libioP.h\"\n>  #include \"stdio.h\"\n>  \n>  int\n> -fseeko (FILE *fp, off_t offset, int whence)\n> +__fseeko (FILE *fp, off_t offset, int whence)\n\nOK.\n\n>  {\n>    int result;\n>    CHECK_FILE (fp, -1);\n> @@ -37,7 +41,11 @@ fseeko (FILE *fp, off_t offset, int whence)\n>    _IO_release_lock (fp);\n>    return result;\n>  }\n> +weak_alias (__fseeko, fseeko)\n\nOK.\n\n>  \n>  #ifdef __OFF_T_MATCHES_OFF64_T\n> -weak_alias (fseeko, fseeko64)\n> +weak_alias (__fseeko, fseeko64)\n> +# undef __fseeko64\n> +strong_alias (__fseeko, __fseeko64)\n> +libc_hidden_ver (__fseeko, __fseeko64)\n\nOK.\n\n>  #endif\n> diff --git a/libio/fseeko64.c b/libio/fseeko64.c\n> index eea6455bc3..1d9bb190a6 100644\n> --- a/libio/fseeko64.c\n> +++ b/libio/fseeko64.c\n> @@ -32,7 +32,7 @@\n>  #ifndef __OFF_T_MATCHES_OFF64_T\n>  \n>  int\n> -fseeko64 (FILE *fp, off64_t offset, int whence)\n> +__fseeko64 (FILE *fp, off64_t offset, int whence)\n\nOK.\n\n>  {\n>    int result;\n>    CHECK_FILE (fp, -1);\n> @@ -41,5 +41,6 @@ fseeko64 (FILE *fp, off64_t offset, int whence)\n>    _IO_release_lock (fp);\n>    return result;\n>  }\n> -\n> +libc_hidden_def (__fseeko64)\n> +weak_alias (__fseeko64, fseeko64)\n\nOK.\n\n>  #endif\n> diff --git a/libio/ftello.c b/libio/ftello.c\n> index 5405821b45..5a3caf4ad9 100644\n> --- a/libio/ftello.c\n> +++ b/libio/ftello.c\n> @@ -24,12 +24,15 @@\n>     This exception applies to code released by its copyright holders\n>     in files containing the exception.  */\n>  \n> +/* We need to disable the redirect for __ftello64 for the alias\n> +   definitions below to work.  */\n> +#define __ftello64 __ftello64_disable\n\nOK.\n\n> +\n>  #include <stdio.h>\n>  #include <stdlib.h>\n>  #include <libioP.h>\n>  #include <errno.h>\n>  \n> -\n>  off_t\n>  __ftello (FILE *fp)\n>  {\n> @@ -61,4 +64,7 @@ weak_alias (__ftello, ftello)\n>  \n>  #ifdef __OFF_T_MATCHES_OFF64_T\n>  weak_alias (__ftello, ftello64)\n> +# undef __ftello64\n> +strong_alias (__ftello, __ftello64)\n> +libc_hidden_ver (__ftello, __ftello64)\n\nOK.\n\n>  #endif\n> diff --git a/libio/ftello64.c b/libio/ftello64.c\n> index 281667fee2..d5546e1fb0 100644\n> --- a/libio/ftello64.c\n> +++ b/libio/ftello64.c\n> @@ -32,7 +32,7 @@\n>  #ifndef __OFF_T_MATCHES_OFF64_T\n>  \n>  off64_t\n> -ftello64 (FILE *fp)\n> +__ftello64 (FILE *fp)\n\nOK.\n\n>  {\n>    off64_t pos;\n>    CHECK_FILE (fp, -1L);\n> @@ -52,5 +52,6 @@ ftello64 (FILE *fp)\n>      }\n>    return pos;\n>  }\n> -\n> +libc_hidden_def (__ftello64)\n> +weak_alias (__ftello64, ftello64)\n\nOK.\n\n>  #endif\n> diff --git a/libio/readline.c b/libio/readline.c\n> new file mode 100644\n> index 0000000000..d5424b1c27\n> --- /dev/null\n> +++ b/libio/readline.c\n> @@ -0,0 +1,169 @@\n> +/* fgets with ERANGE error reporting and size_t buffer length.\n\nOK.\n\n> +   Copyright (C) 2017 Free Software Foundation, Inc.\n> +   This file is part of the GNU C Library.\n> +\n> +   The GNU C Library is free software; you can redistribute it and/or\n> +   modify it under the terms of the GNU Lesser General Public\n> +   License as published by the Free Software Foundation; either\n> +   version 2.1 of the License, or (at your option) any later version.\n> +\n> +   The GNU C Library is distributed in the hope that it will be useful,\n> +   but WITHOUT ANY WARRANTY; without even the implied warranty of\n> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n> +   Lesser General Public License for more details.\n> +\n> +   You should have received a copy of the GNU Lesser General Public\n> +   License along with the GNU C Library; if not, see\n> +   <http://www.gnu.org/licenses/>.  */\n> +\n> +#include <assert.h>\n> +#include <errno.h>\n> +#include <stdio.h>\n> +#include <string.h>\n> +\n> +#include \"libioP.h\"\n> +\n> +/* Return -1 and set errno to EINVAL if it is ERANGE.  */\n> +static ssize_t\n> +fail_no_erange (void)\n> +{\n> +  if (errno == ERANGE)\n> +    __set_errno (EINVAL);\n> +  return -1;\n> +}\n\nOK.\n\n> +\n> +/* Slow path for reading the line.  Called with no data in the stream\n> +   read buffer.  Write data to [BUFFER, BUFFER_END).  */\n> +static ssize_t\n> +readline_slow (FILE *fp, char *buffer, char *buffer_end)\n> +{\n> +  char *start = buffer;\n> +\n> +  while (buffer < buffer_end)\n> +    {\n> +      if (__underflow (fp) == EOF)\n> +        {\n> +          if (_IO_ferror_unlocked (fp))\n> +            /* If the EOF was caused by a read error, report it.  */\n> +            return fail_no_erange ();\n> +          *buffer = '\\0';\n> +          /* Do not include the null terminator.  */\n> +          return buffer - start;\n> +        }\n\nOK.\n\n> +\n> +      /* __underflow has filled the buffer.  */\n> +      char *readptr = fp->_IO_read_ptr;\n> +      ssize_t readlen = fp->_IO_read_end - readptr;\n> +      assert (readlen > 0);\n\nPlease add a comment explaining why readlen > 0, nominally\nI expect it's because __underflow would have returned EOF\nif it *was* 0 and we'd be in the above case. I think this needs\ncalling out with a comment here (or adjust the existing comment\na bit).\n\n> +      char *pnl = memchr (readptr, '\\n', readlen);\n> +      if (pnl != NULL)\n> +        {\n> +          /* We found the terminator.  */\n> +          size_t line_length = pnl - readptr;\n> +          if (line_length + 2 > buffer_end - buffer)\n> +            /* Not enough room in the caller-supplied buffer.  */\n> +            break;\n> +          memcpy (buffer, readptr, line_length + 1);\n> +          buffer[line_length + 1] = '\\0';\n> +          fp->_IO_read_ptr = pnl + 1;\n> +          /* Do not include the null terminator.  */\n> +          return buffer - start + line_length + 1;\n\nOK.\n\n> +        }\n> +\n> +      if (readlen >= buffer_end - buffer)\n> +        /* Not enough room in the caller-supplied buffer.  */\n> +        break;\n\nOK.\n\n> +\n> +      /* Save and consume the stream buffer.  */\n> +      memcpy (buffer, readptr, readlen);\n> +      fp->_IO_read_ptr = fp->_IO_read_end;\n> +      buffer += readlen;\n\nOK.\n\n> +    }\n> +\n> +  /* The line does not fit into the buffer.  */\n> +  __set_errno (ERANGE);\n> +  return -1;\n\nOK.\n\n> +}\n> +\n> +ssize_t\n> +__libc_readline_unlocked (FILE *fp, char *buffer, size_t buffer_length)\n> +{\n> +  char *buffer_end = buffer + buffer_length;\n> +\n> +  /* Orient the stream.  */\n> +  if (__builtin_expect (fp->_mode, -1) == 0)\n> +    _IO_fwide (fp, -1);\n> +\n> +  /* Fast path: The line terminator is found in the buffer.  */\n> +  char *readptr = fp->_IO_read_ptr;\n> +  ssize_t readlen = fp->_IO_read_end - readptr;\n> +  off64_t start_offset;         /* File offset before reading anything.  */\n> +  if (readlen > 0)\n> +    {\n> +      char *pnl = memchr (readptr, '\\n', readlen);\n> +      if (pnl != NULL)\n> +        {\n> +          size_t line_length = pnl - readptr;\n> +          /* Account for line and null terminators.  */\n> +          if (line_length + 2 > buffer_length)\n> +            {\n> +              __set_errno (ERANGE);\n> +              return -1;\n\nOK.\n\n> +            }\n> +          memcpy (buffer, readptr, line_length + 1);\n> +          buffer[line_length + 1] = '\\0';\n> +          /* Consume the entire line.  */\n> +          fp->_IO_read_ptr = pnl + 1;\n> +          return line_length + 1;\n\nOK.\n\n> +        }\n> +\n> +      /* If the buffer does not have enough space for what is pending\n> +         in the stream (plus a NUL terminator), the buffer is too\n> +         small.  */\n> +      if (readlen + 1 > buffer_length)\n> +        {\n> +          __set_errno (ERANGE);\n> +          return -1;\n\nOK.\n\n> +        }\n> +\n> +      /* End of line not found.  We need all the buffered data.  Fall\n> +         through to the slow path.  */\n> +      memcpy (buffer, readptr, readlen);\n> +      buffer += readlen;\n> +      /* The original length is invalid after this point.  Use\n> +         buffer_end instead.  */\n> +#pragma GCC poison buffer_length\n> +      /* Read the old offset before updating the read pointer.  */\n> +      start_offset = __ftello64 (fp);\n> +      fp->_IO_read_ptr = fp->_IO_read_end;\n> +    }\n> +  else\n> +    {\n> +      readlen = 0;\n> +      start_offset = __ftello64 (fp);\n> +    }\n> +\n> +  /* Slow path: Read more data from the underlying file.  We need to\n> +     restore the file pointer if the buffer is too small.  First,\n> +     check if the __ftello64 call above failed.  */\n> +  if (start_offset < 0)\n> +    return fail_no_erange ();\n\nOK.\n\n> +\n> +  ssize_t result = readline_slow (fp, buffer, buffer_end);\n\nOK, calling readline_slow from above.\n\n> +  if (result < 0)\n> +    {\n> +      if (errno == ERANGE)\n> +        {\n> +          /* Restore the file pointer so that the caller may read the\n> +             same line again.  */\n> +          if (__fseeko64 (fp, start_offset, SEEK_SET) < 0)\n\nOK. Allows caller to re-read the same line with a longer buffer.\n\n> +            return fail_no_erange ();\n> +          __set_errno (ERANGE);\n> +        }\n> +      /* Do not restore the file position on other errors; it is\n> +         likely that the __fseeko64 call would fail, too.  */\n> +      return -1;\n\nOk.\n\n> +    }\n> +  return readlen + result;\n> +}\n> +libc_hidden_def (__libc_readline_unlocked)\n> diff --git a/libio/tst-readline.c b/libio/tst-readline.c\n> new file mode 100644\n> index 0000000000..79ed6ea699\n> --- /dev/null\n> +++ b/libio/tst-readline.c\n> @@ -0,0 +1,235 @@\n> +/* Test the __libc_readline_unlocked function.\n\nOK.\n\n> +   Copyright (C) 2017 Free Software Foundation, Inc.\n> +   This file is part of the GNU C Library.\n> +\n> +   The GNU C Library is free software; you can redistribute it and/or\n> +   modify it under the terms of the GNU Lesser General Public\n> +   License as published by the Free Software Foundation; either\n> +   version 2.1 of the License, or (at your option) any later version.\n> +\n> +   The GNU C Library is distributed in the hope that it will be useful,\n> +   but WITHOUT ANY WARRANTY; without even the implied warranty of\n> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n> +   Lesser General Public License for more details.\n> +\n> +   You should have received a copy of the GNU Lesser General Public\n> +   License along with the GNU C Library; if not, see\n> +   <http://www.gnu.org/licenses/>.  */\n> +\n> +/* Exercise __libc_readline_unlocked with various combinations of line\n> +   lengths, stdio buffer sizes, and line read buffer sizes.  */\n> +\n> +#include <errno.h>\n> +#include <stdbool.h>\n> +#include <stdio.h>\n> +#include <support/check.h>\n> +#include <support/test-driver.h>\n> +#include <support/support.h>\n> +#include <support/xstdio.h>\n> +#include <support/xmemstream.h>\n> +#include <support/temp_file.h>\n> +#include <support/xunistd.h>\n> +\n> +enum\n> +  {\n> +    maximum_line_length = 7,\n> +    number_of_lines = 3,\n> +  };\n\nOK.\n\n> +\n> +/* -1: Do not set buffer size.  0: unbuffered.  Otherwise, use this as\n> +   the size of the buffer.  */\n> +static int buffer_size;\n> +\n> +/* These size of the buffer used for reading.  Must be at least 2.  */\n> +static int read_size;\n> +\n> +/* If a read files with ERANGE, increase the buffer size by this\n> +   amount.  Must be positive.  */\n> +static int read_size_increment;\n> +\n> +/* If non-zero, do not reset the read size after an ERANGE error.  */\n> +static int read_size_preserve;\n> +\n> +/* If non-zero, no '\\n' at the end of the file.  */\n> +static int no_newline_at_eof;\n> +\n> +/* Length of the line, or -1 if the line is not present.  */\n> +static int line_lengths[number_of_lines];\n> +\n> +/* The name of the test file.  */\n> +static char *test_file_path;\n> +\n> +/* The contents of the test file.  */\n> +static char expected_contents[(maximum_line_length + 2) * number_of_lines + 1];\n> +static size_t expected_length;\n> +\n> +/* Returns a random byte which is not zero or the line terminator.  */\n> +static char\n> +random_char (void)\n> +{\n> +  static unsigned int rand_state = 1;\n> +  while (true)\n> +    {\n> +      char result = rand_r (&rand_state) >> 16;\n> +      if (result != 0 && result != '\\n')\n> +        return result;\n> +    }\n> +}\n\nOK.\n\n> +\n> +/* Create the test file.  */\n> +static void\n> +prepare (int argc, char **argv)\n> +{\n> +  int fd = create_temp_file (\"tst-readline-\", &test_file_path);\n> +  TEST_VERIFY_EXIT (fd >= 0);\n> +  xclose (fd);\n> +}\n\nOK.\n\n> +\n> +/* Prepare the test file.  Return false if the test parameters are\n> +   incongruent and the test should be skipped.  */\n> +static bool\n> +write_test_file (void)\n> +{\n> +  expected_length = 0;\n> +  char *p = expected_contents;\n> +  for (int lineno = 0; lineno < number_of_lines; ++lineno)\n> +    for (int i = 0; i < line_lengths[lineno]; ++i)\n> +      *p++ = random_char ();\n> +  expected_length = p - &expected_contents[0];\n> +  if (no_newline_at_eof)\n> +    {\n> +      if (expected_length == 0)\n> +        return false;\n> +      --expected_length;\n> +      --p;\n> +    }\n> +  if (test_verbose > 0)\n> +    {\n> +      printf (\"info: writing test file of %zu bytes:\\n\", expected_length);\n> +      for (int i = 0; i < number_of_lines; ++i)\n> +        printf (\" line %d: %d\\n\", i, line_lengths[i]);\n> +      if (no_newline_at_eof)\n> +        puts (\"  (no newline at EOF)\");\n> +    }\n> +  TEST_VERIFY_EXIT (expected_length < sizeof (expected_contents));\n> +  *p++ = '\\0';\n> +  support_write_file_string (test_file_path, expected_contents);\n> +  return true;\n> +}\n\nOK.\n\n> +\n> +/* Run a single test (a combination of a test file and read\n> +   parameters).  */\n> +static void\n> +run_test (void)\n> +{\n> +  TEST_VERIFY_EXIT (read_size_increment > 0);\n> +  if (test_verbose > 0)\n> +    {\n> +      printf (\"info: running test: buffer_size=%d read_size=%d\\n\"\n> +              \"  read_size_increment=%d read_size_preserve=%d\\n\",\n> +              buffer_size, read_size, read_size_increment, read_size_preserve);\n> +    }\n> +\n> +  struct xmemstream result;\n> +  xopen_memstream (&result);\n> +\n> +  FILE *fp = xfopen (test_file_path, \"rce\");\n> +  char *fp_buffer = NULL;\n> +  if (buffer_size == 0)\n> +    TEST_VERIFY_EXIT (setvbuf (fp, NULL, _IONBF, 0) == 0);\n> +  if (buffer_size > 0)\n> +    {\n> +      fp_buffer = xmalloc (buffer_size);\n> +      TEST_VERIFY_EXIT (setvbuf (fp, fp_buffer, _IOFBF, buffer_size) == 0);\n> +    }\n> +\n> +  char *line_buffer = xmalloc (read_size);\n> +  size_t line_buffer_size = read_size;\n> +\n> +  while (true)\n> +    {\n> +      ssize_t ret = __libc_readline_unlocked\n> +        (fp, line_buffer, line_buffer_size);\n\nOK.\n\n> +      if (ret < 0)\n> +        {\n> +          TEST_VERIFY (ret == -1);\n> +          if (errno != ERANGE)\n> +            FAIL_EXIT1 (\"__libc_readline_unlocked: %m\");\n> +          line_buffer_size += read_size_increment;\n> +          free (line_buffer);\n> +          line_buffer = xmalloc (line_buffer_size);\n> +          /* Try reading this line again.  */\n\nOK.\n\n> +        }\n> +      else if (ret == 0)\n> +        break;\n> +      else\n> +        {\n> +          /* A line has been read.  Save it.  */\n> +          TEST_VERIFY (ret == strlen (line_buffer));\n> +          const char *pnl = strchr (line_buffer, '\\n');\n> +          /* If there is a \\n, it must be at the end.  */\n> +          TEST_VERIFY (pnl == NULL || pnl == line_buffer + ret - 1);\n> +          fputs (line_buffer, result.out);\n> +\n> +          /* Restore the original read size if required.  */\n> +          if (line_buffer_size > read_size && !read_size_preserve)\n> +            {\n> +              line_buffer_size = read_size;\n> +              free (line_buffer);\n> +              line_buffer = xmalloc (line_buffer_size);\n> +            }\n> +        }\n> +    }\n> +\n\nOK.\n\n> +  xfclose (fp);\n> +  free (fp_buffer);\n> +  free (line_buffer);\n> +\n> +  xfclose_memstream (&result);\n> +  TEST_VERIFY (result.length == expected_length);\n> +  TEST_VERIFY (strcmp (result.buffer, expected_contents) == 0);\n> +  if (test_verbose > 0)\n> +    {\n> +      printf (\"info: expected (%zu): [[%s]]\\n\",\n> +              expected_length, expected_contents);\n> +      printf (\"info:   actual (%zu): [[%s]]\\n\", result.length, result.buffer);\n> +    }\n> +  free (result.buffer);\n\nOK.\n\n> +}\n> +\n> +/* Test one test file with multiple read parameters.  */\n> +static void\n> +test_one_file (void)\n> +{\n> +  for (buffer_size = -1; buffer_size <= maximum_line_length + 1; ++buffer_size)\n> +    for (read_size = 2; read_size <= maximum_line_length + 2; ++read_size)\n> +      for (read_size_increment = 1; read_size_increment <= 4;\n> +           ++read_size_increment)\n> +        for (read_size_preserve = 0; read_size_preserve < 2;\n> +             ++read_size_preserve)\n> +          run_test ();\n\nOK.\n\n> +}\n> +\n> +\n> +static int\n> +do_test (void)\n> +{\n> +  /* Set up the test file contents.  */\n> +  for (line_lengths[0] = -1; line_lengths[0] <= maximum_line_length;\n> +       ++line_lengths[0])\n> +    for (line_lengths[1] = -1; line_lengths[1] <= maximum_line_length;\n> +         ++line_lengths[1])\n> +      for (line_lengths[2] = -1; line_lengths[2] <= maximum_line_length;\n> +           ++line_lengths[2])\n> +        for (no_newline_at_eof = 0; no_newline_at_eof < 2; ++no_newline_at_eof)\n> +          {\n> +            if (!write_test_file ())\n> +              continue;\n> +            test_one_file ();\n> +          }\n> +  free (test_file_path);\n> +  return 0;\n\nOK. Permute over the lines from min to max length and EOF or no EOF at end of file.\n\nLooks good.\n\n> +}\n> +\n> +#define PREPARE prepare\n> +#include <support/test-driver.c>","headers":{"Return-Path":"<libc-alpha-return-94074-incoming=patchwork.ozlabs.org@sourceware.org>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":["patchwork-incoming@bilbo.ozlabs.org","mailing list libc-alpha@sourceware.org"],"Authentication-Results":["ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=sourceware.org\n\t(client-ip=209.132.180.131; helo=sourceware.org;\n\tenvelope-from=libc-alpha-return-94074-incoming=patchwork.ozlabs.org@sourceware.org;\n\treceiver=<UNKNOWN>)","ozlabs.org;\n\tdmarc=fail (p=none dis=none) header.from=redhat.com","ozlabs.org; dkim=pass (1024-bit key;\n\tsecure) header.d=sourceware.org header.i=@sourceware.org\n\theader.b=\"ulUyZr1f\"; dkim-atps=neutral","sourceware.org; auth=none"],"Received":["from sourceware.org (server1.sourceware.org [209.132.180.131])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256\n\tbits)) (No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 41MZln69dtz9s4c\n\tfor <incoming@patchwork.ozlabs.org>;\n\tFri,  6 Jul 2018 23:08:05 +1000 (AEST)","(qmail 124660 invoked by alias); 6 Jul 2018 13:07:59 -0000","(qmail 124642 invoked by uid 89); 6 Jul 2018 13:07:58 -0000"],"DomainKey-Signature":"a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id\n\t:list-unsubscribe:list-subscribe:list-archive:list-post\n\t:list-help:sender:subject:to:cc:references:from:message-id:date\n\t:mime-version:in-reply-to:content-type\n\t:content-transfer-encoding; q=dns; s=default; b=auqcf11By5TNpdvx\n\tkDfw4w3o/t6Rymt/3xnbvD0yZ1qby+XqI3PoyfzKIDHiIsI6SXXFnU9vWxIvfBXs\n\tf2Kvssgwsw9zNpczzApVZqZeWr7/KLPnqU4VGj/Y1H307/fZb0NV5Xg7x8gXKYFW\n\tlHiK/XLJEaM+6deWp9yNNdNahB0=","DKIM-Signature":"v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id\n\t:list-unsubscribe:list-subscribe:list-archive:list-post\n\t:list-help:sender:subject:to:cc:references:from:message-id:date\n\t:mime-version:in-reply-to:content-type\n\t:content-transfer-encoding; s=default; bh=meym7On9qD1+C7/EPsJPS3\n\t8zU9o=; b=ulUyZr1fPVD7iY2/Vfe9yileOpzrvSte4FycCKmSZr6VLHzP58kJMm\n\tknMs7bPxpvP6a4YwfcDUWHYeHgU3SoAxOnr5ExWtGYm02ik1G1pGGbIYYsWgpTQK\n\t0m3D6fGhpHjMOzN4NlJPl+9tl2HFHuD/3hcp2MEcV2D4DDKigfuqo=","Mailing-List":"contact libc-alpha-help@sourceware.org; run by ezmlm","Precedence":"bulk","List-Id":"<libc-alpha.sourceware.org>","List-Unsubscribe":"<mailto:libc-alpha-unsubscribe-incoming=patchwork.ozlabs.org@sourceware.org>","List-Subscribe":"<mailto:libc-alpha-subscribe@sourceware.org>","List-Archive":"<http://sourceware.org/ml/libc-alpha/>","List-Post":"<mailto:libc-alpha@sourceware.org>","List-Help":"<mailto:libc-alpha-help@sourceware.org>,\n\t<http://sourceware.org/ml/#faqs>","Sender":"libc-alpha-owner@sourceware.org","X-Spam-SWARE-Status":"No, score=-23.7 required=5.0 tests=AWL, BAYES_00,\n\tGIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3,\n\tKAM_LAZY_DOMAIN_SECURITY, KAM_SHORT,\n\tRCVD_IN_DNSWL_NONE autolearn=ham version=3.3.2 spammy=so","X-HELO":"mail-qt0-f194.google.com","Subject":"Re: [PATCH] libio: Implement internal function\n\t__libc_readline_unlocked","To":"Florian Weimer <fweimer@redhat.com>, Jonathan Nieder <jrnieder@gmail.com>","Cc":"libc-alpha@sourceware.org","References":"<20170901154335.E5819439942E3@oldenburg.str.redhat.com>\n\t<4694e740-6bdb-ef22-a945-21359367c788@redhat.com>\n\t<ab9faefa-7875-4380-fca0-87767bf271f0@redhat.com>\n\t<20171122055001.GC7625@aiede.mtv.corp.google.com>\n\t<33d730f8-4ad2-4055-fdcc-98117ecc3f45@redhat.com>\n\t<50086f64-2ea0-18ae-60f4-7b149493a79b@redhat.com>","From":"Carlos O'Donell <carlos@redhat.com>","Openpgp":"preference=signencrypt","Message-ID":"<61d534c7-0d53-a1d2-dc1f-b99ea1fae92f@redhat.com>","Date":"Fri, 6 Jul 2018 09:07:49 -0400","User-Agent":"Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101\n\tThunderbird/52.8.0","MIME-Version":"1.0","In-Reply-To":"<50086f64-2ea0-18ae-60f4-7b149493a79b@redhat.com>","Content-Type":"text/plain; charset=utf-8","Content-Transfer-Encoding":"8bit"}},{"id":1948983,"web_url":"http://patchwork.ozlabs.org/comment/1948983/","msgid":"<20180706182823.GA6195@aiede.svl.corp.google.com>","list_archive_url":null,"date":"2018-07-06T18:28:23","subject":"Re: [PATCH] libio: Implement internal function\n\t__libc_readline_unlocked","submitter":{"id":8008,"url":"http://patchwork.ozlabs.org/api/people/8008/","name":"Jonathan Nieder","email":"jrnieder@gmail.com"},"content":"Hi,\n\nFlorian Weimer wrote:\n> On 07/06/2018 02:31 PM, Florian Weimer wrote:\n\n>> The caller should not call the function if the stream is in an error\n>> condition I added a comment to the header file.\n\nThanks.\n\n[...]\n> --- a/include/stdio.h\n> +++ b/include/stdio.h\n> @@ -127,6 +127,19 @@ extern int __fxprintf (FILE *__fp, const char *__fmt, ...)\n>  extern int __fxprintf_nocancel (FILE *__fp, const char *__fmt, ...)\n>       __attribute__ ((__format__ (__printf__, 2, 3))) attribute_hidden;\n>  \n> +/* Read the next line from FP into BUFFER, of LENGTH bytes.  LINE will\n> +   include the line terminator and a NUL terminator.  On success,\n> +   return the length of the line, including the line terminator, but\n> +   excluding the NUL termintor.  On EOF, return zero and write a NUL\n> +   terminator.  On error, return -1 and set errno.  If the total byte\n> +   count (line and both terminators) exceeds LENGTH, return -1 and set\n> +   errno to ERANGE (but do not mark the stream as failed).\n> +\n> +   The behavior is undefined if FP is not seekable, or if the stream\n> +   is already in an error state.  */\n> +ssize_t __libc_readline_unlocked (FILE *fp, char *buffer, size_t length);\n> +libc_hidden_proto (__libc_readline_unlocked);\n\nMakes sense.\n\nWhat kind of stability guarantees do we make for this kind of\ndouble-underscored GLIBC_PRIVATE symbol?  E.g. if we decide to remove\nit later or change its behavior, is that easy to do?\n\nI'm not looking for any particular answer --- an answer like \"see\nsuch-and-such wiki page\" or \"see such-and-such bug about missing\ndocumentation\" would be the ideal.\n\n[...]\n> --- /dev/null\n> +++ b/libio/readline.c\n> @@ -0,0 +1,169 @@\n> +/* fgets with ERANGE error reporting and size_t buffer length.\n> +   Copyright (C) 2017 Free Software Foundation, Inc.\n> +   This file is part of the GNU C Library.\n\noptional: could put 2018 here, since this will have been first\npublished as part of glibc in 2018.\n\n[...]\n> --- /dev/null\n> +++ b/libio/tst-readline.c\n> @@ -0,0 +1,235 @@\n> +/* Test the __libc_readline_unlocked function.\n> +   Copyright (C) 2017 Free Software Foundation, Inc.\n\nLikewise.\n\nThe rest looks good, too.\n\nReviewed-by: Jonathan Nieder <jrnieder@gmail.com>\n\nThanks for your patient work.","headers":{"Return-Path":"<libc-alpha-return-94101-incoming=patchwork.ozlabs.org@sourceware.org>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":["patchwork-incoming@bilbo.ozlabs.org","mailing list libc-alpha@sourceware.org"],"Authentication-Results":["ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=sourceware.org\n\t(client-ip=209.132.180.131; helo=sourceware.org;\n\tenvelope-from=libc-alpha-return-94101-incoming=patchwork.ozlabs.org@sourceware.org;\n\treceiver=<UNKNOWN>)","ozlabs.org;\n\tdmarc=pass (p=none dis=none) header.from=gmail.com","ozlabs.org; dkim=pass (1024-bit key;\n\tsecure) header.d=sourceware.org header.i=@sourceware.org\n\theader.b=\"W239XmkD\"; dkim=pass (2048-bit key;\n\tunprotected) header.d=gmail.com header.i=@gmail.com\n\theader.b=\"suWLe5b+\"; dkim-atps=neutral","sourceware.org; auth=none"],"Received":["from sourceware.org (server1.sourceware.org [209.132.180.131])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256\n\tbits)) (No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 41Mjt16Lp9z9rxs\n\tfor <incoming@patchwork.ozlabs.org>;\n\tSat,  7 Jul 2018 04:28:57 +1000 (AEST)","(qmail 75298 invoked by alias); 6 Jul 2018 18:28:51 -0000","(qmail 75286 invoked by uid 89); 6 Jul 2018 18:28:50 -0000"],"DomainKey-Signature":"a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id\n\t:list-unsubscribe:list-subscribe:list-archive:list-post\n\t:list-help:sender:date:from:to:cc:subject:message-id:references\n\t:mime-version:content-type:in-reply-to; q=dns; s=default; b=l9Lu\n\t+qqzMDtXmssH6JFGQvU5H2pQVUsDuSGVngkF8SJOWpODc19i/jftAAJzHJY0Qmmd\n\tvcQGjmBcCsOs22EbdjsfFVwC2A/OpXx//oCwh/y9DNR2IM8qRgIJretEVa9IzzCL\n\t57wCRnd7M2RRnj8BNEnx6Qk5SuL9S5KKawyWlZE=","DKIM-Signature":["v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id\n\t:list-unsubscribe:list-subscribe:list-archive:list-post\n\t:list-help:sender:date:from:to:cc:subject:message-id:references\n\t:mime-version:content-type:in-reply-to; s=default; bh=UOXZNL75dm\n\tLJsUSBA9aS+k1sqYg=; b=W239XmkD45QIUlmVm9Olo2AYkzuJqwA7GlrfbO9WzA\n\tw1spwa8Ft2snrevOXIDheVv0gyHkrQ8Xbs2GCO0MWnFiP7viPCJK9k83OphWxYZd\n\t7NuEt1zdd4lCaBz3dFRIpBcUDgMr58hBqvexuGLieQFpLNKGeU710+yDnhM4jRqj\n\t4=","v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=gmail.com; s=20161025;\n\th=date:from:to:cc:subject:message-id:references:mime-version\n\t:content-disposition:in-reply-to:user-agent;\n\tbh=Jnerxz/Ee9QeaVcOpWQ7rQAgILDVyFD697Jkf2E4ctg=;\n\tb=suWLe5b+8skFtajZzh7ZAT+gdiEPOa4ykoSzP9yPUN6LNfMsU4wepKUfALwBI9sE+X\n\tWVCvQDmQRtnejYC9Oi1y/9b0vP0MBKDwWp2LsAmvfxXo281RLAsOXgC3jharfgqi9441\n\tNCQKxSLCCIxpEKb5fYRZMv3me6JPle3N88og2dsBYYyf19hhuYTm2zp8EwGczAYMnHXK\n\tK0SfCL9mS/lyc53/10mBX/SJIUaqWxsxdS6n2gTdVbYLfdVOiOCMrRoz3Sy2hBTDcWu2\n\tpg7cNDiyDD3JeaGieytxTWOgGM6cJOC9uCpxJpucahRrOJ2mltZ+ixGg54cJsz8ydNkc\n\t5Isw=="],"Mailing-List":"contact libc-alpha-help@sourceware.org; run by ezmlm","Precedence":"bulk","List-Id":"<libc-alpha.sourceware.org>","List-Unsubscribe":"<mailto:libc-alpha-unsubscribe-incoming=patchwork.ozlabs.org@sourceware.org>","List-Subscribe":"<mailto:libc-alpha-subscribe@sourceware.org>","List-Archive":"<http://sourceware.org/ml/libc-alpha/>","List-Post":"<mailto:libc-alpha@sourceware.org>","List-Help":"<mailto:libc-alpha-help@sourceware.org>,\n\t<http://sourceware.org/ml/#faqs>","Sender":"libc-alpha-owner@sourceware.org","X-Spam-SWARE-Status":"No, score=-11.9 required=5.0 tests=BAYES_00,\n\tFREEMAIL_FROM, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE,\n\tSPF_PASS autolearn=ham version=3.3.2\n\tspammy=HX-Gm-Message-State:APt69E2, stability, H*r:sk:30-v6so","X-HELO":"mail-pl0-f67.google.com","Date":"Fri, 6 Jul 2018 11:28:23 -0700","From":"Jonathan Nieder <jrnieder@gmail.com>","To":"Florian Weimer <fweimer@redhat.com>","Cc":"libc-alpha@sourceware.org, Carlos O'Donell <carlos@redhat.com>","Subject":"Re: [PATCH] libio: Implement internal function\n\t__libc_readline_unlocked","Message-ID":"<20180706182823.GA6195@aiede.svl.corp.google.com>","References":"<20170901154335.E5819439942E3@oldenburg.str.redhat.com>\n\t<4694e740-6bdb-ef22-a945-21359367c788@redhat.com>\n\t<ab9faefa-7875-4380-fca0-87767bf271f0@redhat.com>\n\t<20171122055001.GC7625@aiede.mtv.corp.google.com>\n\t<33d730f8-4ad2-4055-fdcc-98117ecc3f45@redhat.com>\n\t<50086f64-2ea0-18ae-60f4-7b149493a79b@redhat.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=us-ascii","Content-Disposition":"inline","In-Reply-To":"<50086f64-2ea0-18ae-60f4-7b149493a79b@redhat.com>","User-Agent":"Mutt/1.9.2 (2017-12-15)"}},{"id":1948996,"web_url":"http://patchwork.ozlabs.org/comment/1948996/","msgid":"<4c24057c-2db6-530d-0185-6c6a2b177e42@redhat.com>","list_archive_url":null,"date":"2018-07-06T18:53:37","subject":"Re: [PATCH] libio: Implement internal function\n\t__libc_readline_unlocked","submitter":{"id":22438,"url":"http://patchwork.ozlabs.org/api/people/22438/","name":"Carlos O'Donell","email":"carlos@redhat.com"},"content":"On 07/06/2018 02:28 PM, Jonathan Nieder wrote:\n> Hi,\n> \n> Florian Weimer wrote:\n>> On 07/06/2018 02:31 PM, Florian Weimer wrote:\n> \n>>> The caller should not call the function if the stream is in an error\n>>> condition I added a comment to the header file.\n> \n> Thanks.\n> \n> [...]\n>> --- a/include/stdio.h\n>> +++ b/include/stdio.h\n>> @@ -127,6 +127,19 @@ extern int __fxprintf (FILE *__fp, const char *__fmt, ...)\n>>  extern int __fxprintf_nocancel (FILE *__fp, const char *__fmt, ...)\n>>       __attribute__ ((__format__ (__printf__, 2, 3))) attribute_hidden;\n>>  \n>> +/* Read the next line from FP into BUFFER, of LENGTH bytes.  LINE will\n>> +   include the line terminator and a NUL terminator.  On success,\n>> +   return the length of the line, including the line terminator, but\n>> +   excluding the NUL termintor.  On EOF, return zero and write a NUL\n>> +   terminator.  On error, return -1 and set errno.  If the total byte\n>> +   count (line and both terminators) exceeds LENGTH, return -1 and set\n>> +   errno to ERANGE (but do not mark the stream as failed).\n>> +\n>> +   The behavior is undefined if FP is not seekable, or if the stream\n>> +   is already in an error state.  */\n>> +ssize_t __libc_readline_unlocked (FILE *fp, char *buffer, size_t length);\n>> +libc_hidden_proto (__libc_readline_unlocked);\n> \n> Makes sense.\n> \n> What kind of stability guarantees do we make for this kind of\n> double-underscored GLIBC_PRIVATE symbol?  E.g. if we decide to remove\n> it later or change its behavior, is that easy to do?\n\nVery easy.\n\n> I'm not looking for any particular answer --- an answer like \"see\n> such-and-such wiki page\" or \"see such-and-such bug about missing\n> documentation\" would be the ideal.\n\nOfficially the use of GLIBC_PRIVATE symbols by anything other than\nglibc is expressly forbidden, but we don't enforce that in any way.\n\nWe can change GLIBC_PRIVATE symbols at will. There is no stability\nguarantee at all.\n\nWe sometimes find out a major project is using a GLIBC_PRIVATE symbol\nfor special reasons and we promise not to remove it until we can\nfind them a better interface e.g. rust vs. __pthread_get_minstack.\n\nIn these cases we have pity on rust and keep the symbol around while\nwe try to solve the larger problem of core runtime <-> high-level\nlanguage interaction.","headers":{"Return-Path":"<libc-alpha-return-94103-incoming=patchwork.ozlabs.org@sourceware.org>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":["patchwork-incoming@bilbo.ozlabs.org","mailing list libc-alpha@sourceware.org"],"Authentication-Results":["ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=sourceware.org\n\t(client-ip=209.132.180.131; helo=sourceware.org;\n\tenvelope-from=libc-alpha-return-94103-incoming=patchwork.ozlabs.org@sourceware.org;\n\treceiver=<UNKNOWN>)","ozlabs.org;\n\tdmarc=fail (p=none dis=none) header.from=redhat.com","ozlabs.org; dkim=pass (1024-bit key;\n\tsecure) header.d=sourceware.org header.i=@sourceware.org\n\theader.b=\"wL4aMhV1\"; dkim-atps=neutral","sourceware.org; auth=none"],"Received":["from sourceware.org (server1.sourceware.org [209.132.180.131])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256\n\tbits)) (No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 41MkQj4XWPz9rxs\n\tfor <incoming@patchwork.ozlabs.org>;\n\tSat,  7 Jul 2018 04:53:49 +1000 (AEST)","(qmail 14132 invoked by alias); 6 Jul 2018 18:53:43 -0000","(qmail 14118 invoked by uid 89); 6 Jul 2018 18:53:43 -0000"],"DomainKey-Signature":"a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id\n\t:list-unsubscribe:list-subscribe:list-archive:list-post\n\t:list-help:sender:subject:to:cc:references:from:message-id:date\n\t:mime-version:in-reply-to:content-type\n\t:content-transfer-encoding; q=dns; s=default; b=h3e1pVvCSlrCIGyN\n\tMMRB+/moBN2GHfXKDBQDS/zChvidI1bk6OAmThRlGCMHiwrPkOFbHX307Sgdj71s\n\tXEw8QHpWsRpX6yRxpXQDFaAYpBCjQmFgoUVbw3ELPrQj3lWxVIQoUYNxTSwg2I9m\n\tCpB2QRh2Ru//O1a/opFD2EOgqTQ=","DKIM-Signature":"v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id\n\t:list-unsubscribe:list-subscribe:list-archive:list-post\n\t:list-help:sender:subject:to:cc:references:from:message-id:date\n\t:mime-version:in-reply-to:content-type\n\t:content-transfer-encoding; s=default; bh=V8odgnwHK78y8sVyiHa6nM\n\teordM=; b=wL4aMhV1USuXzGviNB8H3BgEYVugqsBIb/5TPqlU/h47agYhUS+bB9\n\t3gQ7JCSPPxuRPZo6VFOdBIVSDP/z4m9oZTHlwql2nvfD/iic6XP9OG1HgGEspKJg\n\tqHcJh6NkVyCm7ChHPs8l2kBW0fBpISq6pzYt1InbC8ZfrP8p3+4ss=","Mailing-List":"contact libc-alpha-help@sourceware.org; run by ezmlm","Precedence":"bulk","List-Id":"<libc-alpha.sourceware.org>","List-Unsubscribe":"<mailto:libc-alpha-unsubscribe-incoming=patchwork.ozlabs.org@sourceware.org>","List-Subscribe":"<mailto:libc-alpha-subscribe@sourceware.org>","List-Archive":"<http://sourceware.org/ml/libc-alpha/>","List-Post":"<mailto:libc-alpha@sourceware.org>","List-Help":"<mailto:libc-alpha-help@sourceware.org>,\n\t<http://sourceware.org/ml/#faqs>","Sender":"libc-alpha-owner@sourceware.org","X-Spam-SWARE-Status":"No, score=-10.2 required=5.0 tests=AWL, BAYES_00,\n\tGIT_PATCH_2, GIT_PATCH_3, KAM_LAZY_DOMAIN_SECURITY,\n\tRCVD_IN_DNSWL_NONE autolearn=ham version=3.3.2 spammy=pity,\n\tforbidden, HX-Received:sk:t21-v6m, H*r:sk:c5-v6so","X-HELO":"mail-qt0-f195.google.com","Subject":"Re: [PATCH] libio: Implement internal function\n\t__libc_readline_unlocked","To":"Jonathan Nieder <jrnieder@gmail.com>, Florian Weimer <fweimer@redhat.com>","Cc":"libc-alpha@sourceware.org","References":"<20170901154335.E5819439942E3@oldenburg.str.redhat.com>\n\t<4694e740-6bdb-ef22-a945-21359367c788@redhat.com>\n\t<ab9faefa-7875-4380-fca0-87767bf271f0@redhat.com>\n\t<20171122055001.GC7625@aiede.mtv.corp.google.com>\n\t<33d730f8-4ad2-4055-fdcc-98117ecc3f45@redhat.com>\n\t<50086f64-2ea0-18ae-60f4-7b149493a79b@redhat.com>\n\t<20180706182823.GA6195@aiede.svl.corp.google.com>","From":"Carlos O'Donell <carlos@redhat.com>","Openpgp":"preference=signencrypt","Message-ID":"<4c24057c-2db6-530d-0185-6c6a2b177e42@redhat.com>","Date":"Fri, 6 Jul 2018 14:53:37 -0400","User-Agent":"Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101\n\tThunderbird/52.8.0","MIME-Version":"1.0","In-Reply-To":"<20180706182823.GA6195@aiede.svl.corp.google.com>","Content-Type":"text/plain; charset=utf-8","Content-Transfer-Encoding":"7bit"}},{"id":1950564,"web_url":"http://patchwork.ozlabs.org/comment/1950564/","msgid":"<6a5f6405-c7f7-56ce-6256-653773a8728c@redhat.com>","list_archive_url":null,"date":"2018-07-10T09:13:32","subject":"Re: [PATCH] libio: Implement internal function\n\t__libc_readline_unlocked","submitter":{"id":14312,"url":"http://patchwork.ozlabs.org/api/people/14312/","name":"Florian Weimer","email":"fweimer@redhat.com"},"content":"On 07/06/2018 08:28 PM, Jonathan Nieder wrote:\n> optional: could put 2018 here, since this will have been first\n> published as part of glibc in 2018.\n\nThanks for review.  I fixed that in a follow-up commit, it should have \nbeen 2018.  I forgot how old these patches were.\n\nFlorian\nSubject: [PATCH COMMITTED] Fix copyright years in recent commits\nTo: libc-alpha@sourceware.org\n\n2018-07-10  Florian Weimer  <fweimer@redhat.com>\n\n\t* libio/readline.c: Fix copyright year.\n\t* libio/tst-readline.c Likewise.\n\t* nss/tst-nss-files-hosts-getent.c: Likewise.\n\ndiff --git a/libio/readline.c b/libio/readline.c\nindex 3638459176..3372ba2999 100644\n--- a/libio/readline.c\n+++ b/libio/readline.c\n@@ -1,5 +1,5 @@\n /* fgets with ERANGE error reporting and size_t buffer length.\n-   Copyright (C) 2017 Free Software Foundation, Inc.\n+   Copyright (C) 2018 Free Software Foundation, Inc.\n    This file is part of the GNU C Library.\n \n    The GNU C Library is free software; you can redistribute it and/or\ndiff --git a/libio/tst-readline.c b/libio/tst-readline.c\nindex 60c58c650a..9322ef68da 100644\n--- a/libio/tst-readline.c\n+++ b/libio/tst-readline.c\n@@ -1,5 +1,5 @@\n /* Test the __libc_readline_unlocked function.\n-   Copyright (C) 2017 Free Software Foundation, Inc.\n+   Copyright (C) 2018 Free Software Foundation, Inc.\n    This file is part of the GNU C Library.\n \n    The GNU C Library is free software; you can redistribute it and/or\ndiff --git a/nss/tst-nss-files-hosts-getent.c b/nss/tst-nss-files-hosts-getent.c\nindex d7514e8e38..3f5baced32 100644\n--- a/nss/tst-nss-files-hosts-getent.c\n+++ b/nss/tst-nss-files-hosts-getent.c\n@@ -1,5 +1,5 @@\n /* Enumerate /etc/hosts with a long line (bug 18991).\n-   Copyright (C) 2017 Free Software Foundation, Inc.\n+   Copyright (C) 2018 Free Software Foundation, Inc.\n    This file is part of the GNU C Library.\n \n    The GNU C Library is free software; you can redistribute it and/or","headers":{"Return-Path":"<libc-alpha-return-94138-incoming=patchwork.ozlabs.org@sourceware.org>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":["patchwork-incoming@bilbo.ozlabs.org","mailing list libc-alpha@sourceware.org"],"Authentication-Results":["ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=sourceware.org\n\t(client-ip=209.132.180.131; helo=sourceware.org;\n\tenvelope-from=libc-alpha-return-94138-incoming=patchwork.ozlabs.org@sourceware.org;\n\treceiver=<UNKNOWN>)","ozlabs.org;\n\tdmarc=fail (p=none dis=none) header.from=redhat.com","ozlabs.org; dkim=pass (1024-bit key;\n\tsecure) header.d=sourceware.org header.i=@sourceware.org\n\theader.b=\"keMgTWkE\"; dkim-atps=neutral","sourceware.org; auth=none"],"Received":["from sourceware.org (server1.sourceware.org [209.132.180.131])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256\n\tbits)) (No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 41PxMc52qdz9s01\n\tfor <incoming@patchwork.ozlabs.org>;\n\tTue, 10 Jul 2018 19:13:47 +1000 (AEST)","(qmail 9079 invoked by alias); 10 Jul 2018 09:13:42 -0000","(qmail 9064 invoked by uid 89); 10 Jul 2018 09:13:40 -0000"],"DomainKey-Signature":"a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id\n\t:list-unsubscribe:list-subscribe:list-archive:list-post\n\t:list-help:sender:subject:to:cc:references:from:message-id:date\n\t:mime-version:in-reply-to:content-type; q=dns; s=default; b=JcQA\n\tSmeCKWRe9cIKl7mz6flF/scxU9nDEuN4fQorLqqQPI8mAd8JOpLe6hN8764jk2Ic\n\tWN//Ec8hCcNQwCf9V1/hO05ZJd2P5oY4jaWg9fF/GKeVextFVW813KzuOyHuhO26\n\tJmlTOqU/45YY7J+4q/D/9NE4+BGUUNQpVOmUDNU=","DKIM-Signature":"v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id\n\t:list-unsubscribe:list-subscribe:list-archive:list-post\n\t:list-help:sender:subject:to:cc:references:from:message-id:date\n\t:mime-version:in-reply-to:content-type; s=default; bh=nzqqoiOVEV\n\tL7wUa3hKqa27MQO0o=; b=keMgTWkEl6HWWYZbBvjam4mtGJIOJ941Yu9G4Fdm8t\n\tnwEgooaAW46QZIIZmJDZB1+JM6uHV6auN0McLLnmVSkg4Qeoox/tAvOGX5FGuksz\n\tgQ7SDYNYoaNWQHiDaa0mYpLcibaje1al2iBUWUfInO/c5Ts3/fk+bYA9YrLwbOD9\n\t4=","Mailing-List":"contact libc-alpha-help@sourceware.org; run by ezmlm","Precedence":"bulk","List-Id":"<libc-alpha.sourceware.org>","List-Unsubscribe":"<mailto:libc-alpha-unsubscribe-incoming=patchwork.ozlabs.org@sourceware.org>","List-Subscribe":"<mailto:libc-alpha-subscribe@sourceware.org>","List-Archive":"<http://sourceware.org/ml/libc-alpha/>","List-Post":"<mailto:libc-alpha@sourceware.org>","List-Help":"<mailto:libc-alpha-help@sourceware.org>,\n\t<http://sourceware.org/ml/#faqs>","Sender":"libc-alpha-owner@sourceware.org","X-Spam-SWARE-Status":"No, score=-23.9 required=5.0 tests=AWL, BAYES_00,\n\tGIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3,\n\tKAM_LAZY_DOMAIN_SECURITY,\n\tSPF_HELO_PASS autolearn=ham version=3.3.2 spammy=","X-HELO":"mx1.redhat.com","Subject":"Re: [PATCH] libio: Implement internal function\n\t__libc_readline_unlocked","To":"Jonathan Nieder <jrnieder@gmail.com>","Cc":"libc-alpha@sourceware.org, Carlos O'Donell <carlos@redhat.com>","References":"<20170901154335.E5819439942E3@oldenburg.str.redhat.com>\n\t<4694e740-6bdb-ef22-a945-21359367c788@redhat.com>\n\t<ab9faefa-7875-4380-fca0-87767bf271f0@redhat.com>\n\t<20171122055001.GC7625@aiede.mtv.corp.google.com>\n\t<33d730f8-4ad2-4055-fdcc-98117ecc3f45@redhat.com>\n\t<50086f64-2ea0-18ae-60f4-7b149493a79b@redhat.com>\n\t<20180706182823.GA6195@aiede.svl.corp.google.com>","From":"Florian Weimer <fweimer@redhat.com>","Message-ID":"<6a5f6405-c7f7-56ce-6256-653773a8728c@redhat.com>","Date":"Tue, 10 Jul 2018 11:13:32 +0200","User-Agent":"Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101\n\tThunderbird/52.8.0","MIME-Version":"1.0","In-Reply-To":"<20180706182823.GA6195@aiede.svl.corp.google.com>","Content-Type":"multipart/mixed;\n\tboundary=\"------------3F442F5C23E82B46037BD47A\""}},{"id":1956303,"web_url":"http://patchwork.ozlabs.org/comment/1956303/","msgid":"<alpine.DEB.2.20.1807181650410.26553@digraph.polyomino.org.uk>","list_archive_url":null,"date":"2018-07-18T16:54:14","subject":"Re: [PATCH] libio: Implement internal function\n\t__libc_readline_unlocked","submitter":{"id":4349,"url":"http://patchwork.ozlabs.org/api/people/4349/","name":"Joseph Myers","email":"joseph@codesourcery.com"},"content":"On Fri, 6 Jul 2018, Carlos O'Donell wrote:\n\n> We can change GLIBC_PRIVATE symbols at will. There is no stability\n> guarantee at all.\n\nWith the caveat that GLIBC_PRIVATE interface changes on a release branch \nare dangerous, because they can affect upgrades on live systems (if a \nrunning process started with old glibc, then there was an upgrade, then \nthe running process dlopens a library from the new glibc that depends on a \nchange to a GLIBC_PRIVATE interface provided by libc - see the issues when \nsome distributions tried to backport the CVE-2014-9761 fix).","headers":{"Return-Path":"<libc-alpha-return-94439-incoming=patchwork.ozlabs.org@sourceware.org>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":["patchwork-incoming@bilbo.ozlabs.org","mailing list libc-alpha@sourceware.org"],"Authentication-Results":["ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=sourceware.org\n\t(client-ip=209.132.180.131; helo=sourceware.org;\n\tenvelope-from=libc-alpha-return-94439-incoming=patchwork.ozlabs.org@sourceware.org;\n\treceiver=<UNKNOWN>)","ozlabs.org; dmarc=none (p=none dis=none)\n\theader.from=codesourcery.com","ozlabs.org; dkim=pass (1024-bit key;\n\tsecure) header.d=sourceware.org header.i=@sourceware.org\n\theader.b=\"cSwNKxEC\"; dkim-atps=neutral","sourceware.org; auth=none"],"Received":["from sourceware.org (server1.sourceware.org [209.132.180.131])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256\n\tbits)) (No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 41W3CW1C00z9s3Z\n\tfor <incoming@patchwork.ozlabs.org>;\n\tThu, 19 Jul 2018 02:54:30 +1000 (AEST)","(qmail 53269 invoked by alias); 18 Jul 2018 16:54:22 -0000","(qmail 53242 invoked by uid 89); 18 Jul 2018 16:54:22 -0000"],"DomainKey-Signature":"a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id\n\t:list-unsubscribe:list-subscribe:list-archive:list-post\n\t:list-help:sender:date:from:to:cc:subject:in-reply-to:message-id\n\t:references:mime-version:content-type; q=dns; s=default; b=UUj0F\n\tcGyRpYIARgKfk2lgn/acGeNCvoxmEW+MC6Qitb6bue0vfqJf6XcEOO3AYWXHVCuY\n\tNkbnjBL05bpNb3Cx20mk+wTd9ja92hk7rG3/jGz/fpkaoFC30HUeIaAxHKtIRpSy\n\tXc+ptRb4psSbQYaBwaUXua0QURp9k02hzhMirU=","DKIM-Signature":"v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id\n\t:list-unsubscribe:list-subscribe:list-archive:list-post\n\t:list-help:sender:date:from:to:cc:subject:in-reply-to:message-id\n\t:references:mime-version:content-type; s=default; bh=yNA7YTYBIQH\n\tv0Hn3PBZcQDOkpYE=; b=cSwNKxECOp+rq3Qqqyd5gEaE9RRiqTHP9MwjsaDaILS\n\t+HBXATC2QZzF0w3PoSVo2sw/QBz0Lq61TegmiA1v6A15gQy99GYOjKHBumNXoGOv\n\t/FUcH2FgaQMILqDiw4U3R6eiPY+DOswUuqzF7wEWO89Ej4js9WDve539rW/NwBfw\n\t=","Mailing-List":"contact libc-alpha-help@sourceware.org; run by ezmlm","Precedence":"bulk","List-Id":"<libc-alpha.sourceware.org>","List-Unsubscribe":"<mailto:libc-alpha-unsubscribe-incoming=patchwork.ozlabs.org@sourceware.org>","List-Subscribe":"<mailto:libc-alpha-subscribe@sourceware.org>","List-Archive":"<http://sourceware.org/ml/libc-alpha/>","List-Post":"<mailto:libc-alpha@sourceware.org>","List-Help":"<mailto:libc-alpha-help@sourceware.org>,\n\t<http://sourceware.org/ml/#faqs>","Sender":"libc-alpha-owner@sourceware.org","X-Spam-SWARE-Status":"No, score=-2.0 required=5.0 tests=AWL, BAYES_00,\n\tRCVD_IN_DNSWL_NONE, SPF_PASS,\n\tURIBL_RED autolearn=ham version=3.3.2 spammy=dangerous,\n\tHx-languages-length:677","X-HELO":"relay1.mentorg.com","Date":"Wed, 18 Jul 2018 16:54:14 +0000","From":"Joseph Myers <joseph@codesourcery.com>","To":"Carlos O'Donell <carlos@redhat.com>","CC":"Jonathan Nieder <jrnieder@gmail.com>, Florian Weimer <fweimer@redhat.com>,\n\t<libc-alpha@sourceware.org>","Subject":"Re: [PATCH] libio: Implement internal function\n\t__libc_readline_unlocked","In-Reply-To":"<4c24057c-2db6-530d-0185-6c6a2b177e42@redhat.com>","Message-ID":"<alpine.DEB.2.20.1807181650410.26553@digraph.polyomino.org.uk>","References":"<20170901154335.E5819439942E3@oldenburg.str.redhat.com>\n\t<4694e740-6bdb-ef22-a945-21359367c788@redhat.com>\n\t<ab9faefa-7875-4380-fca0-87767bf271f0@redhat.com>\n\t<20171122055001.GC7625@aiede.mtv.corp.google.com>\n\t<33d730f8-4ad2-4055-fdcc-98117ecc3f45@redhat.com>\n\t<50086f64-2ea0-18ae-60f4-7b149493a79b@redhat.com>\n\t<20180706182823.GA6195@aiede.svl.corp.google.com>\n\t<4c24057c-2db6-530d-0185-6c6a2b177e42@redhat.com>","User-Agent":"Alpine 2.20 (DEB 67 2015-01-07)","MIME-Version":"1.0","Content-Type":"text/plain; charset=\"US-ASCII\""}},{"id":1956353,"web_url":"http://patchwork.ozlabs.org/comment/1956353/","msgid":"<75554035-1459-6307-773b-c5c9847a2d67@redhat.com>","list_archive_url":null,"date":"2018-07-18T18:13:23","subject":"Re: [PATCH] libio: Implement internal function\n\t__libc_readline_unlocked","submitter":{"id":22438,"url":"http://patchwork.ozlabs.org/api/people/22438/","name":"Carlos O'Donell","email":"carlos@redhat.com"},"content":"On 07/18/2018 12:54 PM, Joseph Myers wrote:\n> On Fri, 6 Jul 2018, Carlos O'Donell wrote:\n> \n>> We can change GLIBC_PRIVATE symbols at will. There is no stability\n>> guarantee at all.\n> \n> With the caveat that GLIBC_PRIVATE interface changes on a release branch \n> are dangerous, because they can affect upgrades on live systems (if a \n> running process started with old glibc, then there was an upgrade, then \n> the running process dlopens a library from the new glibc that depends on a \n> change to a GLIBC_PRIVATE interface provided by libc - see the issues when \n> some distributions tried to backport the CVE-2014-9761 fix).\nAgreed, GLIBC_PRIVATE changes on a release branch are dangerous, and this is\nnot the case here.\n\nI've seen similar problems in the last year with various backports we've done\nfrom stable.\n\nMy opinion is that glibc upgrades are not carried out correctly by any of the\ndistributions, and I've outlined that in the FAQ:\nhttps://sourceware.org/glibc/wiki/FAQ#How_do_I_install_all_of_the_GNU_C_Library_project_libraries_that_I_just_built.3F\n\nI think I can reduce the upgrade race in Fedora by using a single symlink.","headers":{"Return-Path":"<libc-alpha-return-94455-incoming=patchwork.ozlabs.org@sourceware.org>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":["patchwork-incoming@bilbo.ozlabs.org","mailing list libc-alpha@sourceware.org"],"Authentication-Results":["ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=sourceware.org\n\t(client-ip=209.132.180.131; helo=sourceware.org;\n\tenvelope-from=libc-alpha-return-94455-incoming=patchwork.ozlabs.org@sourceware.org;\n\treceiver=<UNKNOWN>)","ozlabs.org;\n\tdmarc=fail (p=none dis=none) header.from=redhat.com","ozlabs.org; dkim=pass (1024-bit key;\n\tsecure) header.d=sourceware.org header.i=@sourceware.org\n\theader.b=\"w2K1WNcG\"; dkim-atps=neutral","sourceware.org; auth=none"],"Received":["from sourceware.org (server1.sourceware.org [209.132.180.131])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256\n\tbits)) (No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 41W4yx0S58z9s3Z\n\tfor <incoming@patchwork.ozlabs.org>;\n\tThu, 19 Jul 2018 04:13:44 +1000 (AEST)","(qmail 71406 invoked by alias); 18 Jul 2018 18:13:32 -0000","(qmail 71223 invoked by uid 89); 18 Jul 2018 18:13:30 -0000"],"DomainKey-Signature":"a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id\n\t:list-unsubscribe:list-subscribe:list-archive:list-post\n\t:list-help:sender:subject:to:cc:references:from:message-id:date\n\t:mime-version:in-reply-to:content-type\n\t:content-transfer-encoding; q=dns; s=default; b=KJs4kUW0ujJYRZgT\n\tvIPKeQqyoRLGAhofSnk39klx82Y7kDySNV0HDpkizBwG+eI44ICAr9hByTgqpDBe\n\tYpUacfYtBbiV67a+utjHO9JAgbeaKsUBlmqyxF7zoi0W0PWla8Tqv+rQhl/B6Exr\n\t8LmyXv+js2FNn9Dn3MiSxuSUVU4=","DKIM-Signature":"v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id\n\t:list-unsubscribe:list-subscribe:list-archive:list-post\n\t:list-help:sender:subject:to:cc:references:from:message-id:date\n\t:mime-version:in-reply-to:content-type\n\t:content-transfer-encoding; s=default; bh=5p1B+Pm/i7jJVscQGg+IcA\n\tpHCWY=; b=w2K1WNcGFye4QmRxeH079Y2c5NV4Lwmn3Ll+YajVP2HbBLXc/AAn0E\n\tY2bnQDz/X/ZRWSImlfuzcndGqk4m8+SzbDefz1O2mb1gpFd4d1YdfqdJ4pSzO55I\n\ty4OPhpBKsOujxmfStVTJygbEZ7oodznBtKeuv9jVAirM0Crk0/ByM=","Mailing-List":"contact libc-alpha-help@sourceware.org; run by ezmlm","Precedence":"bulk","List-Id":"<libc-alpha.sourceware.org>","List-Unsubscribe":"<mailto:libc-alpha-unsubscribe-incoming=patchwork.ozlabs.org@sourceware.org>","List-Subscribe":"<mailto:libc-alpha-subscribe@sourceware.org>","List-Archive":"<http://sourceware.org/ml/libc-alpha/>","List-Post":"<mailto:libc-alpha@sourceware.org>","List-Help":"<mailto:libc-alpha-help@sourceware.org>,\n\t<http://sourceware.org/ml/#faqs>","Sender":"libc-alpha-owner@sourceware.org","X-Spam-SWARE-Status":"No, score=-2.3 required=5.0 tests=AWL, BAYES_00,\n\tRCVD_IN_DNSWL_NONE autolearn=ham version=3.3.2\n\tspammy=H*r:sk:v4-v6sm, H*RU:sk:v4-v6sm,\n\tHx-spam-relays-external:sk:v4-v6sm","X-HELO":"mail-qk0-f195.google.com","Subject":"Re: [PATCH] libio: Implement internal function\n\t__libc_readline_unlocked","To":"Joseph Myers <joseph@codesourcery.com>","Cc":"Jonathan Nieder <jrnieder@gmail.com>, Florian Weimer\n\t<fweimer@redhat.com>, libc-alpha@sourceware.org","References":"<20170901154335.E5819439942E3@oldenburg.str.redhat.com>\n\t<4694e740-6bdb-ef22-a945-21359367c788@redhat.com>\n\t<ab9faefa-7875-4380-fca0-87767bf271f0@redhat.com>\n\t<20171122055001.GC7625@aiede.mtv.corp.google.com>\n\t<33d730f8-4ad2-4055-fdcc-98117ecc3f45@redhat.com>\n\t<50086f64-2ea0-18ae-60f4-7b149493a79b@redhat.com>\n\t<20180706182823.GA6195@aiede.svl.corp.google.com>\n\t<4c24057c-2db6-530d-0185-6c6a2b177e42@redhat.com>\n\t<alpine.DEB.2.20.1807181650410.26553@digraph.polyomino.org.uk>","From":"Carlos O'Donell <carlos@redhat.com>","Openpgp":"preference=signencrypt","Message-ID":"<75554035-1459-6307-773b-c5c9847a2d67@redhat.com>","Date":"Wed, 18 Jul 2018 14:13:23 -0400","User-Agent":"Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101\n\tThunderbird/52.8.0","MIME-Version":"1.0","In-Reply-To":"<alpine.DEB.2.20.1807181650410.26553@digraph.polyomino.org.uk>","Content-Type":"text/plain; charset=utf-8","Content-Transfer-Encoding":"7bit"}}]