/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* Chunk I/O * ========= * Copyright 2018 Eduardo Silva * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include #include struct cio_memfs *cio_memfs_open(struct cio_ctx *ctx, struct cio_stream *st, struct cio_chunk *ch, int flags, size_t size) { struct cio_memfs *mf; (void) flags; (void) ctx; (void) ch; (void) st; mf = calloc(1, sizeof(struct cio_memfs)); if (!mf) { cio_errno(); return NULL; } mf->crc_cur = cio_crc32_init(); mf->buf_data = malloc(size); if (!mf->buf_data) { cio_errno(); free(mf->name); free(mf); return NULL; } mf->buf_size = size; mf->buf_len = 0; if (ctx->realloc_size_hint > 0) { mf->realloc_size = ctx->realloc_size_hint; } else { mf->realloc_size = cio_getpagesize() * 8; } return mf; } void cio_memfs_close(struct cio_chunk *ch) { struct cio_memfs *mf = ch->backend; if (!mf) { return; } free(mf->name); free(mf->buf_data); free(mf->meta_data); free(mf); } int cio_memfs_write(struct cio_chunk *ch, const void *buf, size_t count) { size_t av_size; size_t new_size; char *tmp; struct cio_memfs *mf = ch->backend; if (count == 0) { return 0; } /* Calculate available size */ av_size = (mf->buf_size - mf->buf_len); if (av_size < count) { /* Suggest initial new size */ new_size = mf->buf_size + mf->realloc_size; while (new_size < (mf->buf_len + count)) { new_size += mf->realloc_size; } tmp = realloc(mf->buf_data, new_size); if (!tmp) { cio_errno(); return -1; } mf->buf_data = tmp; mf->buf_size = new_size; } memcpy(mf->buf_data + mf->buf_len, buf, count); mf->buf_len += count; return 0; } int cio_memfs_content_copy(struct cio_chunk *ch, void **out_buf, size_t *out_size) { char *buf; struct cio_memfs *mf = ch->backend; buf = malloc(mf->buf_len + 1); if (!buf) { cio_errno(); return -1; } /* Copy the data and append an extra NULL byte */ memcpy(buf, mf->buf_data, mf->buf_len); buf[mf->buf_len] = '\0'; *out_buf = buf; *out_size = mf->buf_len; return 0; } void cio_memfs_scan_dump(struct cio_ctx *ctx, struct cio_stream *st) { char tmp[PATH_MAX]; struct mk_list *head; struct cio_memfs *mf; struct cio_chunk *ch; (void) ctx; mk_list_foreach(head, &st->chunks) { ch = mk_list_entry(head, struct cio_chunk, _head); mf = ch->backend; snprintf(tmp, sizeof(tmp) -1, "%s/%s", ch->st->name, ch->name); printf(" %-60s", tmp); printf("meta_len=%i, data_size=%zu\n", mf->meta_len, mf->buf_len); } }