static file_ptr cache_btell (struct bfd *abfd) { FILE *f = bfd_cache_lookup (abfd, CACHE_NO_OPEN); if (f == NULL) return abfd->where; return _bfd_real_ftell (f); }
static int cache_bseek (struct bfd *abfd, file_ptr offset, int whence) { FILE *f = bfd_cache_lookup (abfd, whence != SEEK_CUR ? CACHE_NO_SEEK : CACHE_NORMAL); if (f == NULL) return -1; return _bfd_real_fseek (f, offset, whence); }
static int cache_bseek (struct bfd *abfd, file_ptr offset, int whence) { FILE *f = bfd_cache_lookup (abfd, whence != SEEK_CUR ? CACHE_NO_SEEK : 0); if (f == NULL) return -1; #if defined(__BEOS__) || defined(__HAIKU__) _bfdio_files[fileno(f)] = 1; #endif return real_fseek (f, offset, whence); }
static int cache_bstat (struct bfd *abfd, struct stat *sb) { int sts; FILE *f = bfd_cache_lookup (abfd, CACHE_NO_SEEK_ERROR); if (f == NULL) return -1; sts = fstat (fileno (f), sb); if (sts < 0) bfd_set_error (bfd_error_system_call); return sts; }
static int cache_bflush (struct bfd *abfd) { int sts; FILE *f = bfd_cache_lookup (abfd, CACHE_NO_OPEN); if (f == NULL) return 0; sts = fflush (f); if (sts < 0) bfd_set_error (bfd_error_system_call); return sts; }
static file_ptr cache_bread_1 (struct bfd *abfd, void *buf, file_ptr nbytes) { FILE *f; file_ptr nread; /* FIXME - this looks like an optimization, but it's really to cover up for a feature of some OSs (not solaris - sigh) that ld/pe-dll.c takes advantage of (apparently) when it creates BFDs internally and tries to link against them. BFD seems to be smart enough to realize there are no symbol records in the "file" that doesn't exist but attempts to read them anyway. On Solaris, attempting to read zero bytes from a NULL file results in a core dump, but on other platforms it just returns zero bytes read. This makes it to something reasonable. - DJ */ if (nbytes == 0) return 0; f = bfd_cache_lookup (abfd, CACHE_NORMAL); if (f == NULL) return 0; #if defined (__VAX) && defined (VMS) /* Apparently fread on Vax VMS does not keep the record length information. */ nread = read (fileno (f), buf, nbytes); /* Set bfd_error if we did not read as much data as we expected. If the read failed due to an error set the bfd_error_system_call, else set bfd_error_file_truncated. */ if (nread == (file_ptr)-1) { bfd_set_error (bfd_error_system_call); return nread; } #else nread = fread (buf, 1, nbytes, f); /* Set bfd_error if we did not read as much data as we expected. If the read failed due to an error set the bfd_error_system_call, else set bfd_error_file_truncated. */ if (nread < nbytes && ferror (f)) { bfd_set_error (bfd_error_system_call); return nread; } #endif if (nread < nbytes) /* This may or may not be an error, but in case the calling code bails out because of it, set the right error code. */ bfd_set_error (bfd_error_file_truncated); return nread; }
static file_ptr cache_bwrite (struct bfd *abfd, const void *where, file_ptr nbytes) { file_ptr nwrite; FILE *f = bfd_cache_lookup (abfd, 0); if (f == NULL) return 0; nwrite = fwrite (where, 1, nbytes, f); if (nwrite < nbytes && ferror (f)) { bfd_set_error (bfd_error_system_call); return -1; } return nwrite; }
static file_ptr cache_bwrite (struct bfd *abfd, const void *where, file_ptr nbytes) { file_ptr nwrite; FILE *f = bfd_cache_lookup (abfd, 0); if (f == NULL) return 0; #if defined(__BEOS__) || defined(__HAIKU__) { if (_bfdio_files[fileno(f)] == 1) { file_ptr eof; file_ptr pos; pos = ftell (f); fseek (f, 0L, SEEK_END); eof = ftell(f); if (eof < pos) { file_ptr diff; static char zeros[512]; diff = pos - eof; while (diff >= sizeof (zeros)) { fwrite(zeros, sizeof (zeros), 1, f); diff -= sizeof (zeros); } if (diff > 0) fwrite(zeros, diff, 1, f); } else fseek (f, pos, SEEK_SET); _bfdio_files[fileno(f)] = 0; } } #endif nwrite = fwrite (where, 1, nbytes, f); if (nwrite < nbytes && ferror (f)) { bfd_set_error (bfd_error_system_call); return -1; } return nwrite; }
static file_ptr cache_bread (struct bfd *abfd, void *buf, file_ptr nbytes) { file_ptr nread = 0; FILE *f; f = bfd_cache_lookup (abfd, CACHE_NORMAL); if (f == NULL) return -1; /* Some filesystems are unable to handle reads that are too large (for instance, NetApp shares with oplocks turned off). To avoid hitting this limitation, we read the buffer in chunks of 8MB max. */ while (nread < nbytes) { const file_ptr max_chunk_size = 0x800000; file_ptr chunk_size = nbytes - nread; file_ptr chunk_nread; if (chunk_size > max_chunk_size) chunk_size = max_chunk_size; chunk_nread = cache_bread_1 (f, (char *) buf + nread, chunk_size); /* Update the nread count. We just have to be careful of the case when cache_bread_1 returns a negative count: If this is our first read, then set nread to that negative count in order to return that negative value to the caller. Otherwise, don't add it to our total count, or we would end up returning a smaller number of bytes read than we actually did. */ if (nread == 0 || chunk_nread > 0) nread += chunk_nread; if (chunk_nread < chunk_size) break; } return nread; }
static bfd_boolean _bfd_get_file_window_mmap(bfd *abfd, ufile_ptr offset, bfd_size_type size, bfd_window *windowp, bfd_window_internal *i, bfd_boolean writable) { static size_t pagesize; bfd_size_type size_to_alloc = size; if (debug_windows) fprintf(stderr, "bfd_get_file_window (%p, %6ld, %6ld, %p<%p,%lx,%p>, %d)", (void *)abfd, (long)offset, (long)size, (void *)windowp, windowp->data, (unsigned long)windowp->size, (void *)windowp->i, writable); /* Make sure we know the page size, so we can be friendly to mmap: */ if (pagesize == 0) pagesize = (size_t)getpagesize(); if (pagesize == 0) abort(); # ifdef HAVE_MMAP if (ok_to_map && ((i->data == 0) || (i->mapped == 1)) && ((abfd->flags & BFD_IN_MEMORY) == 0)) { file_ptr file_offset, offset2; size_t real_size; int fd; FILE *f; /* Find the real file and the real offset into it: */ while (abfd->my_archive != NULL) { offset += abfd->origin; abfd = abfd->my_archive; } f = bfd_cache_lookup(abfd); fd = fileno(f); /* Compute offsets and size for mmap and for the user's data: */ offset2 = (file_ptr)(offset % pagesize); if (offset2 < 0) abort(); file_offset = ((file_ptr)offset - offset2); real_size = (size_t)(offset + size - (unsigned long)file_offset); real_size = (real_size + pagesize - 1UL); real_size -= (real_size % pagesize); /* If we are re-using a memory region, make sure it is big enough: */ if (i->data && (i->size < size)) { munmap(i->data, (size_t)i->size); i->data = 0; } i->data = mmap(i->data, real_size, (writable ? (PROT_WRITE | PROT_READ) : PROT_READ), (writable ? (MAP_FILE | MAP_PRIVATE) : (MAP_FILE | MAP_SHARED)), fd, (off_t)file_offset); if (i->data == (void *)-1) { /* An error happened. Report it, or try using malloc, or * something: */ bfd_set_error(bfd_error_system_call); i->data = 0; windowp->data = 0; if (debug_windows) fprintf(stderr, "\t\tmmap failed!\n"); return FALSE; } if (debug_windows) fprintf(stderr, "\n\tmapped %ld at %p, offset is %ld\n", (long)real_size, i->data, (long)offset2); i->size = real_size; windowp->data = ((bfd_byte *)i->data + offset2); windowp->size = size; i->mapped = 1; return TRUE; } else if (debug_windows) { if (ok_to_map) fprintf(stderr, _("not mapping: data=%lx mapped=%d\n"), (unsigned long)i->data, (int)i->mapped); else fprintf(stderr, _("not mapping: env var not set\n")); } # else ok_to_map = 0; # endif /* HAVE_MMAP */ # ifdef HAVE_MPROTECT if (!writable) { size_to_alloc += (pagesize - 1); size_to_alloc -= (size_to_alloc % pagesize); } # endif /* HAVE_MPROTECT */ if (debug_windows) fprintf(stderr, "\n\t%s(%6ld)", (i->data ? "realloc" : " malloc"), (long)size_to_alloc); i->data = bfd_realloc(i->data, size_to_alloc); if (debug_windows) fprintf(stderr, "\t-> %p\n", i->data); i->refcount = 1; if (i->data == NULL) { if (size_to_alloc == 0) return TRUE; return FALSE; } if (bfd_seek(abfd, (file_ptr)offset, SEEK_SET) != 0) return FALSE; i->size = bfd_bread(i->data, size, abfd); if (i->size != size) return FALSE; i->mapped = 0; # ifdef HAVE_MPROTECT if (!writable) { if (debug_windows) fprintf(stderr, "\tmprotect (%p, %ld, PROT_READ)\n", i->data, (long)i->size); mprotect(i->data, i->size, PROT_READ); } # endif /* HAVE_MPROTECT */ windowp->data = i->data; windowp->size = i->size; return TRUE; }