2 * Copyright (c) 2012 Michihiro NAKAJIMA
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 #include "bsdtar_platform.h"
27 __FBSDID("$FreeBSD$");
42 int program; /* Set 1 if filter is a program name */
48 struct suffix_code_t {
54 get_suffix_code(const struct suffix_code_t *tbl, const char *suffix)
60 for (i = 0; tbl[i].suffix != NULL; i++) {
61 if (strcmp(tbl[i].suffix, suffix) == 0)
68 get_filter_code(const char *suffix)
70 /* A pair of suffix and compression/filter. */
71 static const struct suffix_code_t filters[] = {
80 { ".uu", "uuencode" },
85 return get_suffix_code(filters, suffix);
89 get_format_code(const char *suffix)
91 /* A pair of suffix and format. */
92 static const struct suffix_code_t formats[] = {
96 { ".iso", "iso9960" },
97 { ".mtree", "mtree" },
105 return get_suffix_code(formats, suffix);
109 decompose_alias(const char *suffix)
111 static const struct suffix_code_t alias[] = {
112 { ".taz", ".tar.gz" },
113 { ".tgz", ".tar.gz" },
114 { ".tbz", ".tar.bz2" },
115 { ".tbz2", ".tar.bz2" },
116 { ".tz2", ".tar.bz2" },
117 { ".tlz", ".tar.lzma" },
118 { ".txz", ".tar.xz" },
119 { ".tzo", ".tar.lzo" },
120 { ".taZ", ".tar.Z" },
125 return get_suffix_code(alias, suffix);
129 _cset_add_filter(struct creation_set *cset, int program, const char *filter)
131 struct filter_set *new_ptr;
134 new_ptr = (struct filter_set *)realloc(cset->filters,
135 sizeof(*cset->filters) * (cset->filter_count + 1));
137 lafe_errc(1, 0, "No memory");
138 new_filter = strdup(filter);
139 if (new_filter == NULL)
140 lafe_errc(1, 0, "No memory");
141 cset->filters = new_ptr;
142 cset->filters[cset->filter_count].program = program;
143 cset->filters[cset->filter_count].filter_name = new_filter;
144 cset->filter_count++;
148 cset_add_filter(struct creation_set *cset, const char *filter)
150 _cset_add_filter(cset, 0, filter);
154 cset_add_filter_program(struct creation_set *cset, const char *filter)
156 _cset_add_filter(cset, 1, filter);
160 cset_read_support_filter_program(struct creation_set *cset, struct archive *a)
164 for (i = 0; i < cset->filter_count; i++) {
165 if (cset->filters[i].program) {
166 archive_read_support_filter_program(a,
167 cset->filters[i].filter_name);
175 cset_write_add_filters(struct creation_set *cset, struct archive *a,
176 const void **filter_name)
180 for (i = 0; i < cset->filter_count; i++) {
181 if (cset->filters[i].program)
182 r = archive_write_add_filter_program(a,
183 cset->filters[i].filter_name);
185 r = archive_write_add_filter_by_name(a,
186 cset->filters[i].filter_name);
187 if (r < ARCHIVE_WARN) {
188 *filter_name = cset->filters[i].filter_name;
197 cset_set_format(struct creation_set *cset, const char *format)
203 lafe_errc(1, 0, "No memory");
204 free(cset->create_format);
205 cset->create_format = f;
209 cset_get_format(struct creation_set *cset)
211 return (cset->create_format);
215 _cleanup_filters(struct filter_set *filters, int count)
219 for (i = 0; i < count; i++)
220 free(filters[i].filter_name);
225 * Clean up a creation set.
228 cset_free(struct creation_set *cset)
230 _cleanup_filters(cset->filters, cset->filter_count);
231 free(cset->create_format);
235 struct creation_set *
238 return calloc(1, sizeof(struct creation_set));
242 * Build a creation set by a file name suffix.
245 cset_auto_compress(struct creation_set *cset, const char *filename)
247 struct filter_set *old_filters;
250 int old_filter_count;
252 name = strdup(filename);
254 lafe_errc(1, 0, "No memory");
255 /* Save previous filters. */
256 old_filters = cset->filters;
257 old_filter_count = cset->filter_count;
258 cset->filters = NULL;
259 cset->filter_count = 0;
262 /* Get the suffix. */
263 p = strrchr(name, '.');
266 /* Suppose it indicates compression/filter type
268 code = get_filter_code(p);
270 cset_add_filter(cset, code);
274 /* Suppose it indicates format type such as ".tar". */
275 code = get_format_code(p);
277 cset_set_format(cset, code);
280 /* Suppose it indicates alias such as ".tgz". */
281 code = decompose_alias(p);
284 /* Replace the suffix. */
286 name = realloc(name, strlen(name) + strlen(code) + 1);
288 lafe_errc(1, 0, "No memory");
293 struct filter_set *v;
296 /* Release previos filters. */
297 _cleanup_filters(old_filters, old_filter_count);
299 v = malloc(sizeof(*v) * cset->filter_count);
301 lafe_errc(1, 0, "No memory");
302 /* Reverse filter sequence. */
303 for (i = 0, r = cset->filter_count; r > 0; )
304 v[i++] = cset->filters[--r];
309 /* Put previos filters back. */
310 cset->filters = old_filters;
311 cset->filter_count = old_filter_count;