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; 47299529Smm enum { lzma = 0, bzip2, gzip, lzo, none, 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 } 72299529Smm data->pdata = __archive_write_program_allocate("lrzip"); 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; 110299529Smm else if (strcmp(value, "none") == 0) 111299529Smm data->compression = none; 112248590Smm else if (strcmp(value, "zpaq") == 0) 113248590Smm data->compression = zpaq; 114248590Smm else 115248590Smm return (ARCHIVE_WARN); 116248590Smm return (ARCHIVE_OK); 117248590Smm } else if (strcmp(key, "compression-level") == 0) { 118248590Smm if (value == NULL || !(value[0] >= '1' && value[0] <= '9') || 119248590Smm value[1] != '\0') 120248590Smm return (ARCHIVE_WARN); 121248590Smm data->compression_level = value[0] - '0'; 122248590Smm return (ARCHIVE_OK); 123248590Smm } 124248590Smm /* Note: The "warn" return is just to inform the options 125248590Smm * supervisor that we didn't handle it. It will generate 126248590Smm * a suitable error if no one used this option. */ 127248590Smm return (ARCHIVE_WARN); 128248590Smm} 129248590Smm 130248590Smmstatic int 131248590Smmarchive_write_lrzip_open(struct archive_write_filter *f) 132248590Smm{ 133248590Smm struct write_lrzip *data = (struct write_lrzip *)f->data; 134248590Smm struct archive_string as; 135248590Smm int r; 136248590Smm 137248590Smm archive_string_init(&as); 138248590Smm archive_strcpy(&as, "lrzip -q"); 139248590Smm 140248590Smm /* Specify compression type. */ 141248590Smm switch (data->compression) { 142248590Smm case lzma:/* default compression */ 143248590Smm break; 144248590Smm case bzip2: 145248590Smm archive_strcat(&as, " -b"); 146248590Smm break; 147248590Smm case gzip: 148248590Smm archive_strcat(&as, " -g"); 149248590Smm break; 150248590Smm case lzo: 151248590Smm archive_strcat(&as, " -l"); 152248590Smm break; 153299529Smm case none: 154299529Smm archive_strcat(&as, " -n"); 155299529Smm break; 156248590Smm case zpaq: 157248590Smm archive_strcat(&as, " -z"); 158248590Smm break; 159248590Smm } 160248590Smm 161248590Smm /* Specify compression level. */ 162248590Smm if (data->compression_level > 0) { 163248590Smm archive_strcat(&as, " -L "); 164248590Smm archive_strappend_char(&as, '0' + data->compression_level); 165248590Smm } 166248590Smm 167248590Smm r = __archive_write_program_open(f, data->pdata, as.s); 168248590Smm archive_string_free(&as); 169248590Smm return (r); 170248590Smm} 171248590Smm 172248590Smmstatic int 173248590Smmarchive_write_lrzip_write(struct archive_write_filter *f, 174248590Smm const void *buff, size_t length) 175248590Smm{ 176248590Smm struct write_lrzip *data = (struct write_lrzip *)f->data; 177248590Smm 178248590Smm return __archive_write_program_write(f, data->pdata, buff, length); 179248590Smm} 180248590Smm 181248590Smmstatic int 182248590Smmarchive_write_lrzip_close(struct archive_write_filter *f) 183248590Smm{ 184248590Smm struct write_lrzip *data = (struct write_lrzip *)f->data; 185248590Smm 186248590Smm return __archive_write_program_close(f, data->pdata); 187248590Smm} 188248590Smm 189248590Smmstatic int 190248590Smmarchive_write_lrzip_free(struct archive_write_filter *f) 191248590Smm{ 192248590Smm struct write_lrzip *data = (struct write_lrzip *)f->data; 193248590Smm 194248590Smm __archive_write_program_free(data->pdata); 195248590Smm free(data); 196248590Smm return (ARCHIVE_OK); 197248590Smm} 198