/* blocks.c -- the kernel serves a node's block requests. See blocks.h. * * This is the one file of v4's that includes v3's headers: every block goes * through v3's own calls. */ #include "v4/blocks.h" #include "block_subsystem.h" int v4_blocks_serve(v4_node *n, v4_cell request) { v4_cell addr, num; uint32_t block; uint8_t *b; unsigned i; int status; if (request != V4_REQ_BLOCK_READ && request != V4_REQ_BLOCK_WRITE) return 0; addr = v4_dstack_pop(&n->ds); num = v4_dstack_pop(&n->ds); block = (uint32_t)num; if (!v4_node_addr_ok(addr) || !v4_node_addr_ok(addr + (v4_cell)(V4_BLOCK_CELLS - 1u))) { status = V4_BLOCK_REFUSED; } else if (num < 1 || (uint64_t)num > 0xFFFFFFFFull || !blk_is_valid(block)) { status = V4_BLOCK_RANGE; } else if (request == V4_REQ_BLOCK_READ) { b = blk_get_buffer(block, 0); status = b ? V4_BLOCK_OK : V4_BLOCK_REFUSED; if (b) for (i = 0; i < V4_BLOCK_CELLS; i++) n->mem[addr + (v4_cell)i] = (v4_cell)((v4_ucell)b[4u * i] | ((v4_ucell)b[4u * i + 1u] << 8) | ((v4_ucell)b[4u * i + 2u] << 16) | ((v4_ucell)b[4u * i + 3u] << 24)); } else { b = blk_get_buffer(block, 1); status = V4_BLOCK_REFUSED; if (b) { for (i = 0; i < V4_BLOCK_CELLS; i++) { v4_ucell w = (v4_ucell)n->mem[addr + (v4_cell)i]; b[4u * i] = (uint8_t)(w & 0xFFu); b[4u * i + 1u] = (uint8_t)((w >> 8) & 0xFFu); b[4u * i + 2u] = (uint8_t)((w >> 16) & 0xFFu); b[4u * i + 3u] = (uint8_t)((w >> 24) & 0xFFu); } if (blk_update(block) == BLK_OK && blk_flush(block) == BLK_OK) status = V4_BLOCK_OK; } } v4_dstack_push(&n->ds, (v4_cell)status); return 1; }