Home | History | Annotate | Line # | Download | only in libarchive
      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 = 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