Path: blob/master/Utilities/cmlibarchive/libarchive/archive_check_magic.c
3153 views
/*-1* Copyright (c) 2003-2010 Tim Kientzle2* All rights reserved.3*4* Redistribution and use in source and binary forms, with or without5* modification, are permitted provided that the following conditions6* are met:7* 1. Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer.9* 2. Redistributions in binary form must reproduce the above copyright10* notice, this list of conditions and the following disclaimer in the11* documentation and/or other materials provided with the distribution.12*13* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR14* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES15* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.16* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,17* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT18* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,19* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY20* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT21* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF22* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.23*/2425#include "archive_platform.h"2627#ifdef HAVE_SYS_TYPES_H28#include <sys/types.h>29#endif3031#include <stdio.h>32#ifdef HAVE_STDLIB_H33#include <stdlib.h>34#endif35#ifdef HAVE_STRING_H36#include <string.h>37#endif38#ifdef HAVE_UNISTD_H39#include <unistd.h>40#endif41#if defined(_WIN32) && !defined(__CYGWIN__)42#include <windows.h>43#include <winbase.h>44#endif4546#include "archive_private.h"4748static void49errmsg(const char *m)50{51size_t s = strlen(m);52ssize_t written;5354while (s > 0) {55written = write(2, m, s);56if (written <= 0)57return;58m += written;59s -= written;60}61}6263static __LA_NORETURN void64diediedie(void)65{66#if defined(_WIN32) && !defined(__CYGWIN__) && defined(_DEBUG)67/* Cause a breakpoint exception */68DebugBreak();69#endif70abort(); /* Terminate the program abnormally. */71}7273static const char *74state_name(unsigned s)75{76switch (s) {77case ARCHIVE_STATE_NEW: return ("new");78case ARCHIVE_STATE_HEADER: return ("header");79case ARCHIVE_STATE_DATA: return ("data");80case ARCHIVE_STATE_EOF: return ("eof");81case ARCHIVE_STATE_CLOSED: return ("closed");82case ARCHIVE_STATE_FATAL: return ("fatal");83default: return ("??");84}85}8687static const char *88archive_handle_type_name(unsigned m)89{90switch (m) {91case ARCHIVE_WRITE_MAGIC: return ("archive_write");92case ARCHIVE_READ_MAGIC: return ("archive_read");93case ARCHIVE_WRITE_DISK_MAGIC: return ("archive_write_disk");94case ARCHIVE_READ_DISK_MAGIC: return ("archive_read_disk");95case ARCHIVE_MATCH_MAGIC: return ("archive_match");96default: return NULL;97}98}99100static void101write_all_states(char *buff, unsigned int states)102{103unsigned int lowbit;104105*buff = '\0';106107/* A trick for computing the lowest set bit. */108while ((lowbit = states & (1 + ~states)) != 0) {109states &= ~lowbit; /* Clear the low bit. */110strcat(buff, state_name(lowbit));111if (states != 0)112strcat(buff, "/");113}114}115116/*117* Check magic value and current state.118* Magic value mismatches are fatal and result in calls to abort().119* State mismatches return ARCHIVE_FATAL.120* Otherwise, returns ARCHIVE_OK.121*122* This is designed to catch serious programming errors that violate123* the libarchive API.124*/125int126__archive_check_magic(struct archive *a, unsigned int magic,127unsigned int state, const char *function)128{129char states1[64];130char states2[64];131const char *handle_type;132133/*134* If this isn't some form of archive handle,135* then the library user has screwed up so bad that136* we don't even have a reliable way to report an error.137*/138handle_type = archive_handle_type_name(a->magic);139140if (!handle_type) {141errmsg("PROGRAMMER ERROR: Function ");142errmsg(function);143errmsg(" invoked with invalid archive handle.\n");144diediedie();145}146147if (a->magic != magic) {148archive_set_error(a, -1,149"PROGRAMMER ERROR: Function '%s' invoked"150" on '%s' archive object, which is not supported.",151function,152handle_type);153a->state = ARCHIVE_STATE_FATAL;154return (ARCHIVE_FATAL);155}156157if ((a->state & state) == 0) {158/* If we're already FATAL, don't overwrite the error. */159if (a->state != ARCHIVE_STATE_FATAL) {160write_all_states(states1, a->state);161write_all_states(states2, state);162archive_set_error(a, -1,163"INTERNAL ERROR: Function '%s' invoked with"164" archive structure in state '%s',"165" should be in state '%s'",166function,167states1,168states2);169}170a->state = ARCHIVE_STATE_FATAL;171return (ARCHIVE_FATAL);172}173return (ARCHIVE_OK);174}175176177