s3: tests: Add new test_stream_dir_rename.sh test.
[Samba.git] / lib / util / util_file.c
blobfa5abadedec89cdf0c1bf7c76f1da81e7a62dbb1
1 /*
2 * Unix SMB/CIFS implementation.
3 * SMB parameters and setup
4 * Copyright (C) Andrew Tridgell 1992-1998 Modified by Jeremy Allison 1995.
6 * Added afdgets() Jelmer Vernooij 2005
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.
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.
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/>.
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"
31 /**
32 * Read one line (data until next newline or eof) and allocate it
34 _PUBLIC_ char *afdgets(int fd, TALLOC_CTX *mem_ctx, size_t hint)
36 char *data = NULL;
37 ssize_t alloc_size = 0, offset = 0, ret;
38 int p;
40 if (hint <= 0) hint = 0x100;
42 do {
43 alloc_size += hint;
45 data = talloc_realloc(mem_ctx, data, char, alloc_size);
47 if (!data)
48 return NULL;
50 ret = read(fd, data + offset, hint);
52 if (ret == 0) {
53 return NULL;
56 if (ret == -1) {
57 talloc_free(data);
58 return NULL;
61 /* Find newline */
62 for (p = 0; p < ret; p++) {
63 if (data[offset + p] == '\n')
64 break;
67 if (p < ret) {
68 data[offset + p] = '\0';
70 /* Go back to position of newline */
71 lseek(fd, p - ret + 1, SEEK_CUR);
72 return data;
75 offset += ret;
77 } while ((size_t)ret == hint);
79 data[offset] = '\0';
81 return data;
84 char *fgets_slash(TALLOC_CTX *mem_ctx, char *s2, size_t maxlen, FILE *f)
86 char *s = s2;
87 size_t len = 0;
88 int c;
89 bool start_of_line = true;
91 if (feof(f)) {
92 return NULL;
95 if (maxlen < 2) {
96 return NULL;
99 if (s2 == NULL) {
100 maxlen = MIN(maxlen,8);
101 s = talloc_array(mem_ctx, char, maxlen);
104 if (s == NULL) {
105 return NULL;
108 *s = 0;
110 while (len < maxlen-1) {
111 c = getc(f);
112 switch (c)
114 case '\r':
115 break;
116 case '\n':
117 while (len > 0 && s[len-1] == ' ') {
118 s[--len] = 0;
120 if (len > 0 && s[len-1] == '\\') {
121 s[--len] = 0;
122 start_of_line = true;
123 break;
125 return s;
126 case EOF:
127 if (len <= 0 && (s2 == NULL)) {
128 TALLOC_FREE(s);
130 return (len>0) ? s : NULL;
131 case ' ':
132 if (start_of_line) {
133 break;
136 FALL_THROUGH;
137 default:
138 start_of_line = false;
139 s[len++] = c;
140 s[len] = 0;
142 if ((s2 == NULL) && (len > maxlen-3)) {
143 size_t m;
144 char *t;
146 m = maxlen * 2;
147 if (m < maxlen) {
148 DBG_ERR("length overflow");
149 TALLOC_FREE(s);
150 return NULL;
152 maxlen = m;
154 t = talloc_realloc(mem_ctx, s, char, maxlen);
155 if (t == NULL) {
156 DBG_ERR("failed to expand buffer!\n");
157 TALLOC_FREE(s);
158 return NULL;
161 s = t;
165 return s;
169 load a file into memory from a fd.
171 _PUBLIC_ char *fd_load(int fd, size_t *psize, size_t maxsize, TALLOC_CTX *mem_ctx)
173 FILE *file;
174 char *p = NULL;
175 size_t size = 0;
176 size_t chunk = 1024;
177 int err;
178 int fd_dup;
180 if (maxsize == 0) {
181 maxsize = SIZE_MAX;
184 fd_dup = dup(fd);
185 if (fd_dup == -1) {
186 return NULL;
189 file = fdopen(fd_dup, "r");
190 if (file == NULL) {
191 close(fd_dup);
192 return NULL;
195 while (size < maxsize) {
196 size_t newbufsize;
197 size_t nread;
199 chunk = MIN(chunk, (maxsize - size));
201 newbufsize = size + (chunk+1); /* chunk+1 can't overflow */
202 if (newbufsize < size) {
203 goto fail; /* overflow */
206 p = talloc_realloc(mem_ctx, p, char, newbufsize);
207 if (p == NULL) {
208 goto fail;
211 nread = fread(p+size, 1, chunk, file);
212 size += nread;
214 if (nread != chunk) {
215 break;
219 err = ferror(file);
220 if (err != 0) {
221 goto fail;
224 p[size] = '\0';
226 if (psize != NULL) {
227 *psize = size;
230 fclose(file);
231 return p;
233 fail:
234 TALLOC_FREE(p);
235 fclose(file);
236 return NULL;
240 load a file into memory
242 _PUBLIC_ char *file_load(const char *fname, size_t *size, size_t maxsize, TALLOC_CTX *mem_ctx)
244 int fd;
245 char *p;
247 if (!fname || !*fname) return NULL;
249 fd = open(fname,O_RDONLY);
250 if (fd == -1) return NULL;
252 p = fd_load(fd, size, maxsize, mem_ctx);
254 close(fd);
256 return p;
260 parse a buffer into lines
261 'p' will be freed on error, and otherwise will be made a child of the returned array
263 static char **file_lines_parse_internal(char *p, size_t size, int *numlines, TALLOC_CTX *mem_ctx)
265 unsigned int i;
266 char *s, **ret;
268 if (!p) return NULL;
270 for (s = p, i=0; s < p+size; s++) {
271 if (s[0] == '\n') i++;
274 ret = talloc_zero_array(mem_ctx, char *, i+2);
275 if (!ret) {
276 talloc_free(p);
277 return NULL;
280 talloc_steal(ret, p);
282 ret[0] = p;
283 for (s = p, i=1; s < p+size; s++) {
284 if (s[0] == '\n') {
285 s[0] = 0;
286 ret[i] = s+1;
287 i++;
289 if (s[0] == '\r') s[0] = 0;
292 /* remove any blank lines at the end */
293 while (i > 0 && ret[i-1][0] == 0) {
294 i--;
297 if (numlines) *numlines = i;
299 return ret;
304 load a file into memory and return an array of pointers to lines in the file
305 must be freed with talloc_free().
307 _PUBLIC_ char **file_lines_load(const char *fname, int *numlines, size_t maxsize, TALLOC_CTX *mem_ctx)
309 char *p;
310 size_t size;
312 p = file_load(fname, &size, maxsize, mem_ctx);
313 if (!p) return NULL;
315 return file_lines_parse_internal(p, size, numlines, mem_ctx);
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.
323 _PUBLIC_ char **fd_lines_load(int fd, int *numlines, size_t maxsize, TALLOC_CTX *mem_ctx)
325 char *p;
326 size_t size;
328 p = fd_load(fd, &size, maxsize, mem_ctx);
329 if (!p) return NULL;
331 return file_lines_parse_internal(p, size, numlines, mem_ctx);
334 _PUBLIC_ char **file_lines_parse(const char *p_in,
335 size_t size,
336 int *numlines,
337 TALLOC_CTX *mem_ctx)
340 * Copy the incoming string so it can end up
341 * being owned by the returned pointer and
342 * freed when that is.
344 char *p = talloc_strdup(mem_ctx, p_in);
345 if (p == NULL) {
346 return NULL;
348 return file_lines_parse_internal(p, size, numlines, mem_ctx);
351 _PUBLIC_ bool file_save_mode(const char *fname, const void *packet,
352 size_t length, mode_t mode)
354 ssize_t num_written;
355 int fd;
356 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, mode);
357 if (fd == -1) {
358 return false;
360 num_written = write(fd, packet, length);
361 if (num_written == -1 || (size_t)num_written != length) {
362 close(fd);
363 return false;
365 close(fd);
366 return true;
370 save a lump of data into a file. Mostly used for debugging
372 _PUBLIC_ bool file_save(const char *fname, const void *packet, size_t length)
374 return file_save_mode(fname, packet, length, 0644);
377 _PUBLIC_ int vfdprintf(int fd, const char *format, va_list ap)
379 char *p;
380 int len, ret;
381 va_list ap2;
383 va_copy(ap2, ap);
384 len = vasprintf(&p, format, ap2);
385 va_end(ap2);
386 if (len <= 0) return len;
387 ret = write(fd, p, len);
388 SAFE_FREE(p);
389 return ret;
392 _PUBLIC_ int fdprintf(int fd, const char *format, ...)
394 va_list ap;
395 int ret;
397 va_start(ap, format);
398 ret = vfdprintf(fd, format, ap);
399 va_end(ap);
400 return ret;
405 compare two files, return true if the two files have the same content
407 bool file_compare(const char *path1, const char *path2)
409 FILE *f1 = NULL, *f2 = NULL;
410 uint8_t buf1[1024], buf2[1024];
411 bool ret = false;
413 f1 = fopen(path1, "r");
414 if (f1 == NULL) {
415 goto done;
417 f2 = fopen(path2, "r");
418 if (f2 == NULL) {
419 goto done;
422 while (!feof(f1)) {
423 size_t n1 = fread(buf1, 1, sizeof(buf1), f1);
424 size_t n2 = fread(buf2, 1, sizeof(buf2), f2);
426 if (n1 != n2) {
427 goto done;
429 if (n1 == 0) {
430 ret = (feof(f1) && feof(f2));
431 goto done;
433 if (memcmp(buf1, buf2, n1) != 0) {
434 goto done;
436 if (n1 < sizeof(buf1)) {
437 bool has_error = (ferror(f1) || ferror(f2));
438 if (has_error) {
439 goto done;
443 ret = true;
444 done:
445 if (f2 != NULL) {
446 fclose(f2);
448 if (f1 != NULL) {
449 fclose(f1);
451 return ret;
455 Load from a pipe into memory.
457 char *file_ploadv(char * const argl[], size_t *size)
459 int fd, n;
460 char *p = NULL;
461 char buf[1024];
462 size_t total;
464 fd = sys_popenv(argl);
465 if (fd == -1) {
466 return NULL;
469 total = 0;
471 while ((n = sys_read(fd, buf, sizeof(buf))) > 0) {
472 p = talloc_realloc(NULL, p, char, total + n + 1);
473 if (p == NULL) {
474 DBG_ERR("failed to expand buffer!\n");
475 close(fd);
476 return NULL;
478 memcpy(p+total, buf, n);
479 total += n;
482 if (p != NULL) {
483 p[total] = 0;
487 * FIXME: Perhaps ought to check that the command completed
488 * successfully (returned 0); if not the data may be
489 * truncated.
491 sys_pclose(fd);
493 if (size) {
494 *size = total;
497 return p;