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 #include "bfd.h"
00046 #include "sysdep.h"
00047 #include "libbfd.h"
00048 #include "libiberty.h"
00049
00050 static bfd_boolean bfd_cache_delete (bfd *);
00051
00052
00053 static file_ptr
00054 cache_btell (struct bfd *abfd)
00055 {
00056 return real_ftell (bfd_cache_lookup (abfd));
00057 }
00058
00059 static int
00060 cache_bseek (struct bfd *abfd, file_ptr offset, int whence)
00061 {
00062 return real_fseek (bfd_cache_lookup (abfd), offset, whence);
00063 }
00064
00065
00066
00067
00068
00069
00070
00071
00072 static file_ptr
00073 cache_bread (struct bfd *abfd, void *buf, file_ptr nbytes)
00074 {
00075 file_ptr nread;
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085 if (nbytes == 0)
00086 return 0;
00087
00088 #if defined (__VAX) && defined (VMS)
00089
00090
00091 nread = read (fileno (bfd_cache_lookup (abfd)), buf, nbytes);
00092
00093
00094
00095 if (nread == (file_ptr)-1)
00096 {
00097 bfd_set_error (bfd_error_system_call);
00098 return -1;
00099 }
00100 #else
00101 nread = fread (buf, 1, nbytes, bfd_cache_lookup (abfd));
00102
00103
00104
00105 if (nread < nbytes && ferror (bfd_cache_lookup (abfd)))
00106 {
00107 bfd_set_error (bfd_error_system_call);
00108 return -1;
00109 }
00110 #endif
00111 return nread;
00112 }
00113
00114 static file_ptr
00115 cache_bwrite (struct bfd *abfd, const void *where, file_ptr nbytes)
00116 {
00117 file_ptr nwrite = fwrite (where, 1, nbytes, bfd_cache_lookup (abfd));
00118 if (nwrite < nbytes && ferror (bfd_cache_lookup (abfd)))
00119 {
00120 bfd_set_error (bfd_error_system_call);
00121 return -1;
00122 }
00123 return nwrite;
00124 }
00125
00126 static int
00127 cache_bclose (struct bfd *abfd)
00128 {
00129 return bfd_cache_close (abfd);
00130 }
00131
00132 static int
00133 cache_bflush (struct bfd *abfd)
00134 {
00135 int sts = fflush (bfd_cache_lookup (abfd));
00136 if (sts < 0)
00137 bfd_set_error (bfd_error_system_call);
00138 return sts;
00139 }
00140
00141 static int
00142 cache_bstat (struct bfd *abfd, struct stat *sb)
00143 {
00144 int sts = fstat (fileno (bfd_cache_lookup (abfd)), sb);
00145 if (sts < 0)
00146 bfd_set_error (bfd_error_system_call);
00147 return sts;
00148 }
00149
00150 static const struct bfd_iovec cache_iovec = {
00151 &cache_bread, &cache_bwrite, &cache_btell, &cache_bseek,
00152 &cache_bclose, &cache_bflush, &cache_bstat
00153 };
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169 static int open_files;
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184 bfd *bfd_last_cache;
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205 static void
00206 insert (bfd *abfd)
00207 {
00208 if (bfd_last_cache == NULL)
00209 {
00210 abfd->lru_next = abfd;
00211 abfd->lru_prev = abfd;
00212 }
00213 else
00214 {
00215 abfd->lru_next = bfd_last_cache;
00216 abfd->lru_prev = bfd_last_cache->lru_prev;
00217 abfd->lru_prev->lru_next = abfd;
00218 abfd->lru_next->lru_prev = abfd;
00219 }
00220 bfd_last_cache = abfd;
00221 }
00222
00223
00224
00225 static void
00226 snip (bfd *abfd)
00227 {
00228 abfd->lru_prev->lru_next = abfd->lru_next;
00229 abfd->lru_next->lru_prev = abfd->lru_prev;
00230 if (abfd == bfd_last_cache)
00231 {
00232 bfd_last_cache = abfd->lru_next;
00233 if (abfd == bfd_last_cache)
00234 bfd_last_cache = NULL;
00235 }
00236 }
00237
00238
00239
00240
00241 static bfd_boolean
00242 close_one (void)
00243 {
00244 register bfd *kill;
00245
00246 if (bfd_last_cache == NULL)
00247 kill = NULL;
00248 else
00249 {
00250 for (kill = bfd_last_cache->lru_prev;
00251 ! kill->cacheable;
00252 kill = kill->lru_prev)
00253 {
00254 if (kill == bfd_last_cache)
00255 {
00256 kill = NULL;
00257 break;
00258 }
00259 }
00260 }
00261
00262 if (kill == NULL)
00263 {
00264
00265 return TRUE;
00266 }
00267
00268 kill->where = real_ftell ((FILE *) kill->iostream);
00269
00270 return bfd_cache_delete (kill);
00271 }
00272
00273
00274
00275 static bfd_boolean
00276 bfd_cache_delete (bfd *abfd)
00277 {
00278 bfd_boolean ret;
00279
00280 if (fclose ((FILE *) abfd->iostream) == 0)
00281 ret = TRUE;
00282 else
00283 {
00284 ret = FALSE;
00285 bfd_set_error (bfd_error_system_call);
00286 }
00287
00288 snip (abfd);
00289
00290 abfd->iostream = NULL;
00291 --open_files;
00292
00293 return ret;
00294 }
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307 bfd_boolean
00308 bfd_cache_init (bfd *abfd)
00309 {
00310 BFD_ASSERT (abfd->iostream != NULL);
00311 if (open_files >= BFD_CACHE_MAX_OPEN)
00312 {
00313 if (! close_one ())
00314 return FALSE;
00315 }
00316 abfd->iovec = &cache_iovec;
00317 insert (abfd);
00318 ++open_files;
00319 return TRUE;
00320 }
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338 bfd_boolean
00339 bfd_cache_close (bfd *abfd)
00340 {
00341 if (abfd->iovec != &cache_iovec)
00342 return TRUE;
00343
00344 if (abfd->iostream == NULL)
00345
00346 return TRUE;
00347
00348 return bfd_cache_delete (abfd);
00349 }
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367 bfd_boolean
00368 bfd_cache_close_all ()
00369 {
00370 bfd_boolean ret = TRUE;
00371
00372 while (bfd_last_cache != NULL)
00373 ret &= bfd_cache_close (bfd_last_cache);
00374
00375 return ret;
00376 }
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393 FILE *
00394 bfd_open_file (bfd *abfd)
00395 {
00396 abfd->cacheable = TRUE;
00397
00398 if (open_files >= BFD_CACHE_MAX_OPEN)
00399 {
00400 if (! close_one ())
00401 return NULL;
00402 }
00403
00404 switch (abfd->direction)
00405 {
00406 case read_direction:
00407 case no_direction:
00408 abfd->iostream = (PTR) fopen (abfd->filename, FOPEN_RB);
00409 break;
00410 case both_direction:
00411 case write_direction:
00412 if (abfd->opened_once)
00413 {
00414 abfd->iostream = (PTR) fopen (abfd->filename, FOPEN_RUB);
00415 if (abfd->iostream == NULL)
00416 abfd->iostream = (PTR) fopen (abfd->filename, FOPEN_WUB);
00417 }
00418 else
00419 {
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435 #ifndef __MSDOS__
00436
00437
00438
00439
00440
00441 struct stat s;
00442
00443 if (stat (abfd->filename, &s) == 0 && s.st_size != 0)
00444 unlink_if_ordinary (abfd->filename);
00445 #endif
00446 abfd->iostream = (PTR) fopen (abfd->filename, FOPEN_WUB);
00447 abfd->opened_once = TRUE;
00448 }
00449 break;
00450 }
00451
00452 if (abfd->iostream != NULL)
00453 {
00454 if (! bfd_cache_init (abfd))
00455 return NULL;
00456 }
00457
00458 return (FILE *) abfd->iostream;
00459 }
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477 FILE *
00478 bfd_cache_lookup_worker (bfd *abfd)
00479 {
00480 if ((abfd->flags & BFD_IN_MEMORY) != 0)
00481 abort ();
00482
00483 if (abfd->my_archive)
00484 abfd = abfd->my_archive;
00485
00486 if (abfd->iostream != NULL)
00487 {
00488
00489 if (abfd != bfd_last_cache)
00490 {
00491 snip (abfd);
00492 insert (abfd);
00493 }
00494 }
00495 else
00496 {
00497 if (bfd_open_file (abfd) == NULL
00498 || abfd->where != (unsigned long) abfd->where
00499 || real_fseek ((FILE *) abfd->iostream, abfd->where, SEEK_SET) != 0)
00500 abort ();
00501 }
00502
00503 return (FILE *) abfd->iostream;
00504 }