-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 According to Jim Meyering on 8/19/2007 2:18 PM: > Eric Blake <[EMAIL PROTECTED]> wrote: >> I could go either way, although I'm leaning toward doing it now; > > I agree. Doing it now is fine.
How about this for the patch, then? Simon, this is your module. The patch includes a couple of bug fixes in getdelim.c: It is valid on entrance for *lineptr to be non-NULL but *n to be 0 (ie. via malloc(0)), but your implementation was leaking that memory. Also, your implementation failed to set errno to EOVERFLOW when it detects that it needs to malloc more than SSIZE_MAX bytes. 2007-08-21 Eric Blake <[EMAIL PROTECTED]> Move getline and getdelim into stdio.h, per POSIX 200x. * modules/getline (Files): Remove getline.h. (Depends-on): Add stdio. (configure.ac): Add module indicator. * modules/getdelim (Files): Remove getdelim.h. (Depends-on): Add stdio. (configure.ac): Add module indicator. * modules/stdio (Makefile.am): Work with new indicators. * m4/stdio_h.m4 (gl_STDIO_H_DEFAULTS): Add new defaults. * m4/getdelim.m4 (gl_FUNC_GETDELIM): Work with stdio needs. * m4/getline.m4 (gl_FUNC_GETLINE): Likewise. * lib/getdelim.h: Delete. * lib/getline.h: Delete. * lib/stdio_.h (getdelim, getline): Declare. * modules/getdelim-tests: New module. * modules/getline-tests: Likewise. * tests/test-getdelim.c: New file. * tests/test-getline.c: Likewise. * NEWS: Document the change. * lib/getline.c: Update choice of header. * lib/csharpcomp.c: Likewise. * lib/getpass.c: Likewise. * lib/javacomp.c: Likewise. * lib/javaversion.c: Likewise. * lib/yesno.c: Likewise. * lib/getdelim.c: Likewise. (getdelim): Set errno on failure, and avoid memory leak. - -- Don't work too hard, make some time for fun as well! Eric Blake [EMAIL PROTECTED] -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.5 (Cygwin) Comment: Public key at home.comcast.net/~ericblake/eblake.gpg Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFGy35+84KuGfSFAYARAmiLAJ9/rWVDeQe67y63aUKYkb7/0mWTbwCgwFOZ Ye5pE0io6+dGz3cM+L/t2G0= =t2L6 -----END PGP SIGNATURE-----
Index: NEWS =================================================================== RCS file: /sources/gnulib/gnulib/NEWS,v retrieving revision 1.29 diff -u -p -r1.29 NEWS --- NEWS 18 Aug 2007 07:16:53 -0000 1.29 +++ NEWS 22 Aug 2007 00:04:01 -0000 @@ -6,6 +6,10 @@ User visible incompatible changes Date Modules Changes +2007-08-21 getdelim, getline + The include file is changed from "getdelim.h" + and "getline.h" to the POSIX 200x <stdio.h>. + 2007-08-18 idcache Now provides prototypes in "idcache.h". 2007-08-10 xstrtol The STRTOL_FATAL_ERROR macro is removed. Index: lib/csharpcomp.c =================================================================== RCS file: /sources/gnulib/gnulib/lib/csharpcomp.c,v retrieving revision 1.8 diff -u -p -r1.8 csharpcomp.c --- lib/csharpcomp.c 9 Jun 2007 11:15:22 -0000 1.8 +++ lib/csharpcomp.c 22 Aug 2007 00:04:01 -0000 @@ -30,7 +30,6 @@ #include "execute.h" #include "pipe.h" #include "wait-process.h" -#include "getline.h" #include "sh-quote.h" #include "safe-read.h" #include "xmalloca.h" Index: lib/getdelim.c =================================================================== RCS file: /sources/gnulib/gnulib/lib/getdelim.c,v retrieving revision 1.7 diff -u -p -r1.7 getdelim.c --- lib/getdelim.c 29 Oct 2006 21:52:55 -0000 1.7 +++ lib/getdelim.c 22 Aug 2007 00:04:01 -0000 @@ -1,5 +1,5 @@ /* getdelim.c --- Implementation of replacement getdelim function. - Copyright (C) 1994, 1996, 1997, 1998, 2001, 2003, 2005, 2006 Free + Copyright (C) 1994, 1996, 1997, 1998, 2001, 2003, 2005, 2006, 2007 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or @@ -21,7 +21,7 @@ #include <config.h> -#include "getdelim.h" +#include <stdio.h> #include <limits.h> #include <stdlib.h> @@ -42,6 +42,11 @@ # define funlockfile(x) ((void) 0) #endif +/* Some systems, like OSF/1 4.0 and Woe32, don't have EOVERFLOW. */ +#ifndef EOVERFLOW +# define EOVERFLOW E2BIG +#endif + /* Read up to (and including) a DELIMITER from FP into *LINEPTR (and NUL-terminate it). *LINEPTR is a pointer returned from malloc (or NULL), pointing to *N characters of space. It is realloc'ed as @@ -62,10 +67,10 @@ getdelim (char **lineptr, size_t *n, int flockfile (fp); - if (*lineptr == NULL || *n == 0) + if (*n == 0) { *n = 120; - *lineptr = (char *) malloc (*n); + *lineptr = (char *) realloc (*lineptr, 120); if (*lineptr == NULL) { result = -1; @@ -97,6 +102,7 @@ getdelim (char **lineptr, size_t *n, int if (cur_len + 1 >= needed) { result = -1; + errno = EOVERFLOW; goto unlock_return; } Index: lib/getline.c =================================================================== RCS file: /sources/gnulib/gnulib/lib/getline.c,v retrieving revision 1.21 diff -u -p -r1.21 getline.c --- lib/getline.c 29 Oct 2006 21:52:55 -0000 1.21 +++ lib/getline.c 22 Aug 2007 00:04:01 -0000 @@ -1,5 +1,5 @@ /* getline.c --- Implementation of replacement getline function. - Copyright (C) 2005, 2006 Free Software Foundation, Inc. + Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -20,8 +20,7 @@ #include <config.h> -#include "getdelim.h" -#include "getline.h" +#include <stdio.h> ssize_t getline (char **lineptr, size_t *n, FILE *stream) Index: lib/getpass.c =================================================================== RCS file: /sources/gnulib/gnulib/lib/getpass.c,v retrieving revision 1.19 diff -u -p -r1.19 getpass.c --- lib/getpass.c 30 Apr 2007 12:00:08 -0000 1.19 +++ lib/getpass.c 22 Aug 2007 00:04:01 -0000 @@ -41,8 +41,6 @@ # include <termios.h> #endif -#include "getline.h" - #if USE_UNLOCKED_IO # include "unlocked-io.h" #else Index: lib/javacomp.c =================================================================== RCS file: /sources/gnulib/gnulib/lib/javacomp.c,v retrieving revision 1.14 diff -u -p -r1.14 javacomp.c --- lib/javacomp.c 9 Jun 2007 11:15:22 -0000 1.14 +++ lib/javacomp.c 22 Aug 2007 00:04:01 -0000 @@ -42,7 +42,6 @@ #include "safe-read.h" #include "xalloc.h" #include "xmalloca.h" -#include "getline.h" #include "filename.h" #include "fwriteerror.h" #include "clean-temp.h" Index: lib/javaversion.c =================================================================== RCS file: /sources/gnulib/gnulib/lib/javaversion.c,v retrieving revision 1.3 diff -u -p -r1.3 javaversion.c --- lib/javaversion.c 18 Sep 2006 20:17:52 -0000 1.3 +++ lib/javaversion.c 22 Aug 2007 00:04:01 -0000 @@ -1,5 +1,5 @@ /* Determine the Java version supported by javaexec. - Copyright (C) 2006 Free Software Foundation, Inc. + Copyright (C) 2006, 2007 Free Software Foundation, Inc. Written by Bruno Haible <[EMAIL PROTECTED]>, 2006. This program is free software; you can redistribute it and/or modify @@ -38,7 +38,6 @@ #include "pipe.h" #include "wait-process.h" #include "error.h" -#include "getline.h" #include "gettext.h" #define _(str) gettext (str) Index: lib/stdio_.h =================================================================== RCS file: /sources/gnulib/gnulib/lib/stdio_.h,v retrieving revision 1.32 diff -u -p -r1.32 stdio_.h --- lib/stdio_.h 21 Jun 2007 04:39:10 -0000 1.32 +++ lib/stdio_.h 22 Aug 2007 00:04:01 -0000 @@ -35,8 +35,11 @@ #include <stdarg.h> #include <stddef.h> -#if (@GNULIB_FSEEKO@ && @REPLACE_FSEEKO@) || (@GNULIB_FTELLO@ && @REPLACE_FTELLO@) -/* Get off_t. */ +#if (@GNULIB_FSEEKO@ && @REPLACE_FSEEKO@) \ + || (@GNULIB_FTELLO@ && @REPLACE_FTELLO@) \ + || (@GNULIB_GETDELIM@ && [EMAIL PROTECTED]@) \ + || (@GNULIB_GETLINE@ && ([EMAIL PROTECTED]@ || @REPLACE_GETLINE@)) +/* Get off_t and ssize_t. */ # include <sys/types.h> #endif @@ -303,6 +306,44 @@ extern long rpl_ftell (FILE *fp); fflush (f)) #endif +#if @GNULIB_GETDELIM@ +# if [EMAIL PROTECTED]@ + /* Read up to (and including) a DELIMITER from FP into *LINEPTR (and + NUL-terminate it). *LINEPTR is a pointer returned from malloc (or + NULL), pointing to *N characters of space. It is realloc'ed as + necessary. Returns the number of characters read (not including + the null terminator), or -1 on error or EOF. */ + extern ssize_t getdelim (char **, size_t *, int delim, FILE *); +# endif +#elif defined GNULIB_POSIXCHECK +# undef getdelim +# define getdelim(l, s, d, f) \ + (GL_LINK_WARNING ("getdelim is unportable - " \ + "use gnulib module getdelim for portability"), \ + getdelim (l, s, d, f)) +#endif + +#if @GNULIB_GETLINE@ +# if @REPLACE_GETLINE@ +# undef getline +# define getline rpl_getline +# endif +# if [EMAIL PROTECTED]@ + /* Read up to (and including) a newline from FP into *LINEPTR (and + NUL-terminate it). *LINEPTR is a pointer returned from malloc (or + NULL), pointing to *N characters of space. It is realloc'ed as + necessary. Returns the number of characters read (not including + the null terminator), or -1 on error or EOF. */ + extern ssize_t getline (char **, size_t *, FILE *); +# endif +#elif defined GNULIB_POSIXCHECK +# undef getline +# define getline(l, s, f) \ + (GL_LINK_WARNING ("getline is unportable - " \ + "use gnulib module getline for portability"), \ + getline (l, s, f)) +#endif + #ifdef __cplusplus } #endif Index: lib/yesno.c =================================================================== RCS file: /sources/gnulib/gnulib/lib/yesno.c,v retrieving revision 1.18 diff -u -p -r1.18 yesno.c --- lib/yesno.c 19 Aug 2007 15:47:15 -0000 1.18 +++ lib/yesno.c 22 Aug 2007 00:04:01 -0000 @@ -24,10 +24,6 @@ #include <stdlib.h> #include <stdio.h> -#if ENABLE_NLS -# include "getline.h" -#endif - extern int rpmatch (char const *response); /* Return true if we read an affirmative line from standard input. Index: m4/getdelim.m4 =================================================================== RCS file: /sources/gnulib/gnulib/m4/getdelim.m4,v retrieving revision 1.2 diff -u -p -r1.2 getdelim.m4 --- m4/getdelim.m4 22 Aug 2006 17:15:28 -0000 1.2 +++ m4/getdelim.m4 22 Aug 2007 00:04:01 -0000 @@ -1,6 +1,6 @@ -# getdelim.m4 serial 2 +# getdelim.m4 serial 3 -dnl Copyright (C) 2005, 2006 Free Software dnl Foundation, Inc. +dnl Copyright (C) 2005, 2006, 2007 Free Software dnl Foundation, Inc. dnl dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -10,6 +10,7 @@ AC_PREREQ(2.52) AC_DEFUN([gl_FUNC_GETDELIM], [ + AC_REQUIRE([gl_STDIO_H_DEFAULTS]) dnl Persuade glibc <stdio.h> to declare getdelim(). AC_REQUIRE([AC_GNU_SOURCE]) @@ -19,6 +20,7 @@ AC_DEFUN([gl_FUNC_GETDELIM], if test $ac_cv_func_getdelim = no; then gl_PREREQ_GETDELIM + HAVE_DECL_GETDELIM=0 fi ]) Index: m4/getline.m4 =================================================================== RCS file: /sources/gnulib/gnulib/m4/getline.m4,v retrieving revision 1.18 diff -u -p -r1.18 getline.m4 --- m4/getline.m4 22 Aug 2006 17:15:28 -0000 1.18 +++ m4/getline.m4 22 Aug 2007 00:04:01 -0000 @@ -1,7 +1,7 @@ -# getline.m4 serial 15 +# getline.m4 serial 16 -dnl Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006 Free Software -dnl Foundation, Inc. +dnl Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006, 2007 Free +dnl Software Foundation, Inc. dnl dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -15,6 +15,8 @@ dnl have a function by that name in -lin dnl to do with the function we need. AC_DEFUN([gl_FUNC_GETLINE], [ + AC_REQUIRE([gl_STDIO_H_DEFAULTS]) + dnl Persuade glibc <stdio.h> to declare getline(). AC_REQUIRE([AC_GNU_SOURCE]) @@ -60,12 +62,12 @@ AC_DEFUN([gl_FUNC_GETLINE], )]) fi + if test $ac_cv_func_getline = no; then + HAVE_DECL_GETLINE=0 + fi + if test $am_cv_func_working_getline = no; then - dnl We must choose a different name for our function, since on ELF systems - dnl a broken getline() in libc.so would override our getline() in - dnl libgettextlib.so. - AC_DEFINE([getline], [gnu_getline], - [Define to a replacement function name for getline().]) + REPLACE_GETLINE=1 AC_LIBOBJ(getline) gl_PREREQ_GETLINE Index: m4/stdio_h.m4 =================================================================== RCS file: /sources/gnulib/gnulib/m4/stdio_h.m4,v retrieving revision 1.17 diff -u -p -r1.17 stdio_h.m4 --- m4/stdio_h.m4 21 Jun 2007 04:39:10 -0000 1.17 +++ m4/stdio_h.m4 22 Aug 2007 00:04:01 -0000 @@ -33,6 +33,8 @@ AC_DEFUN([gl_STDIO_H_DEFAULTS], GNULIB_FTELL=0; AC_SUBST([GNULIB_FTELL]) GNULIB_FTELLO=0; AC_SUBST([GNULIB_FTELLO]) GNULIB_FFLUSH=0; AC_SUBST([GNULIB_FFLUSH]) + GNULIB_GETDELIM=0; AC_SUBST([GNULIB_GETDELIM]) + GNULIB_GETLINE=0; AC_SUBST([GNULIB_GETLINE]) dnl Assume proper GNU behavior unless another module says otherwise. REPLACE_FPRINTF=0; AC_SUBST([REPLACE_FPRINTF]) REPLACE_VFPRINTF=0; AC_SUBST([REPLACE_VFPRINTF]) @@ -53,6 +55,9 @@ AC_DEFUN([gl_STDIO_H_DEFAULTS], REPLACE_FTELLO=0; AC_SUBST([REPLACE_FTELLO]) REPLACE_FTELL=0; AC_SUBST([REPLACE_FTELL]) REPLACE_FFLUSH=0; AC_SUBST([REPLACE_FFLUSH]) + HAVE_DECL_GETDELIM=1; AC_SUBST([HAVE_DECL_GETDELIM]) + HAVE_DECL_GETLINE=1; AC_SUBST([HAVE_DECL_GETLINE]) + REPLACE_GETLINE=0; AC_SUBST([REPLACE_GETLINE]) ]) dnl Code shared by fseeko and ftello. Determine if large files are supported, Index: modules/getdelim =================================================================== RCS file: /sources/gnulib/gnulib/modules/getdelim,v retrieving revision 1.5 diff -u -p -r1.5 getdelim --- modules/getdelim 16 Jul 2007 10:54:16 -0000 1.5 +++ modules/getdelim 22 Aug 2007 00:04:01 -0000 @@ -2,19 +2,20 @@ Description: Read character delimited data from a stream. Files: -lib/getdelim.h lib/getdelim.c m4/getdelim.m4 Depends-on: +stdio configure.ac: gl_FUNC_GETDELIM +gl_STDIO_MODULE_INDICATOR([getdelim]) Makefile.am: Include: -"getdelim.h" +<stdio.h> License: LGPLv2+ Index: modules/getdelim-tests =================================================================== RCS file: modules/getdelim-tests diff -N modules/getdelim-tests --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/getdelim-tests 22 Aug 2007 00:04:01 -0000 @@ -0,0 +1,11 @@ +Files: +tests/test-getdelim.c + +Depends-on: + +configure.ac: + +Makefile.am: +TESTS += test-getdelim +check_PROGRAMS += test-getdelim +MOSTLYCLEANFILES += test-getdelim.txt Index: modules/getline =================================================================== RCS file: /sources/gnulib/gnulib/modules/getline,v retrieving revision 1.14 diff -u -p -r1.14 getline --- modules/getline 16 Jul 2007 10:45:27 -0000 1.14 +++ modules/getline 22 Aug 2007 00:04:01 -0000 @@ -2,20 +2,21 @@ Description: Read a line from a stream. Files: -lib/getline.h lib/getline.c m4/getline.m4 Depends-on: getdelim +stdio configure.ac: gl_FUNC_GETLINE +gl_STDIO_MODULE_INDICATOR([getline]) Makefile.am: Include: -"getline.h" +<stdio.h> License: LGPLv2+ Index: modules/getline-tests =================================================================== RCS file: modules/getline-tests diff -N modules/getline-tests --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/getline-tests 22 Aug 2007 00:04:01 -0000 @@ -0,0 +1,11 @@ +Files: +tests/test-getline.c + +Depends-on: + +configure.ac: + +Makefile.am: +TESTS += test-getline +check_PROGRAMS += test-getline +MOSTLYCLEANFILES += test-getline.txt Index: modules/stdio =================================================================== RCS file: /sources/gnulib/gnulib/modules/stdio,v retrieving revision 1.20 diff -u -p -r1.20 stdio --- modules/stdio 16 Jul 2007 10:45:29 -0000 1.20 +++ modules/stdio 22 Aug 2007 00:04:01 -0000 @@ -36,6 +36,8 @@ stdio.h: stdio_.h -e 's|@''GNULIB_FTELL''@|$(GNULIB_FTELL)|g' \ -e 's|@''GNULIB_FTELLO''@|$(GNULIB_FTELLO)|g' \ -e 's|@''GNULIB_FFLUSH''@|$(GNULIB_FFLUSH)|g' \ + -e 's|@''GNULIB_GETDELIM''@|$(GNULIB_GETDELIM)|g' \ + -e 's|@''GNULIB_GETLINE''@|$(GNULIB_GETLINE)|g' \ -e 's|@''REPLACE_FPRINTF''@|$(REPLACE_FPRINTF)|g' \ -e 's|@''REPLACE_VFPRINTF''@|$(REPLACE_VFPRINTF)|g' \ -e 's|@''REPLACE_PRINTF''@|$(REPLACE_PRINTF)|g' \ @@ -53,6 +55,9 @@ stdio.h: stdio_.h -e 's|@''REPLACE_FTELLO''@|$(REPLACE_FTELLO)|g' \ -e 's|@''REPLACE_FTELL''@|$(REPLACE_FTELL)|g' \ -e 's|@''REPLACE_FFLUSH''@|$(REPLACE_FFLUSH)|g' \ + -e 's|@''HAVE_DECL_GETDELIM''@|$(HAVE_DECL_GETDELIM)|g' \ + -e 's|@''HAVE_DECL_GETLINE''@|$(HAVE_DECL_GETLINE)|g' \ + -e 's|@''REPLACE_GETLINE''@|$(REPLACE_GETLINE)|g' \ -e '/definition of GL_LINK_WARNING/r $(LINK_WARNING_H)' \ < $(srcdir)/stdio_.h; \ } > [EMAIL PROTECTED] Index: tests/test-getdelim.c =================================================================== RCS file: tests/test-getdelim.c diff -N tests/test-getdelim.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ tests/test-getdelim.c 22 Aug 2007 00:04:01 -0000 @@ -0,0 +1,89 @@ +/* Test of getdelim() function. + Copyright (C) 2007 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +/* Written by Eric Blake <[EMAIL PROTECTED]>, 2007. */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define ASSERT(expr) \ + do \ + { \ + if (!(expr)) \ + { \ + fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \ + abort (); \ + } \ + } \ + while (0) + +int +main (int argc, char **argv) +{ + FILE *f; + char *line = NULL; + size_t len = 0; + ssize_t result; + + /* Create test file. */ + f = fopen ("test-getdelim.txt", "wb"); + if (!f || fwrite ("anbcnd\0f", 1, 8, f) != 8 || fclose (f) != 0) + { + fputs ("Failed to create sample file.\n", stderr); + unlink ("test-getdelim.txt"); + return 1; + } + f = fopen ("test-getdelim.txt", "rb"); + if (!f) + { + fputs ("Failed to reopen sample file.\n", stderr); + unlink ("test-getdelim.txt"); + return 1; + } + + /* Test initial allocation, which must include trailing NUL. */ + result = getdelim (&line, &len, 'n', f); + ASSERT (result == 2); + ASSERT (strcmp (line, "an") == 0); + ASSERT (2 < len); + + /* Test growth of buffer. */ + free (line); + line = malloc (1); + len = 1; + result = getdelim (&line, &len, 'n', f); + ASSERT (result == 3); + ASSERT (strcmp (line, "bcn") == 0); + ASSERT (3 < len); + + /* Test embedded NULs and EOF behavior. */ + result = getdelim (&line, &len, 'n', f); + ASSERT (result == 3); + ASSERT (memcmp (line, "d\0f", 4) == 0); + ASSERT (3 < len); + + result = getdelim (&line, &len, 'n', f); + ASSERT (result == -1); + + free (line); + fclose (f); + unlink ("test-getdelim.txt"); + return 0; +} Index: tests/test-getline.c =================================================================== RCS file: tests/test-getline.c diff -N tests/test-getline.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ tests/test-getline.c 22 Aug 2007 00:04:01 -0000 @@ -0,0 +1,89 @@ +/* Test of getline() function. + Copyright (C) 2007 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +/* Written by Eric Blake <[EMAIL PROTECTED]>, 2007. */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define ASSERT(expr) \ + do \ + { \ + if (!(expr)) \ + { \ + fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \ + abort (); \ + } \ + } \ + while (0) + +int +main (int argc, char **argv) +{ + FILE *f; + char *line = NULL; + size_t len = 0; + ssize_t result; + + /* Create test file. */ + f = fopen ("test-getline.txt", "wb"); + if (!f || fwrite ("a\nbc\nd\0f", 1, 8, f) != 8 || fclose (f) != 0) + { + fputs ("Failed to create sample file.\n", stderr); + unlink ("test-getline.txt"); + return 1; + } + f = fopen ("test-getline.txt", "rb"); + if (!f) + { + fputs ("Failed to reopen sample file.\n", stderr); + unlink ("test-getline.txt"); + return 1; + } + + /* Test initial allocation, which must include trailing NUL. */ + result = getline (&line, &len, f); + ASSERT (result == 2); + ASSERT (strcmp (line, "a\n") == 0); + ASSERT (2 < len); + + /* Test growth of buffer, must not leak. */ + free (line); + line = malloc (1); + len = 0; + result = getline (&line, &len, f); + ASSERT (result == 3); + ASSERT (strcmp (line, "bc\n") == 0); + ASSERT (3 < len); + + /* Test embedded NULs and EOF behavior. */ + result = getline (&line, &len, f); + ASSERT (result == 3); + ASSERT (memcmp (line, "d\0f", 4) == 0); + ASSERT (3 < len); + + result = getline (&line, &len, f); + ASSERT (result == -1); + + free (line); + fclose (f); + unlink ("test-getline.txt"); + return 0; +}