1/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */ 2 3/* 4 * Copyright (C) 2014 Rob Clark <robclark@freedesktop.org> 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the next 14 * paragraph) shall be included in all copies or substantial portions of the 15 * Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 * SOFTWARE. 24 * 25 * Authors: 26 * Rob Clark <robclark@freedesktop.org> 27 */ 28 29#include <archive.h> 30#include <fcntl.h> 31#include <stdlib.h> 32#include <string.h> 33#include <sys/stat.h> 34#include <sys/types.h> 35#include <archive_entry.h> 36 37#include "io.h" 38 39struct io { 40 struct archive *a; 41 struct archive_entry *entry; 42 unsigned offset; 43}; 44 45static void 46io_error(struct io *io) 47{ 48 fprintf(stderr, "%s\n", archive_error_string(io->a)); 49 io_close(io); 50} 51 52static struct io * 53io_new(void) 54{ 55 struct io *io = calloc(1, sizeof(*io)); 56 int ret; 57 58 if (!io) 59 return NULL; 60 61 io->a = archive_read_new(); 62 ret = archive_read_support_filter_gzip(io->a); 63 if (ret != ARCHIVE_OK) { 64 io_error(io); 65 return NULL; 66 } 67 68 ret = archive_read_support_filter_none(io->a); 69 if (ret != ARCHIVE_OK) { 70 io_error(io); 71 return NULL; 72 } 73 74 ret = archive_read_support_format_all(io->a); 75 if (ret != ARCHIVE_OK) { 76 io_error(io); 77 return NULL; 78 } 79 80 ret = archive_read_support_format_raw(io->a); 81 if (ret != ARCHIVE_OK) { 82 io_error(io); 83 return NULL; 84 } 85 86 return io; 87} 88 89struct io * 90io_open(const char *filename) 91{ 92 struct io *io = io_new(); 93 int ret; 94 95 if (!io) 96 return NULL; 97 98 ret = archive_read_open_filename(io->a, filename, 10240); 99 if (ret != ARCHIVE_OK) { 100 io_error(io); 101 return NULL; 102 } 103 104 ret = archive_read_next_header(io->a, &io->entry); 105 if (ret != ARCHIVE_OK) { 106 io_error(io); 107 return NULL; 108 } 109 110 return io; 111} 112 113struct io * 114io_openfd(int fd) 115{ 116 struct io *io = io_new(); 117 int ret; 118 119 if (!io) 120 return NULL; 121 122 ret = archive_read_open_fd(io->a, fd, 10240); 123 if (ret != ARCHIVE_OK) { 124 io_error(io); 125 return NULL; 126 } 127 128 ret = archive_read_next_header(io->a, &io->entry); 129 if (ret != ARCHIVE_OK) { 130 io_error(io); 131 return NULL; 132 } 133 134 return io; 135} 136 137void 138io_close(struct io *io) 139{ 140 archive_read_free(io->a); 141 free(io); 142} 143 144unsigned 145io_offset(struct io *io) 146{ 147 return io->offset; 148} 149 150#include <assert.h> 151int 152io_readn(struct io *io, void *buf, int nbytes) 153{ 154 char *ptr = buf; 155 int ret = 0; 156 while (nbytes > 0) { 157 int n = archive_read_data(io->a, ptr, nbytes); 158 if (n < 0) { 159 fprintf(stderr, "%s\n", archive_error_string(io->a)); 160 return n; 161 } 162 if (n == 0) 163 break; 164 ptr += n; 165 nbytes -= n; 166 ret += n; 167 io->offset += n; 168 } 169 return ret; 170} 171