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