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)
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
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/>.
23 #include "system/shmem.h"
24 #include "system/filesys.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"
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
)
37 ssize_t alloc_size
= 0, offset
= 0, ret
;
40 if (hint
<= 0) hint
= 0x100;
45 data
= talloc_realloc(mem_ctx
, data
, char, alloc_size
);
50 ret
= read(fd
, data
+ offset
, hint
);
62 for (p
= 0; p
< ret
; p
++) {
63 if (data
[offset
+ p
] == '\n')
68 data
[offset
+ p
] = '\0';
70 /* Go back to position of newline */
71 lseek(fd
, p
- ret
+ 1, SEEK_CUR
);
77 } while ((size_t)ret
== hint
);
84 char *fgets_slash(TALLOC_CTX
*mem_ctx
, char *s2
, size_t maxlen
, FILE *f
)
89 bool start_of_line
= true;
100 maxlen
= MIN(maxlen
,8);
101 s
= talloc_array(mem_ctx
, char, maxlen
);
110 while (len
< maxlen
-1) {
117 while (len
> 0 && s
[len
-1] == ' ') {
120 if (len
> 0 && s
[len
-1] == '\\') {
122 start_of_line
= true;
127 if (len
<= 0 && (s2
== NULL
)) {
130 return (len
>0) ? s
: NULL
;
138 start_of_line
= false;
142 if ((s2
== NULL
) && (len
> maxlen
-3)) {
148 DBG_ERR("length overflow");
154 t
= talloc_realloc(mem_ctx
, s
, char, maxlen
);
156 DBG_ERR("failed to expand buffer!\n");
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
)
183 file
= fdopen(fd
, "r");
188 while (size
< maxsize
) {
192 chunk
= MIN(chunk
, (maxsize
- size
));
194 newbufsize
= size
+ (chunk
+1); /* chunk+1 can't overflow */
195 if (newbufsize
< size
) {
196 goto fail
; /* overflow */
199 p
= talloc_realloc(mem_ctx
, p
, char, newbufsize
);
204 nread
= fread(p
+size
, 1, chunk
, file
);
207 if (nread
!= chunk
) {
233 load a file into memory
235 _PUBLIC_
char *file_load(const char *fname
, size_t *size
, size_t maxsize
, TALLOC_CTX
*mem_ctx
)
240 if (!fname
|| !*fname
) return NULL
;
242 fd
= open(fname
,O_RDONLY
);
243 if (fd
== -1) return NULL
;
245 p
= fd_load(fd
, size
, maxsize
, mem_ctx
);
253 parse a buffer into lines
254 'p' will be freed on error, and otherwise will be made a child of the returned array
256 static char **file_lines_parse_internal(char *p
, size_t size
, int *numlines
, TALLOC_CTX
*mem_ctx
)
263 for (s
= p
, i
=0; s
< p
+size
; s
++) {
264 if (s
[0] == '\n') i
++;
267 ret
= talloc_zero_array(mem_ctx
, char *, i
+2);
273 talloc_steal(ret
, p
);
276 for (s
= p
, i
=1; s
< p
+size
; s
++) {
282 if (s
[0] == '\r') s
[0] = 0;
285 /* remove any blank lines at the end */
286 while (i
> 0 && ret
[i
-1][0] == 0) {
290 if (numlines
) *numlines
= i
;
297 load a file into memory and return an array of pointers to lines in the file
298 must be freed with talloc_free().
300 _PUBLIC_
char **file_lines_load(const char *fname
, int *numlines
, size_t maxsize
, TALLOC_CTX
*mem_ctx
)
305 p
= file_load(fname
, &size
, maxsize
, mem_ctx
);
308 return file_lines_parse_internal(p
, size
, numlines
, mem_ctx
);
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
316 _PUBLIC_
char **fd_lines_load(int fd
, int *numlines
, size_t maxsize
, TALLOC_CTX
*mem_ctx
)
321 p
= fd_load(fd
, &size
, maxsize
, mem_ctx
);
324 return file_lines_parse_internal(p
, size
, numlines
, mem_ctx
);
327 _PUBLIC_
char **file_lines_parse(const char *p_in
,
333 * Copy the incoming string so it can end up
334 * being owned by the returned pointer and
335 * freed when that is.
337 char *p
= talloc_strdup(mem_ctx
, p_in
);
341 return file_lines_parse_internal(p
, size
, numlines
, mem_ctx
);
344 _PUBLIC_
bool file_save_mode(const char *fname
, const void *packet
,
345 size_t length
, mode_t mode
)
349 fd
= open(fname
, O_WRONLY
|O_CREAT
|O_EXCL
, mode
);
353 num_written
= write(fd
, packet
, length
);
354 if (num_written
== -1 || (size_t)num_written
!= length
) {
363 save a lump of data into a file. Mostly used for debugging
365 _PUBLIC_
bool file_save(const char *fname
, const void *packet
, size_t length
)
367 return file_save_mode(fname
, packet
, length
, 0644);
370 _PUBLIC_
int vfdprintf(int fd
, const char *format
, va_list ap
)
377 len
= vasprintf(&p
, format
, ap2
);
379 if (len
<= 0) return len
;
380 ret
= write(fd
, p
, len
);
385 _PUBLIC_
int fdprintf(int fd
, const char *format
, ...)
390 va_start(ap
, format
);
391 ret
= vfdprintf(fd
, format
, ap
);
398 compare two files, return true if the two files have the same content
400 bool file_compare(const char *path1
, const char *path2
)
402 FILE *f1
= NULL
, *f2
= NULL
;
403 uint8_t buf1
[1024], buf2
[1024];
406 f1
= fopen(path1
, "r");
410 f2
= fopen(path2
, "r");
416 size_t n1
= fread(buf1
, 1, sizeof(buf1
), f1
);
417 size_t n2
= fread(buf2
, 1, sizeof(buf2
), f2
);
423 ret
= (feof(f1
) && feof(f2
));
426 if (memcmp(buf1
, buf2
, n1
) != 0) {
429 if (n1
< sizeof(buf1
)) {
430 bool has_error
= (ferror(f1
) || ferror(f2
));
448 Load from a pipe into memory.
450 char *file_ploadv(char * const argl
[], size_t *size
)
457 fd
= sys_popenv(argl
);
464 while ((n
= sys_read(fd
, buf
, sizeof(buf
))) > 0) {
465 p
= talloc_realloc(NULL
, p
, char, total
+ n
+ 1);
467 DBG_ERR("failed to expand buffer!\n");
471 memcpy(p
+total
, buf
, n
);
480 * FIXME: Perhaps ought to check that the command completed
481 * successfully (returned 0); if not the data may be