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 44 struct write_lrzip { 45 struct archive_write_program_data *pdata; 46 int compression_level; 47 enum { lzma = 0, bzip2, gzip, lzo, none, zpaq } compression; 48 }; 49 50 static int archive_write_lrzip_open(struct archive_write_filter *); 51 static int archive_write_lrzip_options(struct archive_write_filter *, 52 const char *, const char *); 53 static int archive_write_lrzip_write(struct archive_write_filter *, 54 const void *, size_t); 55 static int archive_write_lrzip_close(struct archive_write_filter *); 56 static int archive_write_lrzip_free(struct archive_write_filter *); 57 58 int 59 archive_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("lrzip"); 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 95 static int 96 archive_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, "none") == 0) 111 data->compression = none; 112 else if (strcmp(value, "zpaq") == 0) 113 data->compression = zpaq; 114 else 115 return (ARCHIVE_WARN); 116 return (ARCHIVE_OK); 117 } else if (strcmp(key, "compression-level") == 0) { 118 if (value == NULL || !(value[0] >= '1' && value[0] <= '9') || 119 value[1] != '\0') 120 return (ARCHIVE_WARN); 121 data->compression_level = value[0] - '0'; 122 return (ARCHIVE_OK); 123 } 124 /* Note: The "warn" return is just to inform the options 125 * supervisor that we didn't handle it. It will generate 126 * a suitable error if no one used this option. */ 127 return (ARCHIVE_WARN); 128 } 129 130 static int 131 archive_write_lrzip_open(struct archive_write_filter *f) 132 { 133 struct write_lrzip *data = (struct write_lrzip *)f->data; 134 struct archive_string as; 135 int r; 136 137 archive_string_init(&as); 138 archive_strcpy(&as, "lrzip -q"); 139 140 /* Specify compression type. */ 141 switch (data->compression) { 142 case lzma:/* default compression */ 143 break; 144 case bzip2: 145 archive_strcat(&as, " -b"); 146 break; 147 case gzip: 148 archive_strcat(&as, " -g"); 149 break; 150 case lzo: 151 archive_strcat(&as, " -l"); 152 break; 153 case none: 154 archive_strcat(&as, " -n"); 155 break; 156 case zpaq: 157 archive_strcat(&as, " -z"); 158 break; 159 } 160 161 /* Specify compression level. */ 162 if (data->compression_level > 0) { 163 archive_strcat(&as, " -L "); 164 archive_strappend_char(&as, '0' + data->compression_level); 165 } 166 167 r = __archive_write_program_open(f, data->pdata, as.s); 168 archive_string_free(&as); 169 return (r); 170 } 171 172 static int 173 archive_write_lrzip_write(struct archive_write_filter *f, 174 const void *buff, size_t length) 175 { 176 struct write_lrzip *data = (struct write_lrzip *)f->data; 177 178 return __archive_write_program_write(f, data->pdata, buff, length); 179 } 180 181 static int 182 archive_write_lrzip_close(struct archive_write_filter *f) 183 { 184 struct write_lrzip *data = (struct write_lrzip *)f->data; 185 186 return __archive_write_program_close(f, data->pdata); 187 } 188 189 static int 190 archive_write_lrzip_free(struct archive_write_filter *f) 191 { 192 struct write_lrzip *data = (struct write_lrzip *)f->data; 193 194 __archive_write_program_free(data->pdata); 195 free(data); 196 return (ARCHIVE_OK); 197 } 198