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