int hash_insert(struct hash *hash, const char *key, void *mem, free_func *freer) { unsigned i, h; struct hash_bucket *bucket = malloc(sizeof *bucket), *iter; if (!bucket) return -1; bucket->key = string_dup(key); if (!bucket->key) { free(bucket); return -1; } bucket->mem = mem; h = hashstr(key, hash->max_size); for (i = 0; i < hash->buckets[h].length; ++i) { darray_at(&hash->buckets[h], i, (void **)&iter); if (!strcmp(iter->key, bucket->key)) { if (freer) freer(hash->buckets[h].mem[i]); hash->buckets[h].mem[i] = bucket; return 0; } } darray_push_back(&hash->buckets[h], bucket); return 0; }
void darray_pop_back(struct darray *arr, free_func *freer) { if (freer) freer(arr->mem[--arr->length]); else arr->length--; }
void pqueue_uninit(struct pqueue *pq, free_func *freer) { unsigned i; if (freer) for (i = 1; i < pq->length + 1; ++i) freer(pq->mem[i]); free(pq->mem); }
void darray_remove(struct darray *arr, free_func *freer, int pos) { if (freer) freer(arr->mem[pos]); arr->length--; memmove(&arr->mem[pos], &arr->mem[pos + 1], sizeof *arr->mem * (arr->length - pos)); }
void stack_pop(struct stack *s, free_func *freer) { struct stack_node *tofree = s->top; s->top = s->top->below; if (freer) freer(tofree->mem); free(tofree); }
void queue_dequeue(struct queue *q, free_func *freer) { struct queue_node *tofree = q->bot; q->bot = q->bot->next; if (!q->bot) q->top = NULL; if (freer) freer(tofree->mem); free(tofree); }
void hash_uninit(struct hash *hash, free_func *freer) { unsigned i, j; struct hash_bucket *iter; for (i = 0; i < hash->max_size; ++i) { for (j = 0; j < hash->buckets[i].length; ++j) { darray_at(&hash->buckets[i], j, (void **)&iter); free(iter->key); if (freer) freer(iter->mem); } darray_uninit(&hash->buckets[i], free); } free(hash->buckets); }
void guestfs_set_private (guestfs_h *g, const char *key, void *data) { if (g->pda == NULL) { g->pda = hash_initialize (16, NULL, hasher, comparator, freer); if (g->pda == NULL) g->abort_cb (); } struct pda_entry *new_entry = safe_malloc (g, sizeof *new_entry); new_entry->key = safe_strdup (g, key); new_entry->data = data; struct pda_entry *old_entry = hash_delete (g->pda, new_entry); freer (old_entry); struct pda_entry *entry = hash_insert (g->pda, new_entry); if (entry == NULL) g->abort_cb (); assert (entry == new_entry); }
void pqueue_pop_max(struct pqueue *pq, free_func *freer, comp_func *comp) { unsigned i, child; void *tofree = pq->mem[1]; void *last = pq->mem[pq->length--]; if (freer) freer(tofree); for (i = 1; i * 2 <= pq->length; i = child) { child = i * 2; if (child != pq->length && comp(pq->mem[child], pq->mem[child + 1]) < 0) child++; if (comp(last, pq->mem[child]) < 0) pq->mem[i] = pq->mem[child]; else break; } pq->mem[i] = last; }
static const struct stat * lsc_lookup (guestfs_h *g, const char *pathname) { const struct entry_common key = { .pathname = (char *) pathname }; struct lsc_entry *entry; time_t now; time (&now); entry = hash_lookup (g->lsc_ht, &key); if (entry && entry->c.timeout >= now) return &entry->statbuf; else return NULL; } static const struct guestfs_xattr_list * xac_lookup (guestfs_h *g, const char *pathname) { const struct entry_common key = { .pathname = (char *) pathname }; struct xac_entry *entry; time_t now; time (&now); entry = hash_lookup (g->xac_ht, &key); if (entry && entry->c.timeout >= now) return entry->xattrs; else return NULL; } static const char * rlc_lookup (guestfs_h *g, const char *pathname) { const struct entry_common key = { .pathname = (char *) pathname }; struct rlc_entry *entry; time_t now; time (&now); entry = hash_lookup (g->rlc_ht, &key); if (entry && entry->c.timeout >= now) return entry->link; else return NULL; } static void gen_remove (Hash_table *ht, const char *pathname, Hash_data_freer freer) { const struct entry_common key = { .pathname = (char *) pathname }; struct entry_common *entry; entry = hash_delete (ht, &key); freer (entry); } static void dir_cache_invalidate (guestfs_h *g, const char *path) { gen_remove (g->lsc_ht, path, lsc_free); gen_remove (g->xac_ht, path, xac_free); gen_remove (g->rlc_ht, path, rlc_free); } #else /* !HAVE_FUSE */ #define FUSE_NOT_SUPPORTED() \ NOT_SUPPORTED (g, -1, _("FUSE is not supported in this build of " \ "libguestfs because libfuse was not found " \ "when libguestfs was compiled")) int guestfs_impl_mount_local (guestfs_h *g, const char *localmountpoint, const struct guestfs_mount_local_argv *optargs) { FUSE_NOT_SUPPORTED (); } int guestfs_impl_mount_local_run (guestfs_h *g) { FUSE_NOT_SUPPORTED (); } int guestfs_impl_umount_local (guestfs_h *g, const struct guestfs_umount_local_argv *optargs) { FUSE_NOT_SUPPORTED (); }
static const struct stat * lsc_lookup (guestfs_h *g, const char *pathname) { const struct lsc_entry key = { .pathname = (char *) pathname }; struct lsc_entry *entry; time_t now; time (&now); entry = hash_lookup (g->lsc_ht, &key); if (entry && entry->timeout >= now) return &entry->statbuf; else return NULL; } static const struct guestfs_xattr_list * xac_lookup (guestfs_h *g, const char *pathname) { const struct xac_entry key = { .pathname = (char *) pathname }; struct xac_entry *entry; time_t now; time (&now); entry = hash_lookup (g->xac_ht, &key); if (entry && entry->timeout >= now) return entry->xattrs; else return NULL; } static const char * rlc_lookup (guestfs_h *g, const char *pathname) { const struct rlc_entry key = { .pathname = (char *) pathname }; struct rlc_entry *entry; time_t now; time (&now); entry = hash_lookup (g->rlc_ht, &key); if (entry && entry->timeout >= now) return entry->link; else return NULL; } static void lsc_remove (Hash_table *ht, const char *pathname, Hash_data_freer freer) { const struct lsc_entry key = { .pathname = (char *) pathname }; struct lsc_entry *entry; entry = hash_delete (ht, &key); freer (entry); } static void dir_cache_invalidate (guestfs_h *g, const char *path) { lsc_remove (g->lsc_ht, path, lsc_free); lsc_remove (g->xac_ht, path, xac_free); lsc_remove (g->rlc_ht, path, rlc_free); } #else /* !HAVE_FUSE */ int guestfs__mount_local (guestfs_h *g, const char *localmountpoint, const struct guestfs_mount_local_argv *optargs) { guestfs_error_errno (g, ENOTSUP, _("FUSE not supported")); return -1; } int guestfs__mount_local_run (guestfs_h *g) { guestfs_error_errno (g, ENOTSUP, _("FUSE not supported")); return -1; } int guestfs__umount_local (guestfs_h *g, const struct guestfs_umount_local_argv *optargs) { guestfs_error_errno (g, ENOTSUP, _("FUSE not supported")); return -1; }