Add read-file module.
[pspp] / lib / read-file.c
1 /* read-file.c -- read file contents into a string
2    Copyright (C) 2006 Free Software Foundation, Inc.
3    Written by Simon Josefsson and Bruno Haible.
4
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2, or (at your option)
8    any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software Foundation,
17    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
18
19 #ifdef HAVE_CONFIG_H
20 # include <config.h>
21 #endif
22
23 #include "read-file.h"
24
25 /* Get realloc, free. */
26 #include <stdlib.h>
27
28 /* Get errno. */
29 #include <errno.h>
30
31 /* Read a STREAM and return a newly allocated string with the content,
32    and set *LENGTH to the length of the string.  The string is
33    zero-terminated, but the terminating zero byte is not counted in
34    *LENGTH.  On errors, *LENGTH is undefined, errno preserves the
35    values set by system functions (if any), and NULL is returned. */
36 char *
37 fread_file (FILE * stream, size_t * length)
38 {
39   char *buf = malloc (1);
40   size_t alloc = 1;
41   size_t size = 0;
42
43   if (!buf)
44     return NULL;
45
46   while (!feof (stream))
47     {
48       size_t count;
49
50       if (size + BUFSIZ + 1 > alloc)
51         {
52           char *new_buf;
53
54           alloc += alloc / 2;
55           if (alloc < size + BUFSIZ + 1)
56             alloc = size + BUFSIZ + 1;
57
58           new_buf = realloc (buf, alloc);
59           if (!new_buf)
60             {
61               int save_errno = errno;
62               free (buf);
63               errno = save_errno;
64               return NULL;
65             }
66
67           buf = new_buf;
68         }
69
70       count = fread (buf + size, 1, alloc - size - 1, stream);
71       size += count;
72
73       if (ferror (stream))
74         {
75           int save_errno = errno;
76           free (buf);
77           errno = save_errno;
78           return NULL;
79         }
80     }
81
82   buf[size] = '\0';
83
84   *length = size;
85
86   return buf;
87 }
88
89 static char *
90 internal_read_file (const char *filename, size_t * length, const char *mode)
91 {
92   FILE *stream = fopen (filename, mode);
93   char *out;
94   int save_errno;
95   int rc;
96
97   if (!stream)
98     return NULL;
99
100   out = fread_file (stream, length);
101
102   save_errno = errno;
103
104   if (fclose (stream) != 0)
105     {
106       if (out)
107         {
108           save_errno = errno;
109           free (out);
110         }
111       errno = save_errno;
112       return NULL;
113     }
114
115   return out;
116 }
117
118 /* Open and read the contents of FILENAME, and return a newly
119    allocated string with the content, and set *LENGTH to the length of
120    the string.  The string is zero-terminated, but the terminating
121    zero byte is not counted in *LENGTH.  On errors, *LENGTH is
122    undefined, errno preserves the values set by system functions (if
123    any), and NULL is returned.  */
124 char *
125 read_file (const char *filename, size_t * length)
126 {
127   return internal_read_file (filename, length, "r");
128 }
129
130 /* Open (on non-POSIX systems, in binary mode) and read the contents
131    of FILENAME, and return a newly allocated string with the content,
132    and set LENGTH to the length of the string.  The string is
133    zero-terminated, but the terminating zero byte is not counted in
134    the LENGTH variable.  On errors, *LENGTH is undefined, errno
135    preserves the values set by system functions (if any), and NULL is
136    returned.  */
137 char *
138 read_binary_file (const char *filename, size_t * length)
139 {
140   return internal_read_file (filename, length, "rb");
141 }