• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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