static int amf0_encode_ref(amf_buf *buf, lua_State *L, int idx, int ridx) { int ref; /* lookup in the ref table */ lua_pushvalue(L, idx); lua_rawget(L, ridx); ref = (lua_isnumber(L, -1) ? lua_tonumber(L, -1) : -1); lua_pop(L, 1); if (ref >= 0) { amf_buf_append_char(buf, AMF0_REFERENCE); if (ref > UINT16_MAX) { luaL_error(L, "amf0 reference overflow"); } amf_buf_append_u16(buf, ref); } else { save_ref(L, idx, ridx); } return ref; }
static int amf3_encode_ref(lua_State *L, amf_buf *buf, int idx, int ridx) { abs_idx(L, idx); lua_pushvalue(L, idx); lua_rawget(L, ridx); int ref = lua_isnumber(L, -1) ? lua_tonumber(L, -1) : -1; lua_pop(L, 1); if (ref >= 0) { if (ref > AMF3_MAX_REFERENCES) { luaL_error(L, "amf reference count overflow"); } amf_buf_append_u29(buf, ref << 1); } else { save_ref(L, idx, ridx); } return ref; }
static int next (struct grub_btrfs_data *data, struct grub_btrfs_leaf_descriptor *desc, grub_disk_addr_t *outaddr, grub_size_t *outsize, struct grub_btrfs_key *key_out) { grub_err_t err; struct grub_btrfs_leaf_node leaf; for (; desc->depth > 0; desc->depth--) { desc->data[desc->depth - 1].iter++; if (desc->data[desc->depth - 1].iter < desc->data[desc->depth - 1].maxiter) break; } if (desc->depth == 0) return 0; while (!desc->data[desc->depth - 1].leaf) { struct grub_btrfs_internal_node node; struct btrfs_header head; err = grub_btrfs_read_logical (data, desc->data[desc->depth - 1].iter * sizeof (node) + sizeof (struct btrfs_header) + desc->data[desc->depth - 1].addr, &node, sizeof (node)); if (err) return -err; err = grub_btrfs_read_logical (data, grub_le_to_cpu64 (node.addr), &head, sizeof (head)); if (err) return -err; save_ref (desc, grub_le_to_cpu64 (node.addr), 0, grub_le_to_cpu32 (head.nitems), !head.level); } err = grub_btrfs_read_logical (data, desc->data[desc->depth - 1].iter * sizeof (leaf) + sizeof (struct btrfs_header) + desc->data[desc->depth - 1].addr, &leaf, sizeof (leaf)); if (err) return -err; *outsize = grub_le_to_cpu32 (leaf.size); *outaddr = desc->data[desc->depth - 1].addr + sizeof (struct btrfs_header) + grub_le_to_cpu32 (leaf.offset); *key_out = leaf.key; return 1; }
static grub_err_t lower_bound (struct grub_btrfs_data *data, const struct grub_btrfs_key *key_in, struct grub_btrfs_key *key_out, grub_disk_addr_t root, grub_disk_addr_t *outaddr, grub_size_t *outsize, struct grub_btrfs_leaf_descriptor *desc) { grub_disk_addr_t addr = root; int depth = -1; if (desc) { desc->allocated = 16; desc->depth = 0; desc->data = grub_malloc (sizeof (desc->data[0]) * desc->allocated); if (!desc->data) return grub_errno; } grub_dprintf ("btrfs", "retrieving %" PRIxGRUB_UINT64_T " %x %" PRIxGRUB_UINT64_T "\n", key_in->object_id, key_in->type, key_in->offset); while (1) { grub_err_t err; struct btrfs_header head; reiter: depth++; /* FIXME: preread few nodes into buffer. */ err = grub_btrfs_read_logical (data, addr, &head, sizeof (head)); if (err) return err; addr += sizeof (head); if (head.level) { unsigned i; struct grub_btrfs_internal_node node, node_last; int have_last = 0; grub_memset (&node_last, 0, sizeof (node_last)); for (i = 0; i < grub_le_to_cpu32 (head.nitems); i++) { err = grub_btrfs_read_logical (data, addr + i * sizeof (node), &node, sizeof (node)); if (err) return err; grub_dprintf ("btrfs", "internal node (depth %d) %" PRIxGRUB_UINT64_T " %x %" PRIxGRUB_UINT64_T "\n", depth, node.key.object_id, node.key.type, node.key.offset); if (key_cmp (&node.key, key_in) == 0) { err = GRUB_ERR_NONE; if (desc) err = save_ref (desc, addr - sizeof (head), i, grub_le_to_cpu32 (head.nitems), 0); if (err) return err; addr = grub_le_to_cpu64 (node.addr); goto reiter; } if (key_cmp (&node.key, key_in) > 0) break; node_last = node; have_last = 1; } if (have_last) { err = GRUB_ERR_NONE; if (desc) err = save_ref (desc, addr - sizeof (head), i - 1, grub_le_to_cpu32 (head.nitems), 0); if (err) return err; addr = grub_le_to_cpu64 (node_last.addr); goto reiter; } *outsize = 0; *outaddr = 0; grub_memset (key_out, 0, sizeof (*key_out)); if (desc) return save_ref (desc, addr - sizeof (head), -1, grub_le_to_cpu32 (head.nitems), 0); return GRUB_ERR_NONE; } { unsigned i; struct grub_btrfs_leaf_node leaf, leaf_last; int have_last = 0; for (i = 0; i < grub_le_to_cpu32 (head.nitems); i++) { err = grub_btrfs_read_logical (data, addr + i * sizeof (leaf), &leaf, sizeof (leaf)); if (err) return err; grub_dprintf ("btrfs", "leaf (depth %d) %" PRIxGRUB_UINT64_T " %x %" PRIxGRUB_UINT64_T "\n", depth, leaf.key.object_id, leaf.key.type, leaf.key.offset); if (key_cmp (&leaf.key, key_in) == 0) { grub_memcpy (key_out, &leaf.key, sizeof(*key_out)); *outsize = grub_le_to_cpu32 (leaf.size); *outaddr = addr + grub_le_to_cpu32 (leaf.offset); if (desc) return save_ref (desc, addr - sizeof (head), i, grub_le_to_cpu32 (head.nitems), 1); return GRUB_ERR_NONE; } if (key_cmp (&leaf.key, key_in) > 0) break; have_last = 1; leaf_last = leaf; } if (have_last) { grub_memcpy (key_out, &leaf_last.key, sizeof(*key_out)); *outsize = grub_le_to_cpu32 (leaf_last.size); *outaddr = addr + grub_le_to_cpu32 (leaf_last.offset); if (desc) return save_ref (desc, addr - sizeof (head), i - 1, grub_le_to_cpu32 (head.nitems), 1); return GRUB_ERR_NONE; } *outsize = 0; *outaddr = 0; grub_memset (key_out, 0, sizeof (*key_out)); if (desc) return save_ref (desc, addr - sizeof (head), -1, grub_le_to_cpu32 (head.nitems), 1); return GRUB_ERR_NONE; } } }