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/util_file.h"
28 : #include "lib/util/sys_popen.h"
29 : #include "lib/util/sys_rw.h"
30 : #include "lib/util/debug.h"
31 :
32 : /**
33 : * Read one line (data until next newline or eof) and allocate it
34 : */
35 10372 : _PUBLIC_ char *afdgets(int fd, TALLOC_CTX *mem_ctx, size_t hint)
36 : {
37 10372 : char *data = NULL;
38 10372 : ssize_t alloc_size = 0, offset = 0, ret;
39 1081 : int p;
40 :
41 10372 : if (hint <= 0) hint = 0x100;
42 :
43 1087 : do {
44 10378 : alloc_size += hint;
45 :
46 10378 : data = talloc_realloc(mem_ctx, data, char, alloc_size);
47 :
48 10378 : if (!data)
49 0 : return NULL;
50 :
51 10378 : ret = read(fd, data + offset, hint);
52 :
53 10378 : if (ret == 0) {
54 198 : return NULL;
55 : }
56 :
57 10156 : if (ret == -1) {
58 0 : talloc_free(data);
59 0 : return NULL;
60 : }
61 :
62 : /* Find newline */
63 237094 : for (p = 0; p < ret; p++) {
64 237087 : if (data[offset + p] == '\n')
65 9093 : break;
66 : }
67 :
68 10156 : if (p < ret) {
69 10149 : data[offset + p] = '\0';
70 :
71 : /* Go back to position of newline */
72 10149 : lseek(fd, p - ret + 1, SEEK_CUR);
73 10149 : return data;
74 : }
75 :
76 7 : offset += ret;
77 :
78 7 : } while ((size_t)ret == hint);
79 :
80 1 : data[offset] = '\0';
81 :
82 1 : return data;
83 : }
84 :
85 274 : char *fgets_slash(TALLOC_CTX *mem_ctx, char *s2, size_t maxlen, FILE *f)
86 : {
87 274 : char *s = s2;
88 274 : size_t len = 0;
89 0 : int c;
90 274 : bool start_of_line = true;
91 :
92 274 : if (feof(f)) {
93 0 : return NULL;
94 : }
95 :
96 274 : if (maxlen < 2) {
97 0 : return NULL;
98 : }
99 :
100 274 : if (s2 == NULL) {
101 42 : maxlen = MIN(maxlen,8);
102 42 : s = talloc_array(mem_ctx, char, maxlen);
103 : }
104 :
105 274 : if (s == NULL) {
106 0 : return NULL;
107 : }
108 :
109 274 : *s = 0;
110 :
111 4068 : while (len < maxlen-1) {
112 4068 : c = getc(f);
113 4068 : switch (c)
114 : {
115 0 : case '\r':
116 0 : break;
117 194 : case '\n':
118 194 : while (len > 0 && s[len-1] == ' ') {
119 0 : s[--len] = 0;
120 : }
121 194 : if (len > 0 && s[len-1] == '\\') {
122 0 : s[--len] = 0;
123 0 : start_of_line = true;
124 0 : break;
125 : }
126 194 : return s;
127 80 : case EOF:
128 80 : if (len <= 0 && (s2 == NULL)) {
129 42 : TALLOC_FREE(s);
130 : }
131 80 : return (len>0) ? s : NULL;
132 308 : case ' ':
133 308 : if (start_of_line) {
134 0 : break;
135 : }
136 :
137 0 : FALL_THROUGH;
138 : default:
139 3794 : start_of_line = false;
140 3794 : s[len++] = c;
141 3794 : s[len] = 0;
142 : }
143 3794 : if ((s2 == NULL) && (len > maxlen-3)) {
144 0 : size_t m;
145 0 : char *t;
146 :
147 0 : m = maxlen * 2;
148 0 : if (m < maxlen) {
149 0 : DBG_ERR("length overflow\n");
150 0 : TALLOC_FREE(s);
151 0 : return NULL;
152 : }
153 0 : maxlen = m;
154 :
155 0 : t = talloc_realloc(mem_ctx, s, char, maxlen);
156 0 : if (t == NULL) {
157 0 : DBG_ERR("failed to expand buffer!\n");
158 0 : TALLOC_FREE(s);
159 0 : return NULL;
160 : }
161 :
162 0 : s = t;
163 : }
164 : }
165 :
166 0 : return s;
167 : }
168 :
169 : /**
170 : load a file into memory from a fd.
171 : **/
172 1673 : _PUBLIC_ char *fd_load(int fd, size_t *psize, size_t maxsize, TALLOC_CTX *mem_ctx)
173 : {
174 38 : FILE *file;
175 1673 : char *p = NULL;
176 1673 : size_t size = 0;
177 1673 : size_t chunk = 1024;
178 38 : int err;
179 :
180 1673 : if (maxsize == 0) {
181 1652 : maxsize = SIZE_MAX;
182 : }
183 :
184 1673 : file = fdopen_keepfd(fd, "r");
185 1673 : if (file == NULL) {
186 0 : return NULL;
187 : }
188 :
189 2262 : while (size < maxsize) {
190 466 : size_t newbufsize;
191 466 : size_t nread;
192 :
193 2261 : chunk = MIN(chunk, (maxsize - size));
194 :
195 2261 : newbufsize = size + (chunk+1); /* chunk+1 can't overflow */
196 2261 : if (newbufsize < size) {
197 0 : goto fail; /* overflow */
198 : }
199 :
200 2261 : p = talloc_realloc(mem_ctx, p, char, newbufsize);
201 2261 : if (p == NULL) {
202 0 : goto fail;
203 : }
204 :
205 2261 : nread = fread(p+size, 1, chunk, file);
206 2261 : size += nread;
207 :
208 2261 : if (nread != chunk) {
209 1635 : break;
210 : }
211 : }
212 :
213 1673 : err = ferror(file);
214 1673 : if (err != 0) {
215 0 : goto fail;
216 : }
217 :
218 1673 : p[size] = '\0';
219 :
220 1673 : if (psize != NULL) {
221 1673 : *psize = size;
222 : }
223 :
224 1673 : fclose(file);
225 1673 : return p;
226 :
227 0 : fail:
228 0 : TALLOC_FREE(p);
229 0 : fclose(file);
230 0 : return NULL;
231 : }
232 :
233 : /**
234 : load a file into memory
235 : **/
236 246 : _PUBLIC_ char *file_load(const char *fname, size_t *size, size_t maxsize, TALLOC_CTX *mem_ctx)
237 : {
238 40 : int fd;
239 40 : char *p;
240 :
241 246 : if (!fname || !*fname) return NULL;
242 :
243 246 : fd = open(fname,O_RDONLY);
244 246 : if (fd == -1) return NULL;
245 :
246 214 : p = fd_load(fd, size, maxsize, mem_ctx);
247 :
248 214 : close(fd);
249 :
250 214 : return p;
251 : }
252 :
253 : /**
254 : parse a buffer into lines
255 : 'p' will be freed on error, and otherwise will be made a child of the returned array
256 : **/
257 3262 : static char **file_lines_parse_internal(char *p, size_t size, int *numlines, TALLOC_CTX *mem_ctx)
258 : {
259 13 : unsigned int i;
260 13 : char *s, **ret;
261 :
262 3262 : if (!p) return NULL;
263 :
264 451925 : for (s = p, i=0; s < p+size; s++) {
265 448663 : if (s[0] == '\n') i++;
266 : }
267 :
268 3262 : ret = talloc_zero_array(mem_ctx, char *, i+2);
269 3262 : if (!ret) {
270 0 : talloc_free(p);
271 0 : return NULL;
272 : }
273 :
274 3262 : talloc_steal(ret, p);
275 :
276 3262 : ret[0] = p;
277 451925 : for (s = p, i=1; s < p+size; s++) {
278 448663 : if (s[0] == '\n') {
279 13138 : s[0] = 0;
280 13138 : ret[i] = s+1;
281 13138 : i++;
282 : }
283 448663 : if (s[0] == '\r') s[0] = 0;
284 : }
285 :
286 : /* remove any blank lines at the end */
287 6535 : while (i > 0 && ret[i-1][0] == 0) {
288 3253 : i--;
289 : }
290 :
291 3262 : if (numlines) *numlines = i;
292 :
293 3249 : return ret;
294 : }
295 :
296 :
297 : /**
298 : load a file into memory and return an array of pointers to lines in the file
299 : must be freed with talloc_free().
300 : **/
301 142 : _PUBLIC_ char **file_lines_load(const char *fname, int *numlines, size_t maxsize, TALLOC_CTX *mem_ctx)
302 : {
303 14 : char *p;
304 14 : size_t size;
305 :
306 142 : p = file_load(fname, &size, maxsize, mem_ctx);
307 142 : if (!p) return NULL;
308 :
309 110 : return file_lines_parse_internal(p, size, numlines, mem_ctx);
310 : }
311 :
312 : /**
313 : load a fd into memory and return an array of pointers to lines in the file
314 : must be freed with talloc_free(). If convert is true calls unix_to_dos on
315 : the list.
316 : **/
317 1451 : _PUBLIC_ char **fd_lines_load(int fd, int *numlines, size_t maxsize, TALLOC_CTX *mem_ctx)
318 : {
319 0 : char *p;
320 0 : size_t size;
321 :
322 1451 : p = fd_load(fd, &size, maxsize, mem_ctx);
323 1451 : if (!p) return NULL;
324 :
325 1451 : return file_lines_parse_internal(p, size, numlines, mem_ctx);
326 : }
327 :
328 1701 : _PUBLIC_ char **file_lines_parse(const char *p_in,
329 : size_t size,
330 : int *numlines,
331 : TALLOC_CTX *mem_ctx)
332 : {
333 : /*
334 : * Copy the incoming string so it can end up
335 : * being owned by the returned pointer and
336 : * freed when that is.
337 : */
338 1701 : char *p = talloc_strdup(mem_ctx, p_in);
339 1701 : if (p == NULL) {
340 0 : return NULL;
341 : }
342 1701 : return file_lines_parse_internal(p, size, numlines, mem_ctx);
343 : }
344 :
345 753050 : _PUBLIC_ bool file_save_mode(const char *fname, const void *packet,
346 : size_t length, mode_t mode)
347 : {
348 8 : ssize_t num_written;
349 8 : int fd;
350 753050 : fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, mode);
351 753050 : if (fd == -1) {
352 405979 : return false;
353 : }
354 347071 : num_written = write(fd, packet, length);
355 347071 : if (num_written == -1 || (size_t)num_written != length) {
356 0 : close(fd);
357 0 : return false;
358 : }
359 347071 : close(fd);
360 347071 : return true;
361 : }
362 :
363 : /**
364 : save a lump of data into a file. Mostly used for debugging
365 : */
366 753017 : _PUBLIC_ bool file_save(const char *fname, const void *packet, size_t length)
367 : {
368 753017 : return file_save_mode(fname, packet, length, 0644);
369 : }
370 :
371 10 : _PUBLIC_ int vfdprintf(int fd, const char *format, va_list ap)
372 : {
373 10 : char *p;
374 10 : int len, ret;
375 10 : va_list ap2;
376 :
377 10 : va_copy(ap2, ap);
378 10 : len = vasprintf(&p, format, ap2);
379 10 : va_end(ap2);
380 10 : if (len <= 0) return len;
381 10 : ret = write(fd, p, len);
382 10 : SAFE_FREE(p);
383 0 : return ret;
384 : }
385 :
386 10 : _PUBLIC_ int fdprintf(int fd, const char *format, ...)
387 : {
388 10 : va_list ap;
389 10 : int ret;
390 :
391 10 : va_start(ap, format);
392 10 : ret = vfdprintf(fd, format, ap);
393 10 : va_end(ap);
394 10 : return ret;
395 : }
396 :
397 :
398 : /*
399 : compare two files, return true if the two files have the same content
400 : */
401 0 : bool file_compare(const char *path1, const char *path2)
402 : {
403 0 : FILE *f1 = NULL, *f2 = NULL;
404 0 : uint8_t buf1[1024], buf2[1024];
405 0 : bool ret = false;
406 :
407 0 : f1 = fopen(path1, "r");
408 0 : if (f1 == NULL) {
409 0 : goto done;
410 : }
411 0 : f2 = fopen(path2, "r");
412 0 : if (f2 == NULL) {
413 0 : goto done;
414 : }
415 :
416 0 : while (!feof(f1)) {
417 0 : size_t n1 = fread(buf1, 1, sizeof(buf1), f1);
418 0 : size_t n2 = fread(buf2, 1, sizeof(buf2), f2);
419 :
420 0 : if (n1 != n2) {
421 0 : goto done;
422 : }
423 0 : if (n1 == 0) {
424 0 : ret = (feof(f1) && feof(f2));
425 0 : goto done;
426 : }
427 0 : if (memcmp(buf1, buf2, n1) != 0) {
428 0 : goto done;
429 : }
430 0 : if (n1 < sizeof(buf1)) {
431 0 : bool has_error = (ferror(f1) || ferror(f2));
432 0 : if (has_error) {
433 0 : goto done;
434 : }
435 : }
436 : }
437 0 : ret = true;
438 0 : done:
439 0 : if (f2 != NULL) {
440 0 : fclose(f2);
441 : }
442 0 : if (f1 != NULL) {
443 0 : fclose(f1);
444 : }
445 0 : return ret;
446 : }
447 :
448 : /**
449 : Load from a pipe into memory.
450 : **/
451 930 : char *file_ploadv(char * const argl[], size_t *size)
452 : {
453 0 : int fd, n;
454 930 : char *p = NULL;
455 0 : char buf[1024];
456 0 : size_t total;
457 :
458 930 : fd = sys_popenv(argl);
459 930 : if (fd == -1) {
460 0 : return NULL;
461 : }
462 :
463 930 : total = 0;
464 :
465 1864 : while ((n = sys_read(fd, buf, sizeof(buf))) > 0) {
466 934 : p = talloc_realloc(NULL, p, char, total + n + 1);
467 934 : if (p == NULL) {
468 0 : DBG_ERR("failed to expand buffer!\n");
469 0 : close(fd);
470 0 : return NULL;
471 : }
472 934 : memcpy(p+total, buf, n);
473 934 : total += n;
474 : }
475 :
476 930 : if (p != NULL) {
477 930 : p[total] = 0;
478 : }
479 :
480 : /*
481 : * FIXME: Perhaps ought to check that the command completed
482 : * successfully (returned 0); if not the data may be
483 : * truncated.
484 : */
485 930 : sys_pclose(fd);
486 :
487 930 : if (size) {
488 930 : *size = total;
489 : }
490 :
491 930 : return p;
492 : }
493 :
494 : /*
495 : * fopen a dup'ed fd. Prevent fclose to close the fd passed in.
496 : *
497 : * Don't use on fd's that have fcntl locks, on error it will close the
498 : * dup'ed fd, thus killing your fcntl locks.
499 : */
500 1673 : FILE *fdopen_keepfd(int fd, const char *mode)
501 : {
502 1673 : FILE *f = NULL;
503 38 : int dup_fd;
504 :
505 1673 : dup_fd = dup(fd);
506 1673 : if (dup_fd == -1) {
507 0 : return NULL;
508 : }
509 :
510 1673 : f = fdopen(dup_fd, mode);
511 1673 : if (f == NULL) {
512 0 : int err = errno;
513 0 : close(dup_fd);
514 0 : errno = err;
515 0 : return NULL;
516 : }
517 :
518 1635 : return f;
519 : }
|