Paul Eggert <[EMAIL PROTECTED]> writes: > Simon Josefsson <[EMAIL PROTECTED]> writes: > >> + if (buf) >> + buf[size] = '\0'; > > The file reading code returns NULL if the file was empty? But the > comments makes it sound like it will return xstrdup (""), and that > would be more consistent. You might also add a test case, to read > from /dev/null.
The intention was to return strdup (""). However, it do seem to behave like that, from this test case: { size_t len; char *out = read_file (FILE2, &len); if (!out) perror ("Could not read file"); if (out[len] != '\0') perror ("BAD: out[len] not zero"); printf ("Read %d from %s...\n", len, FILE2); free (out); } If FILE2 is /dev/zero it prints: Read 0 from /dev/null... Looking at the code, it seems it depends on whether feof() return true immediately after fopen on a zero-size file. Does the standards says anything about this? Anyway, I changed the code to don't assume that feof() return non-true without a fread on zero-size files. See below. > The following replacement code is a bit clearer, at least to my eyes: Incorporated too. Thanks! /* read-file.c -- read file contents into a string Copyright (C) 2006 Free Software Foundation, Inc. Written by Simon Josefsson and Bruno Haible. 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 2, 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. */ #ifdef HAVE_CONFIG_H # include <config.h> #endif #include "read-file.h" /* Get realloc, free. */ #include <stdlib.h> /* Get errno. */ #include <errno.h> /* Read a STREAM and return a newly allocated string with the content, and set *LENGTH to the length of the string. The string is zero-terminated, but the terminating zero byte is not counted in *LENGTH. On errors, *LENGTH is undefined, errno preserves the values set by system functions (if any), and NULL is returned. */ char * fread_file (FILE * stream, size_t * length) { char *buf = malloc (1); size_t alloc = 1; size_t size = 0; if (!buf) return NULL; while (!feof (stream)) { size_t count; if (size + BUFSIZ + 1 > alloc) { char *new_buf; alloc += alloc / 2; if (alloc < size + BUFSIZ + 1) alloc = size + BUFSIZ + 1; new_buf = realloc (buf, alloc); if (!new_buf) { int save_errno = errno; free (buf); errno = save_errno; return NULL; } buf = new_buf; } count = fread (buf + size, 1, alloc - size - 1, stream); size += count; if (ferror (stream)) { int save_errno = errno; free (buf); errno = save_errno; return NULL; } } buf[size] = '\0'; *length = size; return buf; } static char * internal_read_file (const char *filename, size_t * length, const char *mode) { FILE *stream = fopen (filename, mode); char *out; int save_errno; int rc; if (!stream) return NULL; out = fread_file (stream, length); save_errno = errno; if (fclose (stream) != 0) { if (out) { save_errno = errno; free (out); } errno = save_errno; return NULL; } return out; } /* Open and read the contents of FILENAME, and return a newly allocated string with the content, and set *LENGTH to the length of the string. The string is zero-terminated, but the terminating zero byte is not counted in *LENGTH. On errors, *LENGTH is undefined, errno preserves the values set by system functions (if any), and NULL is returned. */ char * read_file (const char *filename, size_t * length) { return internal_read_file (filename, length, "r"); } /* Open (on non-POSIX systems, in binary mode) and read the contents of FILENAME, and return a newly allocated string with the content, and set LENGTH to the length of the string. The string is zero-terminated, but the terminating zero byte is not counted in the LENGTH variable. On errors, *LENGTH is undefined, errno preserves the values set by system functions (if any), and NULL is returned. */ char * read_binary_file (const char *filename, size_t * length) { return internal_read_file (filename, length, "rb"); }