Git fork
at reftables-rust 179 lines 3.8 kB view raw
1/* 2 * Copyright 2020 Google LLC 3 * 4 * Use of this source code is governed by a BSD-style 5 * license that can be found in the LICENSE file or at 6 * https://developers.google.com/open-source/licenses/bsd 7 */ 8 9#include "system.h" 10 11#include "basics.h" 12#include "blocksource.h" 13#include "reftable-blocksource.h" 14#include "reftable-error.h" 15 16void block_source_release_data(struct reftable_block_data *data) 17{ 18 struct reftable_block_source source = data->source; 19 if (data && source.ops) 20 source.ops->release_data(source.arg, data); 21 data->data = NULL; 22 data->len = 0; 23 data->source.ops = NULL; 24 data->source.arg = NULL; 25} 26 27void block_source_close(struct reftable_block_source *source) 28{ 29 if (!source->ops) { 30 return; 31 } 32 33 source->ops->close(source->arg); 34 source->ops = NULL; 35} 36 37ssize_t block_source_read_data(struct reftable_block_source *source, 38 struct reftable_block_data *dest, uint64_t off, 39 uint32_t size) 40{ 41 ssize_t result = source->ops->read_data(source->arg, dest, off, size); 42 dest->source = *source; 43 return result; 44} 45 46uint64_t block_source_size(struct reftable_block_source *source) 47{ 48 return source->ops->size(source->arg); 49} 50 51static void reftable_buf_release_data(void *b REFTABLE_UNUSED, struct reftable_block_data *dest) 52{ 53 if (dest->len) 54 memset(dest->data, 0xff, dest->len); 55 reftable_free(dest->data); 56} 57 58static void reftable_buf_close(void *b REFTABLE_UNUSED) 59{ 60} 61 62static ssize_t reftable_buf_read_data(void *v, struct reftable_block_data *dest, 63 uint64_t off, uint32_t size) 64{ 65 struct reftable_buf *b = v; 66 assert(off + size <= b->len); 67 REFTABLE_CALLOC_ARRAY(dest->data, size); 68 if (!dest->data) 69 return -1; 70 memcpy(dest->data, b->buf + off, size); 71 dest->len = size; 72 return size; 73} 74 75static uint64_t reftable_buf_size(void *b) 76{ 77 return ((struct reftable_buf *)b)->len; 78} 79 80static struct reftable_block_source_vtable reftable_buf_vtable = { 81 .size = &reftable_buf_size, 82 .read_data = &reftable_buf_read_data, 83 .release_data = &reftable_buf_release_data, 84 .close = &reftable_buf_close, 85}; 86 87void block_source_from_buf(struct reftable_block_source *bs, 88 struct reftable_buf *buf) 89{ 90 assert(!bs->ops); 91 bs->ops = &reftable_buf_vtable; 92 bs->arg = buf; 93} 94 95struct file_block_source { 96 uint64_t size; 97 unsigned char *data; 98}; 99 100static uint64_t file_size(void *b) 101{ 102 return ((struct file_block_source *)b)->size; 103} 104 105static void file_release_data(void *b REFTABLE_UNUSED, struct reftable_block_data *dest REFTABLE_UNUSED) 106{ 107} 108 109static void file_close(void *v) 110{ 111 struct file_block_source *b = v; 112 munmap(b->data, b->size); 113 reftable_free(b); 114} 115 116static ssize_t file_read_data(void *v, struct reftable_block_data *dest, uint64_t off, 117 uint32_t size) 118{ 119 struct file_block_source *b = v; 120 assert(off + size <= b->size); 121 dest->data = b->data + off; 122 dest->len = size; 123 return size; 124} 125 126static struct reftable_block_source_vtable file_vtable = { 127 .size = &file_size, 128 .read_data = &file_read_data, 129 .release_data = &file_release_data, 130 .close = &file_close, 131}; 132 133int reftable_block_source_from_file(struct reftable_block_source *bs, 134 const char *name) 135{ 136 struct file_block_source *p = NULL; 137 struct stat st; 138 int fd, err; 139 140 fd = open(name, O_RDONLY); 141 if (fd < 0) { 142 if (errno == ENOENT) 143 return REFTABLE_NOT_EXIST_ERROR; 144 err = -1; 145 goto out; 146 } 147 148 if (fstat(fd, &st) < 0) { 149 err = REFTABLE_IO_ERROR; 150 goto out; 151 } 152 153 REFTABLE_CALLOC_ARRAY(p, 1); 154 if (!p) { 155 err = REFTABLE_OUT_OF_MEMORY_ERROR; 156 goto out; 157 } 158 159 p->size = st.st_size; 160 p->data = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); 161 if (p->data == MAP_FAILED) { 162 err = REFTABLE_IO_ERROR; 163 p->data = NULL; 164 goto out; 165 } 166 167 assert(!bs->ops); 168 bs->ops = &file_vtable; 169 bs->arg = p; 170 171 err = 0; 172 173out: 174 if (fd >= 0) 175 close(fd); 176 if (err < 0) 177 reftable_free(p); 178 return err; 179}