1/*- 2 * Copyright (c) 2003-2007 Tim Kientzle 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 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. 13 * 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. 24 */ 25 26#include "archive_platform.h" 27 28__FBSDID("$FreeBSD$"); 29 30#ifdef HAVE_ERRNO_H 31#include <errno.h> 32#endif 33#ifdef HAVE_STDLIB_H 34#include <stdlib.h> 35#endif 36#ifdef HAVE_STRING_H 37#include <string.h> 38#endif 39 40#include "archive.h" 41#include "archive_string.h" 42#include "archive_write_private.h" 43 44struct write_lrzip { 45 struct archive_write_program_data *pdata; 46 int compression_level; 47 enum { lzma = 0, bzip2, gzip, lzo, zpaq } compression; 48}; 49 50static int archive_write_lrzip_open(struct archive_write_filter *); 51static int archive_write_lrzip_options(struct archive_write_filter *, 52 const char *, const char *); 53static int archive_write_lrzip_write(struct archive_write_filter *, 54 const void *, size_t); 55static int archive_write_lrzip_close(struct archive_write_filter *); 56static int archive_write_lrzip_free(struct archive_write_filter *); 57 58int 59archive_write_add_filter_lrzip(struct archive *_a) 60{ 61 struct archive_write_filter *f = __archive_write_allocate_filter(_a); 62 struct write_lrzip *data; 63 64 archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, 65 ARCHIVE_STATE_NEW, "archive_write_add_filter_lrzip"); 66 67 data = calloc(1, sizeof(*data)); 68 if (data == NULL) { 69 archive_set_error(_a, ENOMEM, "Can't allocate memory"); 70 return (ARCHIVE_FATAL); 71 } 72 data->pdata = __archive_write_program_allocate(); 73 if (data->pdata == NULL) { 74 free(data); 75 archive_set_error(_a, ENOMEM, "Can't allocate memory"); 76 return (ARCHIVE_FATAL); 77 } 78 79 f->name = "lrzip"; 80 f->code = ARCHIVE_FILTER_LRZIP; 81 f->data = data; 82 f->open = archive_write_lrzip_open; 83 f->options = archive_write_lrzip_options; 84 f->write = archive_write_lrzip_write; 85 f->close = archive_write_lrzip_close; 86 f->free = archive_write_lrzip_free; 87 88 /* Note: This filter always uses an external program, so we 89 * return "warn" to inform of the fact. */ 90 archive_set_error(_a, ARCHIVE_ERRNO_MISC, 91 "Using external lrzip program for lrzip compression"); 92 return (ARCHIVE_WARN); 93} 94 95static int 96archive_write_lrzip_options(struct archive_write_filter *f, const char *key, 97 const char *value) 98{ 99 struct write_lrzip *data = (struct write_lrzip *)f->data; 100 101 if (strcmp(key, "compression") == 0) { 102 if (value == NULL) 103 return (ARCHIVE_WARN); 104 else if (strcmp(value, "bzip2") == 0) 105 data->compression = bzip2; 106 else if (strcmp(value, "gzip") == 0) 107 data->compression = gzip; 108 else if (strcmp(value, "lzo") == 0) 109 data->compression = lzo; 110 else if (strcmp(value, "zpaq") == 0) 111 data->compression = zpaq; 112 else 113 return (ARCHIVE_WARN); 114 return (ARCHIVE_OK); 115 } else if (strcmp(key, "compression-level") == 0) { 116 if (value == NULL || !(value[0] >= '1' && value[0] <= '9') || 117 value[1] != '\0') 118 return (ARCHIVE_WARN); 119 data->compression_level = value[0] - '0'; 120 return (ARCHIVE_OK); 121 } 122 /* Note: The "warn" return is just to inform the options 123 * supervisor that we didn't handle it. It will generate 124 * a suitable error if no one used this option. */ 125 return (ARCHIVE_WARN); 126} 127 128static int 129archive_write_lrzip_open(struct archive_write_filter *f) 130{ 131 struct write_lrzip *data = (struct write_lrzip *)f->data; 132 struct archive_string as; 133 int r; 134 135 archive_string_init(&as); 136 archive_strcpy(&as, "lrzip -q"); 137 138 /* Specify compression type. */ 139 switch (data->compression) { 140 case lzma:/* default compression */ 141 break; 142 case bzip2: 143 archive_strcat(&as, " -b"); 144 break; 145 case gzip: 146 archive_strcat(&as, " -g"); 147 break; 148 case lzo: 149 archive_strcat(&as, " -l"); 150 break; 151 case zpaq: 152 archive_strcat(&as, " -z"); 153 break; 154 } 155 156 /* Specify compression level. */ 157 if (data->compression_level > 0) { 158 archive_strcat(&as, " -L "); 159 archive_strappend_char(&as, '0' + data->compression_level); 160 } 161 162 r = __archive_write_program_open(f, data->pdata, as.s); 163 archive_string_free(&as); 164 return (r); 165} 166 167static int 168archive_write_lrzip_write(struct archive_write_filter *f, 169 const void *buff, size_t length) 170{ 171 struct write_lrzip *data = (struct write_lrzip *)f->data; 172 173 return __archive_write_program_write(f, data->pdata, buff, length); 174} 175 176static int 177archive_write_lrzip_close(struct archive_write_filter *f) 178{ 179 struct write_lrzip *data = (struct write_lrzip *)f->data; 180 181 return __archive_write_program_close(f, data->pdata); 182} 183 184static int 185archive_write_lrzip_free(struct archive_write_filter *f) 186{ 187 struct write_lrzip *data = (struct write_lrzip *)f->data; 188 189 __archive_write_program_free(data->pdata); 190 free(data); 191 return (ARCHIVE_OK); 192} 193