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 <stdlib.h>
30 #include <string.h>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <fcntl.h>
34 #include <archive.h>
35 #include <archive_entry.h>
36
37 #include "io.h"
38
39 struct io {
40 struct archive *a;
41 struct archive_entry *entry;
42 unsigned offset;
43 };
44
io_error(struct io * io)45 static void io_error(struct io *io)
46 {
47 fprintf(stderr, "%s\n", archive_error_string(io->a));
48 io_close(io);
49 }
50
io_new(void)51 static struct io * io_new(void)
52 {
53 struct io *io = calloc(1, sizeof(*io));
54 int ret;
55
56 if (!io)
57 return NULL;
58
59 io->a = archive_read_new();
60 ret = archive_read_support_filter_gzip(io->a);
61 if (ret != ARCHIVE_OK) {
62 io_error(io);
63 return NULL;
64 }
65
66 ret = archive_read_support_filter_none(io->a);
67 if (ret != ARCHIVE_OK) {
68 io_error(io);
69 return NULL;
70 }
71
72 ret = archive_read_support_format_all(io->a);
73 if (ret != ARCHIVE_OK) {
74 io_error(io);
75 return NULL;
76 }
77
78 ret = archive_read_support_format_raw(io->a);
79 if (ret != ARCHIVE_OK) {
80 io_error(io);
81 return NULL;
82 }
83
84 return io;
85 }
86
io_open(const char * filename)87 struct io * io_open(const char *filename)
88 {
89 struct io *io = io_new();
90 int ret;
91
92 if (!io)
93 return NULL;
94
95 ret = archive_read_open_filename(io->a, filename, 10240);
96 if (ret != ARCHIVE_OK) {
97 io_error(io);
98 return NULL;
99 }
100
101 ret = archive_read_next_header(io->a, &io->entry);
102 if (ret != ARCHIVE_OK) {
103 io_error(io);
104 return NULL;
105 }
106
107 return io;
108 }
109
io_openfd(int fd)110 struct io * io_openfd(int fd)
111 {
112 struct io *io = io_new();
113 int ret;
114
115 if (!io)
116 return NULL;
117
118 ret = archive_read_open_fd(io->a, fd, 10240);
119 if (ret != ARCHIVE_OK) {
120 io_error(io);
121 return NULL;
122 }
123
124 ret = archive_read_next_header(io->a, &io->entry);
125 if (ret != ARCHIVE_OK) {
126 io_error(io);
127 return NULL;
128 }
129
130 return io;
131 }
132
io_close(struct io * io)133 void io_close(struct io *io)
134 {
135 archive_read_free(io->a);
136 free(io);
137 }
138
io_offset(struct io * io)139 unsigned io_offset(struct io *io)
140 {
141 return io->offset;
142 }
143
144 #include <assert.h>
io_readn(struct io * io,void * buf,int nbytes)145 int io_readn(struct io *io, void *buf, int nbytes)
146 {
147 char *ptr = buf;
148 int ret = 0;
149 while (nbytes > 0) {
150 int n = archive_read_data(io->a, ptr, nbytes);
151 if (n < 0) {
152 fprintf(stderr, "%s\n", archive_error_string(io->a));
153 return n;
154 }
155 if (n == 0)
156 break;
157 ptr += n;
158 nbytes -= n;
159 ret += n;
160 io->offset += n;
161 }
162 return ret;
163 }
164