1228753Smm/*- 2232153Smm * Copyright (c) 2003-2010 Tim Kientzle 3228753Smm * All rights reserved. 4228753Smm * 5228753Smm * Redistribution and use in source and binary forms, with or without 6228753Smm * modification, are permitted provided that the following conditions 7228753Smm * are met: 8228753Smm * 1. Redistributions of source code must retain the above copyright 9228753Smm * notice, this list of conditions and the following disclaimer. 10228753Smm * 2. Redistributions in binary form must reproduce the above copyright 11228753Smm * notice, this list of conditions and the following disclaimer in the 12228753Smm * documentation and/or other materials provided with the distribution. 13228753Smm * 14228753Smm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 15228753Smm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16228753Smm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17228753Smm * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 18228753Smm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19228753Smm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20228753Smm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21228753Smm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22228753Smm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23228753Smm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24228753Smm */ 25228753Smm 26228753Smm#include "archive_platform.h" 27228763Smm__FBSDID("$FreeBSD$"); 28228753Smm 29228753Smm#ifdef HAVE_SYS_TYPES_H 30228753Smm#include <sys/types.h> 31228753Smm#endif 32228753Smm 33228753Smm#include <stdio.h> 34228753Smm#ifdef HAVE_STDLIB_H 35228753Smm#include <stdlib.h> 36228753Smm#endif 37228753Smm#ifdef HAVE_STRING_H 38228753Smm#include <string.h> 39228753Smm#endif 40228753Smm#ifdef HAVE_UNISTD_H 41228753Smm#include <unistd.h> 42228753Smm#endif 43228753Smm#if defined(_WIN32) && !defined(__CYGWIN__) 44228753Smm#include <windows.h> 45228753Smm#include <winbase.h> 46228753Smm#endif 47228753Smm 48228753Smm#include "archive_private.h" 49228753Smm 50228753Smmstatic void 51228753Smmerrmsg(const char *m) 52228753Smm{ 53228753Smm size_t s = strlen(m); 54228753Smm ssize_t written; 55228753Smm 56228753Smm while (s > 0) { 57228753Smm written = write(2, m, strlen(m)); 58228753Smm if (written <= 0) 59228753Smm return; 60228753Smm m += written; 61228753Smm s -= written; 62228753Smm } 63228753Smm} 64228753Smm 65228753Smmstatic void 66228753Smmdiediedie(void) 67228753Smm{ 68228753Smm#if defined(_WIN32) && !defined(__CYGWIN__) && defined(_DEBUG) 69228753Smm /* Cause a breakpoint exception */ 70228753Smm DebugBreak(); 71228753Smm#endif 72228753Smm abort(); /* Terminate the program abnormally. */ 73228753Smm} 74228753Smm 75228753Smmstatic const char * 76228753Smmstate_name(unsigned s) 77228753Smm{ 78228753Smm switch (s) { 79228753Smm case ARCHIVE_STATE_NEW: return ("new"); 80228753Smm case ARCHIVE_STATE_HEADER: return ("header"); 81228753Smm case ARCHIVE_STATE_DATA: return ("data"); 82228753Smm case ARCHIVE_STATE_EOF: return ("eof"); 83228753Smm case ARCHIVE_STATE_CLOSED: return ("closed"); 84228753Smm case ARCHIVE_STATE_FATAL: return ("fatal"); 85228753Smm default: return ("??"); 86228753Smm } 87228753Smm} 88228753Smm 89232153Smmstatic const char * 90232153Smmarchive_handle_type_name(unsigned m) 91232153Smm{ 92232153Smm switch (m) { 93232153Smm case ARCHIVE_WRITE_MAGIC: return ("archive_write"); 94232153Smm case ARCHIVE_READ_MAGIC: return ("archive_read"); 95232153Smm case ARCHIVE_WRITE_DISK_MAGIC: return ("archive_write_disk"); 96232153Smm case ARCHIVE_READ_DISK_MAGIC: return ("archive_read_disk"); 97238856Smm case ARCHIVE_MATCH_MAGIC: return ("archive_match"); 98232153Smm default: return NULL; 99232153Smm } 100232153Smm} 101228753Smm 102232153Smm 103232153Smmstatic char * 104232153Smmwrite_all_states(char *buff, unsigned int states) 105228753Smm{ 106228753Smm unsigned int lowbit; 107228753Smm 108232153Smm buff[0] = '\0'; 109232153Smm 110228753Smm /* A trick for computing the lowest set bit. */ 111228753Smm while ((lowbit = states & (1 + ~states)) != 0) { 112228753Smm states &= ~lowbit; /* Clear the low bit. */ 113232153Smm strcat(buff, state_name(lowbit)); 114228753Smm if (states != 0) 115232153Smm strcat(buff, "/"); 116228753Smm } 117232153Smm return buff; 118228753Smm} 119228753Smm 120228753Smm/* 121232153Smm * Check magic value and current state. 122232153Smm * Magic value mismatches are fatal and result in calls to abort(). 123232153Smm * State mismatches return ARCHIVE_FATAL. 124232153Smm * Otherwise, returns ARCHIVE_OK. 125228753Smm * 126228753Smm * This is designed to catch serious programming errors that violate 127228753Smm * the libarchive API. 128228753Smm */ 129232153Smmint 130228753Smm__archive_check_magic(struct archive *a, unsigned int magic, 131228753Smm unsigned int state, const char *function) 132228753Smm{ 133232153Smm char states1[64]; 134232153Smm char states2[64]; 135232153Smm const char *handle_type; 136232153Smm 137232153Smm /* 138232153Smm * If this isn't some form of archive handle, 139232153Smm * then the library user has screwed up so bad that 140232153Smm * we don't even have a reliable way to report an error. 141232153Smm */ 142232153Smm handle_type = archive_handle_type_name(a->magic); 143232153Smm 144232153Smm if (!handle_type) { 145232153Smm errmsg("PROGRAMMER ERROR: Function "); 146228753Smm errmsg(function); 147232153Smm errmsg(" invoked with invalid archive handle.\n"); 148228753Smm diediedie(); 149228753Smm } 150228753Smm 151232153Smm if (a->magic != magic) { 152232153Smm archive_set_error(a, -1, 153232153Smm "PROGRAMMER ERROR: Function '%s' invoked" 154232153Smm " on '%s' archive object, which is not supported.", 155232153Smm function, 156232153Smm handle_type); 157232153Smm a->state = ARCHIVE_STATE_FATAL; 158232153Smm return (ARCHIVE_FATAL); 159232153Smm } 160228753Smm 161228753Smm if ((a->state & state) == 0) { 162232153Smm /* If we're already FATAL, don't overwrite the error. */ 163232153Smm if (a->state != ARCHIVE_STATE_FATAL) 164232153Smm archive_set_error(a, -1, 165232153Smm "INTERNAL ERROR: Function '%s' invoked with" 166232153Smm " archive structure in state '%s'," 167232153Smm " should be in state '%s'", 168232153Smm function, 169232153Smm write_all_states(states1, a->state), 170232153Smm write_all_states(states2, state)); 171232153Smm a->state = ARCHIVE_STATE_FATAL; 172232153Smm return (ARCHIVE_FATAL); 173228753Smm } 174232153Smm return ARCHIVE_OK; 175228753Smm} 176