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