1 /*-
2  * Copyright (c) 2013 Marek Kubica
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #include "archive_platform.h"
27 
28 #ifdef HAVE_ERRNO_H
29 #include <errno.h>
30 #endif
31 
32 #include "archive_entry.h"
33 #include "archive_write_private.h"
34 
35 static ssize_t	archive_write_raw_data(struct archive_write *,
36 		    const void *buff, size_t s);
37 static int	archive_write_raw_free(struct archive_write *);
38 static int	archive_write_raw_header(struct archive_write *,
39 		    struct archive_entry *);
40 
41 struct raw {
42         int entries_written;
43 };
44 
45 /*
46  * Set output format to 'raw' format.
47  */
48 int
49 archive_write_set_format_raw(struct archive *_a)
50 {
51 	struct archive_write *a = (struct archive_write *)_a;
52 	struct raw *raw;
53 
54 	archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
55 	    ARCHIVE_STATE_NEW, "archive_write_set_format_raw");
56 
57 	/* If someone else was already registered, unregister them. */
58 	if (a->format_free != NULL)
59 		(a->format_free)(a);
60 
61 	raw = (struct raw *)calloc(1, sizeof(*raw));
62 	if (raw == NULL) {
63 		archive_set_error(&a->archive, ENOMEM, "Can't allocate raw data");
64 		return (ARCHIVE_FATAL);
65 	}
66 	raw->entries_written = 0;
67 	a->format_data = raw;
68 	a->format_name = "raw";
69         /* no options exist for this format */
70 	a->format_options = NULL;
71 	a->format_write_header = archive_write_raw_header;
72 	a->format_write_data = archive_write_raw_data;
73 	a->format_finish_entry = NULL;
74         /* nothing needs to be done on closing */
75 	a->format_close = NULL;
76 	a->format_free = archive_write_raw_free;
77 	a->archive.archive_format = ARCHIVE_FORMAT_RAW;
78 	a->archive.archive_format_name = "RAW";
79 	return (ARCHIVE_OK);
80 }
81 
82 static int
83 archive_write_raw_header(struct archive_write *a, struct archive_entry *entry)
84 {
85 	struct raw *raw = (struct raw *)a->format_data;
86 
87 	if (archive_entry_filetype(entry) != AE_IFREG) {
88 		archive_set_error(&a->archive, ERANGE,
89 		    "Raw format only supports filetype AE_IFREG");
90 		return (ARCHIVE_FATAL);
91 	}
92 
93 
94 	if (raw->entries_written > 0) {
95 		archive_set_error(&a->archive, ERANGE,
96 		    "Raw format only supports one entry per archive");
97 		return (ARCHIVE_FATAL);
98 	}
99 	raw->entries_written++;
100 
101 	return (ARCHIVE_OK);
102 }
103 
104 static ssize_t
105 archive_write_raw_data(struct archive_write *a, const void *buff, size_t s)
106 {
107 	int ret;
108 
109 	ret = __archive_write_output(a, buff, s);
110 	if (ret >= 0)
111 		return (s);
112 	else
113 		return (ret);
114 }
115 
116 static int
117 archive_write_raw_free(struct archive_write *a)
118 {
119 	struct raw *raw;
120 
121 	raw = (struct raw *)a->format_data;
122 	free(raw);
123 	a->format_data = NULL;
124 	return (ARCHIVE_OK);
125 }
126