archive_read_support_format_raw.c revision 232153
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: head/contrib/libarchive/libarchive/archive_read_support_format_raw.c 232153 2012-02-25 10:58:02Z 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,
80228753Smm	    archive_read_format_raw_cleanup);
81228753Smm	if (r != ARCHIVE_OK)
82228753Smm		free(info);
83228753Smm	return (r);
84228753Smm}
85228753Smm
86228753Smm/*
87228753Smm * Bid 1 if this is a non-empty file.  Anyone who can really support
88228753Smm * this should outbid us, so it should generally be safe to use "raw"
89228753Smm * in conjunction with other formats.  But, this could really confuse
90228753Smm * folks if there are bid errors or minor file damage, so we don't
91228753Smm * include "raw" as part of support_format_all().
92228753Smm */
93228753Smmstatic int
94232153Smmarchive_read_format_raw_bid(struct archive_read *a, int best_bid)
95228753Smm{
96232153Smm	if (best_bid < 1 && __archive_read_ahead(a, 1, NULL) != NULL)
97232153Smm		return (1);
98232153Smm	return (-1);
99228753Smm}
100228753Smm
101228753Smm/*
102228753Smm * Mock up a fake header.
103228753Smm */
104228753Smmstatic int
105228753Smmarchive_read_format_raw_read_header(struct archive_read *a,
106228753Smm    struct archive_entry *entry)
107228753Smm{
108228753Smm	struct raw_info *info;
109228753Smm
110228753Smm	info = (struct raw_info *)(a->format->data);
111228753Smm	if (info->end_of_file)
112228753Smm		return (ARCHIVE_EOF);
113228753Smm
114228753Smm	a->archive.archive_format = ARCHIVE_FORMAT_RAW;
115232153Smm	a->archive.archive_format_name = "raw";
116228753Smm	archive_entry_set_pathname(entry, "data");
117232153Smm	archive_entry_set_filetype(entry, AE_IFREG);
118232153Smm	archive_entry_set_perm(entry, 0644);
119228753Smm	/* I'm deliberately leaving most fields unset here. */
120228753Smm	return (ARCHIVE_OK);
121228753Smm}
122228753Smm
123228753Smmstatic int
124228753Smmarchive_read_format_raw_read_data(struct archive_read *a,
125232153Smm    const void **buff, size_t *size, int64_t *offset)
126228753Smm{
127228753Smm	struct raw_info *info;
128228753Smm	ssize_t avail;
129228753Smm
130228753Smm	info = (struct raw_info *)(a->format->data);
131232153Smm
132232153Smm	/* Consume the bytes we read last time. */
133232153Smm	if (info->unconsumed) {
134232153Smm		__archive_read_consume(a, info->unconsumed);
135232153Smm		info->unconsumed = 0;
136232153Smm	}
137232153Smm
138228753Smm	if (info->end_of_file)
139228753Smm		return (ARCHIVE_EOF);
140228753Smm
141228753Smm	/* Get whatever bytes are immediately available. */
142228753Smm	*buff = __archive_read_ahead(a, 1, &avail);
143228753Smm	if (avail > 0) {
144232153Smm		/* Return the bytes we just read */
145228753Smm		*size = avail;
146228753Smm		*offset = info->offset;
147228753Smm		info->offset += *size;
148232153Smm		info->unconsumed = avail;
149228753Smm		return (ARCHIVE_OK);
150228753Smm	} else if (0 == avail) {
151228753Smm		/* Record and return end-of-file. */
152228753Smm		info->end_of_file = 1;
153228753Smm		*size = 0;
154228753Smm		*offset = info->offset;
155228753Smm		return (ARCHIVE_EOF);
156228753Smm	} else {
157228753Smm		/* Record and return an error. */
158228753Smm		*size = 0;
159228753Smm		*offset = info->offset;
160228753Smm		return (avail);
161228753Smm	}
162228753Smm}
163228753Smm
164228753Smmstatic int
165228753Smmarchive_read_format_raw_read_data_skip(struct archive_read *a)
166228753Smm{
167232153Smm	struct raw_info *info = (struct raw_info *)(a->format->data);
168228753Smm
169232153Smm	/* Consume the bytes we read last time. */
170232153Smm	if (info->unconsumed) {
171232153Smm		__archive_read_consume(a, info->unconsumed);
172232153Smm		info->unconsumed = 0;
173232153Smm	}
174228753Smm	info->end_of_file = 1;
175232153Smm	return (ARCHIVE_OK);
176228753Smm}
177228753Smm
178228753Smmstatic int
179228753Smmarchive_read_format_raw_cleanup(struct archive_read *a)
180228753Smm{
181228753Smm	struct raw_info *info;
182228753Smm
183228753Smm	info = (struct raw_info *)(a->format->data);
184228753Smm	free(info);
185228753Smm	a->format->data = NULL;
186228753Smm	return (ARCHIVE_OK);
187228753Smm}
188