2 * Copyright (c) 2003-2009 Tim Kientzle
\r
3 * All rights reserved.
\r
5 * Redistribution and use in source and binary forms, with or without
\r
6 * modification, are permitted provided that the following conditions
\r
8 * 1. Redistributions of source code must retain the above copyright
\r
9 * notice, this list of conditions and the following disclaimer.
\r
10 * 2. Redistributions in binary form must reproduce the above copyright
\r
11 * notice, this list of conditions and the following disclaimer in the
\r
12 * documentation and/or other materials provided with the distribution.
\r
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
\r
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
\r
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
\r
17 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
\r
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
\r
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
\r
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
\r
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
\r
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
\r
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\r
25 #include "archive_platform.h"
\r
26 __FBSDID("$FreeBSD$");
\r
32 #ifdef HAVE_STDLIB_H
\r
36 #include "archive.h"
\r
37 #include "archive_entry.h"
\r
38 #include "archive_private.h"
\r
39 #include "archive_read_private.h"
\r
42 int64_t offset; /* Current position in the file. */
\r
46 static int archive_read_format_raw_bid(struct archive_read *);
\r
47 static int archive_read_format_raw_cleanup(struct archive_read *);
\r
48 static int archive_read_format_raw_read_data(struct archive_read *,
\r
49 const void **, size_t *, off_t *);
\r
50 static int archive_read_format_raw_read_data_skip(struct archive_read *);
\r
51 static int archive_read_format_raw_read_header(struct archive_read *,
\r
52 struct archive_entry *);
\r
55 archive_read_support_format_raw(struct archive *_a)
\r
57 struct raw_info *info;
\r
58 struct archive_read *a = (struct archive_read *)_a;
\r
61 info = (struct raw_info *)calloc(1, sizeof(*info));
\r
63 archive_set_error(&a->archive, ENOMEM,
\r
64 "Can't allocate raw_info data");
\r
65 return (ARCHIVE_FATAL);
\r
68 r = __archive_read_register_format(a,
\r
71 archive_read_format_raw_bid,
\r
73 archive_read_format_raw_read_header,
\r
74 archive_read_format_raw_read_data,
\r
75 archive_read_format_raw_read_data_skip,
\r
76 archive_read_format_raw_cleanup);
\r
77 if (r != ARCHIVE_OK)
\r
83 * Bid 1 if this is a non-empty file. Anyone who can really support
\r
84 * this should outbid us, so it should generally be safe to use "raw"
\r
85 * in conjunction with other formats. But, this could really confuse
\r
86 * folks if there are bid errors or minor file damage, so we don't
\r
87 * include "raw" as part of support_format_all().
\r
90 archive_read_format_raw_bid(struct archive_read *a)
\r
94 if ((p = __archive_read_ahead(a, 1, NULL)) == NULL)
\r
100 * Mock up a fake header.
\r
103 archive_read_format_raw_read_header(struct archive_read *a,
\r
104 struct archive_entry *entry)
\r
106 struct raw_info *info;
\r
108 info = (struct raw_info *)(a->format->data);
\r
109 if (info->end_of_file)
\r
110 return (ARCHIVE_EOF);
\r
112 a->archive.archive_format = ARCHIVE_FORMAT_RAW;
\r
113 a->archive.archive_format_name = "Raw data";
\r
114 archive_entry_set_pathname(entry, "data");
\r
115 /* XXX should we set mode to mimic a regular file? XXX */
\r
116 /* I'm deliberately leaving most fields unset here. */
\r
117 return (ARCHIVE_OK);
\r
121 archive_read_format_raw_read_data(struct archive_read *a,
\r
122 const void **buff, size_t *size, off_t *offset)
\r
124 struct raw_info *info;
\r
127 info = (struct raw_info *)(a->format->data);
\r
128 if (info->end_of_file)
\r
129 return (ARCHIVE_EOF);
\r
131 /* Get whatever bytes are immediately available. */
\r
132 *buff = __archive_read_ahead(a, 1, &avail);
\r
134 /* Consume and return the bytes we just read */
\r
135 __archive_read_consume(a, avail);
\r
137 *offset = info->offset;
\r
138 info->offset += *size;
\r
139 return (ARCHIVE_OK);
\r
140 } else if (0 == avail) {
\r
141 /* Record and return end-of-file. */
\r
142 info->end_of_file = 1;
\r
144 *offset = info->offset;
\r
145 return (ARCHIVE_EOF);
\r
147 /* Record and return an error. */
\r
149 *offset = info->offset;
\r
152 return (ARCHIVE_OK);
\r
156 archive_read_format_raw_read_data_skip(struct archive_read *a)
\r
158 struct raw_info *info;
\r
159 off_t bytes_skipped;
\r
160 int64_t request = 1024 * 1024 * 1024UL; /* Skip 1 GB at a time. */
\r
162 info = (struct raw_info *)(a->format->data);
\r
163 if (info->end_of_file)
\r
164 return (ARCHIVE_EOF);
\r
165 info->end_of_file = 1;
\r
168 bytes_skipped = __archive_read_skip_lenient(a, request);
\r
169 if (bytes_skipped < 0)
\r
170 return (ARCHIVE_FATAL);
\r
171 if (bytes_skipped < request)
\r
172 return (ARCHIVE_OK);
\r
173 /* We skipped all the bytes we asked for. There might
\r
174 * be more, so try again. */
\r
179 archive_read_format_raw_cleanup(struct archive_read *a)
\r
181 struct raw_info *info;
\r
183 info = (struct raw_info *)(a->format->data);
\r
185 a->format->data = NULL;
\r
186 return (ARCHIVE_OK);
\r