1228753Smm/*- 2228753Smm * Copyright (c) 2009 Michihiro NAKAJIMA 3228753Smm * Copyright (c) 2003-2007 Tim Kientzle 4228753Smm * All rights reserved. 5228753Smm * 6228753Smm * Redistribution and use in source and binary forms, with or without 7228753Smm * modification, are permitted provided that the following conditions 8228753Smm * are met: 9228753Smm * 1. Redistributions of source code must retain the above copyright 10228753Smm * notice, this list of conditions and the following disclaimer. 11228753Smm * 2. Redistributions in binary form must reproduce the above copyright 12228753Smm * notice, this list of conditions and the following disclaimer in the 13228753Smm * documentation and/or other materials provided with the distribution. 14228753Smm * 15228753Smm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 16228753Smm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17228753Smm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18228753Smm * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 19228753Smm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20228753Smm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21228753Smm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22228753Smm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23228753Smm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24228753Smm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25228753Smm */ 26228753Smm 27228753Smm#include "archive_platform.h" 28229592Smm__FBSDID("$FreeBSD$"); 29228753Smm 30228753Smm#ifdef HAVE_SYS_TYPES_H 31228753Smm#include <sys/types.h> 32228753Smm#endif 33228753Smm#ifdef HAVE_STDLIB_H 34228753Smm#include <stdlib.h> 35228753Smm#endif 36228753Smm#ifdef HAVE_STRING_H 37228753Smm#include <string.h> 38228753Smm#endif 39228753Smm 40228753Smm#include "archive.h" 41228753Smm#include "archive_private.h" 42228753Smm#include "archive_string.h" 43228753Smm 44228753Smm#if ARCHIVE_VERSION_NUMBER < 3000000 45228753Smm/* These disappear in libarchive 3.0 */ 46228753Smm/* Deprecated. */ 47228753Smmint 48228753Smmarchive_api_feature(void) 49228753Smm{ 50228753Smm return (ARCHIVE_API_FEATURE); 51228753Smm} 52228753Smm 53228753Smm/* Deprecated. */ 54228753Smmint 55228753Smmarchive_api_version(void) 56228753Smm{ 57228753Smm return (ARCHIVE_API_VERSION); 58228753Smm} 59228753Smm 60228753Smm/* Deprecated synonym for archive_version_number() */ 61228753Smmint 62228753Smmarchive_version_stamp(void) 63228753Smm{ 64228753Smm return (archive_version_number()); 65228753Smm} 66228753Smm 67228753Smm/* Deprecated synonym for archive_version_string() */ 68228753Smmconst char * 69228753Smmarchive_version(void) 70228753Smm{ 71228753Smm return (archive_version_string()); 72228753Smm} 73228753Smm#endif 74228753Smm 75228753Smmint 76228753Smmarchive_version_number(void) 77228753Smm{ 78228753Smm return (ARCHIVE_VERSION_NUMBER); 79228753Smm} 80228753Smm 81228753Smmconst char * 82228753Smmarchive_version_string(void) 83228753Smm{ 84228753Smm return (ARCHIVE_VERSION_STRING); 85228753Smm} 86228753Smm 87228753Smmint 88228753Smmarchive_errno(struct archive *a) 89228753Smm{ 90228753Smm return (a->archive_error_number); 91228753Smm} 92228753Smm 93228753Smmconst char * 94228753Smmarchive_error_string(struct archive *a) 95228753Smm{ 96228753Smm 97228753Smm if (a->error != NULL && *a->error != '\0') 98228753Smm return (a->error); 99228753Smm else 100228753Smm return ("(Empty error message)"); 101228753Smm} 102228753Smm 103228753Smmint 104228753Smmarchive_file_count(struct archive *a) 105228753Smm{ 106228753Smm return (a->file_count); 107228753Smm} 108228753Smm 109228753Smmint 110228753Smmarchive_format(struct archive *a) 111228753Smm{ 112228753Smm return (a->archive_format); 113228753Smm} 114228753Smm 115228753Smmconst char * 116228753Smmarchive_format_name(struct archive *a) 117228753Smm{ 118228753Smm return (a->archive_format_name); 119228753Smm} 120228753Smm 121228753Smm 122228753Smmint 123228753Smmarchive_compression(struct archive *a) 124228753Smm{ 125228753Smm return (a->compression_code); 126228753Smm} 127228753Smm 128228753Smmconst char * 129228753Smmarchive_compression_name(struct archive *a) 130228753Smm{ 131228753Smm return (a->compression_name); 132228753Smm} 133228753Smm 134228753Smm 135228753Smm/* 136228753Smm * Return a count of the number of compressed bytes processed. 137228753Smm */ 138228753Smmint64_t 139228753Smmarchive_position_compressed(struct archive *a) 140228753Smm{ 141228753Smm return (a->raw_position); 142228753Smm} 143228753Smm 144228753Smm/* 145228753Smm * Return a count of the number of uncompressed bytes processed. 146228753Smm */ 147228753Smmint64_t 148228753Smmarchive_position_uncompressed(struct archive *a) 149228753Smm{ 150228753Smm return (a->file_position); 151228753Smm} 152228753Smm 153228753Smmvoid 154228753Smmarchive_clear_error(struct archive *a) 155228753Smm{ 156228753Smm archive_string_empty(&a->error_string); 157228753Smm a->error = NULL; 158228753Smm a->archive_error_number = 0; 159228753Smm} 160228753Smm 161228753Smmvoid 162228753Smmarchive_set_error(struct archive *a, int error_number, const char *fmt, ...) 163228753Smm{ 164228753Smm va_list ap; 165228753Smm 166228753Smm a->archive_error_number = error_number; 167228753Smm if (fmt == NULL) { 168228753Smm a->error = NULL; 169228753Smm return; 170228753Smm } 171228753Smm 172228753Smm va_start(ap, fmt); 173228753Smm archive_string_vsprintf(&(a->error_string), fmt, ap); 174228753Smm va_end(ap); 175228753Smm a->error = a->error_string.s; 176228753Smm} 177228753Smm 178228753Smmvoid 179228753Smmarchive_copy_error(struct archive *dest, struct archive *src) 180228753Smm{ 181228753Smm dest->archive_error_number = src->archive_error_number; 182228753Smm 183228753Smm archive_string_copy(&dest->error_string, &src->error_string); 184228753Smm dest->error = dest->error_string.s; 185228753Smm} 186228753Smm 187228753Smmvoid 188228753Smm__archive_errx(int retvalue, const char *msg) 189228753Smm{ 190228753Smm static const char *msg1 = "Fatal Internal Error in libarchive: "; 191228753Smm size_t s; 192228753Smm 193228753Smm s = write(2, msg1, strlen(msg1)); 194228753Smm (void)s; /* UNUSED */ 195228753Smm s = write(2, msg, strlen(msg)); 196228753Smm (void)s; /* UNUSED */ 197228753Smm s = write(2, "\n", 1); 198228753Smm (void)s; /* UNUSED */ 199228753Smm exit(retvalue); 200228753Smm} 201228753Smm 202228753Smm/* 203228753Smm * Parse option strings 204228753Smm * Detail of option format. 205228753Smm * - The option can accept: 206228753Smm * "opt-name", "!opt-name", "opt-name=value". 207228753Smm * 208228753Smm * - The option entries are separated by comma. 209228753Smm * e.g "compression=9,opt=XXX,opt-b=ZZZ" 210228753Smm * 211228753Smm * - The name of option string consist of '-' and alphabet 212228753Smm * but character '-' cannot be used for the first character. 213228753Smm * (Regular expression is [a-z][-a-z]+) 214228753Smm * 215228753Smm * - For a specfic format/filter, using the format name with ':'. 216228753Smm * e.g "zip:compression=9" 217228753Smm * (This "compression=9" option entry is for "zip" format only) 218228753Smm * 219228753Smm * If another entries follow it, those are not for 220228753Smm * the specfic format/filter. 221228753Smm * e.g handle "zip:compression=9,opt=XXX,opt-b=ZZZ" 222228753Smm * "zip" format/filter handler will get "compression=9" 223228753Smm * all format/filter handler will get "opt=XXX" 224228753Smm * all format/filter handler will get "opt-b=ZZZ" 225228753Smm * 226228753Smm * - Whitespace and tab are bypassed. 227228753Smm * 228228753Smm */ 229228753Smmint 230228753Smm__archive_parse_options(const char *p, const char *fn, int keysize, char *key, 231228753Smm int valsize, char *val) 232228753Smm{ 233228753Smm const char *p_org; 234228753Smm int apply; 235228753Smm int kidx, vidx; 236228753Smm int negative; 237228753Smm enum { 238228753Smm /* Requested for initialization. */ 239228753Smm INIT, 240228753Smm /* Finding format/filter-name and option-name. */ 241228753Smm F_BOTH, 242228753Smm /* Finding option-name only. 243228753Smm * (already detected format/filter-name) */ 244228753Smm F_NAME, 245228753Smm /* Getting option-value. */ 246228753Smm G_VALUE, 247228753Smm } state; 248228753Smm 249228753Smm p_org = p; 250228753Smm state = INIT; 251228753Smm kidx = vidx = negative = 0; 252228753Smm apply = 1; 253228753Smm while (*p) { 254228753Smm switch (state) { 255228753Smm case INIT: 256228753Smm kidx = vidx = 0; 257228753Smm negative = 0; 258228753Smm apply = 1; 259228753Smm state = F_BOTH; 260228753Smm break; 261228753Smm case F_BOTH: 262228753Smm case F_NAME: 263228753Smm if ((*p >= 'a' && *p <= 'z') || 264228753Smm (*p >= '0' && *p <= '9') || *p == '-') { 265228753Smm if (kidx == 0 && !(*p >= 'a' && *p <= 'z')) 266228753Smm /* Illegal sequence. */ 267228753Smm return (-1); 268228753Smm if (kidx >= keysize -1) 269228753Smm /* Too many characters. */ 270228753Smm return (-1); 271228753Smm key[kidx++] = *p++; 272228753Smm } else if (*p == '!') { 273228753Smm if (kidx != 0) 274228753Smm /* Illegal sequence. */ 275228753Smm return (-1); 276228753Smm negative = 1; 277228753Smm ++p; 278228753Smm } else if (*p == ',') { 279228753Smm if (kidx == 0) 280228753Smm /* Illegal sequence. */ 281228753Smm return (-1); 282228753Smm if (!negative) 283228753Smm val[vidx++] = '1'; 284228753Smm /* We have got boolean option data. */ 285228753Smm ++p; 286228753Smm if (apply) 287228753Smm goto complete; 288228753Smm else 289228753Smm /* This option does not apply to the 290228753Smm * format which the fn variable 291228753Smm * indicate. */ 292228753Smm state = INIT; 293228753Smm } else if (*p == ':') { 294228753Smm /* obuf data is format name */ 295228753Smm if (state == F_NAME) 296228753Smm /* We already found it. */ 297228753Smm return (-1); 298228753Smm if (kidx == 0) 299228753Smm /* Illegal sequence. */ 300228753Smm return (-1); 301228753Smm if (negative) 302228753Smm /* We cannot accept "!format-name:". */ 303228753Smm return (-1); 304228753Smm key[kidx] = '\0'; 305228753Smm if (strcmp(fn, key) != 0) 306228753Smm /* This option does not apply to the 307228753Smm * format which the fn variable 308228753Smm * indicate. */ 309228753Smm apply = 0; 310228753Smm kidx = 0; 311228753Smm ++p; 312228753Smm state = F_NAME; 313228753Smm } else if (*p == '=') { 314228753Smm if (kidx == 0) 315228753Smm /* Illegal sequence. */ 316228753Smm return (-1); 317228753Smm if (negative) 318228753Smm /* We cannot accept "!opt-name=value". */ 319228753Smm return (-1); 320228753Smm ++p; 321228753Smm state = G_VALUE; 322228753Smm } else if (*p == ' ') { 323228753Smm /* Pass the space character */ 324228753Smm ++p; 325228753Smm } else { 326228753Smm /* Illegal character. */ 327228753Smm return (-1); 328228753Smm } 329228753Smm break; 330228753Smm case G_VALUE: 331228753Smm if (*p == ',') { 332228753Smm if (vidx == 0) 333228753Smm /* Illegal sequence. */ 334228753Smm return (-1); 335228753Smm /* We have got option data. */ 336228753Smm ++p; 337228753Smm if (apply) 338228753Smm goto complete; 339228753Smm else 340228753Smm /* This option does not apply to the 341228753Smm * format which the fn variable 342228753Smm * indicate. */ 343228753Smm state = INIT; 344228753Smm } else if (*p == ' ') { 345228753Smm /* Pass the space character */ 346228753Smm ++p; 347228753Smm } else { 348228753Smm if (vidx >= valsize -1) 349228753Smm /* Too many characters. */ 350228753Smm return (-1); 351228753Smm val[vidx++] = *p++; 352228753Smm } 353228753Smm break; 354228753Smm } 355228753Smm } 356228753Smm 357228753Smm switch (state) { 358228753Smm case F_BOTH: 359228753Smm case F_NAME: 360228753Smm if (kidx != 0) { 361228753Smm if (!negative) 362228753Smm val[vidx++] = '1'; 363228753Smm /* We have got boolean option. */ 364228753Smm if (apply) 365228753Smm /* This option apply to the format which the 366228753Smm * fn variable indicate. */ 367228753Smm goto complete; 368228753Smm } 369228753Smm break; 370228753Smm case G_VALUE: 371228753Smm if (vidx == 0) 372228753Smm /* Illegal sequence. */ 373228753Smm return (-1); 374228753Smm /* We have got option value. */ 375228753Smm if (apply) 376228753Smm /* This option apply to the format which the fn 377228753Smm * variable indicate. */ 378228753Smm goto complete; 379228753Smm break; 380228753Smm case INIT:/* nothing */ 381228753Smm break; 382228753Smm } 383228753Smm 384228753Smm /* End of Option string. */ 385228753Smm return (0); 386228753Smm 387228753Smmcomplete: 388228753Smm key[kidx] = '\0'; 389228753Smm val[vidx] = '\0'; 390228753Smm /* Return a size which we've consumed for detecting option */ 391228753Smm return ((int)(p - p_org)); 392228753Smm} 393