1/* 2 * Unix SMB/CIFS implementation. 3 * SMB parameters and setup 4 * Copyright (C) Andrew Tridgell 1992-1998 Modified by Jeremy Allison 1995. 5 * 6 * This program is free software; you can redistribute it and/or modify it under 7 * the terms of the GNU General Public License as published by the Free 8 * Software Foundation; either version 2 of the License, or (at your option) 9 * any later version. 10 * 11 * This program is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 14 * more details. 15 * 16 * You should have received a copy of the GNU General Public License along with 17 * this program; if not, write to the Free Software Foundation, Inc., 675 18 * Mass Ave, Cambridge, MA 02139, USA. 19 */ 20 21#include "includes.h" 22 23#ifndef MAP_FAILED 24#define MAP_FAILED ((void *)-1) 25#endif 26 27/**************************************************************************** 28 Read a line from a file with possible \ continuation chars. 29 Blanks at the start or end of a line are stripped. 30 The string will be allocated if s2 is NULL. 31****************************************************************************/ 32 33char *fgets_slash(char *s2,int maxlen,XFILE *f) 34{ 35 char *s=s2; 36 int len = 0; 37 int c; 38 BOOL start_of_line = True; 39 40 if (x_feof(f)) { 41 return(NULL); 42 } 43 44 if (maxlen <2) { 45 return(NULL); 46 } 47 48 if (!s2) { 49 maxlen = MIN(maxlen,8); 50 s = (char *)SMB_MALLOC(maxlen); 51 } 52 53 if (!s) { 54 return(NULL); 55 } 56 57 *s = 0; 58 59 while (len < maxlen-1) { 60 c = x_getc(f); 61 switch (c) { 62 case '\r': 63 break; 64 case '\n': 65 while (len > 0 && s[len-1] == ' ') { 66 s[--len] = 0; 67 } 68 if (len > 0 && s[len-1] == '\\') { 69 s[--len] = 0; 70 start_of_line = True; 71 break; 72 } 73 return(s); 74 case EOF: 75 if (len <= 0 && !s2) { 76 SAFE_FREE(s); 77 } 78 return(len>0?s:NULL); 79 case ' ': 80 if (start_of_line) { 81 break; 82 } 83 default: 84 start_of_line = False; 85 s[len++] = c; 86 s[len] = 0; 87 } 88 89 if (!s2 && len > maxlen-3) { 90 maxlen *= 2; 91 s = (char *)SMB_REALLOC(s,maxlen); 92 if (!s) { 93 DEBUG(0,("fgets_slash: failed to expand buffer!\n")); 94 return(NULL); 95 } 96 } 97 } 98 return(s); 99} 100 101/**************************************************************************** 102 Load from a pipe into memory. 103****************************************************************************/ 104 105char *file_pload(char *syscmd, size_t *size) 106{ 107 int fd, n; 108 char *p; 109 pstring buf; 110 size_t total; 111 112 fd = sys_popen(syscmd); 113 if (fd == -1) { 114 return NULL; 115 } 116 117 p = NULL; 118 total = 0; 119 120 while ((n = read(fd, buf, sizeof(buf))) > 0) { 121 p = (char *)SMB_REALLOC(p, total + n + 1); 122 if (!p) { 123 DEBUG(0,("file_pload: failed to expand buffer!\n")); 124 close(fd); 125 return NULL; 126 } 127 memcpy(p+total, buf, n); 128 total += n; 129 } 130 131 if (p) { 132 p[total] = 0; 133 } 134 135 /* FIXME: Perhaps ought to check that the command completed 136 * successfully (returned 0); if not the data may be 137 * truncated. */ 138 sys_pclose(fd); 139 140 if (size) { 141 *size = total; 142 } 143 144 return p; 145} 146 147/**************************************************************************** 148 Load a file into memory from a fd. 149 Truncate at maxsize. If maxsize == 0 - no limit. 150****************************************************************************/ 151 152char *fd_load(int fd, size_t *psize, size_t maxsize) 153{ 154 SMB_STRUCT_STAT sbuf; 155 size_t size; 156 char *p; 157 158 if (sys_fstat(fd, &sbuf) != 0) { 159 return NULL; 160 } 161 162 size = sbuf.st_size; 163 if (maxsize) { 164 size = MIN(size, maxsize); 165 } 166 167 p = (char *)SMB_MALLOC(size+1); 168 if (!p) { 169 return NULL; 170 } 171 172 if (read(fd, p, size) != size) { 173 SAFE_FREE(p); 174 return NULL; 175 } 176 p[size] = 0; 177 178 if (psize) { 179 *psize = size; 180 } 181 182 return p; 183} 184 185/**************************************************************************** 186 Load a file into memory. 187****************************************************************************/ 188 189char *file_load(const char *fname, size_t *size, size_t maxsize) 190{ 191 int fd; 192 char *p; 193 194 if (!fname || !*fname) { 195 return NULL; 196 } 197 198 fd = open(fname,O_RDONLY); 199 if (fd == -1) { 200 return NULL; 201 } 202 203 p = fd_load(fd, size, maxsize); 204 close(fd); 205 return p; 206} 207 208/******************************************************************* 209 unmap or free memory 210*******************************************************************/ 211 212BOOL unmap_file(void* start, size_t size) 213{ 214#ifdef HAVE_MMAP 215 if ( munmap( start, size ) != 0 ) { 216 DEBUG( 1, ("map_file: Failed to unmap address %p " 217 "of size %u - %s\n", 218 start, (unsigned int)size, strerror(errno) )); 219 return False; 220 } 221 return True; 222#else 223 SAFE_FREE( start ); 224 return True; 225#endif 226} 227 228/******************************************************************* 229 mmap (if possible) or read a file. 230********************************************************************/ 231 232void *map_file(char *fname, size_t size) 233{ 234 size_t s2 = 0; 235 void *p = NULL; 236#ifdef HAVE_MMAP 237 int fd; 238 fd = open(fname, O_RDONLY, 0); 239 if (fd == -1) { 240 DEBUG(2,("map_file: Failed to load %s - %s\n", fname, strerror(errno))); 241 return NULL; 242 } 243 p = mmap(NULL, size, PROT_READ, MAP_SHARED|MAP_FILE, fd, 0); 244 close(fd); 245 if (p == MAP_FAILED) { 246 DEBUG(1,("map_file: Failed to mmap %s - %s\n", fname, strerror(errno))); 247 return NULL; 248 } 249#endif 250 if (!p) { 251 p = file_load(fname, &s2, 0); 252 if (!p) { 253 return NULL; 254 } 255 if (s2 != size) { 256 DEBUG(1,("map_file: incorrect size for %s - got %lu expected %lu\n", 257 fname, (unsigned long)s2, (unsigned long)size)); 258 SAFE_FREE(p); 259 return NULL; 260 } 261 } 262 return p; 263} 264 265/**************************************************************************** 266 Parse a buffer into lines. 267****************************************************************************/ 268 269static char **file_lines_parse(char *p, size_t size, int *numlines) 270{ 271 int i; 272 char *s, **ret; 273 274 if (!p) { 275 return NULL; 276 } 277 278 for (s = p, i=0; s < p+size; s++) { 279 if (s[0] == '\n') i++; 280 } 281 282 ret = SMB_MALLOC_ARRAY(char *, i+2); 283 if (!ret) { 284 SAFE_FREE(p); 285 return NULL; 286 } 287 memset(ret, 0, sizeof(ret[0])*(i+2)); 288 289 ret[0] = p; 290 for (s = p, i=0; s < p+size; s++) { 291 if (s[0] == '\n') { 292 s[0] = 0; 293 i++; 294 ret[i] = s+1; 295 } 296 if (s[0] == '\r') { 297 s[0] = 0; 298 } 299 } 300 301 /* remove any blank lines at the end */ 302 while (i > 0 && ret[i-1][0] == 0) { 303 i--; 304 } 305 306 if (numlines) { 307 *numlines = i; 308 } 309 310 return ret; 311} 312 313/**************************************************************************** 314 Load a file into memory and return an array of pointers to lines in the file 315 must be freed with file_lines_free(). 316****************************************************************************/ 317 318char **file_lines_load(const char *fname, int *numlines, size_t maxsize) 319{ 320 char *p; 321 size_t size = 0; 322 323 p = file_load(fname, &size, maxsize); 324 if (!p) { 325 return NULL; 326 } 327 328 return file_lines_parse(p, size, numlines); 329} 330 331/**************************************************************************** 332 Load a fd into memory and return an array of pointers to lines in the file 333 must be freed with file_lines_free(). If convert is true calls unix_to_dos on 334 the list. 335****************************************************************************/ 336 337char **fd_lines_load(int fd, int *numlines, size_t maxsize) 338{ 339 char *p; 340 size_t size; 341 342 p = fd_load(fd, &size, maxsize); 343 if (!p) { 344 return NULL; 345 } 346 347 return file_lines_parse(p, size, numlines); 348} 349 350/**************************************************************************** 351 Load a pipe into memory and return an array of pointers to lines in the data 352 must be freed with file_lines_free(). 353****************************************************************************/ 354 355char **file_lines_pload(char *syscmd, int *numlines) 356{ 357 char *p; 358 size_t size; 359 360 p = file_pload(syscmd, &size); 361 if (!p) { 362 return NULL; 363 } 364 365 return file_lines_parse(p, size, numlines); 366} 367 368/**************************************************************************** 369 Free lines loaded with file_lines_load. 370****************************************************************************/ 371 372void file_lines_free(char **lines) 373{ 374 if (!lines) { 375 return; 376 } 377 SAFE_FREE(lines[0]); 378 SAFE_FREE(lines); 379} 380 381/**************************************************************************** 382 Take a list of lines and modify them to produce a list where \ continues 383 a line. 384****************************************************************************/ 385 386void file_lines_slashcont(char **lines) 387{ 388 int i, j; 389 390 for (i=0; lines[i];) { 391 int len = strlen(lines[i]); 392 if (lines[i][len-1] == '\\') { 393 lines[i][len-1] = ' '; 394 if (lines[i+1]) { 395 char *p = &lines[i][len]; 396 while (p < lines[i+1]) { 397 *p++ = ' '; 398 } 399 for (j = i+1; lines[j]; j++) { 400 lines[j] = lines[j+1]; 401 } 402 } 403 } else { 404 i++; 405 } 406 } 407} 408 409/**************************************************************************** 410 Save a lump of data into a file. Mostly used for debugging. 411****************************************************************************/ 412 413BOOL file_save(const char *fname, void *packet, size_t length) 414{ 415 int fd; 416 fd = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0644); 417 if (fd == -1) { 418 return False; 419 } 420 if (write(fd, packet, length) != (size_t)length) { 421 return False; 422 } 423 close(fd); 424 return True; 425} 426