From 08c03e591ea25f38405e5e06f1565e01feabb591 Mon Sep 17 00:00:00 2001 From: Simon Josefsson Date: Fri, 16 Jun 2006 19:40:12 +0000 Subject: [PATCH] Add read-file module. --- lib/read-file.c | 141 ++++++++++++++++++++++++++++++++++++++++ lib/read-file.h | 34 ++++++++++ m4/read-file.m4 | 15 +++++ modules/read-file | 23 +++++++ modules/read-file-tests | 10 +++ tests/test-read-file.c | 65 ++++++++++++++++++ 6 files changed, 288 insertions(+) create mode 100644 lib/read-file.c create mode 100644 lib/read-file.h create mode 100644 m4/read-file.m4 create mode 100644 modules/read-file create mode 100644 modules/read-file-tests create mode 100644 tests/test-read-file.c diff --git a/lib/read-file.c b/lib/read-file.c new file mode 100644 index 0000000000..ac53dd4c90 --- /dev/null +++ b/lib/read-file.c @@ -0,0 +1,141 @@ +/* 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 +#endif + +#include "read-file.h" + +/* Get realloc, free. */ +#include + +/* Get errno. */ +#include + +/* 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"); +} diff --git a/lib/read-file.h b/lib/read-file.h new file mode 100644 index 0000000000..f8c712e720 --- /dev/null +++ b/lib/read-file.h @@ -0,0 +1,34 @@ +/* read-file.h -- read file contents into a string + Copyright (C) 2006 Free Software Foundation, Inc. + Written by Simon Josefsson. + + 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. */ + +#ifndef READ_FILE_H +#define READ_FILE_H + +/* Get size_t. */ +#include + +/* Get FILE. */ +#include + +extern char *fread_file (FILE * stream, size_t * length); + +extern char *read_file (const char *filename, size_t * length); + +extern char *read_binary_file (const char *filename, size_t * length); + +#endif /* READ_FILE_H */ diff --git a/m4/read-file.m4 b/m4/read-file.m4 new file mode 100644 index 0000000000..15bcad98b4 --- /dev/null +++ b/m4/read-file.m4 @@ -0,0 +1,15 @@ +# read-file.m4 serial 1 +dnl Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_FUNC_READ_FILE], +[ + AC_LIBSOURCES([read-file.c, read-file.h]) + AC_LIBOBJ([read-file]) + gl_PREREQ_READ_FILE +]) + +# Prerequisites of lib/read-file.c. +AC_DEFUN([gl_PREREQ_READ_FILE], [:]) diff --git a/modules/read-file b/modules/read-file new file mode 100644 index 0000000000..1b7263eb32 --- /dev/null +++ b/modules/read-file @@ -0,0 +1,23 @@ +Description: +read_file() function: read the contents of a file into a string + +Files: +lib/read-file.h +lib/read-file.c +m4/read-file.m4 + +Depends-on: + +configure.ac: +gl_FUNC_READ_FILE + +Makefile.am: + +Include: +"read-file.h" + +License: +LGPL + +Maintainer: +Simon Josefsson diff --git a/modules/read-file-tests b/modules/read-file-tests new file mode 100644 index 0000000000..bdb7c63d5c --- /dev/null +++ b/modules/read-file-tests @@ -0,0 +1,10 @@ +Files: +tests/test-read-file.c + +Depends-on: + +configure.ac: + +Makefile.am: +TESTS += test-read-file$(EXEEXT) +check_PROGRAMS += test-read-file diff --git a/tests/test-read-file.c b/tests/test-read-file.c new file mode 100644 index 0000000000..1e90cd4566 --- /dev/null +++ b/tests/test-read-file.c @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2006 Free Software Foundation + * Written by Simon Josefsson + * + * 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 +#endif + +#include "read-file.h" + +#include + +#define FILE1 "/etc/resolv.conf" +#define FILE2 "/dev/null" + +int +main (void) +{ + { + size_t len; + char *out = read_file (FILE1, &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, FILE1); + + free (out); + } + + { + 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); + } + + return 0; +} -- 2.30.2