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#ifdef HAVE_ERRNO_H 29#include <errno.h> 30#endif 31#ifdef HAVE_STDLIB_H 32#include <stdlib.h> 33#endif 34#ifdef HAVE_STRING_H 35#include <string.h> 36#endif 37 38#include "archive.h" 39#include "archive_string.h" 40#include "archive_write_private.h" 41 42struct write_lrzip { 43 struct archive_write_program_data *pdata; 44 int compression_level; 45 enum { lzma = 0, bzip2, gzip, lzo, none, zpaq } compression; 46}; 47 48static int archive_write_lrzip_open(struct archive_write_filter *); 49static int archive_write_lrzip_options(struct archive_write_filter *, 50 const char *, const char *); 51static int archive_write_lrzip_write(struct archive_write_filter *, 52 const void *, size_t); 53static int archive_write_lrzip_close(struct archive_write_filter *); 54static int archive_write_lrzip_free(struct archive_write_filter *); 55 56int 57archive_write_add_filter_lrzip(struct archive *_a) 58{ 59 struct archive_write_filter *f = __archive_write_allocate_filter(_a); 60 struct write_lrzip *data; 61 62 archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, 63 ARCHIVE_STATE_NEW, "archive_write_add_filter_lrzip"); 64 65 data = calloc(1, sizeof(*data)); 66 if (data == NULL) { 67 archive_set_error(_a, ENOMEM, "Can't allocate memory"); 68 return (ARCHIVE_FATAL); 69 } 70 data->pdata = __archive_write_program_allocate("lrzip"); 71 if (data->pdata == NULL) { 72 free(data); 73 archive_set_error(_a, ENOMEM, "Can't allocate memory"); 74 return (ARCHIVE_FATAL); 75 } 76 77 f->name = "lrzip"; 78 f->code = ARCHIVE_FILTER_LRZIP; 79 f->data = data; 80 f->open = archive_write_lrzip_open; 81 f->options = archive_write_lrzip_options; 82 f->write = archive_write_lrzip_write; 83 f->close = archive_write_lrzip_close; 84 f->free = archive_write_lrzip_free; 85 86 /* Note: This filter always uses an external program, so we 87 * return "warn" to inform of the fact. */ 88 archive_set_error(_a, ARCHIVE_ERRNO_MISC, 89 "Using external lrzip program for lrzip compression"); 90 return (ARCHIVE_WARN); 91} 92 93static int 94archive_write_lrzip_options(struct archive_write_filter *f, const char *key, 95 const char *value) 96{ 97 struct write_lrzip *data = (struct write_lrzip *)f->data; 98 99 if (strcmp(key, "compression") == 0) { 100 if (value == NULL) 101 return (ARCHIVE_WARN); 102 else if (strcmp(value, "bzip2") == 0) 103 data->compression = bzip2; 104 else if (strcmp(value, "gzip") == 0) 105 data->compression = gzip; 106 else if (strcmp(value, "lzo") == 0) 107 data->compression = lzo; 108 else if (strcmp(value, "none") == 0) 109 data->compression = none; 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 none: 152 archive_strcat(&as, " -n"); 153 break; 154 case zpaq: 155 archive_strcat(&as, " -z"); 156 break; 157 } 158 159 /* Specify compression level. */ 160 if (data->compression_level > 0) { 161 archive_strcat(&as, " -L "); 162 archive_strappend_char(&as, '0' + data->compression_level); 163 } 164 165 r = __archive_write_program_open(f, data->pdata, as.s); 166 archive_string_free(&as); 167 return (r); 168} 169 170static int 171archive_write_lrzip_write(struct archive_write_filter *f, 172 const void *buff, size_t length) 173{ 174 struct write_lrzip *data = (struct write_lrzip *)f->data; 175 176 return __archive_write_program_write(f, data->pdata, buff, length); 177} 178 179static int 180archive_write_lrzip_close(struct archive_write_filter *f) 181{ 182 struct write_lrzip *data = (struct write_lrzip *)f->data; 183 184 return __archive_write_program_close(f, data->pdata); 185} 186 187static int 188archive_write_lrzip_free(struct archive_write_filter *f) 189{ 190 struct write_lrzip *data = (struct write_lrzip *)f->data; 191 192 __archive_write_program_free(data->pdata); 193 free(data); 194 return (ARCHIVE_OK); 195} 196