sync with SAMBA_2_2
[Samba/gbeck.git] / source / lib / util_file.c
blob4e2adc97bccfd46ee513d1c4552c8b151080ba87
1 /*
2 * Unix SMB/Netbios implementation. Version 1.9. SMB parameters and setup
3 * Copyright (C) Andrew Tridgell 1992-1998 Modified by Jeremy Allison 1995.
4 *
5 * This program is free software; you can redistribute it and/or modify it under
6 * the terms of the GNU General Public License as published by the Free
7 * Software Foundation; either version 2 of the License, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
15 * You should have received a copy of the GNU General Public License along with
16 * this program; if not, write to the Free Software Foundation, Inc., 675
17 * Mass Ave, Cambridge, MA 02139, USA.
20 #include "includes.h"
22 extern int DEBUGLEVEL;
24 static int gotalarm;
26 /***************************************************************
27 Signal function to tell us we timed out.
28 ****************************************************************/
30 static void gotalarm_sig(void)
32 gotalarm = 1;
35 /***************************************************************
36 Lock or unlock a fd for a known lock type. Abandon after waitsecs
37 seconds.
38 ****************************************************************/
40 BOOL do_file_lock(int fd, int waitsecs, int type)
42 SMB_STRUCT_FLOCK lock;
43 int ret;
45 gotalarm = 0;
46 CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig);
48 lock.l_type = type;
49 lock.l_whence = SEEK_SET;
50 lock.l_start = 0;
51 lock.l_len = 1;
52 lock.l_pid = 0;
54 alarm(waitsecs);
55 ret = fcntl(fd, SMB_F_SETLKW, &lock);
56 alarm(0);
57 CatchSignal(SIGALRM, SIGNAL_CAST SIG_DFL);
59 if (gotalarm) {
60 DEBUG(0, ("do_file_lock: failed to %s file.\n",
61 type == F_UNLCK ? "unlock" : "lock"));
62 return False;
65 return (ret == 0);
69 /***************************************************************
70 Lock an fd. Abandon after waitsecs seconds.
71 ****************************************************************/
73 BOOL file_lock(int fd, int type, int secs, int *plock_depth)
75 if (fd < 0)
76 return False;
78 (*plock_depth)++;
80 if ((*plock_depth) == 0)
82 if (!do_file_lock(fd, secs, type)) {
83 DEBUG(10,("file_lock: locking file failed, error = %s.\n",
84 strerror(errno)));
85 return False;
89 return True;
92 /***************************************************************
93 Unlock an fd. Abandon after waitsecs seconds.
94 ****************************************************************/
96 BOOL file_unlock(int fd, int *plock_depth)
98 BOOL ret=True;
100 if(*plock_depth == 1)
101 ret = do_file_lock(fd, 5, F_UNLCK);
103 (*plock_depth)--;
105 if(!ret)
106 DEBUG(10,("file_unlock: unlocking file failed, error = %s.\n",
107 strerror(errno)));
108 return ret;
111 /***************************************************************
112 locks a file for enumeration / modification.
113 update to be set = True if modification is required.
114 ****************************************************************/
116 void *startfilepwent(char *pfile, char *s_readbuf, int bufsize,
117 int *file_lock_depth, BOOL update)
119 FILE *fp = NULL;
121 if (!*pfile)
123 DEBUG(0, ("startfilepwent: No file set\n"));
124 return (NULL);
126 DEBUG(10, ("startfilepwent: opening file %s\n", pfile));
128 fp = sys_fopen(pfile, update ? "r+b" : "rb");
130 if (fp == NULL) {
131 DEBUG(0, ("startfilepwent: unable to open file %s\n", pfile));
132 return NULL;
135 /* Set a buffer to do more efficient reads */
136 setvbuf(fp, s_readbuf, _IOFBF, bufsize);
138 if (!file_lock(fileno(fp), (update ? F_WRLCK : F_RDLCK), 5, file_lock_depth))
140 DEBUG(0, ("startfilepwent: unable to lock file %s\n", pfile));
141 fclose(fp);
142 return NULL;
145 /* Make sure it is only rw by the owner */
146 chmod(pfile, 0600);
148 /* We have a lock on the file. */
149 return (void *)fp;
152 /***************************************************************
153 End enumeration of the file.
154 ****************************************************************/
155 void endfilepwent(void *vp, int *file_lock_depth)
157 FILE *fp = (FILE *)vp;
159 file_unlock(fileno(fp), file_lock_depth);
160 fclose(fp);
161 DEBUG(7, ("endfilepwent: closed file.\n"));
164 /*************************************************************************
165 Return the current position in the file list as an SMB_BIG_UINT.
166 This must be treated as an opaque token.
167 *************************************************************************/
168 SMB_BIG_UINT getfilepwpos(void *vp)
170 return (SMB_BIG_UINT)sys_ftell((FILE *)vp);
173 /*************************************************************************
174 Set the current position in the file list from an SMB_BIG_UINT.
175 This must be treated as an opaque token.
176 *************************************************************************/
177 BOOL setfilepwpos(void *vp, SMB_BIG_UINT tok)
179 return !sys_fseek((FILE *)vp, (SMB_OFF_T)tok, SEEK_SET);
182 /*************************************************************************
183 gets a line out of a file.
184 line is of format "xxxx:xxxxxx:xxxxx:".
185 lines with "#" at the front are ignored.
186 *************************************************************************/
187 int getfileline(void *vp, char *linebuf, int linebuf_size)
189 /* Static buffers we will return. */
190 FILE *fp = (FILE *)vp;
191 unsigned char c;
192 unsigned char *p;
193 size_t linebuf_len;
195 if (fp == NULL)
197 DEBUG(0,("getfileline: Bad file pointer.\n"));
198 return -1;
202 * Scan the file, a line at a time.
204 while (!feof(fp))
206 linebuf[0] = '\0';
208 fgets(linebuf, linebuf_size, fp);
209 if (ferror(fp))
211 return -1;
215 * Check if the string is terminated with a newline - if not
216 * then we must keep reading and discard until we get one.
219 linebuf_len = strlen(linebuf);
220 if (linebuf_len == 0)
222 linebuf[0] = '\0';
223 return 0;
226 if (linebuf[linebuf_len - 1] != '\n')
228 c = '\0';
229 while (!ferror(fp) && !feof(fp))
231 c = fgetc(fp);
232 if (c == '\n')
234 break;
238 else
240 linebuf[linebuf_len - 1] = '\0';
243 #ifdef DEBUG_PASSWORD
244 DEBUG(100, ("getfileline: got line |%s|\n", linebuf));
245 #endif
246 if ((linebuf[0] == 0) && feof(fp))
248 DEBUG(4, ("getfileline: end of file reached\n"));
249 return 0;
252 if (linebuf[0] == '#' || linebuf[0] == '\0')
254 DEBUG(6, ("getfileline: skipping comment or blank line\n"));
255 continue;
258 p = (unsigned char *) strchr(linebuf, ':');
259 if (p == NULL)
261 DEBUG(0, ("getfileline: malformed line entry (no :)\n"));
262 continue;
264 return linebuf_len;
266 return -1;
270 /****************************************************************************
271 read a line from a file with possible \ continuation chars.
272 Blanks at the start or end of a line are stripped.
273 The string will be allocated if s2 is NULL
274 ****************************************************************************/
275 char *fgets_slash(char *s2,int maxlen,FILE *f)
277 char *s=s2;
278 int len = 0;
279 int c;
280 BOOL start_of_line = True;
282 if (feof(f))
283 return(NULL);
285 if (!s2)
287 maxlen = MIN(maxlen,8);
288 s = (char *)Realloc(s,maxlen);
291 if (!s || maxlen < 2) return(NULL);
293 *s = 0;
295 while (len < maxlen-1)
297 c = getc(f);
298 switch (c)
300 case '\r':
301 break;
302 case '\n':
303 while (len > 0 && s[len-1] == ' ')
305 s[--len] = 0;
307 if (len > 0 && s[len-1] == '\\')
309 s[--len] = 0;
310 start_of_line = True;
311 break;
313 return(s);
314 case EOF:
315 if (len <= 0 && !s2)
316 free(s);
317 return(len>0?s:NULL);
318 case ' ':
319 if (start_of_line)
320 break;
321 default:
322 start_of_line = False;
323 s[len++] = c;
324 s[len] = 0;
326 if (!s2 && len > maxlen-3)
328 maxlen *= 2;
329 s = (char *)Realloc(s,maxlen);
330 if (!s) return(NULL);
333 return(s);
337 /****************************************************************************
338 load from a pipe into memory
339 ****************************************************************************/
340 char *file_pload(char *syscmd, size_t *size)
342 int fd, n;
343 char *p;
344 pstring buf;
345 size_t total;
347 fd = sys_popen(syscmd);
348 if (fd == -1) return NULL;
350 p = NULL;
351 total = 0;
353 while ((n = read(fd, buf, sizeof(buf))) > 0) {
354 p = Realloc(p, total + n + 1);
355 if (!p) {
356 close(fd);
357 return NULL;
359 memcpy(p+total, buf, n);
360 total += n;
362 if (p) p[total] = 0;
364 sys_pclose(fd);
366 if (size) *size = total;
368 return p;
371 /****************************************************************************
372 load a file into memory from a fd.
373 ****************************************************************************/
375 char *fd_load(int fd, size_t *size)
377 SMB_STRUCT_STAT sbuf;
378 char *p;
380 if (sys_fstat(fd, &sbuf) != 0) return NULL;
382 p = (char *)malloc(sbuf.st_size+1);
383 if (!p) return NULL;
385 if (read(fd, p, sbuf.st_size) != sbuf.st_size) {
386 free(p);
387 return NULL;
389 p[sbuf.st_size] = 0;
391 if (size) *size = sbuf.st_size;
393 return p;
396 /****************************************************************************
397 load a file into memory
398 ****************************************************************************/
399 char *file_load(char *fname, size_t *size)
401 int fd;
402 char *p;
404 if (!fname || !*fname) return NULL;
406 fd = open(fname,O_RDONLY);
407 if (fd == -1) return NULL;
409 p = fd_load(fd, size);
411 close(fd);
413 return p;
417 /****************************************************************************
418 parse a buffer into lines
419 ****************************************************************************/
420 static char **file_lines_parse(char *p, size_t size, int *numlines, BOOL convert)
422 int i;
423 char *s, **ret;
425 if (!p) return NULL;
427 for (s = p, i=0; s < p+size; s++) {
428 if (s[0] == '\n') i++;
431 ret = (char **)malloc(sizeof(ret[0])*(i+2));
432 if (!ret) {
433 free(p);
434 return NULL;
436 memset(ret, 0, sizeof(ret[0])*(i+2));
437 if (numlines) *numlines = i;
439 ret[0] = p;
440 for (s = p, i=0; s < p+size; s++) {
441 if (s[0] == '\n') {
442 s[0] = 0;
443 i++;
444 ret[i] = s+1;
446 if (s[0] == '\r') s[0] = 0;
449 if (convert) {
450 for (i = 0; ret[i]; i++)
451 unix_to_dos(ret[i], True);
454 return ret;
458 /****************************************************************************
459 load a file into memory and return an array of pointers to lines in the file
460 must be freed with file_lines_free(). If convert is true calls unix_to_dos on
461 the list.
462 ****************************************************************************/
463 char **file_lines_load(char *fname, int *numlines, BOOL convert)
465 char *p;
466 size_t size;
468 p = file_load(fname, &size);
469 if (!p) return NULL;
471 return file_lines_parse(p, size, numlines, convert);
474 /****************************************************************************
475 load a fd into memory and return an array of pointers to lines in the file
476 must be freed with file_lines_free(). If convert is true calls unix_to_dos on
477 the list.
478 ****************************************************************************/
479 char **fd_lines_load(int fd, int *numlines, BOOL convert)
481 char *p;
482 size_t size;
484 p = fd_load(fd, &size);
485 if (!p) return NULL;
487 return file_lines_parse(p, size, numlines, convert);
491 /****************************************************************************
492 load a pipe into memory and return an array of pointers to lines in the data
493 must be freed with file_lines_free(). If convert is true calls unix_to_dos on
494 the list.
495 ****************************************************************************/
496 char **file_lines_pload(char *syscmd, int *numlines, BOOL convert)
498 char *p;
499 size_t size;
501 p = file_pload(syscmd, &size);
502 if (!p) return NULL;
504 return file_lines_parse(p, size, numlines, convert);
507 /****************************************************************************
508 free lines loaded with file_lines_load
509 ****************************************************************************/
510 void file_lines_free(char **lines)
512 if (!lines) return;
513 free(lines[0]);
514 free(lines);
518 /****************************************************************************
519 take a lislist of lines and modify them to produce a list where \ continues
520 a line
521 ****************************************************************************/
522 void file_lines_slashcont(char **lines)
524 int i, j;
526 for (i=0; lines[i];) {
527 int len = strlen(lines[i]);
528 if (lines[i][len-1] == '\\') {
529 lines[i][len-1] = ' ';
530 if (lines[i+1]) {
531 char *p = &lines[i][len];
532 while (p < lines[i+1]) *p++ = ' ';
533 for (j = i+1; lines[j]; j++) lines[j] = lines[j+1];
535 } else {
536 i++;