void libxl__ptr_add(libxl__gc *gc, void *ptr) { int i; if (!libxl__gc_is_real(gc)) return; if (!ptr) return; /* fast case: we have space in the array for storing the pointer */ for (i = 0; i < gc->alloc_maxsize; i++) { if (!gc->alloc_ptrs[i]) { gc->alloc_ptrs[i] = ptr; return; } } int new_maxsize = gc->alloc_maxsize * 2 + 25; assert(new_maxsize < INT_MAX / sizeof(void*) / 2); gc->alloc_ptrs = realloc(gc->alloc_ptrs, new_maxsize * sizeof(void *)); if (!gc->alloc_ptrs) libxl__alloc_failed(CTX, __func__, new_maxsize, sizeof(void*)); gc->alloc_ptrs[gc->alloc_maxsize++] = ptr; while (gc->alloc_maxsize < new_maxsize) gc->alloc_ptrs[gc->alloc_maxsize++] = 0; return; }
void *libxl__calloc(libxl__gc *gc, size_t nmemb, size_t size) { void *ptr = calloc(nmemb, size); if (!ptr) libxl__alloc_failed(CTX, __func__, nmemb, size); libxl__ptr_add(gc, ptr); return ptr; }
void *libxl__malloc(libxl__gc *gc, size_t size) { void *ptr = malloc(size); if (!ptr) libxl__alloc_failed(CTX, __func__, size, 1); libxl__ptr_add(gc, ptr); return ptr; }
void *libxl__zalloc(libxl__gc *gc, int bytes) { void *ptr = calloc(bytes, 1); if (!ptr) libxl__alloc_failed(CTX, __func__, bytes, 1); libxl__ptr_add(gc, ptr); return ptr; }
char *libxl__strndup(libxl__gc *gc, const char *c, size_t n) { char *s = strndup(c, n); if (!s) libxl__alloc_failed(CTX, __func__, n, 1); return s; }
char *libxl__strdup(libxl__gc *gc, const char *c) { char *s = strdup(c); if (!s) libxl__alloc_failed(CTX, __func__, strlen(c), 1); libxl__ptr_add(gc, s); return s; }
char *libxl__strndup(libxl__gc *gc, const char *c, size_t n) { char *s; if (!c) return NULL; s = strndup(c, n); if (!s) libxl__alloc_failed(CTX, __func__, n, 1); libxl__ptr_add(gc, s); return s; }
void *libxl__realloc(libxl__gc *gc, void *ptr, size_t new_size) { void *new_ptr = realloc(ptr, new_size); int i = 0; if (new_ptr == NULL && new_size != 0) libxl__alloc_failed(CTX, __func__, new_size, 1); if (ptr == NULL) { libxl__ptr_add(gc, new_ptr); } else if (new_ptr != ptr && libxl__gc_is_real(gc)) { for (i = 0; i < gc->alloc_maxsize; i++) { if (gc->alloc_ptrs[i] == ptr) { gc->alloc_ptrs[i] = new_ptr; break; } } } return new_ptr; }
static void datacopier_readable(libxl__egc *egc, libxl__ev_fd *ev, int fd, short events, short revents) { libxl__datacopier_state *dc = CONTAINER_OF(ev, *dc, toread); STATE_AO_GC(dc->ao); if (datacopier_pollhup_handled(egc, dc, revents, 0)) return; if (revents & ~POLLIN) { LOG(ERROR, "unexpected poll event 0x%x (should be POLLIN)" " on %s during copy of %s", revents, dc->readwhat, dc->copywhat); datacopier_callback(egc, dc, -1, 0); return; } assert(revents & POLLIN); for (;;) { while (dc->used >= dc->maxsz) { libxl__datacopier_buf *rm = LIBXL_TAILQ_FIRST(&dc->bufs); dc->used -= rm->used; assert(dc->used >= 0); LIBXL_TAILQ_REMOVE(&dc->bufs, rm, entry); free(rm); } libxl__datacopier_buf *buf = LIBXL_TAILQ_LAST(&dc->bufs, libxl__datacopier_bufs); if (!buf || buf->used >= sizeof(buf->buf)) { buf = malloc(sizeof(*buf)); if (!buf) libxl__alloc_failed(CTX, __func__, 1, sizeof(*buf)); buf->used = 0; LIBXL_TAILQ_INSERT_TAIL(&dc->bufs, buf, entry); } int r = read(ev->fd, buf->buf + buf->used, sizeof(buf->buf) - buf->used); if (r < 0) { if (errno == EINTR) continue; if (errno == EWOULDBLOCK) break; LOGE(ERROR, "error reading %s during copy of %s", dc->readwhat, dc->copywhat); datacopier_callback(egc, dc, 0, errno); return; } if (r == 0) { libxl__ev_fd_deregister(gc, &dc->toread); break; } if (dc->log) { int wrote = fwrite(buf->buf + buf->used, 1, r, dc->log); if (wrote != r) { assert(ferror(dc->log)); assert(errno); LOGE(ERROR, "error logging %s", dc->copywhat); datacopier_callback(egc, dc, 0, errno); return; } } buf->used += r; dc->used += r; assert(buf->used <= sizeof(buf->buf)); } datacopier_check_state(egc, dc); }