2 * Unix SMB/Netbios implementation. Version 1.9. SMB parameters and setup
3 * Copyright (C) Andrew Tridgell 1992-1998 Modified by Jeremy Allison 1995.
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)
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
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.
24 /***************************************************************
25 Signal function to tell us we timed out.
26 ****************************************************************/
28 static void gotalarm_sig(void)
33 /***************************************************************
34 Lock or unlock a fd for a known lock type. Abandon after waitsecs
36 ****************************************************************/
38 BOOL do_file_lock(int fd, int waitsecs, int type)
40 SMB_STRUCT_FLOCK lock;
44 CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig);
47 lock.l_whence = SEEK_SET;
53 ret = fcntl(fd, SMB_F_SETLKW, &lock);
55 CatchSignal(SIGALRM, SIGNAL_CAST SIG_DFL);
58 DEBUG(0, ("do_file_lock: failed to %s file.\n",
59 type == F_UNLCK ? "unlock" : "lock"));
67 /***************************************************************
68 Lock an fd. Abandon after waitsecs seconds.
69 ****************************************************************/
71 BOOL file_lock(int fd, int type, int secs, int *plock_depth)
78 if ((*plock_depth) == 0)
80 if (!do_file_lock(fd, secs, type)) {
81 DEBUG(10,("file_lock: locking file failed, error = %s.\n",
90 /***************************************************************
91 Unlock an fd. Abandon after waitsecs seconds.
92 ****************************************************************/
94 BOOL file_unlock(int fd, int *plock_depth)
99 ret = do_file_lock(fd, 5, F_UNLCK);
104 DEBUG(10,("file_unlock: unlocking file failed, error = %s.\n",
109 /***************************************************************
110 locks a file for enumeration / modification.
111 update to be set = True if modification is required.
112 ****************************************************************/
114 void *startfilepwent(char *pfile, char *s_readbuf, int bufsize,
115 int *file_lock_depth, BOOL update)
121 DEBUG(0, ("startfilepwent: No file set\n"));
124 DEBUG(10, ("startfilepwent: opening file %s\n", pfile));
126 fp = sys_fopen(pfile, update ? "r+b" : "rb");
129 DEBUG(0, ("startfilepwent: unable to open file %s\n", pfile));
133 /* Set a buffer to do more efficient reads */
134 setvbuf(fp, s_readbuf, _IOFBF, bufsize);
136 if (!file_lock(fileno(fp), (update ? F_WRLCK : F_RDLCK), 5, file_lock_depth))
138 DEBUG(0, ("startfilepwent: unable to lock file %s\n", pfile));
143 /* Make sure it is only rw by the owner */
146 /* We have a lock on the file. */
150 /***************************************************************
151 End enumeration of the file.
152 ****************************************************************/
153 void endfilepwent(void *vp, int *file_lock_depth)
155 FILE *fp = (FILE *)vp;
157 file_unlock(fileno(fp), file_lock_depth);
159 DEBUG(7, ("endfilepwent: closed file.\n"));
162 /*************************************************************************
163 Return the current position in the file list as an SMB_BIG_UINT.
164 This must be treated as an opaque token.
165 *************************************************************************/
166 SMB_BIG_UINT getfilepwpos(void *vp)
168 return (SMB_BIG_UINT)sys_ftell((FILE *)vp);
171 /*************************************************************************
172 Set the current position in the file list from an SMB_BIG_UINT.
173 This must be treated as an opaque token.
174 *************************************************************************/
175 BOOL setfilepwpos(void *vp, SMB_BIG_UINT tok)
177 return !sys_fseek((FILE *)vp, (SMB_OFF_T)tok, SEEK_SET);
180 /*************************************************************************
181 gets a line out of a file.
182 line is of format "xxxx:xxxxxx:xxxxx:".
183 lines with "#" at the front are ignored.
184 *************************************************************************/
185 int getfileline(void *vp, char *linebuf, int linebuf_size)
187 /* Static buffers we will return. */
188 FILE *fp = (FILE *)vp;
195 DEBUG(0,("getfileline: Bad file pointer.\n"));
200 * Scan the file, a line at a time.
206 fgets(linebuf, linebuf_size, fp);
213 * Check if the string is terminated with a newline - if not
214 * then we must keep reading and discard until we get one.
217 linebuf_len = strlen(linebuf);
218 if (linebuf_len == 0)
224 if (linebuf[linebuf_len - 1] != '\n')
227 while (!ferror(fp) && !feof(fp))
238 linebuf[linebuf_len - 1] = '\0';
241 #ifdef DEBUG_PASSWORD
242 DEBUG(100, ("getfileline: got line |%s|\n", linebuf));
244 if ((linebuf[0] == 0) && feof(fp))
246 DEBUG(4, ("getfileline: end of file reached\n"));
250 if (linebuf[0] == '#' || linebuf[0] == '\0')
252 DEBUG(6, ("getfileline: skipping comment or blank line\n"));
256 p = (unsigned char *) strchr_m(linebuf, ':');
259 DEBUG(0, ("getfileline: malformed line entry (no :)\n"));
268 /****************************************************************************
269 read a line from a file with possible \ continuation chars.
270 Blanks at the start or end of a line are stripped.
271 The string will be allocated if s2 is NULL
272 ****************************************************************************/
273 char *fgets_slash(char *s2,int maxlen,XFILE *f)
278 BOOL start_of_line = True;
283 if (maxlen <2) return(NULL);
287 maxlen = MIN(maxlen,8);
288 s = (char *)malloc(maxlen);
291 if (!s) return(NULL);
295 while (len < maxlen-1)
303 while (len > 0 && s[len-1] == ' ')
307 if (len > 0 && s[len-1] == '\\')
310 start_of_line = True;
317 return(len>0?s:NULL);
322 start_of_line = False;
326 if (!s2 && len > maxlen-3)
331 t = (char *)Realloc(s,maxlen);
333 DEBUG(0,("fgets_slash: failed to expand buffer!\n"));
343 /****************************************************************************
344 load from a pipe into memory
345 ****************************************************************************/
346 char *file_pload(char *syscmd, size_t *size)
353 fd = sys_popen(syscmd);
354 if (fd == -1) return NULL;
359 while ((n = read(fd, buf, sizeof(buf))) > 0) {
360 tp = Realloc(p, total + n + 1);
362 DEBUG(0,("file_pload: failed to exand buffer!\n"));
367 memcpy(p+total, buf, n);
374 if (size) *size = total;
379 /****************************************************************************
380 load a file into memory from a fd.
381 ****************************************************************************/
383 char *fd_load(int fd, size_t *size)
385 SMB_STRUCT_STAT sbuf;
388 if (sys_fstat(fd, &sbuf) != 0) return NULL;
390 p = (char *)malloc(sbuf.st_size+1);
393 if (read(fd, p, sbuf.st_size) != sbuf.st_size) {
399 if (size) *size = sbuf.st_size;
404 /****************************************************************************
405 load a file into memory
406 ****************************************************************************/
407 char *file_load(const char *fname, size_t *size)
412 if (!fname || !*fname) return NULL;
414 fd = open(fname,O_RDONLY);
415 if (fd == -1) return NULL;
417 p = fd_load(fd, size);
425 /*******************************************************************
426 mmap (if possible) or read a file
427 ********************************************************************/
428 void *map_file(char *fname, size_t size)
434 fd = open(fname, O_RDONLY, 0);
436 DEBUG(1,("Failed to load %s - %s\n", fname, strerror(errno)));
439 p = mmap(NULL, size, PROT_READ, MAP_SHARED|MAP_FILE, fd, 0);
441 if (p == MAP_FAILED) {
442 DEBUG(1,("Failed to mmap %s - %s\n", fname, strerror(errno)));
447 p = file_load(fname, &s2);
448 if (!p || s2 != size) {
449 DEBUG(1,("incorrect size for %s - got %d expected %d\n",
460 /****************************************************************************
461 parse a buffer into lines
462 ****************************************************************************/
463 static char **file_lines_parse(char *p, size_t size, int *numlines)
470 for (s = p, i=0; s < p+size; s++) {
471 if (s[0] == '\n') i++;
474 ret = (char **)malloc(sizeof(ret[0])*(i+2));
479 memset(ret, 0, sizeof(ret[0])*(i+2));
480 if (numlines) *numlines = i;
483 for (s = p, i=0; s < p+size; s++) {
489 if (s[0] == '\r') s[0] = 0;
496 /****************************************************************************
497 load a file into memory and return an array of pointers to lines in the file
498 must be freed with file_lines_free().
499 ****************************************************************************/
500 char **file_lines_load(const char *fname, int *numlines)
505 p = file_load(fname, &size);
508 return file_lines_parse(p, size, numlines);
511 /****************************************************************************
512 load a fd into memory and return an array of pointers to lines in the file
513 must be freed with file_lines_free(). If convert is true calls unix_to_dos on
515 ****************************************************************************/
516 char **fd_lines_load(int fd, int *numlines)
521 p = fd_load(fd, &size);
524 return file_lines_parse(p, size, numlines);
528 /****************************************************************************
529 load a pipe into memory and return an array of pointers to lines in the data
530 must be freed with file_lines_free().
531 ****************************************************************************/
532 char **file_lines_pload(char *syscmd, int *numlines)
537 p = file_pload(syscmd, &size);
540 return file_lines_parse(p, size, numlines);
543 /****************************************************************************
544 free lines loaded with file_lines_load
545 ****************************************************************************/
546 void file_lines_free(char **lines)
554 /****************************************************************************
555 take a lislist of lines and modify them to produce a list where \ continues
557 ****************************************************************************/
558 void file_lines_slashcont(char **lines)
562 for (i=0; lines[i];) {
563 int len = strlen(lines[i]);
564 if (lines[i][len-1] == '\\') {
565 lines[i][len-1] = ' ';
567 char *p = &lines[i][len];
568 while (p < lines[i+1]) *p++ = ' ';
569 for (j = i+1; lines[j]; j++) lines[j] = lines[j+1];
578 save a lump of data into a file. Mostly used for debugging
580 BOOL file_save(const char *fname, void *packet, size_t length)
583 fd = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0644);
587 if (write(fd, packet, length) != length) {