• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /***
2   This file is part of eudev, forked from systemd.
3 
4   Copyright 2010 Lennart Poettering
5 
6   systemd is free software; you can redistribute it and/or modify it
7   under the terms of the GNU Lesser General Public License as published by
8   the Free Software Foundation; either version 2.1 of the License, or
9   (at your option) any later version.
10 
11   systemd is distributed in the hope that it will be useful, but
12   WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14   Lesser General Public License for more details.
15 
16   You should have received a copy of the GNU Lesser General Public License
17   along with systemd; If not, see <http://www.gnu.org/licenses/>.
18 ***/
19 
20 #include <unistd.h>
21 #include <sys/sendfile.h>
22 #include "fileio.h"
23 #include "util.h"
24 #include "strv.h"
25 #include "utf8.h"
26 #include "ctype.h"
27 
write_string_stream(FILE * f,const char * line)28 int write_string_stream(FILE *f, const char *line) {
29         assert(f);
30         assert(line);
31 
32         errno = 0;
33 
34         fputs(line, f);
35         if (!endswith(line, "\n"))
36                 fputc('\n', f);
37 
38         fflush(f);
39 
40         if (ferror(f))
41                 return errno ? -errno : -EIO;
42 
43         return 0;
44 }
45 
write_string_file(const char * fn,const char * line)46 int write_string_file(const char *fn, const char *line) {
47         _cleanup_fclose_ FILE *f = NULL;
48 
49         assert(fn);
50         assert(line);
51 
52         f = fopen(fn, "we");
53         if (!f)
54                 return -errno;
55 
56         return write_string_stream(f, line);
57 }
read_one_line_file(const char * fn,char ** line)58 int read_one_line_file(const char *fn, char **line) {
59         _cleanup_fclose_ FILE *f = NULL;
60         char t[LINE_MAX], *c;
61 
62         assert(fn);
63         assert(line);
64 
65         f = fopen(fn, "re");
66         if (!f)
67                 return -errno;
68 
69         if (!fgets(t, sizeof(t), f)) {
70 
71                 if (ferror(f))
72                         return errno ? -errno : -EIO;
73 
74                 t[0] = 0;
75         }
76 
77         c = strdup(t);
78         if (!c)
79                 return -ENOMEM;
80         truncate_nl(c);
81 
82         *line = c;
83         return 0;
84 }
85 
read_full_stream(FILE * f,char ** contents,size_t * size)86 int read_full_stream(FILE *f, char **contents, size_t *size) {
87         size_t n, l;
88         _cleanup_free_ char *buf = NULL;
89         struct stat st;
90 
91         assert(f);
92         assert(contents);
93 
94         if (fstat(fileno(f), &st) < 0)
95                 return -errno;
96 
97         n = LINE_MAX;
98 
99         if (S_ISREG(st.st_mode)) {
100 
101                 /* Safety check */
102                 if (st.st_size > 4*1024*1024)
103                         return -E2BIG;
104 
105                 /* Start with the right file size, but be prepared for
106                  * files from /proc which generally report a file size
107                  * of 0 */
108                 if (st.st_size > 0)
109                         n = st.st_size;
110         }
111 
112         l = 0;
113         for (;;) {
114                 char *t;
115                 size_t k;
116 
117                 t = realloc(buf, n+1);
118                 if (!t)
119                         return -ENOMEM;
120 
121                 buf = t;
122                 k = fread(buf + l, 1, n - l, f);
123 
124                 if (k <= 0) {
125                         if (ferror(f))
126                                 return -errno;
127 
128                         break;
129                 }
130 
131                 l += k;
132                 n *= 2;
133 
134                 /* Safety check */
135                 if (n > 4*1024*1024)
136                         return -E2BIG;
137         }
138 
139         buf[l] = 0;
140         *contents = buf;
141         buf = NULL; /* do not free */
142 
143         if (size)
144                 *size = l;
145 
146         return 0;
147 }
148 
read_full_file(const char * fn,char ** contents,size_t * size)149 int read_full_file(const char *fn, char **contents, size_t *size) {
150         _cleanup_fclose_ FILE *f = NULL;
151 
152         assert(fn);
153         assert(contents);
154 
155         f = fopen(fn, "re");
156         if (!f)
157                 return -errno;
158 
159         return read_full_stream(f, contents, size);
160 }
161