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
39 struct io {
40 struct archive *a;
41 struct archive_entry *entry;
42 unsigned offset;
43 };
44
45 static void
io_error(struct io * io)46 io_error(struct io *io)
47 {
48 fprintf(stderr, "%s\n", archive_error_string(io->a));
49 io_close(io);
50 }
51
52 static struct io *
io_new(void)53 io_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
89 struct io *
io_open(const char * filename)90 io_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
113 struct io *
io_openfd(int fd)114 io_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
137 void
io_close(struct io * io)138 io_close(struct io *io)
139 {
140 archive_read_free(io->a);
141 free(io);
142 }
143
144 unsigned
io_offset(struct io * io)145 io_offset(struct io *io)
146 {
147 return io->offset;
148 }
149
150 #include <assert.h>
151 int
io_readn(struct io * io,void * buf,int nbytes)152 io_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