fmap_t *fmap_check_empty(int fd, off_t offset, size_t len, int *empty) { /* WIN32 */ unsigned int pages, mapsz, hdrsz; int pgsz = cli_getpagesize(); STATBUF st; fmap_t *m; const void *data; HANDLE fh; HANDLE mh; *empty = 0; if(FSTAT(fd, &st)) { cli_warnmsg("fmap: fstat failed\n"); return NULL; } if(offset < 0 || offset != fmap_align_to(offset, pgsz)) { cli_warnmsg("fmap: attempted mapping with unaligned offset\n"); return NULL; } if(!len) len = st.st_size - offset; /* bound checked later */ if(!len) { cli_dbgmsg("fmap: attempted void mapping\n"); *empty = 1; return NULL; } if(!CLI_ISCONTAINED(0, st.st_size, offset, len)) { cli_warnmsg("fmap: attempted oof mapping\n"); return NULL; } pages = fmap_align_items(len, pgsz); hdrsz = fmap_align_to(sizeof(fmap_t), pgsz); if((fh = (HANDLE)_get_osfhandle(fd)) == INVALID_HANDLE_VALUE) { cli_errmsg("fmap: cannot get a valid handle for descriptor %d\n", fd); return NULL; } if(!(mh = CreateFileMapping(fh, NULL, PAGE_READONLY, (DWORD)((len>>31)>>1), (DWORD)len, NULL))) { cli_errmsg("fmap: cannot create a map of descriptor %d\n", fd); CloseHandle(fh); return NULL; } if(!(data = MapViewOfFile(mh, FILE_MAP_READ, (DWORD)((offset>>31)>>1), (DWORD)(offset), len))) { cli_errmsg("fmap: cannot map file descriptor %d\n", fd); CloseHandle(mh); CloseHandle(fh); return NULL; } if(!(m = cl_fmap_open_memory(data, len))) { cli_errmsg("fmap: canot allocate fmap_t\n", fd); CloseHandle(mh); CloseHandle(fh); return NULL; } m->handle = (void*)(ssize_t)fd; m->handle_is_fd = 1; m->fh = fh; m->mh = mh; m->unmap = unmap_win32; return m; }
extern cl_fmap_t *cl_fmap_open_memory(const void *start, size_t len) { int pgsz = cli_getpagesize(); cl_fmap_t *m = cli_calloc(1, sizeof(*m)); if (!m) { cli_warnmsg("fmap: map allocation failed\n"); return NULL; } m->data = start; m->len = len; m->real_len = len; m->pgsz = pgsz; m->pages = fmap_align_items(len, pgsz); m->unmap = unmap_malloc; m->need = mem_need; m->need_offstr = mem_need_offstr; m->gets = mem_gets; m->unneed_off = mem_unneed_off; return m; }
/* * Returns <0 for failure */ int blobAddData(blob *b, const unsigned char *data, size_t len) { #if HAVE_CLI_GETPAGESIZE static int pagesize; int growth; #endif assert(b != NULL); assert(b->magic == BLOBCLASS); assert(data != NULL); if(len == 0) return 0; if(b->isClosed) { /* * Should be cli_dbgmsg, but I want to see them for now, * and cli_dbgmsg doesn't support debug levels */ cli_warnmsg("Reopening closed blob\n"); b->isClosed = 0; } /* * The payoff here is between reducing the number of calls to * malloc/realloc and not overallocating memory. A lot of machines * are more tight with memory than one may imagine which is why * we don't just allocate a *huge* amount and be done with it. Closing * the blob helps because that reclaims memory. If you know the maximum * size of a blob before you start adding data, use blobGrow() that's * the most optimum */ #if HAVE_CLI_GETPAGESIZE if(pagesize == 0) { pagesize = cli_getpagesize(); if(pagesize == 0) pagesize = 4096; } growth = pagesize; if(len >= (size_t)pagesize) growth = ((len / pagesize) + 1) * pagesize; /*cli_dbgmsg("blobGrow: b->size %lu, b->len %lu, len %lu, growth = %u\n", b->size, b->len, len, growth);*/ if(b->data == NULL) { assert(b->len == 0); assert(b->size == 0); b->size = growth; b->data = cli_malloc(growth); } else if(b->size < b->len + (off_t)len) { unsigned char *p = cli_realloc(b->data, b->size + growth); if(p == NULL) return -1; b->size += growth; b->data = p; } #else if(b->data == NULL) { assert(b->len == 0); assert(b->size == 0); b->size = (off_t)len * 4; b->data = cli_malloc(b->size); } else if(b->size < b->len + (off_t)len) { unsigned char *p = cli_realloc(b->data, b->size + (len * 4)); if(p == NULL) return -1; b->size += (off_t)len * 4; b->data = p; } #endif if(b->data) { memcpy(&b->data[b->len], data, len); b->len += (off_t)len; } return 0; }
extern cl_fmap_t *cl_fmap_open_handle(void *handle, size_t offset, size_t len, clcb_pread pread_cb, int use_aging) { unsigned int pages, mapsz, hdrsz; cl_fmap_t *m; int pgsz = cli_getpagesize(); if((off_t)offset < 0 || offset != fmap_align_to(offset, pgsz)) { cli_warnmsg("fmap: attempted mapping with unaligned offset\n"); return NULL; } if(!len) { cli_dbgmsg("fmap: attempted void mapping\n"); return NULL; } if (offset >= len) { cli_warnmsg("fmap: attempted oof mapping\n"); return NULL; } pages = fmap_align_items(len, pgsz); hdrsz = fmap_align_to(sizeof(fmap_t) + (pages-1) * sizeof(uint32_t), pgsz); /* fmap_t includes 1 bitmap slot, hence (pages-1) */ mapsz = pages * pgsz + hdrsz; #ifndef ANONYMOUS_MAP use_aging = 0; #endif #ifdef ANONYMOUS_MAP if (use_aging) { fmap_lock; if ((m = (fmap_t *)mmap(NULL, mapsz, PROT_READ | PROT_WRITE, MAP_PRIVATE|/*FIXME: MAP_POPULATE is ~8% faster but more memory intensive */ANONYMOUS_MAP, -1, 0)) == MAP_FAILED) { m = NULL; } else { #if HAVE_MADVISE madvise((void *)m, mapsz, MADV_RANDOM|MADV_DONTFORK); #endif /* madvise */ /* fault the header while we still have the lock - we DO context switch here a lot here :@ */ memset(fmap_bitmap, 0, sizeof(uint32_t) * pages); } fmap_unlock; } #endif /* ANONYMOUS_MAP */ if (!use_aging) { m = (fmap_t *)cli_malloc(mapsz); if (!(m)) { cli_warnmsg("fmap: map allocation failed\n"); return NULL; } memset(m, 0, hdrsz); } if(!m) { cli_warnmsg("fmap: map allocation failed\n"); return NULL; } m->handle = handle; m->pread_cb = pread_cb; m->aging = use_aging; m->offset = offset; m->nested_offset = 0; m->len = len;/* m->nested_offset + m->len = m->real_len */ m->real_len = len; m->pages = pages; m->hdrsz = hdrsz; m->pgsz = pgsz; m->paged = 0; m->dont_cache_flag = 0; m->unmap = use_aging ? unmap_mmap : unmap_malloc; m->need = handle_need; m->need_offstr = handle_need_offstr; m->gets = handle_gets; m->unneed_off = handle_unneed_off; return m; }
fmap_t *fmap_check_empty(int fd, off_t offset, size_t len, int *empty) { unsigned int pages, mapsz, hdrsz; unsigned short dumb = 1; int pgsz = cli_getpagesize(); struct stat st; fmap_t *m; *empty = 0; if(fstat(fd, &st)) { cli_warnmsg("fmap: fstat failed\n"); return NULL; } if(offset < 0 || offset != fmap_align_to(offset, pgsz)) { cli_warnmsg("fmap: attempted mapping with unaligned offset\n"); return NULL; } if(!len) len = st.st_size - offset; /* bound checked later */ if(!len) { cli_dbgmsg("fmap: attempted void mapping\n"); *empty = 1; return NULL; } if(!CLI_ISCONTAINED(0, st.st_size, offset, len)) { cli_warnmsg("fmap: attempted oof mapping\n"); return NULL; } pages = fmap_align_items(len, pgsz); hdrsz = fmap_align_to(sizeof(fmap_t) + (pages-1) * sizeof(uint32_t), pgsz); /* fmap_t includes 1 bitmap slot, hence (pages-1) */ mapsz = pages * pgsz + hdrsz; fmap_lock; #ifdef ANONYMOUS_MAP if ((m = (fmap_t *)mmap(NULL, mapsz, PROT_READ | PROT_WRITE, MAP_PRIVATE|/*FIXME: MAP_POPULATE is ~8% faster but more memory intensive */ANONYMOUS_MAP, -1, 0)) == MAP_FAILED) { m = NULL; } else { dumb = 0; #if HAVE_MADVISE madvise((void *)m, mapsz, MADV_RANDOM|MADV_DONTFORK); #endif /* madvise */ } #else /* ! ANONYMOUS_MAP */ m = (fmap_t *)cli_malloc(mapsz); #endif /* ANONYMOUS_MAP */ if(!m) { cli_warnmsg("fmap: map allocation failed\n"); fmap_unlock; return NULL; } /* fault the header while we still have the lock - we DO context switch here a lot here :@ */ memset(fmap_bitmap, 0, sizeof(uint32_t) * pages); fmap_unlock; m->fd = fd; m->dumb = dumb; m->mtime = st.st_mtime; m->offset = offset; m->len = len; m->pages = pages; m->hdrsz = hdrsz; m->pgsz = pgsz; m->paged = 0; m->dont_cache_flag = 0; return m; }
fmap_t *fmap_check_empty(int fd, off_t offset, size_t len, int *empty) { /* WIN32 */ unsigned int pages, mapsz, hdrsz; unsigned short dumb = 1; int pgsz = cli_getpagesize(); struct stat st; fmap_t *m; *empty = 0; if(fstat(fd, &st)) { cli_warnmsg("fmap: fstat failed\n"); return NULL; } if(offset < 0 || offset != fmap_align_to(offset, pgsz)) { cli_warnmsg("fmap: attempted mapping with unaligned offset\n"); return NULL; } if(!len) len = st.st_size - offset; /* bound checked later */ if(!len) { cli_dbgmsg("fmap: attempted void mapping\n"); *empty = 1; return NULL; } if(!CLI_ISCONTAINED(0, st.st_size, offset, len)) { cli_warnmsg("fmap: attempted oof mapping\n"); return NULL; } pages = fmap_align_items(len, pgsz); hdrsz = fmap_align_to(sizeof(fmap_t), pgsz); if(!(m = (fmap_t *)cli_malloc(sizeof(fmap_t)))) { cli_errmsg("fmap: canot allocate fmap_t\n", fd); return NULL; } if((m->fh = (HANDLE)_get_osfhandle(fd)) == INVALID_HANDLE_VALUE) { cli_errmsg("fmap: cannot get a valid handle for descriptor %d\n", fd); free(m); return NULL; } if(!(m->mh = CreateFileMapping(m->fh, NULL, PAGE_READONLY, (DWORD)((len>>31)>>1), (DWORD)len, NULL))) { cli_errmsg("fmap: cannot create a map of descriptor %d\n", fd); free(m); return NULL; } if(!(m->data = MapViewOfFile(m->mh, FILE_MAP_READ, (DWORD)((offset>>31)>>1), (DWORD)(offset), len))) { cli_errmsg("fmap: cannot map file descriptor %d\n", fd); CloseHandle(m->mh); free(m); return NULL; } m->fd = fd; m->dumb = dumb; m->mtime = st.st_mtime; m->offset = offset; m->len = len; m->pages = pages; m->hdrsz = hdrsz; m->pgsz = pgsz; m->paged = 0; m->dont_cache_flag = 0; return m; }