getline: Update regarding AIX.
[gnulib.git] / lib / read-file.c
1 /* read-file.c -- read file contents into a string
2    Copyright (C) 2006, 2009, 2010 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 realloc, free. */
24 #include <stdlib.h>
25
26 /* Get errno. */
27 #include <errno.h>
28
29 /* Read a STREAM and return a newly allocated string with the content,
30    and set *LENGTH to the length of the string.  The string is
31    zero-terminated, but the terminating zero byte is not counted in
32    *LENGTH.  On errors, *LENGTH is undefined, errno preserves the
33    values set by system functions (if any), and NULL is returned. */
34 char *
35 fread_file (FILE * stream, size_t * length)
36 {
37   char *buf = NULL;
38   size_t alloc = 0;
39   size_t size = 0;
40   int save_errno;
41
42   for (;;)
43     {
44       size_t count;
45       size_t requested;
46
47       if (size + BUFSIZ + 1 > alloc)
48         {
49           char *new_buf;
50
51           alloc += alloc / 2;
52           if (alloc < size + BUFSIZ + 1)
53             alloc = size + BUFSIZ + 1;
54
55           new_buf = realloc (buf, alloc);
56           if (!new_buf)
57             {
58               save_errno = errno;
59               break;
60             }
61
62           buf = new_buf;
63         }
64
65       requested = alloc - size - 1;
66       count = fread (buf + size, 1, requested, stream);
67       size += count;
68
69       if (count != requested)
70         {
71           save_errno = errno;
72           if (ferror (stream))
73             break;
74           buf[size] = '\0';
75           *length = size;
76           return buf;
77         }
78     }
79
80   free (buf);
81   errno = save_errno;
82   return NULL;
83 }
84
85 static char *
86 internal_read_file (const char *filename, size_t * length, const char *mode)
87 {
88   FILE *stream = fopen (filename, mode);
89   char *out;
90   int save_errno;
91
92   if (!stream)
93     return NULL;
94
95   out = fread_file (stream, length);
96
97   save_errno = errno;
98
99   if (fclose (stream) != 0)
100     {
101       if (out)
102         {
103           save_errno = errno;
104           free (out);
105         }
106       errno = save_errno;
107       return NULL;
108     }
109
110   return out;
111 }
112
113 /* Open and read the contents of FILENAME, and return a newly
114    allocated string with the content, and set *LENGTH to the length of
115    the string.  The string is zero-terminated, but the terminating
116    zero byte is not counted in *LENGTH.  On errors, *LENGTH is
117    undefined, errno preserves the values set by system functions (if
118    any), and NULL is returned.  */
119 char *
120 read_file (const char *filename, size_t * length)
121 {
122   return internal_read_file (filename, length, "r");
123 }
124
125 /* Open (on non-POSIX systems, in binary mode) and read the contents
126    of FILENAME, and return a newly allocated string with the content,
127    and set LENGTH to the length of the string.  The string is
128    zero-terminated, but the terminating zero byte is not counted in
129    the LENGTH variable.  On errors, *LENGTH is undefined, errno
130    preserves the values set by system functions (if any), and NULL is
131    returned.  */
132 char *
133 read_binary_file (const char *filename, size_t * length)
134 {
135   return internal_read_file (filename, length, "rb");
136 }