/* * Map a file (from fd's current offset) into a shared, read-only memory * segment. The file offset must be a multiple of the page size. * * On success, returns 0 and fills out "pMap". On failure, returns a nonzero * value and does not disturb "pMap". */ int sysMapFileInShmem(int fd, MemMapping* pMap) { #ifdef HAVE_POSIX_FILEMAP off_t start; size_t length; void* memPtr; assert(pMap != NULL); if (getFileStartAndLength(fd, &start, &length) < 0) return -1; memPtr = mmap(NULL, length, PROT_READ, MAP_FILE | MAP_SHARED, fd, start); if (memPtr == MAP_FAILED) { LOGW("mmap(%d, R, FILE|SHARED, %d, %d) failed: %s\n", (int) length, fd, (int) start, strerror(errno)); return -1; } pMap->baseAddr = pMap->addr = memPtr; pMap->baseLength = pMap->length = length; return 0; #else /* No MMAP, just fake it by copying the bits. For Win32 we could use MapViewOfFile if really necessary (see libs/utils/FileMap.cpp). */ off_t start; size_t length; void* memPtr; assert(pMap != NULL); if (getFileStartAndLength(fd, &start, &length) < 0) return -1; memPtr = malloc(length); if (read(fd, memPtr, length) < 0) { LOGW("read(fd=%d, start=%d, length=%d) failed: %s\n", (int) length, fd, (int) start, strerror(errno)); return -1; } pMap->baseAddr = pMap->addr = memPtr; pMap->baseLength = pMap->length = length; return 0; #endif }
/* * Map a file (from fd's current offset) into a private, read-only memory * segment. The file offset must be a multiple of the page size. * * On success, returns 0 and fills out "pMap". On failure, returns a nonzero * value and does not disturb "pMap". */ static int sysMapFD(int fd, MemMapping* pMap) { off_t start; size_t length; void* memPtr; assert(pMap != NULL); if (getFileStartAndLength(fd, &start, &length) < 0) return -1; memPtr = mmap(NULL, length, PROT_READ, MAP_PRIVATE, fd, start); if (memPtr == MAP_FAILED) { LOGW("mmap(%d, R, PRIVATE, %d, %d) failed: %s\n", (int) length, fd, (int) start, strerror(errno)); return -1; } pMap->addr = memPtr; pMap->length = length; pMap->range_count = 1; pMap->ranges = malloc(sizeof(MappedRange)); pMap->ranges[0].addr = memPtr; pMap->ranges[0].length = length; return 0; }
/* * Pull the contents of a file into an new shared memory segment. We grab * everything from fd's current offset on. * * We need to know the length ahead of time so we can allocate a segment * of sufficient size. */ int sysLoadFileInShmem(int fd, MemMapping* pMap) { loff_t start; size_t length, actual; void* memPtr; assert(pMap != NULL); if (getFileStartAndLength(fd, &start, &length) < 0) return -1; memPtr = sysCreateAnonShmem(length); if (memPtr == NULL) return -1; actual = read(fd, memPtr, length); if (actual != length) { LOGE("only read %d of %d bytes\n", (int) actual, (int) length); sysReleaseShmem(pMap); return -1; } pMap->baseAddr = pMap->addr = memPtr; pMap->baseLength = pMap->length = length; return 0; }
/* * Map a file (from fd's current offset) into a shared, read-only memory * segment. The file offset must be a multiple of the page size. * * On success, returns 0 and fills out "pMap". On failure, returns a nonzero * value and does not disturb "pMap". */ int sysMapFileInShmem (int fd, MemMapping * pMap) { off_t start; size_t length; void *memPtr; assert (pMap != NULL); if (getFileStartAndLength (fd, &start, &length) < 0) return -1; memPtr = mmap (NULL, length, PROT_READ, MAP_FILE | MAP_SHARED, fd, start); if (memPtr == MAP_FAILED) { LOGW ("mmap(%d, R, FILE|SHARED, %d, %d) failed: %s\n", (int) length, fd, (int) start, strerror (errno)); return -1; } pMap->baseAddr = pMap->addr = memPtr; pMap->baseLength = pMap->length = length; return 0; }
/* * Map a file (from fd's current offset) into a private, read-write memory * segment that will be marked read-only (a/k/a "writable read-only"). The * file offset must be a multiple of the system page size. * * In some cases the mapping will be fully writable (e.g. for files on * FAT filesystems). * * On success, returns 0 and fills out "pMap". On failure, returns a nonzero * value and does not disturb "pMap". */ int sysMapFileInShmemWritableReadOnly(int fd, MemMapping* pMap) { #ifdef HAVE_POSIX_FILEMAP off_t start; size_t length; void* memPtr; assert(pMap != NULL); if (getFileStartAndLength(fd, &start, &length) < 0) return -1; memPtr = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_FILE | MAP_PRIVATE, fd, start); if (memPtr == MAP_FAILED) { ALOGW("mmap(%d, R/W, FILE|PRIVATE, %d, %d) failed: %s", (int) length, fd, (int) start, strerror(errno)); return -1; } if (mprotect(memPtr, length, PROT_READ) < 0) { /* this fails with EACCESS on FAT filesystems, e.g. /sdcard */ int err = errno; ALOGV("mprotect(%p, %d, PROT_READ) failed: %s", memPtr, length, strerror(err)); ALOGD("mprotect(RO) failed (%d), file will remain read-write", err); } pMap->baseAddr = pMap->addr = memPtr; pMap->baseLength = pMap->length = length; return 0; #else return sysFakeMapFile(fd, pMap); #endif }
int sysFakeMapFile(int fd, MemMapping* pMap) { /* No MMAP, just fake it by copying the bits. For Win32 we could use MapViewOfFile if really necessary (see libs/utils/FileMap.cpp). */ off_t start; size_t length; void* memPtr; assert(pMap != NULL); if (getFileStartAndLength(fd, &start, &length) < 0) return -1; memPtr = malloc(length); if (read(fd, memPtr, length) < 0) { ALOGW("read(fd=%d, start=%d, length=%d) failed: %s", (int) length, fd, (int) start, strerror(errno)); return -1; } pMap->baseAddr = pMap->addr = memPtr; pMap->baseLength = pMap->length = length; return 0; }
/* * Map a file (from fd's current offset) into a shared, read-only memory * segment. The file offset must be a multiple of the system page size. * * On success, returns 0 and fills out "pMap". On failure, returns a nonzero * value and does not disturb "pMap". */ int sysMapFileInShmemReadOnly(int fd, MemMapping* pMap) { #ifdef HAVE_POSIX_FILEMAP off_t start; size_t length; void* memPtr; assert(pMap != NULL); if (getFileStartAndLength(fd, &start, &length) < 0) return -1; memPtr = mmap(NULL, length, PROT_READ, MAP_FILE | MAP_SHARED, fd, start); if (memPtr == MAP_FAILED) { ALOGW("mmap(%d, RO, FILE|SHARED, %d, %d) failed: %s", (int) length, fd, (int) start, strerror(errno)); return -1; } pMap->baseAddr = pMap->addr = memPtr; pMap->baseLength = pMap->length = length; return 0; #else return sysFakeMapFile(fd, pMap); #endif }
/* * Pull the contents of a file into an new shared memory segment. We grab * everything from fd's current offset on. * * We need to know the length ahead of time so we can allocate a segment * of sufficient size. */ int sysLoadFileInShmem(int fd, MemMapping* pMap) { #ifdef HAVE_POSIX_FILEMAP off_t start; size_t length, actual; void* memPtr; assert(pMap != NULL); if (getFileStartAndLength(fd, &start, &length) < 0) return -1; memPtr = sysCreateAnonShmem(length); if (memPtr == NULL) return -1; actual = read(fd, memPtr, length); if (actual != length) { ALOGE("only read %d of %d bytes", (int) actual, (int) length); sysReleaseShmem(pMap); return -1; } pMap->baseAddr = pMap->addr = memPtr; pMap->baseLength = pMap->length = length; return 0; #else ALOGE("sysLoadFileInShmem not implemented."); return -1; #endif }
/* * Map part of a file (from fd's current offset) into a shared, read-only * memory segment. * * On success, returns 0 and fills out "pMap". On failure, returns a nonzero * value and does not disturb "pMap". */ int sysMapFileSegmentInShmem(int fd, off_t start, long length, MemMapping* pMap) { #ifdef HAVE_POSIX_FILEMAP off_t dummy; size_t fileLength, actualLength; off_t actualStart; int adjust; void* memPtr; assert(pMap != NULL); if (getFileStartAndLength(fd, &dummy, &fileLength) < 0) return -1; if (start + length > (long)fileLength) { LOGW("bad segment: st=%d len=%ld flen=%d\n", (int) start, length, (int) fileLength); return -1; } /* adjust to be page-aligned */ adjust = start % DEFAULT_PAGE_SIZE; actualStart = start - adjust; actualLength = length + adjust; memPtr = mmap(NULL, actualLength, PROT_READ, MAP_FILE | MAP_SHARED, fd, actualStart); if (memPtr == MAP_FAILED) { LOGW("mmap(%d, R, FILE|SHARED, %d, %d) failed: %s\n", (int) actualLength, fd, (int) actualStart, strerror(errno)); return -1; } pMap->baseAddr = memPtr; pMap->baseLength = actualLength; pMap->addr = (char*)memPtr + adjust; pMap->length = length; LOGVV("mmap seg (st=%d ln=%d): bp=%p bl=%d ad=%p ln=%d\n", (int) start, (int) length, pMap->baseAddr, (int) pMap->baseLength, pMap->addr, (int) pMap->length); return 0; #else LOGE("sysMapFileSegmentInShmem not implemented.\n"); return -1; #endif }