maint: update almost all copyright ranges to include 2011
[gnulib.git] / lib / read-file.c
1 /* read-file.c -- read file contents into a string
2    Copyright (C) 2006, 2009-2011 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 #include <config.h>
20
21 #include "read-file.h"
22
23 /* Get fstat.  */
24 #include <sys/stat.h>
25
26 /* Get ftello.  */
27 #include <stdio.h>
28
29 /* Get SIZE_MAX.  */
30 #include <stdint.h>
31
32 /* Get malloc, realloc, free. */
33 #include <stdlib.h>
34
35 /* Get errno. */
36 #include <errno.h>
37
38 /* Read a STREAM and return a newly allocated string with the content,
39    and set *LENGTH to the length of the string.  The string is
40    zero-terminated, but the terminating zero byte is not counted in
41    *LENGTH.  On errors, *LENGTH is undefined, errno preserves the
42    values set by system functions (if any), and NULL is returned.  */
43 char *
44 fread_file (FILE *stream, size_t *length)
45 {
46   char *buf = NULL;
47   size_t alloc = BUFSIZ;
48
49   /* For a regular file, allocate a buffer that has exactly the right
50      size.  This avoids the need to do dynamic reallocations later.  */
51   {
52     struct stat st;
53
54     if (fstat (fileno (stream), &st) >= 0 && S_ISREG (st.st_mode))
55       {
56         off_t pos = ftello (stream);
57
58         if (pos >= 0 && pos < st.st_size)
59           {
60             off_t alloc_off = st.st_size - pos;
61
62             /* '1' below, accounts for the trailing NUL.  */
63             if (SIZE_MAX - 1 < alloc_off)
64               {
65                 errno = ENOMEM;
66                 return NULL;
67               }
68
69             alloc = alloc_off + 1;
70           }
71       }
72   }
73
74   if (!(buf = malloc (alloc)))
75     return NULL; /* errno is ENOMEM.  */
76
77   {
78     size_t size = 0; /* number of bytes read so far */
79     int save_errno;
80
81     for (;;)
82       {
83         /* This reads 1 more than the size of a regular file
84            so that we get eof immediately.  */
85         size_t requested = alloc - size;
86         size_t count = fread (buf + size, 1, requested, stream);
87         size += count;
88
89         if (count != requested)
90           {
91             save_errno = errno;
92             if (ferror (stream))
93               break;
94
95             /* Shrink the allocated memory if possible.  */
96             if (size < alloc - 1)
97               {
98                 char *smaller_buf = realloc (buf, size + 1);
99                 if (smaller_buf != NULL)
100                   buf = smaller_buf;
101               }
102
103             buf[size] = '\0';
104             *length = size;
105             return buf;
106           }
107
108         {
109           char *new_buf;
110
111           if (alloc == SIZE_MAX)
112             {
113               save_errno = ENOMEM;
114               break;
115             }
116
117           if (alloc < SIZE_MAX - alloc / 2)
118             alloc = alloc + alloc / 2;
119           else
120             alloc = SIZE_MAX;
121
122           if (!(new_buf = realloc (buf, alloc)))
123             {
124               save_errno = errno;
125               break;
126             }
127
128           buf = new_buf;
129         }
130       }
131
132     free (buf);
133     errno = save_errno;
134     return NULL;
135   }
136 }
137
138 static char *
139 internal_read_file (const char *filename, size_t *length, const char *mode)
140 {
141   FILE *stream = fopen (filename, mode);
142   char *out;
143   int save_errno;
144
145   if (!stream)
146     return NULL;
147
148   out = fread_file (stream, length);
149
150   save_errno = errno;
151
152   if (fclose (stream) != 0)
153     {
154       if (out)
155         {
156           save_errno = errno;
157           free (out);
158         }
159       errno = save_errno;
160       return NULL;
161     }
162
163   return out;
164 }
165
166 /* Open and read the contents of FILENAME, and return a newly
167    allocated string with the content, and set *LENGTH to the length of
168    the string.  The string is zero-terminated, but the terminating
169    zero byte is not counted in *LENGTH.  On errors, *LENGTH is
170    undefined, errno preserves the values set by system functions (if
171    any), and NULL is returned.  */
172 char *
173 read_file (const char *filename, size_t *length)
174 {
175   return internal_read_file (filename, length, "r");
176 }
177
178 /* Open (on non-POSIX systems, in binary mode) and read the contents
179    of FILENAME, and return a newly allocated string with the content,
180    and set LENGTH to the length of the string.  The string is
181    zero-terminated, but the terminating zero byte is not counted in
182    the LENGTH variable.  On errors, *LENGTH is undefined, errno
183    preserves the values set by system functions (if any), and NULL is
184    returned.  */
185 char *
186 read_binary_file (const char *filename, size_t *length)
187 {
188   return internal_read_file (filename, length, "rb");
189 }