1248590Smm/*- 2248590Smm * Copyright (c) 2003-2007 Tim Kientzle 3248590Smm * All rights reserved. 4248590Smm * 5248590Smm * Redistribution and use in source and binary forms, with or without 6248590Smm * modification, are permitted provided that the following conditions 7248590Smm * are met: 8248590Smm * 1. Redistributions of source code must retain the above copyright 9248590Smm * notice, this list of conditions and the following disclaimer. 10248590Smm * 2. Redistributions in binary form must reproduce the above copyright 11248590Smm * notice, this list of conditions and the following disclaimer in the 12248590Smm * documentation and/or other materials provided with the distribution. 13248590Smm * 14248590Smm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 15248590Smm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16248590Smm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17248590Smm * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 18248590Smm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19248590Smm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20248590Smm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21248590Smm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22248590Smm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23248590Smm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24248590Smm */ 25248590Smm 26248590Smm#include "archive_platform.h" 27248590Smm 28248590Smm__FBSDID("$FreeBSD$"); 29248590Smm 30248590Smm#ifdef HAVE_ERRNO_H 31248590Smm#include <errno.h> 32248590Smm#endif 33248590Smm#ifdef HAVE_STDLIB_H 34248590Smm#include <stdlib.h> 35248590Smm#endif 36248590Smm#ifdef HAVE_STRING_H 37248590Smm#include <string.h> 38248590Smm#endif 39248590Smm 40248590Smm#include "archive.h" 41248590Smm#include "archive_string.h" 42248590Smm#include "archive_write_private.h" 43248590Smm 44248590Smmstruct write_lrzip { 45248590Smm struct archive_write_program_data *pdata; 46248590Smm int compression_level; 47248590Smm enum { lzma = 0, bzip2, gzip, lzo, zpaq } compression; 48248590Smm}; 49248590Smm 50248590Smmstatic int archive_write_lrzip_open(struct archive_write_filter *); 51248590Smmstatic int archive_write_lrzip_options(struct archive_write_filter *, 52248590Smm const char *, const char *); 53248590Smmstatic int archive_write_lrzip_write(struct archive_write_filter *, 54248590Smm const void *, size_t); 55248590Smmstatic int archive_write_lrzip_close(struct archive_write_filter *); 56248590Smmstatic int archive_write_lrzip_free(struct archive_write_filter *); 57248590Smm 58248590Smmint 59248590Smmarchive_write_add_filter_lrzip(struct archive *_a) 60248590Smm{ 61248590Smm struct archive_write_filter *f = __archive_write_allocate_filter(_a); 62248590Smm struct write_lrzip *data; 63248590Smm 64248590Smm archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, 65248590Smm ARCHIVE_STATE_NEW, "archive_write_add_filter_lrzip"); 66248590Smm 67248590Smm data = calloc(1, sizeof(*data)); 68248590Smm if (data == NULL) { 69248590Smm archive_set_error(_a, ENOMEM, "Can't allocate memory"); 70248590Smm return (ARCHIVE_FATAL); 71248590Smm } 72248590Smm data->pdata = __archive_write_program_allocate(); 73248590Smm if (data->pdata == NULL) { 74248590Smm free(data); 75248590Smm archive_set_error(_a, ENOMEM, "Can't allocate memory"); 76248590Smm return (ARCHIVE_FATAL); 77248590Smm } 78248590Smm 79248590Smm f->name = "lrzip"; 80248590Smm f->code = ARCHIVE_FILTER_LRZIP; 81248590Smm f->data = data; 82248590Smm f->open = archive_write_lrzip_open; 83248590Smm f->options = archive_write_lrzip_options; 84248590Smm f->write = archive_write_lrzip_write; 85248590Smm f->close = archive_write_lrzip_close; 86248590Smm f->free = archive_write_lrzip_free; 87248590Smm 88248590Smm /* Note: This filter always uses an external program, so we 89248590Smm * return "warn" to inform of the fact. */ 90248590Smm archive_set_error(_a, ARCHIVE_ERRNO_MISC, 91248590Smm "Using external lrzip program for lrzip compression"); 92248590Smm return (ARCHIVE_WARN); 93248590Smm} 94248590Smm 95248590Smmstatic int 96248590Smmarchive_write_lrzip_options(struct archive_write_filter *f, const char *key, 97248590Smm const char *value) 98248590Smm{ 99248590Smm struct write_lrzip *data = (struct write_lrzip *)f->data; 100248590Smm 101248590Smm if (strcmp(key, "compression") == 0) { 102248590Smm if (value == NULL) 103248590Smm return (ARCHIVE_WARN); 104248590Smm else if (strcmp(value, "bzip2") == 0) 105248590Smm data->compression = bzip2; 106248590Smm else if (strcmp(value, "gzip") == 0) 107248590Smm data->compression = gzip; 108248590Smm else if (strcmp(value, "lzo") == 0) 109248590Smm data->compression = lzo; 110248590Smm else if (strcmp(value, "zpaq") == 0) 111248590Smm data->compression = zpaq; 112248590Smm else 113248590Smm return (ARCHIVE_WARN); 114248590Smm return (ARCHIVE_OK); 115248590Smm } else if (strcmp(key, "compression-level") == 0) { 116248590Smm if (value == NULL || !(value[0] >= '1' && value[0] <= '9') || 117248590Smm value[1] != '\0') 118248590Smm return (ARCHIVE_WARN); 119248590Smm data->compression_level = value[0] - '0'; 120248590Smm return (ARCHIVE_OK); 121248590Smm } 122248590Smm /* Note: The "warn" return is just to inform the options 123248590Smm * supervisor that we didn't handle it. It will generate 124248590Smm * a suitable error if no one used this option. */ 125248590Smm return (ARCHIVE_WARN); 126248590Smm} 127248590Smm 128248590Smmstatic int 129248590Smmarchive_write_lrzip_open(struct archive_write_filter *f) 130248590Smm{ 131248590Smm struct write_lrzip *data = (struct write_lrzip *)f->data; 132248590Smm struct archive_string as; 133248590Smm int r; 134248590Smm 135248590Smm archive_string_init(&as); 136248590Smm archive_strcpy(&as, "lrzip -q"); 137248590Smm 138248590Smm /* Specify compression type. */ 139248590Smm switch (data->compression) { 140248590Smm case lzma:/* default compression */ 141248590Smm break; 142248590Smm case bzip2: 143248590Smm archive_strcat(&as, " -b"); 144248590Smm break; 145248590Smm case gzip: 146248590Smm archive_strcat(&as, " -g"); 147248590Smm break; 148248590Smm case lzo: 149248590Smm archive_strcat(&as, " -l"); 150248590Smm break; 151248590Smm case zpaq: 152248590Smm archive_strcat(&as, " -z"); 153248590Smm break; 154248590Smm } 155248590Smm 156248590Smm /* Specify compression level. */ 157248590Smm if (data->compression_level > 0) { 158248590Smm archive_strcat(&as, " -L "); 159248590Smm archive_strappend_char(&as, '0' + data->compression_level); 160248590Smm } 161248590Smm 162248590Smm r = __archive_write_program_open(f, data->pdata, as.s); 163248590Smm archive_string_free(&as); 164248590Smm return (r); 165248590Smm} 166248590Smm 167248590Smmstatic int 168248590Smmarchive_write_lrzip_write(struct archive_write_filter *f, 169248590Smm const void *buff, size_t length) 170248590Smm{ 171248590Smm struct write_lrzip *data = (struct write_lrzip *)f->data; 172248590Smm 173248590Smm return __archive_write_program_write(f, data->pdata, buff, length); 174248590Smm} 175248590Smm 176248590Smmstatic int 177248590Smmarchive_write_lrzip_close(struct archive_write_filter *f) 178248590Smm{ 179248590Smm struct write_lrzip *data = (struct write_lrzip *)f->data; 180248590Smm 181248590Smm return __archive_write_program_close(f, data->pdata); 182248590Smm} 183248590Smm 184248590Smmstatic int 185248590Smmarchive_write_lrzip_free(struct archive_write_filter *f) 186248590Smm{ 187248590Smm struct write_lrzip *data = (struct write_lrzip *)f->data; 188248590Smm 189248590Smm __archive_write_program_free(data->pdata); 190248590Smm free(data); 191248590Smm return (ARCHIVE_OK); 192248590Smm} 193