00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052 #ifndef lint
00053 static const char libbu_mappedfile_RCSid[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/libbu/mappedfile.c,v 14.16 2006/09/03 15:14:07 lbutler Exp $ (ARL)";
00054 #endif
00055
00056 #include "common.h"
00057
00058 #include <stdio.h>
00059 #include <math.h>
00060 #include <fcntl.h>
00061 #ifdef HAVE_UNISTD_H
00062 # include <unistd.h>
00063 #endif
00064 #ifdef HAVE_STRING_H
00065 # include <string.h>
00066 #else
00067 # include <strings.h>
00068 #endif
00069
00070 #include "machine.h"
00071
00072 #ifdef HAVE_UNIX_IO
00073 # include <sys/types.h>
00074 # include <sys/stat.h>
00075 #endif
00076
00077 #ifdef HAVE_SYS_MMAN_H
00078 # include <sys/mman.h>
00079 # if !defined(MAP_FAILED)
00080 # define MAP_FAILED ((void *)-1)
00081 # endif
00082 #endif
00083
00084 #include "bu.h"
00085
00086
00087 static struct bu_list bu_mapped_file_list = {
00088 0,
00089 (struct bu_list *)NULL,
00090 (struct bu_list *)NULL
00091 };
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103 struct bu_mapped_file *
00104 bu_open_mapped_file(const char *name, const char *appl)
00105
00106
00107 {
00108 struct bu_mapped_file *mp = (struct bu_mapped_file *)NULL;
00109 #ifdef HAVE_UNIX_IO
00110 struct stat sb;
00111 int fd;
00112 #else
00113 FILE *fp = (FILE *)NULL;
00114 #endif
00115 int ret;
00116
00117 if( bu_debug&BU_DEBUG_MAPPED_FILE )
00118 #ifdef HAVE_SBRK
00119 bu_log("bu_open_mapped_file(%s, %s) sbrk=x%lx\n", name, appl?appl:"(NIL)", (long)sbrk(0));
00120 #else
00121 bu_log("bu_open_mapped_file(%s, %s)\n", name, appl?appl:"(NIL)");
00122 #endif
00123
00124
00125 bu_semaphore_acquire(BU_SEM_MAPPEDFILE);
00126 if( BU_LIST_UNINITIALIZED( &bu_mapped_file_list ) ) {
00127 BU_LIST_INIT( &bu_mapped_file_list );
00128 }
00129 for( BU_LIST_FOR( mp, bu_mapped_file, &bu_mapped_file_list ) ) {
00130 BU_CK_MAPPED_FILE(mp);
00131 if( strcmp( name, mp->name ) ) continue;
00132 if( appl && strcmp( appl, mp->appl ) )
00133 continue;
00134
00135 #ifdef HAVE_UNIX_IO
00136 if( !mp->dont_restat ) {
00137 bu_semaphore_acquire(BU_SEM_SYSCALL);
00138 ret = stat( name, &sb );
00139 bu_semaphore_release(BU_SEM_SYSCALL);
00140 if( ret < 0 ) goto do_reuse;
00141 if( sb.st_size != mp->buflen ) {
00142 bu_log("bu_open_mapped_file(%s) WARNING: File size changed from %ld to %ld, opening new version.\n",
00143 name, (long)mp->buflen, (long)sb.st_size );
00144 goto dont_reuse;
00145 }
00146 if( (long)sb.st_mtime != mp->modtime ) {
00147 bu_log("bu_open_mapped_file(%s) WARNING: File modified since last mapped, opening new version.\n",
00148 name);
00149 goto dont_reuse;
00150 }
00151
00152 }
00153 #endif
00154 do_reuse:
00155
00156 mp->uses++;
00157 bu_semaphore_release(BU_SEM_MAPPEDFILE);
00158 if( bu_debug&BU_DEBUG_MAPPED_FILE )
00159 bu_pr_mapped_file("open_reused", mp);
00160 return mp;
00161 dont_reuse:
00162
00163 mp->appl = "__STALE__";
00164
00165
00166 }
00167 bu_semaphore_release(BU_SEM_MAPPEDFILE);
00168 mp = (struct bu_mapped_file *)NULL;
00169
00170
00171 #ifdef HAVE_UNIX_IO
00172 bu_semaphore_acquire(BU_SEM_SYSCALL);
00173 fd = open( name, O_RDONLY );
00174 bu_semaphore_release(BU_SEM_SYSCALL);
00175
00176 if( fd < 0 ) {
00177 if (bu_debug&BU_DEBUG_DB)
00178 perror(name);
00179 goto fail;
00180 }
00181
00182 bu_semaphore_acquire(BU_SEM_SYSCALL);
00183 ret = fstat( fd, &sb );
00184 bu_semaphore_release(BU_SEM_SYSCALL);
00185
00186 if( ret < 0 ) {
00187 perror(name);
00188 goto fail;
00189 }
00190
00191 if( sb.st_size == 0 ) {
00192 bu_log("bu_open_mapped_file(%s) 0-length file\n", name);
00193 goto fail;
00194 }
00195 #endif
00196
00197
00198 BU_GETSTRUCT( mp, bu_mapped_file );
00199 mp->name = bu_strdup( name );
00200 if( appl ) mp->appl = bu_strdup( appl );
00201
00202 #ifdef HAVE_UNIX_IO
00203 mp->buflen = (size_t)sb.st_size;
00204 mp->modtime = (long)sb.st_mtime;
00205 # ifdef HAVE_SYS_MMAN_H
00206
00207
00208 bu_semaphore_acquire(BU_SEM_SYSCALL);
00209 mp->buf = mmap((caddr_t)0, (size_t)sb.st_size, PROT_READ, MAP_PRIVATE, fd, (off_t)0 );
00210 bu_semaphore_release(BU_SEM_SYSCALL);
00211
00212 if( mp->buf == MAP_FAILED ) perror(name);
00213 if( mp->buf != MAP_FAILED ) {
00214
00215 mp->is_mapped = 1;
00216
00217 } else
00218 # endif
00219 {
00220
00221 mp->buf = bu_malloc( (size_t)sb.st_size, name );
00222
00223 bu_semaphore_acquire(BU_SEM_SYSCALL);
00224 ret = read( fd, mp->buf, (size_t)sb.st_size );
00225 bu_semaphore_release(BU_SEM_SYSCALL);
00226
00227 if( ret != sb.st_size ) {
00228 perror(name);
00229 bu_free( mp->buf, name );
00230 bu_semaphore_acquire(BU_SEM_SYSCALL);
00231 (void)close(fd);
00232 bu_semaphore_release(BU_SEM_SYSCALL);
00233 goto fail;
00234 }
00235 }
00236
00237 bu_semaphore_acquire(BU_SEM_SYSCALL);
00238 (void)close(fd);
00239 bu_semaphore_release(BU_SEM_SYSCALL);
00240
00241 #else
00242
00243
00244 bu_semaphore_acquire(BU_SEM_SYSCALL);
00245 #if defined(_WIN32) && !defined(__CYGWIN__)
00246 fp = fopen( name, "rb");
00247 #else
00248 fp = fopen( name, "r");
00249 #endif
00250 bu_semaphore_release(BU_SEM_SYSCALL);
00251
00252 if( fp == NULL ) {
00253 perror(name);
00254 goto fail;
00255 }
00256
00257 {
00258 char buf[32768] = {0};
00259 int got;
00260 mp->buflen = 0;
00261
00262 bu_semaphore_acquire(BU_SEM_SYSCALL);
00263 while( (got = fread( buf, 1, sizeof(buf), fp )) > 0 )
00264 mp->buflen += got;
00265 rewind(fp);
00266 bu_semaphore_release(BU_SEM_SYSCALL);
00267
00268 }
00269
00270 mp->buf = bu_malloc( mp->buflen, name );
00271
00272
00273 bu_semaphore_acquire(BU_SEM_SYSCALL);
00274 ret = fread( mp->buf, mp->buflen, 1, fp );
00275 bu_semaphore_release(BU_SEM_SYSCALL);
00276
00277 if( ret != 1 ) {
00278 bu_semaphore_acquire(BU_SEM_SYSCALL);
00279 perror("fread");
00280 fclose(fp);
00281 bu_semaphore_release(BU_SEM_SYSCALL);
00282
00283 bu_log("bu_open_mapped_file() 2nd fread failed? len=%d\n", mp->buflen);
00284 bu_free( mp->buf, "non-unix fread buf" );
00285 goto fail;
00286 }
00287
00288 bu_semaphore_acquire(BU_SEM_SYSCALL);
00289 fclose(fp);
00290 bu_semaphore_release(BU_SEM_SYSCALL);
00291 #endif
00292
00293 mp->uses = 1;
00294 mp->l.magic = BU_MAPPED_FILE_MAGIC;
00295
00296 bu_semaphore_acquire(BU_SEM_MAPPEDFILE);
00297 BU_LIST_APPEND( &bu_mapped_file_list, &mp->l );
00298 bu_semaphore_release(BU_SEM_MAPPEDFILE);
00299
00300 if( bu_debug&BU_DEBUG_MAPPED_FILE ) {
00301 bu_pr_mapped_file("1st_open", mp);
00302 #ifdef HAVE_SBRK
00303 bu_log("bu_open_mapped_file() sbrk=x%lx\n", (long)sbrk(0));
00304 #endif
00305 }
00306 return mp;
00307
00308 fail:
00309 if( mp ) {
00310 bu_free( mp->name, "mp->name" );
00311 if( mp->appl ) bu_free( mp->appl, "mp->appl" );
00312
00313 bu_free( mp, "mp from bu_open_mapped_file fail");
00314 }
00315
00316 if (bu_debug&BU_DEBUG_DB)
00317 bu_log("bu_open_mapped_file(%s, %s) can't open file\n",
00318 name, appl?appl:"(NIL)" );
00319
00320 return (struct bu_mapped_file *)NULL;
00321 }
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335 void
00336 bu_close_mapped_file(struct bu_mapped_file *mp)
00337 {
00338 BU_CK_MAPPED_FILE(mp);
00339
00340 if( bu_debug&BU_DEBUG_MAPPED_FILE )
00341 bu_pr_mapped_file("close:uses--", mp);
00342
00343 if (! mp) {
00344 bu_log("bu_close_mapped_file() called with null pointer\n");
00345 return;
00346 }
00347
00348 bu_semaphore_acquire(BU_SEM_MAPPEDFILE);
00349 --mp->uses;
00350 bu_semaphore_release(BU_SEM_MAPPEDFILE);
00351 }
00352
00353
00354
00355
00356 void
00357 bu_pr_mapped_file(const char *title, const struct bu_mapped_file *mp)
00358 {
00359 BU_CK_MAPPED_FILE(mp);
00360
00361 bu_log("%8lx mapped_file %s %lx len=%ld mapped=%d, uses=%d %s\n",
00362 (long)mp, mp->name, (long)mp->buf, mp->buflen,
00363 mp->is_mapped, mp->uses,
00364 title );
00365 }
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376 void
00377 bu_free_mapped_files(int verbose)
00378 {
00379 struct bu_mapped_file *mp, *next;
00380
00381 if( bu_debug&BU_DEBUG_MAPPED_FILE )
00382 bu_log("bu_free_mapped_files(verbose=%d)\n", verbose);
00383
00384 bu_semaphore_acquire(BU_SEM_MAPPEDFILE);
00385
00386 next = BU_LIST_FIRST( bu_mapped_file, &bu_mapped_file_list );
00387 while( BU_LIST_NOT_HEAD( next, &bu_mapped_file_list ) ) {
00388 BU_CK_MAPPED_FILE(next);
00389 mp = next;
00390 next = BU_LIST_NEXT( bu_mapped_file, &mp->l );
00391
00392 if( mp->uses > 0 ) continue;
00393
00394
00395 if(verbose || (bu_debug&BU_DEBUG_MAPPED_FILE))
00396 bu_pr_mapped_file( "freeing", mp );
00397
00398 BU_LIST_DEQUEUE( &mp->l );
00399
00400
00401
00402
00403 if( mp->apbuf == mp->buf ) mp->apbuf = (genptr_t)NULL;
00404
00405 #ifdef HAVE_SYS_MMAN_H
00406 if( mp->is_mapped ) {
00407 int ret;
00408 bu_semaphore_acquire(BU_SEM_SYSCALL);
00409 ret = munmap( mp->buf, (size_t)mp->buflen );
00410 bu_semaphore_release(BU_SEM_SYSCALL);
00411 if( ret < 0 ) perror("munmap");
00412
00413 } else
00414 #endif
00415 {
00416 bu_free( mp->buf, "bu_mapped_file.buf[]" );
00417 }
00418 mp->buf = (genptr_t)NULL;
00419 bu_free( (genptr_t)mp->name, "bu_mapped_file.name" );
00420 if( mp->appl ) bu_free( (genptr_t)mp->appl, "bu_mapped_file.appl" );
00421 bu_free( (genptr_t)mp, "struct bu_mapped_file" );
00422 }
00423 bu_semaphore_release(BU_SEM_MAPPEDFILE);
00424 }
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435 struct bu_mapped_file *
00436 bu_open_mapped_file_with_path(char *const *path, const char *name, const char *appl)
00437
00438
00439
00440 {
00441 char * const *pathp = path;
00442 struct bu_vls str;
00443 struct bu_mapped_file *ret;
00444
00445 BU_ASSERT_PTR( name, !=, NULL );
00446 BU_ASSERT_PTR( pathp, !=, NULL );
00447
00448
00449 if( name[0] == '/' )
00450 return bu_open_mapped_file( name, appl );
00451
00452 bu_vls_init(&str);
00453
00454
00455 for( ; *pathp != NULL; pathp++ ) {
00456 bu_vls_strcpy( &str, *pathp );
00457 bu_vls_putc( &str, '/' );
00458 bu_vls_strcat( &str, name );
00459
00460 ret = bu_open_mapped_file( bu_vls_addr(&str), appl );
00461 if( ret ) {
00462 bu_vls_free( &str );
00463 return ret;
00464 }
00465 }
00466
00467
00468 bu_vls_free( &str );
00469 return (struct bu_mapped_file *)NULL;
00470 }
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481