1/*-
2 * Copyright (c) 2003-2007 Tim Kientzle
3 * Copyright (c) 2006 Rudolf Marek SYSGO s.r.o.
4 * Copyright (c) 2011-2012 Michihiro NAKAJIMA
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include "archive_platform.h"
29__FBSDID("$FreeBSD$");
30
31#ifdef HAVE_ERRNO_H
32#include <errno.h>
33#endif
34#include <stdio.h>
35#ifdef HAVE_STDLIB_H
36#include <stdlib.h>
37#endif
38#ifdef HAVE_STRING_H
39#include <string.h>
40#endif
41
42#include "archive.h"
43#include "archive_entry.h"
44#include "archive_entry_locale.h"
45#include "archive_private.h"
46#include "archive_write_private.h"
47#include "archive_write_set_format_private.h"
48
49static ssize_t	archive_write_newc_data(struct archive_write *,
50		    const void *buff, size_t s);
51static int	archive_write_newc_close(struct archive_write *);
52static int	archive_write_newc_free(struct archive_write *);
53static int	archive_write_newc_finish_entry(struct archive_write *);
54static int	archive_write_newc_header(struct archive_write *,
55		    struct archive_entry *);
56static int      archive_write_newc_options(struct archive_write *,
57		    const char *, const char *);
58static int	format_hex(int64_t, void *, int);
59static int64_t	format_hex_recursive(int64_t, char *, int);
60static int	write_header(struct archive_write *, struct archive_entry *);
61
62struct cpio {
63	uint64_t	  entry_bytes_remaining;
64	int		  padding;
65
66	struct archive_string_conv *opt_sconv;
67	struct archive_string_conv *sconv_default;
68	int		  init_default_conversion;
69};
70
71#define	c_magic_offset 0
72#define	c_magic_size 6
73#define	c_ino_offset 6
74#define	c_ino_size 8
75#define	c_mode_offset 14
76#define	c_mode_size 8
77#define	c_uid_offset 22
78#define	c_uid_size 8
79#define	c_gid_offset 30
80#define	c_gid_size 8
81#define	c_nlink_offset 38
82#define	c_nlink_size 8
83#define	c_mtime_offset 46
84#define	c_mtime_size 8
85#define	c_filesize_offset 54
86#define	c_filesize_size 8
87#define	c_devmajor_offset 62
88#define	c_devmajor_size 8
89#define	c_devminor_offset 70
90#define	c_devminor_size 8
91#define	c_rdevmajor_offset 78
92#define	c_rdevmajor_size 8
93#define	c_rdevminor_offset 86
94#define	c_rdevminor_size 8
95#define	c_namesize_offset 94
96#define	c_namesize_size 8
97#define	c_checksum_offset 102
98#define	c_checksum_size 8
99#define	c_header_size 110
100
101/* Logic trick: difference between 'n' and next multiple of 4 */
102#define PAD4(n)	(3 & (1 + ~(n)))
103
104/*
105 * Set output format to 'cpio' format.
106 */
107int
108archive_write_set_format_cpio_newc(struct archive *_a)
109{
110	struct archive_write *a = (struct archive_write *)_a;
111	struct cpio *cpio;
112
113	archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
114	    ARCHIVE_STATE_NEW, "archive_write_set_format_cpio_newc");
115
116	/* If someone else was already registered, unregister them. */
117	if (a->format_free != NULL)
118		(a->format_free)(a);
119
120	cpio = (struct cpio *)calloc(1, sizeof(*cpio));
121	if (cpio == NULL) {
122		archive_set_error(&a->archive, ENOMEM, "Can't allocate cpio data");
123		return (ARCHIVE_FATAL);
124	}
125	a->format_data = cpio;
126	a->format_name = "cpio";
127	a->format_options = archive_write_newc_options;
128	a->format_write_header = archive_write_newc_header;
129	a->format_write_data = archive_write_newc_data;
130	a->format_finish_entry = archive_write_newc_finish_entry;
131	a->format_close = archive_write_newc_close;
132	a->format_free = archive_write_newc_free;
133	a->archive.archive_format = ARCHIVE_FORMAT_CPIO_SVR4_NOCRC;
134	a->archive.archive_format_name = "SVR4 cpio nocrc";
135	return (ARCHIVE_OK);
136}
137
138static int
139archive_write_newc_options(struct archive_write *a, const char *key,
140    const char *val)
141{
142	struct cpio *cpio = (struct cpio *)a->format_data;
143	int ret = ARCHIVE_FAILED;
144
145	if (strcmp(key, "hdrcharset")  == 0) {
146		if (val == NULL || val[0] == 0)
147			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
148			    "%s: hdrcharset option needs a character-set name",
149			    a->format_name);
150		else {
151			cpio->opt_sconv = archive_string_conversion_to_charset(
152			    &a->archive, val, 0);
153			if (cpio->opt_sconv != NULL)
154				ret = ARCHIVE_OK;
155			else
156				ret = ARCHIVE_FATAL;
157		}
158		return (ret);
159	}
160
161	/* Note: The "warn" return is just to inform the options
162	 * supervisor that we didn't handle it.  It will generate
163	 * a suitable error if no one used this option. */
164	return (ARCHIVE_WARN);
165}
166
167static struct archive_string_conv *
168get_sconv(struct archive_write *a)
169{
170	struct cpio *cpio;
171	struct archive_string_conv *sconv;
172
173	cpio = (struct cpio *)a->format_data;
174	sconv = cpio->opt_sconv;
175	if (sconv == NULL) {
176		if (!cpio->init_default_conversion) {
177			cpio->sconv_default =
178			    archive_string_default_conversion_for_write(
179			      &(a->archive));
180			cpio->init_default_conversion = 1;
181		}
182		sconv = cpio->sconv_default;
183	}
184	return (sconv);
185}
186
187static int
188archive_write_newc_header(struct archive_write *a, struct archive_entry *entry)
189{
190	const char *path;
191	size_t len;
192
193	if (archive_entry_filetype(entry) == 0 && archive_entry_hardlink(entry) == NULL) {
194		archive_set_error(&a->archive, -1, "Filetype required");
195		return (ARCHIVE_FAILED);
196	}
197
198	if (archive_entry_pathname_l(entry, &path, &len, get_sconv(a)) != 0
199	    && errno == ENOMEM) {
200		archive_set_error(&a->archive, ENOMEM,
201		    "Can't allocate memory for Pathname");
202		return (ARCHIVE_FATAL);
203	}
204	if (len == 0 || path == NULL || path[0] == '\0') {
205		archive_set_error(&a->archive, -1, "Pathname required");
206		return (ARCHIVE_FAILED);
207	}
208
209	if (archive_entry_hardlink(entry) == NULL
210	    && (!archive_entry_size_is_set(entry) || archive_entry_size(entry) < 0)) {
211		archive_set_error(&a->archive, -1, "Size required");
212		return (ARCHIVE_FAILED);
213	}
214	return write_header(a, entry);
215}
216
217static int
218write_header(struct archive_write *a, struct archive_entry *entry)
219{
220	int64_t ino;
221	struct cpio *cpio;
222	const char *p, *path;
223	int pathlength, ret, ret_final;
224	char h[c_header_size];
225	struct archive_string_conv *sconv;
226	struct archive_entry *entry_main;
227	size_t len;
228	int pad;
229
230	cpio = (struct cpio *)a->format_data;
231	ret_final = ARCHIVE_OK;
232	sconv = get_sconv(a);
233
234#if defined(_WIN32) && !defined(__CYGWIN__)
235	/* Make sure the path separators in pathname, hardlink and symlink
236	 * are all slash '/', not the Windows path separator '\'. */
237	entry_main = __la_win_entry_in_posix_pathseparator(entry);
238	if (entry_main == NULL) {
239		archive_set_error(&a->archive, ENOMEM,
240		    "Can't allocate ustar data");
241		return(ARCHIVE_FATAL);
242	}
243	if (entry != entry_main)
244		entry = entry_main;
245	else
246		entry_main = NULL;
247#else
248	entry_main = NULL;
249#endif
250
251	ret = archive_entry_pathname_l(entry, &path, &len, sconv);
252	if (ret != 0) {
253		if (errno == ENOMEM) {
254			archive_set_error(&a->archive, ENOMEM,
255			    "Can't allocate memory for Pathname");
256			ret_final = ARCHIVE_FATAL;
257			goto exit_write_header;
258		}
259		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
260		    "Can't translate pathname '%s' to %s",
261		    archive_entry_pathname(entry),
262		    archive_string_conversion_charset_name(sconv));
263		ret_final = ARCHIVE_WARN;
264	}
265	pathlength = (int)len + 1; /* Include trailing null. */
266
267	memset(h, 0, c_header_size);
268	format_hex(0x070701, h + c_magic_offset, c_magic_size);
269	format_hex(archive_entry_devmajor(entry), h + c_devmajor_offset,
270	    c_devmajor_size);
271	format_hex(archive_entry_devminor(entry), h + c_devminor_offset,
272	    c_devminor_size);
273
274	ino = archive_entry_ino64(entry);
275	if (ino > 0xffffffff) {
276		archive_set_error(&a->archive, ERANGE,
277		    "large inode number truncated");
278		ret_final = ARCHIVE_WARN;
279	}
280
281	/* TODO: Set ret_final to ARCHIVE_WARN if any of these overflow. */
282	format_hex(ino & 0xffffffff, h + c_ino_offset, c_ino_size);
283	format_hex(archive_entry_mode(entry), h + c_mode_offset, c_mode_size);
284	format_hex(archive_entry_uid(entry), h + c_uid_offset, c_uid_size);
285	format_hex(archive_entry_gid(entry), h + c_gid_offset, c_gid_size);
286	format_hex(archive_entry_nlink(entry), h + c_nlink_offset, c_nlink_size);
287	if (archive_entry_filetype(entry) == AE_IFBLK
288	    || archive_entry_filetype(entry) == AE_IFCHR) {
289	    format_hex(archive_entry_rdevmajor(entry), h + c_rdevmajor_offset, c_rdevmajor_size);
290	    format_hex(archive_entry_rdevminor(entry), h + c_rdevminor_offset, c_rdevminor_size);
291	} else {
292	    format_hex(0, h + c_rdevmajor_offset, c_rdevmajor_size);
293	    format_hex(0, h + c_rdevminor_offset, c_rdevminor_size);
294	}
295	format_hex(archive_entry_mtime(entry), h + c_mtime_offset, c_mtime_size);
296	format_hex(pathlength, h + c_namesize_offset, c_namesize_size);
297	format_hex(0, h + c_checksum_offset, c_checksum_size);
298
299	/* Non-regular files don't store bodies. */
300	if (archive_entry_filetype(entry) != AE_IFREG)
301		archive_entry_set_size(entry, 0);
302
303	/* Symlinks get the link written as the body of the entry. */
304	ret = archive_entry_symlink_l(entry, &p, &len, sconv);
305	if (ret != 0) {
306		if (errno == ENOMEM) {
307			archive_set_error(&a->archive, ENOMEM,
308			    "Can't allocate memory for Likname");
309			ret_final = ARCHIVE_FATAL;
310			goto exit_write_header;
311		}
312		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
313		    "Can't translate linkname '%s' to %s",
314		    archive_entry_symlink(entry),
315		    archive_string_conversion_charset_name(sconv));
316		ret_final = ARCHIVE_WARN;
317	}
318	if (len > 0 && p != NULL  &&  *p != '\0')
319		ret = format_hex(strlen(p), h + c_filesize_offset,
320		    c_filesize_size);
321	else
322		ret = format_hex(archive_entry_size(entry),
323		    h + c_filesize_offset, c_filesize_size);
324	if (ret) {
325		archive_set_error(&a->archive, ERANGE,
326		    "File is too large for this format.");
327		ret_final = ARCHIVE_FAILED;
328		goto exit_write_header;
329	}
330
331	ret = __archive_write_output(a, h, c_header_size);
332	if (ret != ARCHIVE_OK) {
333		ret_final = ARCHIVE_FATAL;
334		goto exit_write_header;
335	}
336
337	/* Pad pathname to even length. */
338	ret = __archive_write_output(a, path, pathlength);
339	if (ret != ARCHIVE_OK) {
340		ret_final = ARCHIVE_FATAL;
341		goto exit_write_header;
342	}
343	pad = PAD4(pathlength + c_header_size);
344	if (pad) {
345		ret = __archive_write_output(a, "\0\0\0", pad);
346		if (ret != ARCHIVE_OK) {
347			ret_final = ARCHIVE_FATAL;
348			goto exit_write_header;
349		}
350	}
351
352	cpio->entry_bytes_remaining = archive_entry_size(entry);
353	cpio->padding = (int)PAD4(cpio->entry_bytes_remaining);
354
355	/* Write the symlink now. */
356	if (p != NULL  &&  *p != '\0') {
357		ret = __archive_write_output(a, p, strlen(p));
358		if (ret != ARCHIVE_OK) {
359			ret_final = ARCHIVE_FATAL;
360			goto exit_write_header;
361		}
362		pad = PAD4(strlen(p));
363		ret = __archive_write_output(a, "\0\0\0", pad);
364		if (ret != ARCHIVE_OK) {
365			ret_final = ARCHIVE_FATAL;
366			goto exit_write_header;
367		}
368	}
369exit_write_header:
370	archive_entry_free(entry_main);
371	return (ret_final);
372}
373
374static ssize_t
375archive_write_newc_data(struct archive_write *a, const void *buff, size_t s)
376{
377	struct cpio *cpio;
378	int ret;
379
380	cpio = (struct cpio *)a->format_data;
381	if (s > cpio->entry_bytes_remaining)
382		s = (size_t)cpio->entry_bytes_remaining;
383
384	ret = __archive_write_output(a, buff, s);
385	cpio->entry_bytes_remaining -= s;
386	if (ret >= 0)
387		return (s);
388	else
389		return (ret);
390}
391
392/*
393 * Format a number into the specified field.
394 */
395static int
396format_hex(int64_t v, void *p, int digits)
397{
398	int64_t	max;
399	int	ret;
400
401	max = (((int64_t)1) << (digits * 4)) - 1;
402	if (v >= 0  &&  v <= max) {
403	    format_hex_recursive(v, (char *)p, digits);
404	    ret = 0;
405	} else {
406	    format_hex_recursive(max, (char *)p, digits);
407	    ret = -1;
408	}
409	return (ret);
410}
411
412static int64_t
413format_hex_recursive(int64_t v, char *p, int s)
414{
415	if (s == 0)
416		return (v);
417	v = format_hex_recursive(v, p+1, s-1);
418	*p = "0123456789abcdef"[v & 0xf];
419	return (v >> 4);
420}
421
422static int
423archive_write_newc_close(struct archive_write *a)
424{
425	int er;
426	struct archive_entry *trailer;
427
428	trailer = archive_entry_new();
429	archive_entry_set_nlink(trailer, 1);
430	archive_entry_set_size(trailer, 0);
431	archive_entry_set_pathname(trailer, "TRAILER!!!");
432	/* Bypass the required data checks. */
433	er = write_header(a, trailer);
434	archive_entry_free(trailer);
435	return (er);
436}
437
438static int
439archive_write_newc_free(struct archive_write *a)
440{
441	struct cpio *cpio;
442
443	cpio = (struct cpio *)a->format_data;
444	free(cpio);
445	a->format_data = NULL;
446	return (ARCHIVE_OK);
447}
448
449static int
450archive_write_newc_finish_entry(struct archive_write *a)
451{
452	struct cpio *cpio;
453
454	cpio = (struct cpio *)a->format_data;
455	return (__archive_write_nulls(a,
456		(size_t)cpio->entry_bytes_remaining + cpio->padding));
457}
458