1228753Smm/*- 2228753Smm * Copyright (c) 2003-2009 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#include "archive_platform.h" 26228763Smm__FBSDID("$FreeBSD: stable/11/contrib/libarchive/libarchive/archive_read_support_format_raw.c 348607 2019-06-04 10:35:54Z mm $"); 27228753Smm 28228753Smm#ifdef HAVE_ERRNO_H 29228753Smm#include <errno.h> 30228753Smm#endif 31228753Smm#include <stdio.h> 32228753Smm#ifdef HAVE_STDLIB_H 33228753Smm#include <stdlib.h> 34228753Smm#endif 35228753Smm 36228753Smm#include "archive.h" 37228753Smm#include "archive_entry.h" 38228753Smm#include "archive_private.h" 39228753Smm#include "archive_read_private.h" 40228753Smm 41228753Smmstruct raw_info { 42228753Smm int64_t offset; /* Current position in the file. */ 43232153Smm int64_t unconsumed; 44228753Smm int end_of_file; 45228753Smm}; 46228753Smm 47232153Smmstatic int archive_read_format_raw_bid(struct archive_read *, int); 48228753Smmstatic int archive_read_format_raw_cleanup(struct archive_read *); 49228753Smmstatic int archive_read_format_raw_read_data(struct archive_read *, 50232153Smm const void **, size_t *, int64_t *); 51228753Smmstatic int archive_read_format_raw_read_data_skip(struct archive_read *); 52228753Smmstatic int archive_read_format_raw_read_header(struct archive_read *, 53228753Smm struct archive_entry *); 54228753Smm 55228753Smmint 56228753Smmarchive_read_support_format_raw(struct archive *_a) 57228753Smm{ 58228753Smm struct raw_info *info; 59228753Smm struct archive_read *a = (struct archive_read *)_a; 60228753Smm int r; 61228753Smm 62232153Smm archive_check_magic(_a, ARCHIVE_READ_MAGIC, 63232153Smm ARCHIVE_STATE_NEW, "archive_read_support_format_raw"); 64232153Smm 65228753Smm info = (struct raw_info *)calloc(1, sizeof(*info)); 66228753Smm if (info == NULL) { 67228753Smm archive_set_error(&a->archive, ENOMEM, 68228753Smm "Can't allocate raw_info data"); 69228753Smm return (ARCHIVE_FATAL); 70228753Smm } 71228753Smm 72228753Smm r = __archive_read_register_format(a, 73228753Smm info, 74228753Smm "raw", 75228753Smm archive_read_format_raw_bid, 76228753Smm NULL, 77228753Smm archive_read_format_raw_read_header, 78228753Smm archive_read_format_raw_read_data, 79228753Smm archive_read_format_raw_read_data_skip, 80248616Smm NULL, 81299529Smm archive_read_format_raw_cleanup, 82299529Smm NULL, 83299529Smm NULL); 84228753Smm if (r != ARCHIVE_OK) 85228753Smm free(info); 86228753Smm return (r); 87228753Smm} 88228753Smm 89228753Smm/* 90228753Smm * Bid 1 if this is a non-empty file. Anyone who can really support 91228753Smm * this should outbid us, so it should generally be safe to use "raw" 92228753Smm * in conjunction with other formats. But, this could really confuse 93228753Smm * folks if there are bid errors or minor file damage, so we don't 94228753Smm * include "raw" as part of support_format_all(). 95228753Smm */ 96228753Smmstatic int 97232153Smmarchive_read_format_raw_bid(struct archive_read *a, int best_bid) 98228753Smm{ 99232153Smm if (best_bid < 1 && __archive_read_ahead(a, 1, NULL) != NULL) 100232153Smm return (1); 101232153Smm return (-1); 102228753Smm} 103228753Smm 104228753Smm/* 105228753Smm * Mock up a fake header. 106228753Smm */ 107228753Smmstatic int 108228753Smmarchive_read_format_raw_read_header(struct archive_read *a, 109228753Smm struct archive_entry *entry) 110228753Smm{ 111228753Smm struct raw_info *info; 112228753Smm 113228753Smm info = (struct raw_info *)(a->format->data); 114228753Smm if (info->end_of_file) 115228753Smm return (ARCHIVE_EOF); 116228753Smm 117228753Smm a->archive.archive_format = ARCHIVE_FORMAT_RAW; 118232153Smm a->archive.archive_format_name = "raw"; 119228753Smm archive_entry_set_pathname(entry, "data"); 120232153Smm archive_entry_set_filetype(entry, AE_IFREG); 121232153Smm archive_entry_set_perm(entry, 0644); 122228753Smm /* I'm deliberately leaving most fields unset here. */ 123348607Smm 124348607Smm /* Let the filter fill out any fields it might have. */ 125348607Smm return __archive_read_header(a, entry); 126228753Smm} 127228753Smm 128228753Smmstatic int 129228753Smmarchive_read_format_raw_read_data(struct archive_read *a, 130232153Smm const void **buff, size_t *size, int64_t *offset) 131228753Smm{ 132228753Smm struct raw_info *info; 133228753Smm ssize_t avail; 134228753Smm 135228753Smm info = (struct raw_info *)(a->format->data); 136232153Smm 137232153Smm /* Consume the bytes we read last time. */ 138232153Smm if (info->unconsumed) { 139232153Smm __archive_read_consume(a, info->unconsumed); 140232153Smm info->unconsumed = 0; 141232153Smm } 142232153Smm 143228753Smm if (info->end_of_file) 144228753Smm return (ARCHIVE_EOF); 145228753Smm 146228753Smm /* Get whatever bytes are immediately available. */ 147228753Smm *buff = __archive_read_ahead(a, 1, &avail); 148228753Smm if (avail > 0) { 149232153Smm /* Return the bytes we just read */ 150228753Smm *size = avail; 151228753Smm *offset = info->offset; 152228753Smm info->offset += *size; 153232153Smm info->unconsumed = avail; 154228753Smm return (ARCHIVE_OK); 155228753Smm } else if (0 == avail) { 156228753Smm /* Record and return end-of-file. */ 157228753Smm info->end_of_file = 1; 158228753Smm *size = 0; 159228753Smm *offset = info->offset; 160228753Smm return (ARCHIVE_EOF); 161228753Smm } else { 162228753Smm /* Record and return an error. */ 163228753Smm *size = 0; 164228753Smm *offset = info->offset; 165248616Smm return ((int)avail); 166228753Smm } 167228753Smm} 168228753Smm 169228753Smmstatic int 170228753Smmarchive_read_format_raw_read_data_skip(struct archive_read *a) 171228753Smm{ 172232153Smm struct raw_info *info = (struct raw_info *)(a->format->data); 173228753Smm 174232153Smm /* Consume the bytes we read last time. */ 175232153Smm if (info->unconsumed) { 176232153Smm __archive_read_consume(a, info->unconsumed); 177232153Smm info->unconsumed = 0; 178232153Smm } 179228753Smm info->end_of_file = 1; 180232153Smm return (ARCHIVE_OK); 181228753Smm} 182228753Smm 183228753Smmstatic int 184228753Smmarchive_read_format_raw_cleanup(struct archive_read *a) 185228753Smm{ 186228753Smm struct raw_info *info; 187228753Smm 188228753Smm info = (struct raw_info *)(a->format->data); 189228753Smm free(info); 190228753Smm a->format->data = NULL; 191228753Smm return (ARCHIVE_OK); 192228753Smm} 193