1228753Smm/*- 2228753Smm * Copyright (c) 2003-2007 Tim Kientzle 3228753Smm * All rights reserved. 4228753Smm * 5228753Smm * Redistribution and use in source and binary forms, with or without 6228753Smm * modification, are permitted provided that the following conditions 7228753Smm * are met: 8228753Smm * 1. Redistributions of source code must retain the above copyright 9228753Smm * notice, this list of conditions and the following disclaimer. 10228753Smm * 2. Redistributions in binary form must reproduce the above copyright 11228753Smm * notice, this list of conditions and the following disclaimer in the 12228753Smm * documentation and/or other materials provided with the distribution. 13228753Smm * 14228753Smm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 15228753Smm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16228753Smm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17228753Smm * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 18228753Smm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19228753Smm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20228753Smm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21228753Smm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22228753Smm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23228753Smm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24228753Smm */ 25228753Smm 26228753Smm#include "archive_platform.h" 27228763Smm__FBSDID("$FreeBSD: stable/10/contrib/libarchive/libarchive/archive_write_open_memory.c 368708 2020-12-16 22:25:40Z mm $"); 28228753Smm 29228753Smm#include <errno.h> 30228753Smm#include <stdlib.h> 31228753Smm#include <string.h> 32228753Smm 33228753Smm#include "archive.h" 34228753Smm 35228753Smmstruct write_memory_data { 36228753Smm size_t used; 37228753Smm size_t size; 38228753Smm size_t * client_size; 39228753Smm unsigned char * buff; 40228753Smm}; 41228753Smm 42368708Smmstatic int memory_write_free(struct archive *, void *); 43228753Smmstatic int memory_write_open(struct archive *, void *); 44228753Smmstatic ssize_t memory_write(struct archive *, void *, const void *buff, size_t); 45228753Smm 46228753Smm/* 47228753Smm * Client provides a pointer to a block of memory to receive 48228753Smm * the data. The 'size' param both tells us the size of the 49228753Smm * client buffer and lets us tell the client the final size. 50228753Smm */ 51228753Smmint 52228753Smmarchive_write_open_memory(struct archive *a, void *buff, size_t buffSize, size_t *used) 53228753Smm{ 54228753Smm struct write_memory_data *mine; 55228753Smm 56311042Smm mine = (struct write_memory_data *)calloc(1, sizeof(*mine)); 57228753Smm if (mine == NULL) { 58228753Smm archive_set_error(a, ENOMEM, "No memory"); 59228753Smm return (ARCHIVE_FATAL); 60228753Smm } 61228753Smm mine->buff = buff; 62228753Smm mine->size = buffSize; 63228753Smm mine->client_size = used; 64368708Smm return (archive_write_open2(a, mine, 65368708Smm memory_write_open, memory_write, NULL, memory_write_free)); 66228753Smm} 67228753Smm 68228753Smmstatic int 69228753Smmmemory_write_open(struct archive *a, void *client_data) 70228753Smm{ 71228753Smm struct write_memory_data *mine; 72228753Smm mine = client_data; 73228753Smm mine->used = 0; 74228753Smm if (mine->client_size != NULL) 75228753Smm *mine->client_size = mine->used; 76228753Smm /* Disable padding if it hasn't been set explicitly. */ 77228753Smm if (-1 == archive_write_get_bytes_in_last_block(a)) 78228753Smm archive_write_set_bytes_in_last_block(a, 1); 79228753Smm return (ARCHIVE_OK); 80228753Smm} 81228753Smm 82228753Smm/* 83228753Smm * Copy the data into the client buffer. 84228753Smm * Note that we update mine->client_size on every write. 85228753Smm * In particular, this means the client can follow exactly 86228753Smm * how much has been written into their buffer at any time. 87228753Smm */ 88228753Smmstatic ssize_t 89228753Smmmemory_write(struct archive *a, void *client_data, const void *buff, size_t length) 90228753Smm{ 91228753Smm struct write_memory_data *mine; 92228753Smm mine = client_data; 93228753Smm 94228753Smm if (mine->used + length > mine->size) { 95228753Smm archive_set_error(a, ENOMEM, "Buffer exhausted"); 96228753Smm return (ARCHIVE_FATAL); 97228753Smm } 98228753Smm memcpy(mine->buff + mine->used, buff, length); 99228753Smm mine->used += length; 100228753Smm if (mine->client_size != NULL) 101228753Smm *mine->client_size = mine->used; 102228753Smm return (length); 103228753Smm} 104228753Smm 105228753Smmstatic int 106368708Smmmemory_write_free(struct archive *a, void *client_data) 107228753Smm{ 108228753Smm struct write_memory_data *mine; 109228753Smm (void)a; /* UNUSED */ 110228753Smm mine = client_data; 111368708Smm if (mine == NULL) 112368708Smm return (ARCHIVE_OK); 113228753Smm free(mine); 114228753Smm return (ARCHIVE_OK); 115228753Smm} 116