1228753Smm/*-
2228753Smm * Copyright (c) 2003-2007 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
26228753Smm#include "archive_platform.h"
27229592Smm__FBSDID("$FreeBSD$");
28228753Smm
29228753Smm
30228753Smm#ifdef HAVE_ERRNO_H
31228753Smm#include <errno.h>
32228753Smm#endif
33228753Smm#include <stdio.h>
34228753Smm#ifdef HAVE_STDLIB_H
35228753Smm#include <stdlib.h>
36228753Smm#endif
37228753Smm#ifdef HAVE_STRING_H
38228753Smm#include <string.h>
39228753Smm#endif
40228753Smm
41228753Smm#include "archive.h"
42228753Smm#include "archive_entry.h"
43228753Smm#include "archive_private.h"
44228753Smm#include "archive_write_private.h"
45228753Smm
46228753Smmstruct ustar {
47228753Smm	uint64_t	entry_bytes_remaining;
48228753Smm	uint64_t	entry_padding;
49228753Smm};
50228753Smm
51228753Smm/*
52228753Smm * Define structure of POSIX 'ustar' tar header.
53228753Smm */
54228753Smm#define	USTAR_name_offset 0
55228753Smm#define	USTAR_name_size 100
56228753Smm#define	USTAR_mode_offset 100
57228753Smm#define	USTAR_mode_size 6
58228753Smm#define	USTAR_mode_max_size 8
59228753Smm#define	USTAR_uid_offset 108
60228753Smm#define	USTAR_uid_size 6
61228753Smm#define	USTAR_uid_max_size 8
62228753Smm#define	USTAR_gid_offset 116
63228753Smm#define	USTAR_gid_size 6
64228753Smm#define	USTAR_gid_max_size 8
65228753Smm#define	USTAR_size_offset 124
66228753Smm#define	USTAR_size_size 11
67228753Smm#define	USTAR_size_max_size 12
68228753Smm#define	USTAR_mtime_offset 136
69228753Smm#define	USTAR_mtime_size 11
70228753Smm#define	USTAR_mtime_max_size 11
71228753Smm#define	USTAR_checksum_offset 148
72228753Smm#define	USTAR_checksum_size 8
73228753Smm#define	USTAR_typeflag_offset 156
74228753Smm#define	USTAR_typeflag_size 1
75228753Smm#define	USTAR_linkname_offset 157
76228753Smm#define	USTAR_linkname_size 100
77228753Smm#define	USTAR_magic_offset 257
78228753Smm#define	USTAR_magic_size 6
79228753Smm#define	USTAR_version_offset 263
80228753Smm#define	USTAR_version_size 2
81228753Smm#define	USTAR_uname_offset 265
82228753Smm#define	USTAR_uname_size 32
83228753Smm#define	USTAR_gname_offset 297
84228753Smm#define	USTAR_gname_size 32
85228753Smm#define	USTAR_rdevmajor_offset 329
86228753Smm#define	USTAR_rdevmajor_size 6
87228753Smm#define	USTAR_rdevmajor_max_size 8
88228753Smm#define	USTAR_rdevminor_offset 337
89228753Smm#define	USTAR_rdevminor_size 6
90228753Smm#define	USTAR_rdevminor_max_size 8
91228753Smm#define	USTAR_prefix_offset 345
92228753Smm#define	USTAR_prefix_size 155
93228753Smm#define	USTAR_padding_offset 500
94228753Smm#define	USTAR_padding_size 12
95228753Smm
96228753Smm/*
97228753Smm * A filled-in copy of the header for initialization.
98228753Smm */
99228753Smmstatic const char template_header[] = {
100228753Smm	/* name: 100 bytes */
101228753Smm	0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
102228753Smm	0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
103228753Smm	0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
104228753Smm	0,0,0,0,
105228753Smm	/* Mode, space-null termination: 8 bytes */
106228753Smm	'0','0','0','0','0','0', ' ','\0',
107228753Smm	/* uid, space-null termination: 8 bytes */
108228753Smm	'0','0','0','0','0','0', ' ','\0',
109228753Smm	/* gid, space-null termination: 8 bytes */
110228753Smm	'0','0','0','0','0','0', ' ','\0',
111228753Smm	/* size, space termation: 12 bytes */
112228753Smm	'0','0','0','0','0','0','0','0','0','0','0', ' ',
113228753Smm	/* mtime, space termation: 12 bytes */
114228753Smm	'0','0','0','0','0','0','0','0','0','0','0', ' ',
115228753Smm	/* Initial checksum value: 8 spaces */
116228753Smm	' ',' ',' ',' ',' ',' ',' ',' ',
117228753Smm	/* Typeflag: 1 byte */
118228753Smm	'0',			/* '0' = regular file */
119228753Smm	/* Linkname: 100 bytes */
120228753Smm	0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
121228753Smm	0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
122228753Smm	0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
123228753Smm	0,0,0,0,
124228753Smm	/* Magic: 6 bytes, Version: 2 bytes */
125228753Smm	'u','s','t','a','r','\0', '0','0',
126228753Smm	/* Uname: 32 bytes */
127228753Smm	0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
128228753Smm	/* Gname: 32 bytes */
129228753Smm	0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
130228753Smm	/* rdevmajor + space/null padding: 8 bytes */
131228753Smm	'0','0','0','0','0','0', ' ','\0',
132228753Smm	/* rdevminor + space/null padding: 8 bytes */
133228753Smm	'0','0','0','0','0','0', ' ','\0',
134228753Smm	/* Prefix: 155 bytes */
135228753Smm	0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
136228753Smm	0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
137228753Smm	0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
138228753Smm	0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
139228753Smm	0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,
140228753Smm	/* Padding: 12 bytes */
141228753Smm	0,0,0,0,0,0,0,0, 0,0,0,0
142228753Smm};
143228753Smm
144228753Smmstatic ssize_t	archive_write_ustar_data(struct archive_write *a, const void *buff,
145228753Smm		    size_t s);
146228753Smmstatic int	archive_write_ustar_destroy(struct archive_write *);
147228753Smmstatic int	archive_write_ustar_finish(struct archive_write *);
148228753Smmstatic int	archive_write_ustar_finish_entry(struct archive_write *);
149228753Smmstatic int	archive_write_ustar_header(struct archive_write *,
150228753Smm		    struct archive_entry *entry);
151228753Smmstatic int	format_256(int64_t, char *, int);
152228753Smmstatic int	format_number(int64_t, char *, int size, int max, int strict);
153228753Smmstatic int	format_octal(int64_t, char *, int);
154228753Smmstatic int	write_nulls(struct archive_write *a, size_t);
155228753Smm
156228753Smm/*
157228753Smm * Set output format to 'ustar' format.
158228753Smm */
159228753Smmint
160228753Smmarchive_write_set_format_ustar(struct archive *_a)
161228753Smm{
162228753Smm	struct archive_write *a = (struct archive_write *)_a;
163228753Smm	struct ustar *ustar;
164228753Smm
165228753Smm	/* If someone else was already registered, unregister them. */
166228753Smm	if (a->format_destroy != NULL)
167228753Smm		(a->format_destroy)(a);
168228753Smm
169228753Smm	/* Basic internal sanity test. */
170228753Smm	if (sizeof(template_header) != 512) {
171228753Smm		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Internal: template_header wrong size: %d should be 512", (int)sizeof(template_header));
172228753Smm		return (ARCHIVE_FATAL);
173228753Smm	}
174228753Smm
175228753Smm	ustar = (struct ustar *)malloc(sizeof(*ustar));
176228753Smm	if (ustar == NULL) {
177228753Smm		archive_set_error(&a->archive, ENOMEM, "Can't allocate ustar data");
178228753Smm		return (ARCHIVE_FATAL);
179228753Smm	}
180228753Smm	memset(ustar, 0, sizeof(*ustar));
181228753Smm	a->format_data = ustar;
182228753Smm
183228753Smm	a->pad_uncompressed = 1;	/* Mimic gtar in this respect. */
184228753Smm	a->format_name = "ustar";
185228753Smm	a->format_write_header = archive_write_ustar_header;
186228753Smm	a->format_write_data = archive_write_ustar_data;
187228753Smm	a->format_finish = archive_write_ustar_finish;
188228753Smm	a->format_destroy = archive_write_ustar_destroy;
189228753Smm	a->format_finish_entry = archive_write_ustar_finish_entry;
190228753Smm	a->archive.archive_format = ARCHIVE_FORMAT_TAR_USTAR;
191228753Smm	a->archive.archive_format_name = "POSIX ustar";
192228753Smm	return (ARCHIVE_OK);
193228753Smm}
194228753Smm
195228753Smmstatic int
196228753Smmarchive_write_ustar_header(struct archive_write *a, struct archive_entry *entry)
197228753Smm{
198228753Smm	char buff[512];
199228753Smm	int ret, ret2;
200228753Smm	struct ustar *ustar;
201228753Smm
202228753Smm	ustar = (struct ustar *)a->format_data;
203228753Smm
204228753Smm	/* Only regular files (not hardlinks) have data. */
205228753Smm	if (archive_entry_hardlink(entry) != NULL ||
206228753Smm	    archive_entry_symlink(entry) != NULL ||
207228753Smm	    !(archive_entry_filetype(entry) == AE_IFREG))
208228753Smm		archive_entry_set_size(entry, 0);
209228753Smm
210228753Smm	if (AE_IFDIR == archive_entry_filetype(entry)) {
211228753Smm		const char *p;
212228753Smm		char *t;
213228753Smm		/*
214228753Smm		 * Ensure a trailing '/'.  Modify the entry so
215228753Smm		 * the client sees the change.
216228753Smm		 */
217228753Smm		p = archive_entry_pathname(entry);
218228753Smm		if (p[strlen(p) - 1] != '/') {
219228753Smm			t = (char *)malloc(strlen(p) + 2);
220228753Smm			if (t == NULL) {
221228753Smm				archive_set_error(&a->archive, ENOMEM,
222228753Smm				"Can't allocate ustar data");
223228753Smm				return(ARCHIVE_FATAL);
224228753Smm			}
225228753Smm			strcpy(t, p);
226228753Smm			strcat(t, "/");
227228753Smm			archive_entry_copy_pathname(entry, t);
228228753Smm			free(t);
229228753Smm		}
230228753Smm	}
231228753Smm
232228753Smm	ret = __archive_write_format_header_ustar(a, buff, entry, -1, 1);
233228753Smm	if (ret < ARCHIVE_WARN)
234228753Smm		return (ret);
235228753Smm	ret2 = (a->compressor.write)(a, buff, 512);
236228753Smm	if (ret2 < ARCHIVE_WARN)
237228753Smm		return (ret2);
238228753Smm	if (ret2 < ret)
239228753Smm		ret = ret2;
240228753Smm
241228753Smm	ustar->entry_bytes_remaining = archive_entry_size(entry);
242228753Smm	ustar->entry_padding = 0x1ff & (-(int64_t)ustar->entry_bytes_remaining);
243228753Smm	return (ret);
244228753Smm}
245228753Smm
246228753Smm/*
247228753Smm * Format a basic 512-byte "ustar" header.
248228753Smm *
249228753Smm * Returns -1 if format failed (due to field overflow).
250228753Smm * Note that this always formats as much of the header as possible.
251228753Smm * If "strict" is set to zero, it will extend numeric fields as
252228753Smm * necessary (overwriting terminators or using base-256 extensions).
253228753Smm *
254228753Smm * This is exported so that other 'tar' formats can use it.
255228753Smm */
256228753Smmint
257228753Smm__archive_write_format_header_ustar(struct archive_write *a, char h[512],
258228753Smm    struct archive_entry *entry, int tartype, int strict)
259228753Smm{
260228753Smm	unsigned int checksum;
261228753Smm	int i, ret;
262228753Smm	size_t copy_length;
263228753Smm	const char *p, *pp;
264228753Smm	int mytartype;
265228753Smm
266228753Smm	ret = 0;
267228753Smm	mytartype = -1;
268228753Smm	/*
269228753Smm	 * The "template header" already includes the "ustar"
270228753Smm	 * signature, various end-of-field markers and other required
271228753Smm	 * elements.
272228753Smm	 */
273228753Smm	memcpy(h, &template_header, 512);
274228753Smm
275228753Smm	/*
276228753Smm	 * Because the block is already null-filled, and strings
277228753Smm	 * are allowed to exactly fill their destination (without null),
278228753Smm	 * I use memcpy(dest, src, strlen()) here a lot to copy strings.
279228753Smm	 */
280228753Smm
281228753Smm	pp = archive_entry_pathname(entry);
282228753Smm	if (strlen(pp) <= USTAR_name_size)
283228753Smm		memcpy(h + USTAR_name_offset, pp, strlen(pp));
284228753Smm	else {
285228753Smm		/* Store in two pieces, splitting at a '/'. */
286228753Smm		p = strchr(pp + strlen(pp) - USTAR_name_size - 1, '/');
287228753Smm		/*
288228753Smm		 * Look for the next '/' if we chose the first character
289228753Smm		 * as the separator.  (ustar format doesn't permit
290228753Smm		 * an empty prefix.)
291228753Smm		 */
292228753Smm		if (p == pp)
293228753Smm			p = strchr(p + 1, '/');
294228753Smm		/* Fail if the name won't fit. */
295228753Smm		if (!p) {
296228753Smm			/* No separator. */
297228753Smm			archive_set_error(&a->archive, ENAMETOOLONG,
298228753Smm			    "Pathname too long");
299228753Smm			ret = ARCHIVE_FAILED;
300228753Smm		} else if (p[1] == '\0') {
301228753Smm			/*
302228753Smm			 * The only feasible separator is a final '/';
303228753Smm			 * this would result in a non-empty prefix and
304228753Smm			 * an empty name, which POSIX doesn't
305228753Smm			 * explicity forbid, but it just feels wrong.
306228753Smm			 */
307228753Smm			archive_set_error(&a->archive, ENAMETOOLONG,
308228753Smm			    "Pathname too long");
309228753Smm			ret = ARCHIVE_FAILED;
310228753Smm		} else if (p  > pp + USTAR_prefix_size) {
311228753Smm			/* Prefix is too long. */
312228753Smm			archive_set_error(&a->archive, ENAMETOOLONG,
313228753Smm			    "Pathname too long");
314228753Smm			ret = ARCHIVE_FAILED;
315228753Smm		} else {
316228753Smm			/* Copy prefix and remainder to appropriate places */
317228753Smm			memcpy(h + USTAR_prefix_offset, pp, p - pp);
318228753Smm			memcpy(h + USTAR_name_offset, p + 1, pp + strlen(pp) - p - 1);
319228753Smm		}
320228753Smm	}
321228753Smm
322228753Smm	p = archive_entry_hardlink(entry);
323228753Smm	if (p != NULL)
324228753Smm		mytartype = '1';
325228753Smm	else
326228753Smm		p = archive_entry_symlink(entry);
327228753Smm	if (p != NULL && p[0] != '\0') {
328228753Smm		copy_length = strlen(p);
329228753Smm		if (copy_length > USTAR_linkname_size) {
330228753Smm			archive_set_error(&a->archive, ENAMETOOLONG,
331228753Smm			    "Link contents too long");
332228753Smm			ret = ARCHIVE_FAILED;
333228753Smm			copy_length = USTAR_linkname_size;
334228753Smm		}
335228753Smm		memcpy(h + USTAR_linkname_offset, p, copy_length);
336228753Smm	}
337228753Smm
338228753Smm	p = archive_entry_uname(entry);
339228753Smm	if (p != NULL && p[0] != '\0') {
340228753Smm		copy_length = strlen(p);
341228753Smm		if (copy_length > USTAR_uname_size) {
342228753Smm			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
343228753Smm			    "Username too long");
344228753Smm			ret = ARCHIVE_FAILED;
345228753Smm			copy_length = USTAR_uname_size;
346228753Smm		}
347228753Smm		memcpy(h + USTAR_uname_offset, p, copy_length);
348228753Smm	}
349228753Smm
350228753Smm	p = archive_entry_gname(entry);
351228753Smm	if (p != NULL && p[0] != '\0') {
352228753Smm		copy_length = strlen(p);
353228753Smm		if (strlen(p) > USTAR_gname_size) {
354228753Smm			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
355228753Smm			    "Group name too long");
356228753Smm			ret = ARCHIVE_FAILED;
357228753Smm			copy_length = USTAR_gname_size;
358228753Smm		}
359228753Smm		memcpy(h + USTAR_gname_offset, p, copy_length);
360228753Smm	}
361228753Smm
362228753Smm	if (format_number(archive_entry_mode(entry) & 07777, h + USTAR_mode_offset, USTAR_mode_size, USTAR_mode_max_size, strict)) {
363228753Smm		archive_set_error(&a->archive, ERANGE, "Numeric mode too large");
364228753Smm		ret = ARCHIVE_FAILED;
365228753Smm	}
366228753Smm
367228753Smm	if (format_number(archive_entry_uid(entry), h + USTAR_uid_offset, USTAR_uid_size, USTAR_uid_max_size, strict)) {
368228753Smm		archive_set_error(&a->archive, ERANGE, "Numeric user ID too large");
369228753Smm		ret = ARCHIVE_FAILED;
370228753Smm	}
371228753Smm
372228753Smm	if (format_number(archive_entry_gid(entry), h + USTAR_gid_offset, USTAR_gid_size, USTAR_gid_max_size, strict)) {
373228753Smm		archive_set_error(&a->archive, ERANGE, "Numeric group ID too large");
374228753Smm		ret = ARCHIVE_FAILED;
375228753Smm	}
376228753Smm
377228753Smm	if (format_number(archive_entry_size(entry), h + USTAR_size_offset, USTAR_size_size, USTAR_size_max_size, strict)) {
378228753Smm		archive_set_error(&a->archive, ERANGE, "File size out of range");
379228753Smm		ret = ARCHIVE_FAILED;
380228753Smm	}
381228753Smm
382228753Smm	if (format_number(archive_entry_mtime(entry), h + USTAR_mtime_offset, USTAR_mtime_size, USTAR_mtime_max_size, strict)) {
383228753Smm		archive_set_error(&a->archive, ERANGE,
384228753Smm		    "File modification time too large");
385228753Smm		ret = ARCHIVE_FAILED;
386228753Smm	}
387228753Smm
388228753Smm	if (archive_entry_filetype(entry) == AE_IFBLK
389228753Smm	    || archive_entry_filetype(entry) == AE_IFCHR) {
390228753Smm		if (format_number(archive_entry_rdevmajor(entry), h + USTAR_rdevmajor_offset,
391228753Smm			USTAR_rdevmajor_size, USTAR_rdevmajor_max_size, strict)) {
392228753Smm			archive_set_error(&a->archive, ERANGE,
393228753Smm			    "Major device number too large");
394228753Smm			ret = ARCHIVE_FAILED;
395228753Smm		}
396228753Smm
397228753Smm		if (format_number(archive_entry_rdevminor(entry), h + USTAR_rdevminor_offset,
398228753Smm			USTAR_rdevminor_size, USTAR_rdevminor_max_size, strict)) {
399228753Smm			archive_set_error(&a->archive, ERANGE,
400228753Smm			    "Minor device number too large");
401228753Smm			ret = ARCHIVE_FAILED;
402228753Smm		}
403228753Smm	}
404228753Smm
405228753Smm	if (tartype >= 0) {
406228753Smm		h[USTAR_typeflag_offset] = tartype;
407228753Smm	} else if (mytartype >= 0) {
408228753Smm		h[USTAR_typeflag_offset] = mytartype;
409228753Smm	} else {
410228753Smm		switch (archive_entry_filetype(entry)) {
411228753Smm		case AE_IFREG: h[USTAR_typeflag_offset] = '0' ; break;
412228753Smm		case AE_IFLNK: h[USTAR_typeflag_offset] = '2' ; break;
413228753Smm		case AE_IFCHR: h[USTAR_typeflag_offset] = '3' ; break;
414228753Smm		case AE_IFBLK: h[USTAR_typeflag_offset] = '4' ; break;
415228753Smm		case AE_IFDIR: h[USTAR_typeflag_offset] = '5' ; break;
416228753Smm		case AE_IFIFO: h[USTAR_typeflag_offset] = '6' ; break;
417228753Smm		case AE_IFSOCK:
418228753Smm			archive_set_error(&a->archive,
419228753Smm			    ARCHIVE_ERRNO_FILE_FORMAT,
420228753Smm			    "tar format cannot archive socket");
421228753Smm			return (ARCHIVE_FAILED);
422228753Smm		default:
423228753Smm			archive_set_error(&a->archive,
424228753Smm			    ARCHIVE_ERRNO_FILE_FORMAT,
425228753Smm			    "tar format cannot archive this (mode=0%lo)",
426228753Smm			    (unsigned long)archive_entry_mode(entry));
427228753Smm			ret = ARCHIVE_FAILED;
428228753Smm		}
429228753Smm	}
430228753Smm
431228753Smm	checksum = 0;
432228753Smm	for (i = 0; i < 512; i++)
433228753Smm		checksum += 255 & (unsigned int)h[i];
434228753Smm	h[USTAR_checksum_offset + 6] = '\0'; /* Can't be pre-set in the template. */
435228753Smm	/* h[USTAR_checksum_offset + 7] = ' '; */ /* This is pre-set in the template. */
436228753Smm	format_octal(checksum, h + USTAR_checksum_offset, 6);
437228753Smm	return (ret);
438228753Smm}
439228753Smm
440228753Smm/*
441228753Smm * Format a number into a field, with some intelligence.
442228753Smm */
443228753Smmstatic int
444228753Smmformat_number(int64_t v, char *p, int s, int maxsize, int strict)
445228753Smm{
446228753Smm	int64_t limit;
447228753Smm
448228753Smm	limit = ((int64_t)1 << (s*3));
449228753Smm
450228753Smm	/* "Strict" only permits octal values with proper termination. */
451228753Smm	if (strict)
452228753Smm		return (format_octal(v, p, s));
453228753Smm
454228753Smm	/*
455228753Smm	 * In non-strict mode, we allow the number to overwrite one or
456228753Smm	 * more bytes of the field termination.  Even old tar
457228753Smm	 * implementations should be able to handle this with no
458228753Smm	 * problem.
459228753Smm	 */
460228753Smm	if (v >= 0) {
461228753Smm		while (s <= maxsize) {
462228753Smm			if (v < limit)
463228753Smm				return (format_octal(v, p, s));
464228753Smm			s++;
465228753Smm			limit <<= 3;
466228753Smm		}
467228753Smm	}
468228753Smm
469228753Smm	/* Base-256 can handle any number, positive or negative. */
470228753Smm	return (format_256(v, p, maxsize));
471228753Smm}
472228753Smm
473228753Smm/*
474228753Smm * Format a number into the specified field using base-256.
475228753Smm */
476228753Smmstatic int
477228753Smmformat_256(int64_t v, char *p, int s)
478228753Smm{
479228753Smm	p += s;
480228753Smm	while (s-- > 0) {
481228753Smm		*--p = (char)(v & 0xff);
482228753Smm		v >>= 8;
483228753Smm	}
484228753Smm	*p |= 0x80; /* Set the base-256 marker bit. */
485228753Smm	return (0);
486228753Smm}
487228753Smm
488228753Smm/*
489228753Smm * Format a number into the specified field.
490228753Smm */
491228753Smmstatic int
492228753Smmformat_octal(int64_t v, char *p, int s)
493228753Smm{
494228753Smm	int len;
495228753Smm
496228753Smm	len = s;
497228753Smm
498228753Smm	/* Octal values can't be negative, so use 0. */
499228753Smm	if (v < 0) {
500228753Smm		while (len-- > 0)
501228753Smm			*p++ = '0';
502228753Smm		return (-1);
503228753Smm	}
504228753Smm
505228753Smm	p += s;		/* Start at the end and work backwards. */
506228753Smm	while (s-- > 0) {
507228753Smm		*--p = (char)('0' + (v & 7));
508228753Smm		v >>= 3;
509228753Smm	}
510228753Smm
511228753Smm	if (v == 0)
512228753Smm		return (0);
513228753Smm
514228753Smm	/* If it overflowed, fill field with max value. */
515228753Smm	while (len-- > 0)
516228753Smm		*p++ = '7';
517228753Smm
518228753Smm	return (-1);
519228753Smm}
520228753Smm
521228753Smmstatic int
522228753Smmarchive_write_ustar_finish(struct archive_write *a)
523228753Smm{
524228753Smm	int r;
525228753Smm
526228753Smm	if (a->compressor.write == NULL)
527228753Smm		return (ARCHIVE_OK);
528228753Smm
529228753Smm	r = write_nulls(a, 512*2);
530228753Smm	return (r);
531228753Smm}
532228753Smm
533228753Smmstatic int
534228753Smmarchive_write_ustar_destroy(struct archive_write *a)
535228753Smm{
536228753Smm	struct ustar *ustar;
537228753Smm
538228753Smm	ustar = (struct ustar *)a->format_data;
539228753Smm	free(ustar);
540228753Smm	a->format_data = NULL;
541228753Smm	return (ARCHIVE_OK);
542228753Smm}
543228753Smm
544228753Smmstatic int
545228753Smmarchive_write_ustar_finish_entry(struct archive_write *a)
546228753Smm{
547228753Smm	struct ustar *ustar;
548228753Smm	int ret;
549228753Smm
550228753Smm	ustar = (struct ustar *)a->format_data;
551228753Smm	ret = write_nulls(a,
552228753Smm	    ustar->entry_bytes_remaining + ustar->entry_padding);
553228753Smm	ustar->entry_bytes_remaining = ustar->entry_padding = 0;
554228753Smm	return (ret);
555228753Smm}
556228753Smm
557228753Smmstatic int
558228753Smmwrite_nulls(struct archive_write *a, size_t padding)
559228753Smm{
560228753Smm	int ret;
561228753Smm	size_t to_write;
562228753Smm
563228753Smm	while (padding > 0) {
564228753Smm		to_write = padding < a->null_length ? padding : a->null_length;
565228753Smm		ret = (a->compressor.write)(a, a->nulls, to_write);
566228753Smm		if (ret != ARCHIVE_OK)
567228753Smm			return (ret);
568228753Smm		padding -= to_write;
569228753Smm	}
570228753Smm	return (ARCHIVE_OK);
571228753Smm}
572228753Smm
573228753Smmstatic ssize_t
574228753Smmarchive_write_ustar_data(struct archive_write *a, const void *buff, size_t s)
575228753Smm{
576228753Smm	struct ustar *ustar;
577228753Smm	int ret;
578228753Smm
579228753Smm	ustar = (struct ustar *)a->format_data;
580228753Smm	if (s > ustar->entry_bytes_remaining)
581228753Smm		s = ustar->entry_bytes_remaining;
582228753Smm	ret = (a->compressor.write)(a, buff, s);
583228753Smm	ustar->entry_bytes_remaining -= s;
584228753Smm	if (ret != ARCHIVE_OK)
585228753Smm		return (ret);
586228753Smm	return (s);
587228753Smm}
588