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"
25 #if _SAMBA_BUILD_ == 3
32 * @brief File-related utility functions
36 read a line from a file with possible \ continuation chars.
37 Blanks at the start or end of a line are stripped.
38 The string will be allocated if s2 is NULL
40 _PUBLIC_
char *fgets_slash(char *s2
,int maxlen
,XFILE
*f
)
45 bool start_of_line
= true;
50 if (maxlen
<2) return(NULL
);
54 maxlen
= MIN(maxlen
,8);
55 s
= (char *)malloc(maxlen
);
62 while (len
< maxlen
-1)
70 while (len
> 0 && s
[len
-1] == ' ')
74 if (len
> 0 && s
[len
-1] == '\\')
90 start_of_line
= false;
94 if (!s2
&& len
> maxlen
-3)
99 t
= realloc_p(s
, char, maxlen
);
101 DEBUG(0,("fgets_slash: failed to expand buffer!\n"));
111 * Read one line (data until next newline or eof) and allocate it
113 _PUBLIC_
char *afdgets(int fd
, TALLOC_CTX
*mem_ctx
, size_t hint
)
116 ssize_t alloc_size
= 0, offset
= 0, ret
;
119 if (hint
<= 0) hint
= 0x100;
124 data
= talloc_realloc(mem_ctx
, data
, char, alloc_size
);
129 ret
= read(fd
, data
+ offset
, hint
);
141 for (p
= 0; p
< ret
; p
++) {
142 if (data
[offset
+ p
] == '\n')
147 data
[offset
+ p
] = '\0';
149 /* Go back to position of newline */
150 lseek(fd
, p
- ret
+ 1, SEEK_CUR
);
156 } while (ret
== hint
);
165 load a file into memory from a fd.
167 _PUBLIC_
char *fd_load(int fd
, size_t *psize
, size_t maxsize
, TALLOC_CTX
*mem_ctx
)
173 if (fstat(fd
, &sbuf
) != 0) return NULL
;
178 size
= MIN(size
, maxsize
);
181 p
= (char *)talloc_size(mem_ctx
, size
+1);
184 if (read(fd
, p
, size
) != size
) {
190 if (psize
) *psize
= size
;
196 load a file into memory
198 _PUBLIC_
char *file_load(const char *fname
, size_t *size
, size_t maxsize
, TALLOC_CTX
*mem_ctx
)
203 if (!fname
|| !*fname
) return NULL
;
205 fd
= open(fname
,O_RDONLY
);
206 if (fd
== -1) return NULL
;
208 p
= fd_load(fd
, size
, maxsize
, mem_ctx
);
217 mmap (if possible) or read a file
219 _PUBLIC_
void *map_file(const char *fname
, size_t size
)
225 fd
= open(fname
, O_RDONLY
, 0);
227 DEBUG(2,("Failed to load %s - %s\n", fname
, strerror(errno
)));
230 p
= mmap(NULL
, size
, PROT_READ
, MAP_SHARED
|MAP_FILE
, fd
, 0);
232 if (p
== MAP_FAILED
) {
233 DEBUG(1,("Failed to mmap %s - %s\n", fname
, strerror(errno
)));
238 p
= file_load(fname
, &s2
, 0, talloc_autofree_context());
241 DEBUG(1,("incorrect size for %s - got %d expected %d\n",
242 fname
, (int)s2
, (int)size
));
255 bool unmap_file(void *start
, size_t size
)
258 if (munmap( start
, size
) != 0) {
259 DEBUG( 1, ("map_file: Failed to unmap address %p "
261 start
, (unsigned int)size
, strerror(errno
) ));
272 parse a buffer into lines
273 'p' will be freed on error, and otherwise will be made a child of the returned array
275 char **file_lines_parse(char *p
, size_t size
, int *numlines
, TALLOC_CTX
*mem_ctx
)
282 for (s
= p
, i
=0; s
< p
+size
; s
++) {
283 if (s
[0] == '\n') i
++;
286 ret
= talloc_array(mem_ctx
, char *, i
+2);
292 talloc_steal(ret
, p
);
294 memset(ret
, 0, sizeof(ret
[0])*(i
+2));
297 for (s
= p
, i
=0; s
< p
+size
; s
++) {
303 if (s
[0] == '\r') s
[0] = 0;
306 /* remove any blank lines at the end */
307 while (i
> 0 && ret
[i
-1][0] == 0) {
311 if (numlines
) *numlines
= i
;
318 load a file into memory and return an array of pointers to lines in the file
319 must be freed with talloc_free().
321 _PUBLIC_
char **file_lines_load(const char *fname
, int *numlines
, size_t maxsize
, TALLOC_CTX
*mem_ctx
)
326 p
= file_load(fname
, &size
, maxsize
, mem_ctx
);
329 return file_lines_parse(p
, size
, numlines
, mem_ctx
);
333 load a fd into memory and return an array of pointers to lines in the file
334 must be freed with talloc_free(). If convert is true calls unix_to_dos on
337 _PUBLIC_
char **fd_lines_load(int fd
, int *numlines
, size_t maxsize
, TALLOC_CTX
*mem_ctx
)
342 p
= fd_load(fd
, &size
, maxsize
, mem_ctx
);
345 return file_lines_parse(p
, size
, numlines
, mem_ctx
);
350 take a list of lines and modify them to produce a list where \ continues
353 _PUBLIC_
void file_lines_slashcont(char **lines
)
357 for (i
=0; lines
[i
];) {
358 int len
= strlen(lines
[i
]);
359 if (lines
[i
][len
-1] == '\\') {
360 lines
[i
][len
-1] = ' ';
362 char *p
= &lines
[i
][len
];
363 while (p
< lines
[i
+1]) *p
++ = ' ';
364 for (j
= i
+1; lines
[j
]; j
++) lines
[j
] = lines
[j
+1];
373 save a lump of data into a file. Mostly used for debugging
375 _PUBLIC_
bool file_save(const char *fname
, const void *packet
, size_t length
)
378 fd
= open(fname
, O_WRONLY
|O_CREAT
|O_TRUNC
, 0644);
382 if (write(fd
, packet
, length
) != (size_t)length
) {
390 _PUBLIC_
int vfdprintf(int fd
, const char *format
, va_list ap
)
397 len
= vasprintf(&p
, format
, ap2
);
399 if (len
<= 0) return len
;
400 ret
= write(fd
, p
, len
);
405 _PUBLIC_
int fdprintf(int fd
, const char *format
, ...)
410 va_start(ap
, format
);
411 ret
= vfdprintf(fd
, format
, ap
);
418 try to determine if the filesystem supports large files
420 _PUBLIC_
bool large_file_support(const char *path
)
426 fd
= open(path
, O_RDWR
|O_CREAT
, 0600);
429 /* have to assume large files are OK */
432 ret
= pread(fd
, &c
, 1, ((uint64_t)1)<<32);
439 compare two files, return true if the two files have the same content
441 bool file_compare(const char *path1
, const char *path2
)
445 TALLOC_CTX
*mem_ctx
= talloc_new(NULL
);
447 p1
= file_load(path1
, &size1
, 0, mem_ctx
);
448 p2
= file_load(path2
, &size2
, 0, mem_ctx
);
449 if (!p1
|| !p2
|| size1
!= size2
) {
450 talloc_free(mem_ctx
);
453 if (memcmp(p1
, p2
, size1
) != 0) {
454 talloc_free(mem_ctx
);
457 talloc_free(mem_ctx
);