1 /*- 2 * Copyright (c) 2003-2007 Tim Kientzle 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include "archive_platform.h" 27 28 #include <errno.h> 29 #include <stdlib.h> 30 #include <string.h> 31 32 #include "archive.h" 33 34 /* 35 * Glue to read an archive from a block of memory. 36 * 37 * This is mostly a huge help in building test harnesses; 38 * test programs can build archives in memory and read them 39 * back again without having to mess with files on disk. 40 */ 41 42 struct read_memory_data { 43 const unsigned char *start; 44 const unsigned char *p; 45 const unsigned char *end; 46 ssize_t read_size; 47 }; 48 49 static int memory_read_close(struct archive *, void *); 50 static int memory_read_open(struct archive *, void *); 51 static int64_t memory_read_seek(struct archive *, void *, int64_t offset, int whence); 52 static int64_t memory_read_skip(struct archive *, void *, int64_t request); 53 static ssize_t memory_read(struct archive *, void *, const void **buff); 54 55 int 56 archive_read_open_memory(struct archive *a, const void *buff, size_t size) 57 { 58 return archive_read_open_memory2(a, buff, size, size); 59 } 60 61 /* 62 * Don't use _open_memory2() in production code; the archive_read_open_memory() 63 * version is the one you really want. This is just here so that 64 * test harnesses can exercise block operations inside the library. 65 */ 66 int 67 archive_read_open_memory2(struct archive *a, const void *buff, 68 size_t size, size_t read_size) 69 { 70 struct read_memory_data *mine; 71 72 mine = (struct read_memory_data *)calloc(1, sizeof(*mine)); 73 if (mine == NULL) { 74 archive_set_error(a, ENOMEM, "No memory"); 75 return (ARCHIVE_FATAL); 76 } 77 mine->start = mine->p = (const unsigned char *)buff; 78 mine->end = mine->start + size; 79 mine->read_size = read_size; 80 archive_read_set_open_callback(a, memory_read_open); 81 archive_read_set_read_callback(a, memory_read); 82 archive_read_set_seek_callback(a, memory_read_seek); 83 archive_read_set_skip_callback(a, memory_read_skip); 84 archive_read_set_close_callback(a, memory_read_close); 85 archive_read_set_callback_data(a, mine); 86 return (archive_read_open1(a)); 87 } 88 89 /* 90 * There's nothing to open. 91 */ 92 static int 93 memory_read_open(struct archive *a, void *client_data) 94 { 95 (void)a; /* UNUSED */ 96 (void)client_data; /* UNUSED */ 97 return (ARCHIVE_OK); 98 } 99 100 /* 101 * This is scary simple: Just advance a pointer. Limiting 102 * to read_size is not technically necessary, but it exercises 103 * more of the internal logic when used with a small block size 104 * in a test harness. Production use should not specify a block 105 * size; then this is much faster. 106 */ 107 static ssize_t 108 memory_read(struct archive *a, void *client_data, const void **buff) 109 { 110 struct read_memory_data *mine = (struct read_memory_data *)client_data; 111 ssize_t size; 112 113 (void)a; /* UNUSED */ 114 *buff = mine->p; 115 size = mine->end - mine->p; 116 if (size > mine->read_size) 117 size = mine->read_size; 118 mine->p += size; 119 return (size); 120 } 121 122 /* 123 * Advancing is just as simple. Again, this is doing more than 124 * necessary in order to better exercise internal code when used 125 * as a test harness. 126 */ 127 static int64_t 128 memory_read_skip(struct archive *a, void *client_data, int64_t skip) 129 { 130 struct read_memory_data *mine = (struct read_memory_data *)client_data; 131 132 (void)a; /* UNUSED */ 133 if ((int64_t)skip > (int64_t)(mine->end - mine->p)) 134 skip = mine->end - mine->p; 135 /* Round down to block size. */ 136 skip /= mine->read_size; 137 skip *= mine->read_size; 138 mine->p += skip; 139 return (skip); 140 } 141 142 /* 143 * Seeking. 144 */ 145 static int64_t 146 memory_read_seek(struct archive *a, void *client_data, int64_t offset, int whence) 147 { 148 struct read_memory_data *mine = (struct read_memory_data *)client_data; 149 150 (void)a; /* UNUSED */ 151 switch (whence) { 152 case SEEK_SET: 153 mine->p = mine->start + offset; 154 break; 155 case SEEK_CUR: 156 mine->p += offset; 157 break; 158 case SEEK_END: 159 mine->p = mine->end + offset; 160 break; 161 default: 162 return ARCHIVE_FATAL; 163 } 164 if (mine->p < mine->start) { 165 mine->p = mine->start; 166 return ARCHIVE_FAILED; 167 } 168 if (mine->p > mine->end) { 169 mine->p = mine->end; 170 return ARCHIVE_FAILED; 171 } 172 return (mine->p - mine->start); 173 } 174 175 /* 176 * Close is just cleaning up our one small bit of data. 177 */ 178 static int 179 memory_read_close(struct archive *a, void *client_data) 180 { 181 struct read_memory_data *mine = (struct read_memory_data *)client_data; 182 (void)a; /* UNUSED */ 183 free(mine); 184 return (ARCHIVE_OK); 185 } 186