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. 14 * 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. 18 */ 19 20#include "includes.h" 21 22extern int DEBUGLEVEL; 23 24static int gotalarm; 25 26/*************************************************************** 27 Signal function to tell us we timed out. 28****************************************************************/ 29 30static void gotalarm_sig(void) 31{ 32 gotalarm = 1; 33} 34 35/*************************************************************** 36 Lock or unlock a fd for a known lock type. Abandon after waitsecs 37 seconds. 38****************************************************************/ 39 40BOOL do_file_lock(int fd, int waitsecs, int type) 41{ 42 SMB_STRUCT_FLOCK lock; 43 int ret; 44 45 gotalarm = 0; 46 CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig); 47 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; 53 54 alarm(waitsecs); 55 ret = fcntl(fd, SMB_F_SETLKW, &lock); 56 alarm(0); 57 CatchSignal(SIGALRM, SIGNAL_CAST SIG_DFL); 58 59 if (gotalarm) { 60 DEBUG(0, ("do_file_lock: failed to %s file.\n", 61 type == F_UNLCK ? "unlock" : "lock")); 62 return False; 63 } 64 65 return (ret == 0); 66} 67 68 69/*************************************************************** 70 Lock an fd. Abandon after waitsecs seconds. 71****************************************************************/ 72 73BOOL file_lock(int fd, int type, int secs, int *plock_depth) 74{ 75 if (fd < 0) 76 return False; 77 78 (*plock_depth)++; 79 80 if ((*plock_depth) == 0) 81 { 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; 86 } 87 } 88 89 return True; 90} 91 92/*************************************************************** 93 Unlock an fd. Abandon after waitsecs seconds. 94****************************************************************/ 95 96BOOL file_unlock(int fd, int *plock_depth) 97{ 98 BOOL ret=True; 99 100 if(*plock_depth == 1) 101 ret = do_file_lock(fd, 5, F_UNLCK); 102 103 (*plock_depth)--; 104 105 if(!ret) 106 DEBUG(10,("file_unlock: unlocking file failed, error = %s.\n", 107 strerror(errno))); 108 return ret; 109} 110 111/*************************************************************** 112 locks a file for enumeration / modification. 113 update to be set = True if modification is required. 114****************************************************************/ 115 116void *startfilepwent(char *pfile, char *s_readbuf, int bufsize, 117 int *file_lock_depth, BOOL update) 118{ 119 FILE *fp = NULL; 120 121 if (!*pfile) 122 { 123 DEBUG(0, ("startfilepwent: No file set\n")); 124 return (NULL); 125 } 126 DEBUG(10, ("startfilepwent: opening file %s\n", pfile)); 127 128 fp = sys_fopen(pfile, update ? "r+b" : "rb"); 129 130 if (fp == NULL) { 131 DEBUG(0, ("startfilepwent: unable to open file %s\n", pfile)); 132 return NULL; 133 } 134 135 /* Set a buffer to do more efficient reads */ 136 setvbuf(fp, s_readbuf, _IOFBF, bufsize); 137 138 if (!file_lock(fileno(fp), (update ? F_WRLCK : F_RDLCK), 5, file_lock_depth)) 139 { 140 DEBUG(0, ("startfilepwent: unable to lock file %s\n", pfile)); 141 fclose(fp); 142 return NULL; 143 } 144 145 /* Make sure it is only rw by the owner */ 146 chmod(pfile, 0600); 147 148 /* We have a lock on the file. */ 149 return (void *)fp; 150} 151 152/*************************************************************** 153 End enumeration of the file. 154****************************************************************/ 155void endfilepwent(void *vp, int *file_lock_depth) 156{ 157 FILE *fp = (FILE *)vp; 158 159 file_unlock(fileno(fp), file_lock_depth); 160 fclose(fp); 161 DEBUG(7, ("endfilepwent: closed file.\n")); 162} 163 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*************************************************************************/ 168SMB_BIG_UINT getfilepwpos(void *vp) 169{ 170 return (SMB_BIG_UINT)sys_ftell((FILE *)vp); 171} 172 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*************************************************************************/ 177BOOL setfilepwpos(void *vp, SMB_BIG_UINT tok) 178{ 179 return !sys_fseek((FILE *)vp, (SMB_OFF_T)tok, SEEK_SET); 180} 181 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*************************************************************************/ 187int getfileline(void *vp, char *linebuf, int linebuf_size) 188{ 189 /* Static buffers we will return. */ 190 FILE *fp = (FILE *)vp; 191 unsigned char c; 192 unsigned char *p; 193 size_t linebuf_len; 194 195 if (fp == NULL) 196 { 197 DEBUG(0,("getfileline: Bad file pointer.\n")); 198 return -1; 199 } 200 201 /* 202 * Scan the file, a line at a time. 203 */ 204 while (!feof(fp)) 205 { 206 linebuf[0] = '\0'; 207 208 fgets(linebuf, linebuf_size, fp); 209 if (ferror(fp)) 210 { 211 return -1; 212 } 213 214 /* 215 * Check if the string is terminated with a newline - if not 216 * then we must keep reading and discard until we get one. 217 */ 218 219 linebuf_len = strlen(linebuf); 220 if (linebuf[linebuf_len - 1] != '\n') 221 { 222 c = '\0'; 223 while (!ferror(fp) && !feof(fp)) 224 { 225 c = fgetc(fp); 226 if (c == '\n') 227 { 228 break; 229 } 230 } 231 } 232 else 233 { 234 linebuf[linebuf_len - 1] = '\0'; 235 } 236 237#ifdef DEBUG_PASSWORD 238 DEBUG(100, ("getfileline: got line |%s|\n", linebuf)); 239#endif 240 if ((linebuf[0] == 0) && feof(fp)) 241 { 242 DEBUG(4, ("getfileline: end of file reached\n")); 243 return 0; 244 } 245 246 if (linebuf[0] == '#' || linebuf[0] == '\0') 247 { 248 DEBUG(6, ("getfileline: skipping comment or blank line\n")); 249 continue; 250 } 251 252 p = (unsigned char *) strchr(linebuf, ':'); 253 if (p == NULL) 254 { 255 DEBUG(0, ("getfileline: malformed line entry (no :)\n")); 256 continue; 257 } 258 return linebuf_len; 259 } 260 return -1; 261} 262 263 264/**************************************************************************** 265read a line from a file with possible \ continuation chars. 266Blanks at the start or end of a line are stripped. 267The string will be allocated if s2 is NULL 268****************************************************************************/ 269char *fgets_slash(char *s2,int maxlen,FILE *f) 270{ 271 char *s=s2; 272 int len = 0; 273 int c; 274 BOOL start_of_line = True; 275 276 if (feof(f)) 277 return(NULL); 278 279 if (!s2) 280 { 281 maxlen = MIN(maxlen,8); 282 s = (char *)Realloc(s,maxlen); 283 } 284 285 if (!s || maxlen < 2) return(NULL); 286 287 *s = 0; 288 289 while (len < maxlen-1) 290 { 291 c = getc(f); 292 switch (c) 293 { 294 case '\r': 295 break; 296 case '\n': 297 while (len > 0 && s[len-1] == ' ') 298 { 299 s[--len] = 0; 300 } 301 if (len > 0 && s[len-1] == '\\') 302 { 303 s[--len] = 0; 304 start_of_line = True; 305 break; 306 } 307 return(s); 308 case EOF: 309 if (len <= 0 && !s2) 310 free(s); 311 return(len>0?s:NULL); 312 case ' ': 313 if (start_of_line) 314 break; 315 default: 316 start_of_line = False; 317 s[len++] = c; 318 s[len] = 0; 319 } 320 if (!s2 && len > maxlen-3) 321 { 322 maxlen *= 2; 323 s = (char *)Realloc(s,maxlen); 324 if (!s) return(NULL); 325 } 326 } 327 return(s); 328} 329 330