Line data Source code
1 : /*
2 : * Unix SMB/CIFS implementation.
3 : * SMB parameters and setup
4 : * Copyright (C) Andrew Tridgell 1992-1998 Modified by Jeremy Allison 1995.
5 : *
6 : * Added afdgets() Jelmer Vernooij 2005
7 : *
8 : * This program is free software; you can redistribute it and/or modify it under
9 : * the terms of the GNU General Public License as published by the Free
10 : * Software Foundation; either version 3 of the License, or (at your option)
11 : * any later version.
12 : *
13 : * This program is distributed in the hope that it will be useful, but WITHOUT
14 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 : * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 : * more details.
17 : *
18 : * You should have received a copy of the GNU General Public License along with
19 : * this program; if not, see <http://www.gnu.org/licenses/>.
20 : */
21 :
22 : #include "replace.h"
23 : #include "system/shmem.h"
24 : #include "system/filesys.h"
25 : #include <talloc.h>
26 : #include "lib/util/samba_util.h"
27 : #include "lib/util/sys_popen.h"
28 : #include "lib/util/sys_rw.h"
29 : #include "lib/util/debug.h"
30 :
31 : /**
32 : * Read one line (data until next newline or eof) and allocate it
33 : */
34 10326 : _PUBLIC_ char *afdgets(int fd, TALLOC_CTX *mem_ctx, size_t hint)
35 : {
36 10326 : char *data = NULL;
37 10326 : ssize_t alloc_size = 0, offset = 0, ret;
38 1081 : int p;
39 :
40 10326 : if (hint <= 0) hint = 0x100;
41 :
42 1087 : do {
43 10332 : alloc_size += hint;
44 :
45 10332 : data = talloc_realloc(mem_ctx, data, char, alloc_size);
46 :
47 10332 : if (!data)
48 0 : return NULL;
49 :
50 10332 : ret = read(fd, data + offset, hint);
51 :
52 10332 : if (ret == 0) {
53 198 : return NULL;
54 : }
55 :
56 10110 : if (ret == -1) {
57 0 : talloc_free(data);
58 0 : return NULL;
59 : }
60 :
61 : /* Find newline */
62 236990 : for (p = 0; p < ret; p++) {
63 236983 : if (data[offset + p] == '\n')
64 9047 : break;
65 : }
66 :
67 10110 : if (p < ret) {
68 10103 : data[offset + p] = '\0';
69 :
70 : /* Go back to position of newline */
71 10103 : lseek(fd, p - ret + 1, SEEK_CUR);
72 10103 : return data;
73 : }
74 :
75 7 : offset += ret;
76 :
77 7 : } while ((size_t)ret == hint);
78 :
79 1 : data[offset] = '\0';
80 :
81 1 : return data;
82 : }
83 :
84 274 : char *fgets_slash(TALLOC_CTX *mem_ctx, char *s2, size_t maxlen, FILE *f)
85 : {
86 274 : char *s = s2;
87 274 : size_t len = 0;
88 0 : int c;
89 274 : bool start_of_line = true;
90 :
91 274 : if (feof(f)) {
92 0 : return NULL;
93 : }
94 :
95 274 : if (maxlen < 2) {
96 0 : return NULL;
97 : }
98 :
99 274 : if (s2 == NULL) {
100 42 : maxlen = MIN(maxlen,8);
101 42 : s = talloc_array(mem_ctx, char, maxlen);
102 : }
103 :
104 274 : if (s == NULL) {
105 0 : return NULL;
106 : }
107 :
108 274 : *s = 0;
109 :
110 4068 : while (len < maxlen-1) {
111 4068 : c = getc(f);
112 4068 : switch (c)
113 : {
114 0 : case '\r':
115 0 : break;
116 194 : case '\n':
117 194 : while (len > 0 && s[len-1] == ' ') {
118 0 : s[--len] = 0;
119 : }
120 194 : if (len > 0 && s[len-1] == '\\') {
121 0 : s[--len] = 0;
122 0 : start_of_line = true;
123 0 : break;
124 : }
125 194 : return s;
126 80 : case EOF:
127 80 : if (len <= 0 && (s2 == NULL)) {
128 42 : TALLOC_FREE(s);
129 : }
130 80 : return (len>0) ? s : NULL;
131 308 : case ' ':
132 308 : if (start_of_line) {
133 0 : break;
134 : }
135 :
136 0 : FALL_THROUGH;
137 : default:
138 3794 : start_of_line = false;
139 3794 : s[len++] = c;
140 3794 : s[len] = 0;
141 : }
142 3794 : if ((s2 == NULL) && (len > maxlen-3)) {
143 0 : size_t m;
144 0 : char *t;
145 :
146 0 : m = maxlen * 2;
147 0 : if (m < maxlen) {
148 0 : DBG_ERR("length overflow\n");
149 0 : TALLOC_FREE(s);
150 0 : return NULL;
151 : }
152 0 : maxlen = m;
153 :
154 0 : t = talloc_realloc(mem_ctx, s, char, maxlen);
155 0 : if (t == NULL) {
156 0 : DBG_ERR("failed to expand buffer!\n");
157 0 : TALLOC_FREE(s);
158 0 : return NULL;
159 : }
160 :
161 0 : s = t;
162 : }
163 : }
164 :
165 0 : return s;
166 : }
167 :
168 : /**
169 : load a file into memory from a fd.
170 : **/
171 1680 : _PUBLIC_ char *fd_load(int fd, size_t *psize, size_t maxsize, TALLOC_CTX *mem_ctx)
172 : {
173 37 : FILE *file;
174 1680 : char *p = NULL;
175 1680 : size_t size = 0;
176 1680 : size_t chunk = 1024;
177 37 : int err;
178 37 : int fd_dup;
179 :
180 1680 : if (maxsize == 0) {
181 1659 : maxsize = SIZE_MAX;
182 : }
183 :
184 1680 : fd_dup = dup(fd);
185 1680 : if (fd_dup == -1) {
186 0 : return NULL;
187 : }
188 :
189 1680 : file = fdopen(fd_dup, "r");
190 1680 : if (file == NULL) {
191 0 : close(fd_dup);
192 0 : return NULL;
193 : }
194 :
195 2269 : while (size < maxsize) {
196 465 : size_t newbufsize;
197 465 : size_t nread;
198 :
199 2268 : chunk = MIN(chunk, (maxsize - size));
200 :
201 2268 : newbufsize = size + (chunk+1); /* chunk+1 can't overflow */
202 2268 : if (newbufsize < size) {
203 0 : goto fail; /* overflow */
204 : }
205 :
206 2268 : p = talloc_realloc(mem_ctx, p, char, newbufsize);
207 2268 : if (p == NULL) {
208 0 : goto fail;
209 : }
210 :
211 2268 : nread = fread(p+size, 1, chunk, file);
212 2268 : size += nread;
213 :
214 2268 : if (nread != chunk) {
215 1643 : break;
216 : }
217 : }
218 :
219 1680 : err = ferror(file);
220 1680 : if (err != 0) {
221 0 : goto fail;
222 : }
223 :
224 1680 : p[size] = '\0';
225 :
226 1680 : if (psize != NULL) {
227 1680 : *psize = size;
228 : }
229 :
230 1680 : fclose(file);
231 1680 : return p;
232 :
233 0 : fail:
234 0 : TALLOC_FREE(p);
235 0 : fclose(file);
236 0 : return NULL;
237 : }
238 :
239 : /**
240 : load a file into memory
241 : **/
242 366 : _PUBLIC_ char *file_load(const char *fname, size_t *size, size_t maxsize, TALLOC_CTX *mem_ctx)
243 : {
244 53 : int fd;
245 53 : char *p;
246 :
247 366 : if (!fname || !*fname) return NULL;
248 :
249 366 : fd = open(fname,O_RDONLY);
250 366 : if (fd == -1) return NULL;
251 :
252 218 : p = fd_load(fd, size, maxsize, mem_ctx);
253 :
254 218 : close(fd);
255 :
256 218 : return p;
257 : }
258 :
259 : /**
260 : parse a buffer into lines
261 : 'p' will be freed on error, and otherwise will be made a child of the returned array
262 : **/
263 3232 : static char **file_lines_parse_internal(char *p, size_t size, int *numlines, TALLOC_CTX *mem_ctx)
264 : {
265 13 : unsigned int i;
266 13 : char *s, **ret;
267 :
268 3232 : if (!p) return NULL;
269 :
270 448376 : for (s = p, i=0; s < p+size; s++) {
271 445144 : if (s[0] == '\n') i++;
272 : }
273 :
274 3232 : ret = talloc_zero_array(mem_ctx, char *, i+2);
275 3232 : if (!ret) {
276 0 : talloc_free(p);
277 0 : return NULL;
278 : }
279 :
280 3232 : talloc_steal(ret, p);
281 :
282 3232 : ret[0] = p;
283 448376 : for (s = p, i=1; s < p+size; s++) {
284 445144 : if (s[0] == '\n') {
285 12855 : s[0] = 0;
286 12855 : ret[i] = s+1;
287 12855 : i++;
288 : }
289 445144 : if (s[0] == '\r') s[0] = 0;
290 : }
291 :
292 : /* remove any blank lines at the end */
293 6475 : while (i > 0 && ret[i-1][0] == 0) {
294 3223 : i--;
295 : }
296 :
297 3232 : if (numlines) *numlines = i;
298 :
299 3219 : return ret;
300 : }
301 :
302 :
303 : /**
304 : load a file into memory and return an array of pointers to lines in the file
305 : must be freed with talloc_free().
306 : **/
307 263 : _PUBLIC_ char **file_lines_load(const char *fname, int *numlines, size_t maxsize, TALLOC_CTX *mem_ctx)
308 : {
309 28 : char *p;
310 28 : size_t size;
311 :
312 263 : p = file_load(fname, &size, maxsize, mem_ctx);
313 263 : if (!p) return NULL;
314 :
315 115 : return file_lines_parse_internal(p, size, numlines, mem_ctx);
316 : }
317 :
318 : /**
319 : load a fd into memory and return an array of pointers to lines in the file
320 : must be freed with talloc_free(). If convert is true calls unix_to_dos on
321 : the list.
322 : **/
323 1454 : _PUBLIC_ char **fd_lines_load(int fd, int *numlines, size_t maxsize, TALLOC_CTX *mem_ctx)
324 : {
325 0 : char *p;
326 0 : size_t size;
327 :
328 1454 : p = fd_load(fd, &size, maxsize, mem_ctx);
329 1454 : if (!p) return NULL;
330 :
331 1454 : return file_lines_parse_internal(p, size, numlines, mem_ctx);
332 : }
333 :
334 1663 : _PUBLIC_ char **file_lines_parse(const char *p_in,
335 : size_t size,
336 : int *numlines,
337 : TALLOC_CTX *mem_ctx)
338 : {
339 : /*
340 : * Copy the incoming string so it can end up
341 : * being owned by the returned pointer and
342 : * freed when that is.
343 : */
344 1663 : char *p = talloc_strdup(mem_ctx, p_in);
345 1663 : if (p == NULL) {
346 0 : return NULL;
347 : }
348 1663 : return file_lines_parse_internal(p, size, numlines, mem_ctx);
349 : }
350 :
351 750108 : _PUBLIC_ bool file_save_mode(const char *fname, const void *packet,
352 : size_t length, mode_t mode)
353 : {
354 8 : ssize_t num_written;
355 8 : int fd;
356 750108 : fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, mode);
357 750108 : if (fd == -1) {
358 404652 : return false;
359 : }
360 345456 : num_written = write(fd, packet, length);
361 345456 : if (num_written == -1 || (size_t)num_written != length) {
362 0 : close(fd);
363 0 : return false;
364 : }
365 345456 : close(fd);
366 345456 : return true;
367 : }
368 :
369 : /**
370 : save a lump of data into a file. Mostly used for debugging
371 : */
372 750075 : _PUBLIC_ bool file_save(const char *fname, const void *packet, size_t length)
373 : {
374 750075 : return file_save_mode(fname, packet, length, 0644);
375 : }
376 :
377 10 : _PUBLIC_ int vfdprintf(int fd, const char *format, va_list ap)
378 : {
379 10 : char *p;
380 10 : int len, ret;
381 10 : va_list ap2;
382 :
383 10 : va_copy(ap2, ap);
384 10 : len = vasprintf(&p, format, ap2);
385 10 : va_end(ap2);
386 10 : if (len <= 0) return len;
387 10 : ret = write(fd, p, len);
388 10 : SAFE_FREE(p);
389 0 : return ret;
390 : }
391 :
392 10 : _PUBLIC_ int fdprintf(int fd, const char *format, ...)
393 : {
394 10 : va_list ap;
395 10 : int ret;
396 :
397 10 : va_start(ap, format);
398 10 : ret = vfdprintf(fd, format, ap);
399 10 : va_end(ap);
400 10 : return ret;
401 : }
402 :
403 :
404 : /*
405 : compare two files, return true if the two files have the same content
406 : */
407 0 : bool file_compare(const char *path1, const char *path2)
408 : {
409 0 : FILE *f1 = NULL, *f2 = NULL;
410 0 : uint8_t buf1[1024], buf2[1024];
411 0 : bool ret = false;
412 :
413 0 : f1 = fopen(path1, "r");
414 0 : if (f1 == NULL) {
415 0 : goto done;
416 : }
417 0 : f2 = fopen(path2, "r");
418 0 : if (f2 == NULL) {
419 0 : goto done;
420 : }
421 :
422 0 : while (!feof(f1)) {
423 0 : size_t n1 = fread(buf1, 1, sizeof(buf1), f1);
424 0 : size_t n2 = fread(buf2, 1, sizeof(buf2), f2);
425 :
426 0 : if (n1 != n2) {
427 0 : goto done;
428 : }
429 0 : if (n1 == 0) {
430 0 : ret = (feof(f1) && feof(f2));
431 0 : goto done;
432 : }
433 0 : if (memcmp(buf1, buf2, n1) != 0) {
434 0 : goto done;
435 : }
436 0 : if (n1 < sizeof(buf1)) {
437 0 : bool has_error = (ferror(f1) || ferror(f2));
438 0 : if (has_error) {
439 0 : goto done;
440 : }
441 : }
442 : }
443 0 : ret = true;
444 0 : done:
445 0 : if (f2 != NULL) {
446 0 : fclose(f2);
447 : }
448 0 : if (f1 != NULL) {
449 0 : fclose(f1);
450 : }
451 0 : return ret;
452 : }
453 :
454 : /**
455 : Load from a pipe into memory.
456 : **/
457 932 : char *file_ploadv(char * const argl[], size_t *size)
458 : {
459 0 : int fd, n;
460 932 : char *p = NULL;
461 0 : char buf[1024];
462 0 : size_t total;
463 :
464 932 : fd = sys_popenv(argl);
465 932 : if (fd == -1) {
466 0 : return NULL;
467 : }
468 :
469 932 : total = 0;
470 :
471 1867 : while ((n = sys_read(fd, buf, sizeof(buf))) > 0) {
472 935 : p = talloc_realloc(NULL, p, char, total + n + 1);
473 935 : if (p == NULL) {
474 0 : DBG_ERR("failed to expand buffer!\n");
475 0 : close(fd);
476 0 : return NULL;
477 : }
478 935 : memcpy(p+total, buf, n);
479 935 : total += n;
480 : }
481 :
482 932 : if (p != NULL) {
483 932 : p[total] = 0;
484 : }
485 :
486 : /*
487 : * FIXME: Perhaps ought to check that the command completed
488 : * successfully (returned 0); if not the data may be
489 : * truncated.
490 : */
491 932 : sys_pclose(fd);
492 :
493 932 : if (size) {
494 932 : *size = total;
495 : }
496 :
497 932 : return p;
498 : }
|