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