1caf54c4fSMartin Matuska /*-
2caf54c4fSMartin Matuska * Copyright (c) 2003-2007 Tim Kientzle
36c95142eSMartin Matuska * Copyright (c) 2011-2012 Michihiro NAKAJIMA
4caf54c4fSMartin Matuska * All rights reserved.
5caf54c4fSMartin Matuska *
6caf54c4fSMartin Matuska * Redistribution and use in source and binary forms, with or without
7caf54c4fSMartin Matuska * modification, are permitted provided that the following conditions
8caf54c4fSMartin Matuska * are met:
9caf54c4fSMartin Matuska * 1. Redistributions of source code must retain the above copyright
10caf54c4fSMartin Matuska * notice, this list of conditions and the following disclaimer.
11caf54c4fSMartin Matuska * 2. Redistributions in binary form must reproduce the above copyright
12caf54c4fSMartin Matuska * notice, this list of conditions and the following disclaimer in the
13caf54c4fSMartin Matuska * documentation and/or other materials provided with the distribution.
14caf54c4fSMartin Matuska *
15caf54c4fSMartin Matuska * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
16caf54c4fSMartin Matuska * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17caf54c4fSMartin Matuska * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18caf54c4fSMartin Matuska * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
19caf54c4fSMartin Matuska * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20caf54c4fSMartin Matuska * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21caf54c4fSMartin Matuska * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22caf54c4fSMartin Matuska * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23caf54c4fSMartin Matuska * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24caf54c4fSMartin Matuska * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25caf54c4fSMartin Matuska */
26caf54c4fSMartin Matuska
27caf54c4fSMartin Matuska #include "archive_platform.h"
28caf54c4fSMartin Matuska
29caf54c4fSMartin Matuska #ifdef HAVE_ERRNO_H
30caf54c4fSMartin Matuska #include <errno.h>
31caf54c4fSMartin Matuska #endif
32caf54c4fSMartin Matuska #include <stdio.h>
33caf54c4fSMartin Matuska #ifdef HAVE_STDLIB_H
34caf54c4fSMartin Matuska #include <stdlib.h>
35caf54c4fSMartin Matuska #endif
36caf54c4fSMartin Matuska #ifdef HAVE_STRING_H
37caf54c4fSMartin Matuska #include <string.h>
38caf54c4fSMartin Matuska #endif
39caf54c4fSMartin Matuska
40caf54c4fSMartin Matuska #include "archive.h"
41caf54c4fSMartin Matuska #include "archive_entry.h"
426c95142eSMartin Matuska #include "archive_entry_locale.h"
43caf54c4fSMartin Matuska #include "archive_private.h"
44caf54c4fSMartin Matuska #include "archive_write_private.h"
45f9762417SMartin Matuska #include "archive_write_set_format_private.h"
46caf54c4fSMartin Matuska
47caf54c4fSMartin Matuska struct ustar {
48caf54c4fSMartin Matuska uint64_t entry_bytes_remaining;
49caf54c4fSMartin Matuska uint64_t entry_padding;
506c95142eSMartin Matuska
516c95142eSMartin Matuska struct archive_string_conv *opt_sconv;
526c95142eSMartin Matuska struct archive_string_conv *sconv_default;
536c95142eSMartin Matuska int init_default_conversion;
54caf54c4fSMartin Matuska };
55caf54c4fSMartin Matuska
56caf54c4fSMartin Matuska /*
57caf54c4fSMartin Matuska * Define structure of POSIX 'ustar' tar header.
58caf54c4fSMartin Matuska */
59caf54c4fSMartin Matuska #define USTAR_name_offset 0
60caf54c4fSMartin Matuska #define USTAR_name_size 100
61caf54c4fSMartin Matuska #define USTAR_mode_offset 100
62caf54c4fSMartin Matuska #define USTAR_mode_size 6
63caf54c4fSMartin Matuska #define USTAR_mode_max_size 8
64caf54c4fSMartin Matuska #define USTAR_uid_offset 108
65caf54c4fSMartin Matuska #define USTAR_uid_size 6
66caf54c4fSMartin Matuska #define USTAR_uid_max_size 8
67caf54c4fSMartin Matuska #define USTAR_gid_offset 116
68caf54c4fSMartin Matuska #define USTAR_gid_size 6
69caf54c4fSMartin Matuska #define USTAR_gid_max_size 8
70caf54c4fSMartin Matuska #define USTAR_size_offset 124
71caf54c4fSMartin Matuska #define USTAR_size_size 11
72caf54c4fSMartin Matuska #define USTAR_size_max_size 12
73caf54c4fSMartin Matuska #define USTAR_mtime_offset 136
74caf54c4fSMartin Matuska #define USTAR_mtime_size 11
75caf54c4fSMartin Matuska #define USTAR_mtime_max_size 11
76caf54c4fSMartin Matuska #define USTAR_checksum_offset 148
77caf54c4fSMartin Matuska #define USTAR_checksum_size 8
78caf54c4fSMartin Matuska #define USTAR_typeflag_offset 156
79caf54c4fSMartin Matuska #define USTAR_typeflag_size 1
80caf54c4fSMartin Matuska #define USTAR_linkname_offset 157
81caf54c4fSMartin Matuska #define USTAR_linkname_size 100
82caf54c4fSMartin Matuska #define USTAR_magic_offset 257
83caf54c4fSMartin Matuska #define USTAR_magic_size 6
84caf54c4fSMartin Matuska #define USTAR_version_offset 263
85caf54c4fSMartin Matuska #define USTAR_version_size 2
86caf54c4fSMartin Matuska #define USTAR_uname_offset 265
87caf54c4fSMartin Matuska #define USTAR_uname_size 32
88caf54c4fSMartin Matuska #define USTAR_gname_offset 297
89caf54c4fSMartin Matuska #define USTAR_gname_size 32
90caf54c4fSMartin Matuska #define USTAR_rdevmajor_offset 329
91caf54c4fSMartin Matuska #define USTAR_rdevmajor_size 6
92caf54c4fSMartin Matuska #define USTAR_rdevmajor_max_size 8
93caf54c4fSMartin Matuska #define USTAR_rdevminor_offset 337
94caf54c4fSMartin Matuska #define USTAR_rdevminor_size 6
95caf54c4fSMartin Matuska #define USTAR_rdevminor_max_size 8
96caf54c4fSMartin Matuska #define USTAR_prefix_offset 345
97caf54c4fSMartin Matuska #define USTAR_prefix_size 155
98caf54c4fSMartin Matuska #define USTAR_padding_offset 500
99caf54c4fSMartin Matuska #define USTAR_padding_size 12
100caf54c4fSMartin Matuska
101caf54c4fSMartin Matuska /*
102caf54c4fSMartin Matuska * A filled-in copy of the header for initialization.
103caf54c4fSMartin Matuska */
104caf54c4fSMartin Matuska static const char template_header[] = {
105caf54c4fSMartin Matuska /* name: 100 bytes */
106caf54c4fSMartin Matuska 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,
107caf54c4fSMartin Matuska 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,
108caf54c4fSMartin Matuska 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,
109caf54c4fSMartin Matuska 0,0,0,0,
110caf54c4fSMartin Matuska /* Mode, space-null termination: 8 bytes */
111caf54c4fSMartin Matuska '0','0','0','0','0','0', ' ','\0',
112caf54c4fSMartin Matuska /* uid, space-null termination: 8 bytes */
113caf54c4fSMartin Matuska '0','0','0','0','0','0', ' ','\0',
114caf54c4fSMartin Matuska /* gid, space-null termination: 8 bytes */
115caf54c4fSMartin Matuska '0','0','0','0','0','0', ' ','\0',
116a2e802b7SMartin Matuska /* size, space termination: 12 bytes */
117caf54c4fSMartin Matuska '0','0','0','0','0','0','0','0','0','0','0', ' ',
118a2e802b7SMartin Matuska /* mtime, space termination: 12 bytes */
119caf54c4fSMartin Matuska '0','0','0','0','0','0','0','0','0','0','0', ' ',
120caf54c4fSMartin Matuska /* Initial checksum value: 8 spaces */
121caf54c4fSMartin Matuska ' ',' ',' ',' ',' ',' ',' ',' ',
122caf54c4fSMartin Matuska /* Typeflag: 1 byte */
123caf54c4fSMartin Matuska '0', /* '0' = regular file */
124caf54c4fSMartin Matuska /* Linkname: 100 bytes */
125caf54c4fSMartin Matuska 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,
126caf54c4fSMartin Matuska 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,
127caf54c4fSMartin Matuska 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,
128caf54c4fSMartin Matuska 0,0,0,0,
129caf54c4fSMartin Matuska /* Magic: 6 bytes, Version: 2 bytes */
130caf54c4fSMartin Matuska 'u','s','t','a','r','\0', '0','0',
131caf54c4fSMartin Matuska /* Uname: 32 bytes */
132caf54c4fSMartin Matuska 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,
133caf54c4fSMartin Matuska /* Gname: 32 bytes */
134caf54c4fSMartin Matuska 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,
135caf54c4fSMartin Matuska /* rdevmajor + space/null padding: 8 bytes */
136caf54c4fSMartin Matuska '0','0','0','0','0','0', ' ','\0',
137caf54c4fSMartin Matuska /* rdevminor + space/null padding: 8 bytes */
138caf54c4fSMartin Matuska '0','0','0','0','0','0', ' ','\0',
139caf54c4fSMartin Matuska /* Prefix: 155 bytes */
140caf54c4fSMartin Matuska 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,
141caf54c4fSMartin Matuska 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,
142caf54c4fSMartin Matuska 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,
143caf54c4fSMartin Matuska 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,
144caf54c4fSMartin Matuska 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,
145caf54c4fSMartin Matuska /* Padding: 12 bytes */
146caf54c4fSMartin Matuska 0,0,0,0,0,0,0,0, 0,0,0,0
147caf54c4fSMartin Matuska };
148caf54c4fSMartin Matuska
149caf54c4fSMartin Matuska static ssize_t archive_write_ustar_data(struct archive_write *a, const void *buff,
150caf54c4fSMartin Matuska size_t s);
1516c95142eSMartin Matuska static int archive_write_ustar_free(struct archive_write *);
1526c95142eSMartin Matuska static int archive_write_ustar_close(struct archive_write *);
153caf54c4fSMartin Matuska static int archive_write_ustar_finish_entry(struct archive_write *);
154caf54c4fSMartin Matuska static int archive_write_ustar_header(struct archive_write *,
155caf54c4fSMartin Matuska struct archive_entry *entry);
1566c95142eSMartin Matuska static int archive_write_ustar_options(struct archive_write *,
1576c95142eSMartin Matuska const char *, const char *);
158caf54c4fSMartin Matuska static int format_256(int64_t, char *, int);
159caf54c4fSMartin Matuska static int format_number(int64_t, char *, int size, int max, int strict);
160caf54c4fSMartin Matuska static int format_octal(int64_t, char *, int);
161caf54c4fSMartin Matuska
162caf54c4fSMartin Matuska /*
163caf54c4fSMartin Matuska * Set output format to 'ustar' format.
164caf54c4fSMartin Matuska */
165caf54c4fSMartin Matuska int
archive_write_set_format_ustar(struct archive * _a)166caf54c4fSMartin Matuska archive_write_set_format_ustar(struct archive *_a)
167caf54c4fSMartin Matuska {
168caf54c4fSMartin Matuska struct archive_write *a = (struct archive_write *)_a;
169caf54c4fSMartin Matuska struct ustar *ustar;
170caf54c4fSMartin Matuska
1716c95142eSMartin Matuska archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
1726c95142eSMartin Matuska ARCHIVE_STATE_NEW, "archive_write_set_format_ustar");
1736c95142eSMartin Matuska
174caf54c4fSMartin Matuska /* If someone else was already registered, unregister them. */
1756c95142eSMartin Matuska if (a->format_free != NULL)
1766c95142eSMartin Matuska (a->format_free)(a);
177caf54c4fSMartin Matuska
178caf54c4fSMartin Matuska /* Basic internal sanity test. */
179caf54c4fSMartin Matuska if (sizeof(template_header) != 512) {
1806c95142eSMartin Matuska archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
1816c95142eSMartin Matuska "Internal: template_header wrong size: %zu should be 512",
1826c95142eSMartin Matuska sizeof(template_header));
183caf54c4fSMartin Matuska return (ARCHIVE_FATAL);
184caf54c4fSMartin Matuska }
185caf54c4fSMartin Matuska
186*bd66c1b4SMartin Matuska ustar = calloc(1, sizeof(*ustar));
187caf54c4fSMartin Matuska if (ustar == NULL) {
1886c95142eSMartin Matuska archive_set_error(&a->archive, ENOMEM,
1896c95142eSMartin Matuska "Can't allocate ustar data");
190caf54c4fSMartin Matuska return (ARCHIVE_FATAL);
191caf54c4fSMartin Matuska }
192caf54c4fSMartin Matuska a->format_data = ustar;
193caf54c4fSMartin Matuska a->format_name = "ustar";
1946c95142eSMartin Matuska a->format_options = archive_write_ustar_options;
195caf54c4fSMartin Matuska a->format_write_header = archive_write_ustar_header;
196caf54c4fSMartin Matuska a->format_write_data = archive_write_ustar_data;
1976c95142eSMartin Matuska a->format_close = archive_write_ustar_close;
1986c95142eSMartin Matuska a->format_free = archive_write_ustar_free;
199caf54c4fSMartin Matuska a->format_finish_entry = archive_write_ustar_finish_entry;
200caf54c4fSMartin Matuska a->archive.archive_format = ARCHIVE_FORMAT_TAR_USTAR;
201caf54c4fSMartin Matuska a->archive.archive_format_name = "POSIX ustar";
202caf54c4fSMartin Matuska return (ARCHIVE_OK);
203caf54c4fSMartin Matuska }
204caf54c4fSMartin Matuska
205caf54c4fSMartin Matuska static int
archive_write_ustar_options(struct archive_write * a,const char * key,const char * val)2066c95142eSMartin Matuska archive_write_ustar_options(struct archive_write *a, const char *key,
2076c95142eSMartin Matuska const char *val)
2086c95142eSMartin Matuska {
2096c95142eSMartin Matuska struct ustar *ustar = (struct ustar *)a->format_data;
2106c95142eSMartin Matuska int ret = ARCHIVE_FAILED;
2116c95142eSMartin Matuska
2126c95142eSMartin Matuska if (strcmp(key, "hdrcharset") == 0) {
2136c95142eSMartin Matuska if (val == NULL || val[0] == 0)
2146c95142eSMartin Matuska archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
2156c95142eSMartin Matuska "%s: hdrcharset option needs a character-set name",
2166c95142eSMartin Matuska a->format_name);
2176c95142eSMartin Matuska else {
2186c95142eSMartin Matuska ustar->opt_sconv = archive_string_conversion_to_charset(
2196c95142eSMartin Matuska &a->archive, val, 0);
2206c95142eSMartin Matuska if (ustar->opt_sconv != NULL)
2216c95142eSMartin Matuska ret = ARCHIVE_OK;
2226c95142eSMartin Matuska else
2236c95142eSMartin Matuska ret = ARCHIVE_FATAL;
2246c95142eSMartin Matuska }
2256c95142eSMartin Matuska return (ret);
2266c95142eSMartin Matuska }
2276c95142eSMartin Matuska
2286c95142eSMartin Matuska /* Note: The "warn" return is just to inform the options
2296c95142eSMartin Matuska * supervisor that we didn't handle it. It will generate
2306c95142eSMartin Matuska * a suitable error if no one used this option. */
2316c95142eSMartin Matuska return (ARCHIVE_WARN);
2326c95142eSMartin Matuska }
2336c95142eSMartin Matuska
2346c95142eSMartin Matuska static int
archive_write_ustar_header(struct archive_write * a,struct archive_entry * entry)235caf54c4fSMartin Matuska archive_write_ustar_header(struct archive_write *a, struct archive_entry *entry)
236caf54c4fSMartin Matuska {
237caf54c4fSMartin Matuska char buff[512];
238caf54c4fSMartin Matuska int ret, ret2;
239caf54c4fSMartin Matuska struct ustar *ustar;
2406c95142eSMartin Matuska struct archive_entry *entry_main;
2416c95142eSMartin Matuska struct archive_string_conv *sconv;
242caf54c4fSMartin Matuska
243caf54c4fSMartin Matuska ustar = (struct ustar *)a->format_data;
244caf54c4fSMartin Matuska
2456c95142eSMartin Matuska /* Setup default string conversion. */
2466c95142eSMartin Matuska if (ustar->opt_sconv == NULL) {
2476c95142eSMartin Matuska if (!ustar->init_default_conversion) {
2486c95142eSMartin Matuska ustar->sconv_default =
2496c95142eSMartin Matuska archive_string_default_conversion_for_write(&(a->archive));
2506c95142eSMartin Matuska ustar->init_default_conversion = 1;
2516c95142eSMartin Matuska }
2526c95142eSMartin Matuska sconv = ustar->sconv_default;
2536c95142eSMartin Matuska } else
2546c95142eSMartin Matuska sconv = ustar->opt_sconv;
2556c95142eSMartin Matuska
2566c95142eSMartin Matuska /* Sanity check. */
257*bd66c1b4SMartin Matuska #if defined(_WIN32) && !defined(__CYGWIN__)
258*bd66c1b4SMartin Matuska if (archive_entry_pathname_w(entry) == NULL) {
259*bd66c1b4SMartin Matuska #else
2606c95142eSMartin Matuska if (archive_entry_pathname(entry) == NULL) {
261*bd66c1b4SMartin Matuska #endif
2626c95142eSMartin Matuska archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
2636c95142eSMartin Matuska "Can't record entry in tar file without pathname");
2646c95142eSMartin Matuska return (ARCHIVE_FAILED);
2656c95142eSMartin Matuska }
2666c95142eSMartin Matuska
267caf54c4fSMartin Matuska /* Only regular files (not hardlinks) have data. */
268caf54c4fSMartin Matuska if (archive_entry_hardlink(entry) != NULL ||
269caf54c4fSMartin Matuska archive_entry_symlink(entry) != NULL ||
270*bd66c1b4SMartin Matuska archive_entry_filetype(entry) != AE_IFREG)
271caf54c4fSMartin Matuska archive_entry_set_size(entry, 0);
272caf54c4fSMartin Matuska
273caf54c4fSMartin Matuska if (AE_IFDIR == archive_entry_filetype(entry)) {
274caf54c4fSMartin Matuska const char *p;
2756c95142eSMartin Matuska size_t path_length;
276caf54c4fSMartin Matuska /*
277caf54c4fSMartin Matuska * Ensure a trailing '/'. Modify the entry so
278caf54c4fSMartin Matuska * the client sees the change.
279caf54c4fSMartin Matuska */
2806c95142eSMartin Matuska #if defined(_WIN32) && !defined(__CYGWIN__)
2816c95142eSMartin Matuska const wchar_t *wp;
2826c95142eSMartin Matuska
2836c95142eSMartin Matuska wp = archive_entry_pathname_w(entry);
2846c95142eSMartin Matuska if (wp != NULL && wp[wcslen(wp) -1] != L'/') {
2856c95142eSMartin Matuska struct archive_wstring ws;
2866c95142eSMartin Matuska
2876c95142eSMartin Matuska archive_string_init(&ws);
2886c95142eSMartin Matuska path_length = wcslen(wp);
2896c95142eSMartin Matuska if (archive_wstring_ensure(&ws,
2906c95142eSMartin Matuska path_length + 2) == NULL) {
2916c95142eSMartin Matuska archive_set_error(&a->archive, ENOMEM,
2926c95142eSMartin Matuska "Can't allocate ustar data");
2936c95142eSMartin Matuska archive_wstring_free(&ws);
2946c95142eSMartin Matuska return(ARCHIVE_FATAL);
2956c95142eSMartin Matuska }
2966c95142eSMartin Matuska /* Should we keep '\' ? */
2976c95142eSMartin Matuska if (wp[path_length -1] == L'\\')
2986c95142eSMartin Matuska path_length--;
2996c95142eSMartin Matuska archive_wstrncpy(&ws, wp, path_length);
3006c95142eSMartin Matuska archive_wstrappend_wchar(&ws, L'/');
3016c95142eSMartin Matuska archive_entry_copy_pathname_w(entry, ws.s);
3026c95142eSMartin Matuska archive_wstring_free(&ws);
3036c95142eSMartin Matuska p = NULL;
3046c95142eSMartin Matuska } else
3056c95142eSMartin Matuska #endif
306caf54c4fSMartin Matuska p = archive_entry_pathname(entry);
3076c95142eSMartin Matuska /*
3086c95142eSMartin Matuska * On Windows, this is a backup operation just in
3096c95142eSMartin Matuska * case getting WCS failed. On POSIX, this is a
3106c95142eSMartin Matuska * normal operation.
3116c95142eSMartin Matuska */
312cfa49a9bSMartin Matuska if (p != NULL && p[0] != '\0' && p[strlen(p) - 1] != '/') {
3136c95142eSMartin Matuska struct archive_string as;
3146c95142eSMartin Matuska
3156c95142eSMartin Matuska archive_string_init(&as);
3166c95142eSMartin Matuska path_length = strlen(p);
3176c95142eSMartin Matuska if (archive_string_ensure(&as,
3186c95142eSMartin Matuska path_length + 2) == NULL) {
3196c95142eSMartin Matuska archive_set_error(&a->archive, ENOMEM,
3206c95142eSMartin Matuska "Can't allocate ustar data");
3216c95142eSMartin Matuska archive_string_free(&as);
3226c95142eSMartin Matuska return(ARCHIVE_FATAL);
3236c95142eSMartin Matuska }
3246c95142eSMartin Matuska #if defined(_WIN32) && !defined(__CYGWIN__)
3256c95142eSMartin Matuska /* NOTE: This might break the pathname
3266c95142eSMartin Matuska * if the current code page is CP932 and
3276c95142eSMartin Matuska * the pathname includes a character '\'
3286c95142eSMartin Matuska * as a part of its multibyte pathname. */
3296c95142eSMartin Matuska if (p[strlen(p) -1] == '\\')
3306c95142eSMartin Matuska path_length--;
3316c95142eSMartin Matuska else
3326c95142eSMartin Matuska #endif
3336c95142eSMartin Matuska archive_strncpy(&as, p, path_length);
3346c95142eSMartin Matuska archive_strappend_char(&as, '/');
3356c95142eSMartin Matuska archive_entry_copy_pathname(entry, as.s);
3366c95142eSMartin Matuska archive_string_free(&as);
3376c95142eSMartin Matuska }
3386c95142eSMartin Matuska }
3396c95142eSMartin Matuska
3406c95142eSMartin Matuska #if defined(_WIN32) && !defined(__CYGWIN__)
341a2e802b7SMartin Matuska /* Make sure the path separators in pathname, hardlink and symlink
3426c95142eSMartin Matuska * are all slash '/', not the Windows path separator '\'. */
3436c95142eSMartin Matuska entry_main = __la_win_entry_in_posix_pathseparator(entry);
3446c95142eSMartin Matuska if (entry_main == NULL) {
345caf54c4fSMartin Matuska archive_set_error(&a->archive, ENOMEM,
346caf54c4fSMartin Matuska "Can't allocate ustar data");
347caf54c4fSMartin Matuska return(ARCHIVE_FATAL);
348caf54c4fSMartin Matuska }
3496c95142eSMartin Matuska if (entry != entry_main)
3506c95142eSMartin Matuska entry = entry_main;
3516c95142eSMartin Matuska else
3526c95142eSMartin Matuska entry_main = NULL;
3536c95142eSMartin Matuska #else
3546c95142eSMartin Matuska entry_main = NULL;
3556c95142eSMartin Matuska #endif
3566c95142eSMartin Matuska ret = __archive_write_format_header_ustar(a, buff, entry, -1, 1, sconv);
3576c95142eSMartin Matuska if (ret < ARCHIVE_WARN) {
3586c95142eSMartin Matuska archive_entry_free(entry_main);
359caf54c4fSMartin Matuska return (ret);
3606c95142eSMartin Matuska }
3616c95142eSMartin Matuska ret2 = __archive_write_output(a, buff, 512);
3626c95142eSMartin Matuska if (ret2 < ARCHIVE_WARN) {
3636c95142eSMartin Matuska archive_entry_free(entry_main);
364caf54c4fSMartin Matuska return (ret2);
3656c95142eSMartin Matuska }
366caf54c4fSMartin Matuska if (ret2 < ret)
367caf54c4fSMartin Matuska ret = ret2;
368caf54c4fSMartin Matuska
369caf54c4fSMartin Matuska ustar->entry_bytes_remaining = archive_entry_size(entry);
370caf54c4fSMartin Matuska ustar->entry_padding = 0x1ff & (-(int64_t)ustar->entry_bytes_remaining);
3716c95142eSMartin Matuska archive_entry_free(entry_main);
372caf54c4fSMartin Matuska return (ret);
373caf54c4fSMartin Matuska }
374caf54c4fSMartin Matuska
375caf54c4fSMartin Matuska /*
376caf54c4fSMartin Matuska * Format a basic 512-byte "ustar" header.
377caf54c4fSMartin Matuska *
378caf54c4fSMartin Matuska * Returns -1 if format failed (due to field overflow).
379caf54c4fSMartin Matuska * Note that this always formats as much of the header as possible.
380caf54c4fSMartin Matuska * If "strict" is set to zero, it will extend numeric fields as
381caf54c4fSMartin Matuska * necessary (overwriting terminators or using base-256 extensions).
382caf54c4fSMartin Matuska *
383caf54c4fSMartin Matuska * This is exported so that other 'tar' formats can use it.
384caf54c4fSMartin Matuska */
385caf54c4fSMartin Matuska int
386caf54c4fSMartin Matuska __archive_write_format_header_ustar(struct archive_write *a, char h[512],
3876c95142eSMartin Matuska struct archive_entry *entry, int tartype, int strict,
3886c95142eSMartin Matuska struct archive_string_conv *sconv)
389caf54c4fSMartin Matuska {
390caf54c4fSMartin Matuska unsigned int checksum;
3916c95142eSMartin Matuska int i, r, ret;
392caf54c4fSMartin Matuska size_t copy_length;
393caf54c4fSMartin Matuska const char *p, *pp;
394caf54c4fSMartin Matuska int mytartype;
395caf54c4fSMartin Matuska
396caf54c4fSMartin Matuska ret = 0;
397caf54c4fSMartin Matuska mytartype = -1;
398caf54c4fSMartin Matuska /*
399caf54c4fSMartin Matuska * The "template header" already includes the "ustar"
400caf54c4fSMartin Matuska * signature, various end-of-field markers and other required
401caf54c4fSMartin Matuska * elements.
402caf54c4fSMartin Matuska */
403caf54c4fSMartin Matuska memcpy(h, &template_header, 512);
404caf54c4fSMartin Matuska
405caf54c4fSMartin Matuska /*
406caf54c4fSMartin Matuska * Because the block is already null-filled, and strings
407caf54c4fSMartin Matuska * are allowed to exactly fill their destination (without null),
408caf54c4fSMartin Matuska * I use memcpy(dest, src, strlen()) here a lot to copy strings.
409caf54c4fSMartin Matuska */
4106c95142eSMartin Matuska r = archive_entry_pathname_l(entry, &pp, ©_length, sconv);
4116c95142eSMartin Matuska if (r != 0) {
4126c95142eSMartin Matuska if (errno == ENOMEM) {
4136c95142eSMartin Matuska archive_set_error(&a->archive, ENOMEM,
4146c95142eSMartin Matuska "Can't allocate memory for Pathname");
4156c95142eSMartin Matuska return (ARCHIVE_FATAL);
4166c95142eSMartin Matuska }
4176c95142eSMartin Matuska archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
4186c95142eSMartin Matuska "Can't translate pathname '%s' to %s",
4196c95142eSMartin Matuska pp, archive_string_conversion_charset_name(sconv));
4206c95142eSMartin Matuska ret = ARCHIVE_WARN;
4216c95142eSMartin Matuska }
4226c95142eSMartin Matuska if (copy_length <= USTAR_name_size)
4236c95142eSMartin Matuska memcpy(h + USTAR_name_offset, pp, copy_length);
424caf54c4fSMartin Matuska else {
425caf54c4fSMartin Matuska /* Store in two pieces, splitting at a '/'. */
4266c95142eSMartin Matuska p = strchr(pp + copy_length - USTAR_name_size - 1, '/');
427caf54c4fSMartin Matuska /*
428caf54c4fSMartin Matuska * Look for the next '/' if we chose the first character
429caf54c4fSMartin Matuska * as the separator. (ustar format doesn't permit
430caf54c4fSMartin Matuska * an empty prefix.)
431caf54c4fSMartin Matuska */
432caf54c4fSMartin Matuska if (p == pp)
433caf54c4fSMartin Matuska p = strchr(p + 1, '/');
434caf54c4fSMartin Matuska /* Fail if the name won't fit. */
435caf54c4fSMartin Matuska if (!p) {
436caf54c4fSMartin Matuska /* No separator. */
437caf54c4fSMartin Matuska archive_set_error(&a->archive, ENAMETOOLONG,
438caf54c4fSMartin Matuska "Pathname too long");
439caf54c4fSMartin Matuska ret = ARCHIVE_FAILED;
440caf54c4fSMartin Matuska } else if (p[1] == '\0') {
441caf54c4fSMartin Matuska /*
442caf54c4fSMartin Matuska * The only feasible separator is a final '/';
443caf54c4fSMartin Matuska * this would result in a non-empty prefix and
444caf54c4fSMartin Matuska * an empty name, which POSIX doesn't
4456c95142eSMartin Matuska * explicitly forbid, but it just feels wrong.
446caf54c4fSMartin Matuska */
447caf54c4fSMartin Matuska archive_set_error(&a->archive, ENAMETOOLONG,
448caf54c4fSMartin Matuska "Pathname too long");
449caf54c4fSMartin Matuska ret = ARCHIVE_FAILED;
450caf54c4fSMartin Matuska } else if (p > pp + USTAR_prefix_size) {
451caf54c4fSMartin Matuska /* Prefix is too long. */
452caf54c4fSMartin Matuska archive_set_error(&a->archive, ENAMETOOLONG,
453caf54c4fSMartin Matuska "Pathname too long");
454caf54c4fSMartin Matuska ret = ARCHIVE_FAILED;
455caf54c4fSMartin Matuska } else {
456caf54c4fSMartin Matuska /* Copy prefix and remainder to appropriate places */
457caf54c4fSMartin Matuska memcpy(h + USTAR_prefix_offset, pp, p - pp);
4586c95142eSMartin Matuska memcpy(h + USTAR_name_offset, p + 1,
4596c95142eSMartin Matuska pp + copy_length - p - 1);
460caf54c4fSMartin Matuska }
461caf54c4fSMartin Matuska }
462caf54c4fSMartin Matuska
4636c95142eSMartin Matuska r = archive_entry_hardlink_l(entry, &p, ©_length, sconv);
4646c95142eSMartin Matuska if (r != 0) {
4656c95142eSMartin Matuska if (errno == ENOMEM) {
4666c95142eSMartin Matuska archive_set_error(&a->archive, ENOMEM,
4676c95142eSMartin Matuska "Can't allocate memory for Linkname");
4686c95142eSMartin Matuska return (ARCHIVE_FATAL);
4696c95142eSMartin Matuska }
4706c95142eSMartin Matuska archive_set_error(&a->archive,
4716c95142eSMartin Matuska ARCHIVE_ERRNO_FILE_FORMAT,
4726c95142eSMartin Matuska "Can't translate linkname '%s' to %s",
4736c95142eSMartin Matuska p, archive_string_conversion_charset_name(sconv));
4746c95142eSMartin Matuska ret = ARCHIVE_WARN;
4756c95142eSMartin Matuska }
4766c95142eSMartin Matuska if (copy_length > 0)
477caf54c4fSMartin Matuska mytartype = '1';
4786c95142eSMartin Matuska else {
4796c95142eSMartin Matuska r = archive_entry_symlink_l(entry, &p, ©_length, sconv);
4806c95142eSMartin Matuska if (r != 0) {
4816c95142eSMartin Matuska if (errno == ENOMEM) {
4826c95142eSMartin Matuska archive_set_error(&a->archive, ENOMEM,
4836c95142eSMartin Matuska "Can't allocate memory for Linkname");
4846c95142eSMartin Matuska return (ARCHIVE_FATAL);
4856c95142eSMartin Matuska }
4866c95142eSMartin Matuska archive_set_error(&a->archive,
4876c95142eSMartin Matuska ARCHIVE_ERRNO_FILE_FORMAT,
4886c95142eSMartin Matuska "Can't translate linkname '%s' to %s",
4896c95142eSMartin Matuska p, archive_string_conversion_charset_name(sconv));
4906c95142eSMartin Matuska ret = ARCHIVE_WARN;
4916c95142eSMartin Matuska }
4926c95142eSMartin Matuska }
4936c95142eSMartin Matuska if (copy_length > 0) {
494caf54c4fSMartin Matuska if (copy_length > USTAR_linkname_size) {
495caf54c4fSMartin Matuska archive_set_error(&a->archive, ENAMETOOLONG,
496caf54c4fSMartin Matuska "Link contents too long");
497caf54c4fSMartin Matuska ret = ARCHIVE_FAILED;
498caf54c4fSMartin Matuska copy_length = USTAR_linkname_size;
499caf54c4fSMartin Matuska }
500caf54c4fSMartin Matuska memcpy(h + USTAR_linkname_offset, p, copy_length);
501caf54c4fSMartin Matuska }
502caf54c4fSMartin Matuska
5036c95142eSMartin Matuska r = archive_entry_uname_l(entry, &p, ©_length, sconv);
5046c95142eSMartin Matuska if (r != 0) {
5056c95142eSMartin Matuska if (errno == ENOMEM) {
5066c95142eSMartin Matuska archive_set_error(&a->archive, ENOMEM,
5076c95142eSMartin Matuska "Can't allocate memory for Uname");
5086c95142eSMartin Matuska return (ARCHIVE_FATAL);
5096c95142eSMartin Matuska }
5106c95142eSMartin Matuska archive_set_error(&a->archive,
5116c95142eSMartin Matuska ARCHIVE_ERRNO_FILE_FORMAT,
5126c95142eSMartin Matuska "Can't translate uname '%s' to %s",
5136c95142eSMartin Matuska p, archive_string_conversion_charset_name(sconv));
5146c95142eSMartin Matuska ret = ARCHIVE_WARN;
5156c95142eSMartin Matuska }
5166c95142eSMartin Matuska if (copy_length > 0) {
517caf54c4fSMartin Matuska if (copy_length > USTAR_uname_size) {
518f9762417SMartin Matuska if (tartype != 'x') {
519f9762417SMartin Matuska archive_set_error(&a->archive,
520f9762417SMartin Matuska ARCHIVE_ERRNO_MISC, "Username too long");
521caf54c4fSMartin Matuska ret = ARCHIVE_FAILED;
522f9762417SMartin Matuska }
523caf54c4fSMartin Matuska copy_length = USTAR_uname_size;
524caf54c4fSMartin Matuska }
525caf54c4fSMartin Matuska memcpy(h + USTAR_uname_offset, p, copy_length);
526caf54c4fSMartin Matuska }
527caf54c4fSMartin Matuska
5286c95142eSMartin Matuska r = archive_entry_gname_l(entry, &p, ©_length, sconv);
5296c95142eSMartin Matuska if (r != 0) {
5306c95142eSMartin Matuska if (errno == ENOMEM) {
5316c95142eSMartin Matuska archive_set_error(&a->archive, ENOMEM,
5326c95142eSMartin Matuska "Can't allocate memory for Gname");
5336c95142eSMartin Matuska return (ARCHIVE_FATAL);
5346c95142eSMartin Matuska }
5356c95142eSMartin Matuska archive_set_error(&a->archive,
5366c95142eSMartin Matuska ARCHIVE_ERRNO_FILE_FORMAT,
5376c95142eSMartin Matuska "Can't translate gname '%s' to %s",
5386c95142eSMartin Matuska p, archive_string_conversion_charset_name(sconv));
5396c95142eSMartin Matuska ret = ARCHIVE_WARN;
5406c95142eSMartin Matuska }
5416c95142eSMartin Matuska if (copy_length > 0) {
542caf54c4fSMartin Matuska if (strlen(p) > USTAR_gname_size) {
543f9762417SMartin Matuska if (tartype != 'x') {
544f9762417SMartin Matuska archive_set_error(&a->archive,
545f9762417SMartin Matuska ARCHIVE_ERRNO_MISC, "Group name too long");
546caf54c4fSMartin Matuska ret = ARCHIVE_FAILED;
547f9762417SMartin Matuska }
548caf54c4fSMartin Matuska copy_length = USTAR_gname_size;
549caf54c4fSMartin Matuska }
550caf54c4fSMartin Matuska memcpy(h + USTAR_gname_offset, p, copy_length);
551caf54c4fSMartin Matuska }
552caf54c4fSMartin Matuska
5536c95142eSMartin Matuska if (format_number(archive_entry_mode(entry) & 07777,
5546c95142eSMartin Matuska h + USTAR_mode_offset, USTAR_mode_size, USTAR_mode_max_size, strict)) {
5556c95142eSMartin Matuska archive_set_error(&a->archive, ERANGE,
5566c95142eSMartin Matuska "Numeric mode too large");
557caf54c4fSMartin Matuska ret = ARCHIVE_FAILED;
558caf54c4fSMartin Matuska }
559caf54c4fSMartin Matuska
5606c95142eSMartin Matuska if (format_number(archive_entry_uid(entry),
5616c95142eSMartin Matuska h + USTAR_uid_offset, USTAR_uid_size, USTAR_uid_max_size, strict)) {
5626c95142eSMartin Matuska archive_set_error(&a->archive, ERANGE,
5636c95142eSMartin Matuska "Numeric user ID too large");
564caf54c4fSMartin Matuska ret = ARCHIVE_FAILED;
565caf54c4fSMartin Matuska }
566caf54c4fSMartin Matuska
5676c95142eSMartin Matuska if (format_number(archive_entry_gid(entry),
5686c95142eSMartin Matuska h + USTAR_gid_offset, USTAR_gid_size, USTAR_gid_max_size, strict)) {
5696c95142eSMartin Matuska archive_set_error(&a->archive, ERANGE,
5706c95142eSMartin Matuska "Numeric group ID too large");
571caf54c4fSMartin Matuska ret = ARCHIVE_FAILED;
572caf54c4fSMartin Matuska }
573caf54c4fSMartin Matuska
5746c95142eSMartin Matuska if (format_number(archive_entry_size(entry),
5756c95142eSMartin Matuska h + USTAR_size_offset, USTAR_size_size, USTAR_size_max_size, strict)) {
5766c95142eSMartin Matuska archive_set_error(&a->archive, ERANGE,
5776c95142eSMartin Matuska "File size out of range");
578caf54c4fSMartin Matuska ret = ARCHIVE_FAILED;
579caf54c4fSMartin Matuska }
580caf54c4fSMartin Matuska
5816c95142eSMartin Matuska if (format_number(archive_entry_mtime(entry),
5826c95142eSMartin Matuska h + USTAR_mtime_offset, USTAR_mtime_size, USTAR_mtime_max_size, strict)) {
583caf54c4fSMartin Matuska archive_set_error(&a->archive, ERANGE,
584caf54c4fSMartin Matuska "File modification time too large");
585caf54c4fSMartin Matuska ret = ARCHIVE_FAILED;
586caf54c4fSMartin Matuska }
587caf54c4fSMartin Matuska
588caf54c4fSMartin Matuska if (archive_entry_filetype(entry) == AE_IFBLK
589caf54c4fSMartin Matuska || archive_entry_filetype(entry) == AE_IFCHR) {
5906c95142eSMartin Matuska if (format_number(archive_entry_rdevmajor(entry),
5916c95142eSMartin Matuska h + USTAR_rdevmajor_offset, USTAR_rdevmajor_size,
5926c95142eSMartin Matuska USTAR_rdevmajor_max_size, strict)) {
593caf54c4fSMartin Matuska archive_set_error(&a->archive, ERANGE,
594caf54c4fSMartin Matuska "Major device number too large");
595caf54c4fSMartin Matuska ret = ARCHIVE_FAILED;
596caf54c4fSMartin Matuska }
597caf54c4fSMartin Matuska
5986c95142eSMartin Matuska if (format_number(archive_entry_rdevminor(entry),
5996c95142eSMartin Matuska h + USTAR_rdevminor_offset, USTAR_rdevminor_size,
6006c95142eSMartin Matuska USTAR_rdevminor_max_size, strict)) {
601caf54c4fSMartin Matuska archive_set_error(&a->archive, ERANGE,
602caf54c4fSMartin Matuska "Minor device number too large");
603caf54c4fSMartin Matuska ret = ARCHIVE_FAILED;
604caf54c4fSMartin Matuska }
605caf54c4fSMartin Matuska }
606caf54c4fSMartin Matuska
607caf54c4fSMartin Matuska if (tartype >= 0) {
608caf54c4fSMartin Matuska h[USTAR_typeflag_offset] = tartype;
609caf54c4fSMartin Matuska } else if (mytartype >= 0) {
610caf54c4fSMartin Matuska h[USTAR_typeflag_offset] = mytartype;
611caf54c4fSMartin Matuska } else {
612caf54c4fSMartin Matuska switch (archive_entry_filetype(entry)) {
613caf54c4fSMartin Matuska case AE_IFREG: h[USTAR_typeflag_offset] = '0' ; break;
614caf54c4fSMartin Matuska case AE_IFLNK: h[USTAR_typeflag_offset] = '2' ; break;
615caf54c4fSMartin Matuska case AE_IFCHR: h[USTAR_typeflag_offset] = '3' ; break;
616caf54c4fSMartin Matuska case AE_IFBLK: h[USTAR_typeflag_offset] = '4' ; break;
617caf54c4fSMartin Matuska case AE_IFDIR: h[USTAR_typeflag_offset] = '5' ; break;
618caf54c4fSMartin Matuska case AE_IFIFO: h[USTAR_typeflag_offset] = '6' ; break;
619f9762417SMartin Matuska default: /* AE_IFSOCK and unknown */
620f9762417SMartin Matuska __archive_write_entry_filetype_unsupported(
621f9762417SMartin Matuska &a->archive, entry, "ustar");
622caf54c4fSMartin Matuska ret = ARCHIVE_FAILED;
623caf54c4fSMartin Matuska }
624caf54c4fSMartin Matuska }
625caf54c4fSMartin Matuska
626caf54c4fSMartin Matuska checksum = 0;
627caf54c4fSMartin Matuska for (i = 0; i < 512; i++)
628caf54c4fSMartin Matuska checksum += 255 & (unsigned int)h[i];
629caf54c4fSMartin Matuska h[USTAR_checksum_offset + 6] = '\0'; /* Can't be pre-set in the template. */
630caf54c4fSMartin Matuska /* h[USTAR_checksum_offset + 7] = ' '; */ /* This is pre-set in the template. */
631caf54c4fSMartin Matuska format_octal(checksum, h + USTAR_checksum_offset, 6);
632caf54c4fSMartin Matuska return (ret);
633caf54c4fSMartin Matuska }
634caf54c4fSMartin Matuska
635caf54c4fSMartin Matuska /*
636caf54c4fSMartin Matuska * Format a number into a field, with some intelligence.
637caf54c4fSMartin Matuska */
638caf54c4fSMartin Matuska static int
639caf54c4fSMartin Matuska format_number(int64_t v, char *p, int s, int maxsize, int strict)
640caf54c4fSMartin Matuska {
641caf54c4fSMartin Matuska int64_t limit;
642caf54c4fSMartin Matuska
643caf54c4fSMartin Matuska limit = ((int64_t)1 << (s*3));
644caf54c4fSMartin Matuska
645caf54c4fSMartin Matuska /* "Strict" only permits octal values with proper termination. */
646caf54c4fSMartin Matuska if (strict)
647caf54c4fSMartin Matuska return (format_octal(v, p, s));
648caf54c4fSMartin Matuska
649caf54c4fSMartin Matuska /*
650caf54c4fSMartin Matuska * In non-strict mode, we allow the number to overwrite one or
651caf54c4fSMartin Matuska * more bytes of the field termination. Even old tar
652caf54c4fSMartin Matuska * implementations should be able to handle this with no
653caf54c4fSMartin Matuska * problem.
654caf54c4fSMartin Matuska */
655caf54c4fSMartin Matuska if (v >= 0) {
656caf54c4fSMartin Matuska while (s <= maxsize) {
657caf54c4fSMartin Matuska if (v < limit)
658caf54c4fSMartin Matuska return (format_octal(v, p, s));
659caf54c4fSMartin Matuska s++;
660caf54c4fSMartin Matuska limit <<= 3;
661caf54c4fSMartin Matuska }
662caf54c4fSMartin Matuska }
663caf54c4fSMartin Matuska
664caf54c4fSMartin Matuska /* Base-256 can handle any number, positive or negative. */
665caf54c4fSMartin Matuska return (format_256(v, p, maxsize));
666caf54c4fSMartin Matuska }
667caf54c4fSMartin Matuska
668caf54c4fSMartin Matuska /*
669caf54c4fSMartin Matuska * Format a number into the specified field using base-256.
670caf54c4fSMartin Matuska */
671caf54c4fSMartin Matuska static int
672caf54c4fSMartin Matuska format_256(int64_t v, char *p, int s)
673caf54c4fSMartin Matuska {
674caf54c4fSMartin Matuska p += s;
675caf54c4fSMartin Matuska while (s-- > 0) {
676caf54c4fSMartin Matuska *--p = (char)(v & 0xff);
677caf54c4fSMartin Matuska v >>= 8;
678caf54c4fSMartin Matuska }
679caf54c4fSMartin Matuska *p |= 0x80; /* Set the base-256 marker bit. */
680caf54c4fSMartin Matuska return (0);
681caf54c4fSMartin Matuska }
682caf54c4fSMartin Matuska
683caf54c4fSMartin Matuska /*
684caf54c4fSMartin Matuska * Format a number into the specified field.
685caf54c4fSMartin Matuska */
686caf54c4fSMartin Matuska static int
687caf54c4fSMartin Matuska format_octal(int64_t v, char *p, int s)
688caf54c4fSMartin Matuska {
689caf54c4fSMartin Matuska int len;
690caf54c4fSMartin Matuska
691caf54c4fSMartin Matuska len = s;
692caf54c4fSMartin Matuska
693caf54c4fSMartin Matuska /* Octal values can't be negative, so use 0. */
694caf54c4fSMartin Matuska if (v < 0) {
695caf54c4fSMartin Matuska while (len-- > 0)
696caf54c4fSMartin Matuska *p++ = '0';
697caf54c4fSMartin Matuska return (-1);
698caf54c4fSMartin Matuska }
699caf54c4fSMartin Matuska
700caf54c4fSMartin Matuska p += s; /* Start at the end and work backwards. */
701caf54c4fSMartin Matuska while (s-- > 0) {
702caf54c4fSMartin Matuska *--p = (char)('0' + (v & 7));
703caf54c4fSMartin Matuska v >>= 3;
704caf54c4fSMartin Matuska }
705caf54c4fSMartin Matuska
706caf54c4fSMartin Matuska if (v == 0)
707caf54c4fSMartin Matuska return (0);
708caf54c4fSMartin Matuska
709caf54c4fSMartin Matuska /* If it overflowed, fill field with max value. */
710caf54c4fSMartin Matuska while (len-- > 0)
711caf54c4fSMartin Matuska *p++ = '7';
712caf54c4fSMartin Matuska
713caf54c4fSMartin Matuska return (-1);
714caf54c4fSMartin Matuska }
715caf54c4fSMartin Matuska
716caf54c4fSMartin Matuska static int
7176c95142eSMartin Matuska archive_write_ustar_close(struct archive_write *a)
718caf54c4fSMartin Matuska {
7196c95142eSMartin Matuska return (__archive_write_nulls(a, 512*2));
720caf54c4fSMartin Matuska }
721caf54c4fSMartin Matuska
722caf54c4fSMartin Matuska static int
7236c95142eSMartin Matuska archive_write_ustar_free(struct archive_write *a)
724caf54c4fSMartin Matuska {
725caf54c4fSMartin Matuska struct ustar *ustar;
726caf54c4fSMartin Matuska
727caf54c4fSMartin Matuska ustar = (struct ustar *)a->format_data;
728caf54c4fSMartin Matuska free(ustar);
729caf54c4fSMartin Matuska a->format_data = NULL;
730caf54c4fSMartin Matuska return (ARCHIVE_OK);
731caf54c4fSMartin Matuska }
732caf54c4fSMartin Matuska
733caf54c4fSMartin Matuska static int
734caf54c4fSMartin Matuska archive_write_ustar_finish_entry(struct archive_write *a)
735caf54c4fSMartin Matuska {
736caf54c4fSMartin Matuska struct ustar *ustar;
737caf54c4fSMartin Matuska int ret;
738caf54c4fSMartin Matuska
739caf54c4fSMartin Matuska ustar = (struct ustar *)a->format_data;
7406c95142eSMartin Matuska ret = __archive_write_nulls(a,
741fd082e96SMartin Matuska (size_t)(ustar->entry_bytes_remaining + ustar->entry_padding));
742caf54c4fSMartin Matuska ustar->entry_bytes_remaining = ustar->entry_padding = 0;
743caf54c4fSMartin Matuska return (ret);
744caf54c4fSMartin Matuska }
745caf54c4fSMartin Matuska
746caf54c4fSMartin Matuska static ssize_t
747caf54c4fSMartin Matuska archive_write_ustar_data(struct archive_write *a, const void *buff, size_t s)
748caf54c4fSMartin Matuska {
749caf54c4fSMartin Matuska struct ustar *ustar;
750caf54c4fSMartin Matuska int ret;
751caf54c4fSMartin Matuska
752caf54c4fSMartin Matuska ustar = (struct ustar *)a->format_data;
753caf54c4fSMartin Matuska if (s > ustar->entry_bytes_remaining)
754fd082e96SMartin Matuska s = (size_t)ustar->entry_bytes_remaining;
7556c95142eSMartin Matuska ret = __archive_write_output(a, buff, s);
756caf54c4fSMartin Matuska ustar->entry_bytes_remaining -= s;
757caf54c4fSMartin Matuska if (ret != ARCHIVE_OK)
758caf54c4fSMartin Matuska return (ret);
759caf54c4fSMartin Matuska return (s);
760caf54c4fSMartin Matuska }
761