Path: blob/master/Utilities/cmlibarchive/libarchive/archive_check_magic.c
5028 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#include <errno.h>33#ifdef HAVE_STDLIB_H34#include <stdlib.h>35#endif36#ifdef HAVE_STRING_H37#include <string.h>38#endif39#ifdef HAVE_UNISTD_H40#include <unistd.h>41#endif42#if defined(_WIN32) && !defined(__CYGWIN__)43#include <windows.h>44#include <winbase.h>45#endif4647#include "archive_private.h"4849static void50errmsg(const char *m)51{52size_t s = strlen(m);53ssize_t written;5455while (s > 0) {56written = write(2, m, s);57if (written == 0)58return;59if (written < 0)60{61if (errno == EINTR)62continue;63return;64}65m += written;66s -= written;67}68}6970static __LA_NORETURN void71diediedie(void)72{73#if defined(_WIN32) && !defined(__CYGWIN__) && defined(_DEBUG)74/* Cause a breakpoint exception */75DebugBreak();76#endif77abort(); /* Terminate the program abnormally. */78}7980static const char *81state_name(unsigned s)82{83switch (s) {84case ARCHIVE_STATE_NEW: return ("new");85case ARCHIVE_STATE_HEADER: return ("header");86case ARCHIVE_STATE_DATA: return ("data");87case ARCHIVE_STATE_EOF: return ("eof");88case ARCHIVE_STATE_CLOSED: return ("closed");89case ARCHIVE_STATE_FATAL: return ("fatal");90default: return ("??");91}92}9394static const char *95archive_handle_type_name(unsigned m)96{97switch (m) {98case ARCHIVE_WRITE_MAGIC: return ("archive_write");99case ARCHIVE_READ_MAGIC: return ("archive_read");100case ARCHIVE_WRITE_DISK_MAGIC: return ("archive_write_disk");101case ARCHIVE_READ_DISK_MAGIC: return ("archive_read_disk");102case ARCHIVE_MATCH_MAGIC: return ("archive_match");103default: return NULL;104}105}106107static void108write_all_states(char *buff, unsigned int states)109{110unsigned int lowbit;111112*buff = '\0';113114/* A trick for computing the lowest set bit. */115while ((lowbit = states & (1 + ~states)) != 0) {116states &= ~lowbit; /* Clear the low bit. */117strcat(buff, state_name(lowbit));118if (states != 0)119strcat(buff, "/");120}121}122123/*124* Check magic value and current state.125* Magic value mismatches are fatal and result in calls to abort().126* State mismatches return ARCHIVE_FATAL.127* Otherwise, returns ARCHIVE_OK.128*129* This is designed to catch serious programming errors that violate130* the libarchive API.131*/132int133__archive_check_magic(struct archive *a, unsigned int magic,134unsigned int state, const char *function)135{136char states1[64];137char states2[64];138const char *handle_type;139140/*141* If this isn't some form of archive handle,142* then the library user has screwed up so bad that143* we don't even have a reliable way to report an error.144*/145handle_type = archive_handle_type_name(a->magic);146147if (!handle_type) {148errmsg("PROGRAMMER ERROR: Function ");149errmsg(function);150errmsg(" invoked with invalid archive handle.\n");151diediedie();152}153154if (a->magic != magic) {155archive_set_error(a, -1,156"PROGRAMMER ERROR: Function '%s' invoked"157" on '%s' archive object, which is not supported.",158function,159handle_type);160a->state = ARCHIVE_STATE_FATAL;161return (ARCHIVE_FATAL);162}163164if ((a->state & state) == 0) {165/* If we're already FATAL, don't overwrite the error. */166if (a->state != ARCHIVE_STATE_FATAL) {167write_all_states(states1, a->state);168write_all_states(states2, state);169archive_set_error(a, -1,170"INTERNAL ERROR: Function '%s' invoked with"171" archive structure in state '%s',"172" should be in state '%s'",173function,174states1,175states2);176}177a->state = ARCHIVE_STATE_FATAL;178return (ARCHIVE_FATAL);179}180return (ARCHIVE_OK);181}182183184