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
[] = {
81 { ".uu", "uuencode" },
86 return get_suffix_code(filters
, suffix
);
90 get_format_code(const char *suffix
)
92 /* A pair of suffix and format. */
93 static const struct suffix_code_t formats
[] = {
97 { ".iso", "iso9960" },
98 { ".mtree", "mtree" },
107 return get_suffix_code(formats
, suffix
);
111 decompose_alias(const char *suffix
)
113 static const struct suffix_code_t alias
[] = {
114 { ".taz", ".tar.gz" },
115 { ".tgz", ".tar.gz" },
116 { ".tbz", ".tar.bz2" },
117 { ".tbz2", ".tar.bz2" },
118 { ".tz2", ".tar.bz2" },
119 { ".tlz", ".tar.lzma" },
120 { ".txz", ".tar.xz" },
121 { ".tzo", ".tar.lzo" },
122 { ".taZ", ".tar.Z" },
127 return get_suffix_code(alias
, suffix
);
131 _cset_add_filter(struct creation_set
*cset
, int program
, const char *filter
)
133 struct filter_set
*new_ptr
;
136 new_ptr
= (struct filter_set
*)realloc(cset
->filters
,
137 sizeof(*cset
->filters
) * (cset
->filter_count
+ 1));
139 lafe_errc(1, 0, "No memory");
140 new_filter
= strdup(filter
);
141 if (new_filter
== NULL
)
142 lafe_errc(1, 0, "No memory");
143 cset
->filters
= new_ptr
;
144 cset
->filters
[cset
->filter_count
].program
= program
;
145 cset
->filters
[cset
->filter_count
].filter_name
= new_filter
;
146 cset
->filter_count
++;
150 cset_add_filter(struct creation_set
*cset
, const char *filter
)
152 _cset_add_filter(cset
, 0, filter
);
156 cset_add_filter_program(struct creation_set
*cset
, const char *filter
)
158 _cset_add_filter(cset
, 1, filter
);
162 cset_read_support_filter_program(struct creation_set
*cset
, struct archive
*a
)
166 for (i
= 0; i
< cset
->filter_count
; i
++) {
167 if (cset
->filters
[i
].program
) {
168 archive_read_support_filter_program(a
,
169 cset
->filters
[i
].filter_name
);
177 cset_write_add_filters(struct creation_set
*cset
, struct archive
*a
,
178 const void **filter_name
)
182 for (i
= 0; i
< cset
->filter_count
; i
++) {
183 if (cset
->filters
[i
].program
)
184 r
= archive_write_add_filter_program(a
,
185 cset
->filters
[i
].filter_name
);
187 r
= archive_write_add_filter_by_name(a
,
188 cset
->filters
[i
].filter_name
);
189 if (r
< ARCHIVE_WARN
) {
190 *filter_name
= cset
->filters
[i
].filter_name
;
199 cset_set_format(struct creation_set
*cset
, const char *format
)
205 lafe_errc(1, 0, "No memory");
206 free(cset
->create_format
);
207 cset
->create_format
= f
;
211 cset_get_format(struct creation_set
*cset
)
213 return (cset
->create_format
);
217 _cleanup_filters(struct filter_set
*filters
, int count
)
221 for (i
= 0; i
< count
; i
++)
222 free(filters
[i
].filter_name
);
227 * Clean up a creation set.
230 cset_free(struct creation_set
*cset
)
232 _cleanup_filters(cset
->filters
, cset
->filter_count
);
233 free(cset
->create_format
);
237 struct creation_set
*
240 return calloc(1, sizeof(struct creation_set
));
244 * Build a creation set by a file name suffix.
247 cset_auto_compress(struct creation_set
*cset
, const char *filename
)
249 struct filter_set
*old_filters
;
252 int old_filter_count
;
254 name
= strdup(filename
);
256 lafe_errc(1, 0, "No memory");
257 /* Save previous filters. */
258 old_filters
= cset
->filters
;
259 old_filter_count
= cset
->filter_count
;
260 cset
->filters
= NULL
;
261 cset
->filter_count
= 0;
264 /* Get the suffix. */
265 p
= strrchr(name
, '.');
268 /* Suppose it indicates compression/filter type
270 code
= get_filter_code(p
);
272 cset_add_filter(cset
, code
);
276 /* Suppose it indicates format type such as ".tar". */
277 code
= get_format_code(p
);
279 cset_set_format(cset
, code
);
282 /* Suppose it indicates alias such as ".tgz". */
283 code
= decompose_alias(p
);
286 /* Replace the suffix. */
288 name
= realloc(name
, strlen(name
) + strlen(code
) + 1);
290 lafe_errc(1, 0, "No memory");
295 struct filter_set
*v
;
298 /* Release previos filters. */
299 _cleanup_filters(old_filters
, old_filter_count
);
301 v
= malloc(sizeof(*v
) * cset
->filter_count
);
303 lafe_errc(1, 0, "No memory");
304 /* Reverse filter sequence. */
305 for (i
= 0, r
= cset
->filter_count
; r
> 0; )
306 v
[i
++] = cset
->filters
[--r
];
311 /* Put previos filters back. */
312 cset
->filters
= old_filters
;
313 cset
->filter_count
= old_filter_count
;