1 /*-
2 * Copyright (c) 2003-2007 Tim Kientzle
3 * Copyright (c) 2011-2012 Michihiro NAKAJIMA
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27 #include "archive_platform.h"
28
29 #ifdef HAVE_ERRNO_H
30 #include <errno.h>
31 #endif
32 #include <stdio.h>
33 #ifdef HAVE_STDLIB_H
34 #include <stdlib.h>
35 #endif
36 #ifdef HAVE_STRING_H
37 #include <string.h>
38 #endif
39
40 #include "archive.h"
41 #include "archive_entry.h"
42 #include "archive_entry_locale.h"
43 #include "archive_private.h"
44 #include "archive_write_private.h"
45 #include "archive_write_set_format_private.h"
46
47 struct ustar {
48 uint64_t entry_bytes_remaining;
49 uint64_t entry_padding;
50
51 struct archive_string_conv *opt_sconv;
52 struct archive_string_conv *sconv_default;
53 int init_default_conversion;
54 };
55
56 /*
57 * Define structure of POSIX 'ustar' tar header.
58 */
59 #define USTAR_name_offset 0
60 #define USTAR_name_size 100
61 #define USTAR_mode_offset 100
62 #define USTAR_mode_size 6
63 #define USTAR_mode_max_size 8
64 #define USTAR_uid_offset 108
65 #define USTAR_uid_size 6
66 #define USTAR_uid_max_size 8
67 #define USTAR_gid_offset 116
68 #define USTAR_gid_size 6
69 #define USTAR_gid_max_size 8
70 #define USTAR_size_offset 124
71 #define USTAR_size_size 11
72 #define USTAR_size_max_size 12
73 #define USTAR_mtime_offset 136
74 #define USTAR_mtime_size 11
75 #define USTAR_mtime_max_size 11
76 #define USTAR_checksum_offset 148
77 #define USTAR_checksum_size 8
78 #define USTAR_typeflag_offset 156
79 #define USTAR_typeflag_size 1
80 #define USTAR_linkname_offset 157
81 #define USTAR_linkname_size 100
82 #define USTAR_magic_offset 257
83 #define USTAR_magic_size 6
84 #define USTAR_version_offset 263
85 #define USTAR_version_size 2
86 #define USTAR_uname_offset 265
87 #define USTAR_uname_size 32
88 #define USTAR_gname_offset 297
89 #define USTAR_gname_size 32
90 #define USTAR_rdevmajor_offset 329
91 #define USTAR_rdevmajor_size 6
92 #define USTAR_rdevmajor_max_size 8
93 #define USTAR_rdevminor_offset 337
94 #define USTAR_rdevminor_size 6
95 #define USTAR_rdevminor_max_size 8
96 #define USTAR_prefix_offset 345
97 #define USTAR_prefix_size 155
98 #define USTAR_padding_offset 500
99 #define USTAR_padding_size 12
100
101 /*
102 * A filled-in copy of the header for initialization.
103 */
104 static const char template_header[] = {
105 /* name: 100 bytes */
106 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,
107 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,
108 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,
109 0,0,0,0,
110 /* Mode, space-null termination: 8 bytes */
111 '0','0','0','0','0','0', ' ','\0',
112 /* uid, space-null termination: 8 bytes */
113 '0','0','0','0','0','0', ' ','\0',
114 /* gid, space-null termination: 8 bytes */
115 '0','0','0','0','0','0', ' ','\0',
116 /* size, space termination: 12 bytes */
117 '0','0','0','0','0','0','0','0','0','0','0', ' ',
118 /* mtime, space termination: 12 bytes */
119 '0','0','0','0','0','0','0','0','0','0','0', ' ',
120 /* Initial checksum value: 8 spaces */
121 ' ',' ',' ',' ',' ',' ',' ',' ',
122 /* Typeflag: 1 byte */
123 '0', /* '0' = regular file */
124 /* Linkname: 100 bytes */
125 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,
126 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,
127 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,
128 0,0,0,0,
129 /* Magic: 6 bytes, Version: 2 bytes */
130 'u','s','t','a','r','\0', '0','0',
131 /* Uname: 32 bytes */
132 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,
133 /* Gname: 32 bytes */
134 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,
135 /* rdevmajor + space/null padding: 8 bytes */
136 '0','0','0','0','0','0', ' ','\0',
137 /* rdevminor + space/null padding: 8 bytes */
138 '0','0','0','0','0','0', ' ','\0',
139 /* Prefix: 155 bytes */
140 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,
141 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,
142 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,
143 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,
144 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,
145 /* Padding: 12 bytes */
146 0,0,0,0,0,0,0,0, 0,0,0,0
147 };
148
149 static ssize_t archive_write_ustar_data(struct archive_write *a, const void *buff,
150 size_t s);
151 static int archive_write_ustar_free(struct archive_write *);
152 static int archive_write_ustar_close(struct archive_write *);
153 static int archive_write_ustar_finish_entry(struct archive_write *);
154 static int archive_write_ustar_header(struct archive_write *,
155 struct archive_entry *entry);
156 static int archive_write_ustar_options(struct archive_write *,
157 const char *, const char *);
158 static int format_256(int64_t, char *, int);
159 static int format_number(int64_t, char *, int size, int max, int strict);
160 static int format_octal(int64_t, char *, int);
161
162 /*
163 * Set output format to 'ustar' format.
164 */
165 int
archive_write_set_format_ustar(struct archive * _a)166 archive_write_set_format_ustar(struct archive *_a)
167 {
168 struct archive_write *a = (struct archive_write *)_a;
169 struct ustar *ustar;
170
171 archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
172 ARCHIVE_STATE_NEW, "archive_write_set_format_ustar");
173
174 /* If someone else was already registered, unregister them. */
175 if (a->format_free != NULL)
176 (a->format_free)(a);
177
178 /* Basic internal sanity test. */
179 if (sizeof(template_header) != 512) {
180 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
181 "Internal: template_header wrong size: %zu should be 512",
182 sizeof(template_header));
183 return (ARCHIVE_FATAL);
184 }
185
186 ustar = calloc(1, sizeof(*ustar));
187 if (ustar == NULL) {
188 archive_set_error(&a->archive, ENOMEM,
189 "Can't allocate ustar data");
190 return (ARCHIVE_FATAL);
191 }
192 a->format_data = ustar;
193 a->format_name = "ustar";
194 a->format_options = archive_write_ustar_options;
195 a->format_write_header = archive_write_ustar_header;
196 a->format_write_data = archive_write_ustar_data;
197 a->format_close = archive_write_ustar_close;
198 a->format_free = archive_write_ustar_free;
199 a->format_finish_entry = archive_write_ustar_finish_entry;
200 a->archive.archive_format = ARCHIVE_FORMAT_TAR_USTAR;
201 a->archive.archive_format_name = "POSIX ustar";
202 return (ARCHIVE_OK);
203 }
204
205 static int
archive_write_ustar_options(struct archive_write * a,const char * key,const char * val)206 archive_write_ustar_options(struct archive_write *a, const char *key,
207 const char *val)
208 {
209 struct ustar *ustar = (struct ustar *)a->format_data;
210 int ret = ARCHIVE_FAILED;
211
212 if (strcmp(key, "hdrcharset") == 0) {
213 if (val == NULL || val[0] == 0)
214 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
215 "%s: hdrcharset option needs a character-set name",
216 a->format_name);
217 else {
218 ustar->opt_sconv = archive_string_conversion_to_charset(
219 &a->archive, val, 0);
220 if (ustar->opt_sconv != NULL)
221 ret = ARCHIVE_OK;
222 else
223 ret = ARCHIVE_FATAL;
224 }
225 return (ret);
226 }
227
228 /* Note: The "warn" return is just to inform the options
229 * supervisor that we didn't handle it. It will generate
230 * a suitable error if no one used this option. */
231 return (ARCHIVE_WARN);
232 }
233
234 static int
archive_write_ustar_header(struct archive_write * a,struct archive_entry * entry)235 archive_write_ustar_header(struct archive_write *a, struct archive_entry *entry)
236 {
237 char buff[512];
238 int ret, ret2;
239 struct ustar *ustar;
240 struct archive_entry *entry_main;
241 struct archive_string_conv *sconv;
242
243 ustar = (struct ustar *)a->format_data;
244
245 /* Setup default string conversion. */
246 if (ustar->opt_sconv == NULL) {
247 if (!ustar->init_default_conversion) {
248 ustar->sconv_default =
249 archive_string_default_conversion_for_write(&(a->archive));
250 ustar->init_default_conversion = 1;
251 }
252 sconv = ustar->sconv_default;
253 } else
254 sconv = ustar->opt_sconv;
255
256 /* Sanity check. */
257 #if defined(_WIN32) && !defined(__CYGWIN__)
258 if (archive_entry_pathname_w(entry) == NULL) {
259 #else
260 if (archive_entry_pathname(entry) == NULL) {
261 #endif
262 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
263 "Can't record entry in tar file without pathname");
264 return (ARCHIVE_FAILED);
265 }
266
267 /* Only regular files (not hardlinks) have data. */
268 if (archive_entry_hardlink(entry) != NULL ||
269 archive_entry_symlink(entry) != NULL ||
270 archive_entry_filetype(entry) != AE_IFREG)
271 archive_entry_set_size(entry, 0);
272
273 if (AE_IFDIR == archive_entry_filetype(entry)) {
274 const char *p;
275 size_t path_length;
276 /*
277 * Ensure a trailing '/'. Modify the entry so
278 * the client sees the change.
279 */
280 #if defined(_WIN32) && !defined(__CYGWIN__)
281 const wchar_t *wp;
282
283 wp = archive_entry_pathname_w(entry);
284 if (wp != NULL && wp[wcslen(wp) -1] != L'/') {
285 struct archive_wstring ws;
286
287 archive_string_init(&ws);
288 path_length = wcslen(wp);
289 if (archive_wstring_ensure(&ws,
290 path_length + 2) == NULL) {
291 archive_set_error(&a->archive, ENOMEM,
292 "Can't allocate ustar data");
293 archive_wstring_free(&ws);
294 return(ARCHIVE_FATAL);
295 }
296 /* Should we keep '\' ? */
297 if (wp[path_length -1] == L'\\')
298 path_length--;
299 archive_wstrncpy(&ws, wp, path_length);
300 archive_wstrappend_wchar(&ws, L'/');
301 archive_entry_copy_pathname_w(entry, ws.s);
302 archive_wstring_free(&ws);
303 p = NULL;
304 } else
305 #endif
306 p = archive_entry_pathname(entry);
307 /*
308 * On Windows, this is a backup operation just in
309 * case getting WCS failed. On POSIX, this is a
310 * normal operation.
311 */
312 if (p != NULL && p[0] != '\0' && p[strlen(p) - 1] != '/') {
313 struct archive_string as;
314
315 archive_string_init(&as);
316 path_length = strlen(p);
317 if (archive_string_ensure(&as,
318 path_length + 2) == NULL) {
319 archive_set_error(&a->archive, ENOMEM,
320 "Can't allocate ustar data");
321 archive_string_free(&as);
322 return(ARCHIVE_FATAL);
323 }
324 #if defined(_WIN32) && !defined(__CYGWIN__)
325 /* NOTE: This might break the pathname
326 * if the current code page is CP932 and
327 * the pathname includes a character '\'
328 * as a part of its multibyte pathname. */
329 if (p[strlen(p) -1] == '\\')
330 path_length--;
331 else
332 #endif
333 archive_strncpy(&as, p, path_length);
334 archive_strappend_char(&as, '/');
335 archive_entry_copy_pathname(entry, as.s);
336 archive_string_free(&as);
337 }
338 }
339
340 #if defined(_WIN32) && !defined(__CYGWIN__)
341 /* Make sure the path separators in pathname, hardlink and symlink
342 * are all slash '/', not the Windows path separator '\'. */
343 entry_main = __la_win_entry_in_posix_pathseparator(entry);
344 if (entry_main == NULL) {
345 archive_set_error(&a->archive, ENOMEM,
346 "Can't allocate ustar data");
347 return(ARCHIVE_FATAL);
348 }
349 if (entry != entry_main)
350 entry = entry_main;
351 else
352 entry_main = NULL;
353 #else
354 entry_main = NULL;
355 #endif
356 ret = __archive_write_format_header_ustar(a, buff, entry, -1, 1, sconv);
357 if (ret < ARCHIVE_WARN) {
358 archive_entry_free(entry_main);
359 return (ret);
360 }
361 ret2 = __archive_write_output(a, buff, 512);
362 if (ret2 < ARCHIVE_WARN) {
363 archive_entry_free(entry_main);
364 return (ret2);
365 }
366 if (ret2 < ret)
367 ret = ret2;
368
369 ustar->entry_bytes_remaining = archive_entry_size(entry);
370 ustar->entry_padding = 0x1ff & (-(int64_t)ustar->entry_bytes_remaining);
371 archive_entry_free(entry_main);
372 return (ret);
373 }
374
375 /*
376 * Format a basic 512-byte "ustar" header.
377 *
378 * Returns -1 if format failed (due to field overflow).
379 * Note that this always formats as much of the header as possible.
380 * If "strict" is set to zero, it will extend numeric fields as
381 * necessary (overwriting terminators or using base-256 extensions).
382 *
383 * This is exported so that other 'tar' formats can use it.
384 */
385 int
386 __archive_write_format_header_ustar(struct archive_write *a, char h[512],
387 struct archive_entry *entry, int tartype, int strict,
388 struct archive_string_conv *sconv)
389 {
390 unsigned int checksum;
391 int i, r, ret;
392 size_t copy_length;
393 const char *p, *pp;
394 int mytartype;
395
396 ret = 0;
397 mytartype = -1;
398 /*
399 * The "template header" already includes the "ustar"
400 * signature, various end-of-field markers and other required
401 * elements.
402 */
403 memcpy(h, &template_header, 512);
404
405 /*
406 * Because the block is already null-filled, and strings
407 * are allowed to exactly fill their destination (without null),
408 * I use memcpy(dest, src, strlen()) here a lot to copy strings.
409 */
410 r = archive_entry_pathname_l(entry, &pp, ©_length, sconv);
411 if (r != 0) {
412 if (errno == ENOMEM) {
413 archive_set_error(&a->archive, ENOMEM,
414 "Can't allocate memory for Pathname");
415 return (ARCHIVE_FATAL);
416 }
417 archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
418 "Can't translate pathname '%s' to %s",
419 pp, archive_string_conversion_charset_name(sconv));
420 ret = ARCHIVE_WARN;
421 }
422 if (copy_length <= USTAR_name_size)
423 memcpy(h + USTAR_name_offset, pp, copy_length);
424 else {
425 /* Store in two pieces, splitting at a '/'. */
426 p = strchr(pp + copy_length - USTAR_name_size - 1, '/');
427 /*
428 * Look for the next '/' if we chose the first character
429 * as the separator. (ustar format doesn't permit
430 * an empty prefix.)
431 */
432 if (p == pp)
433 p = strchr(p + 1, '/');
434 /* Fail if the name won't fit. */
435 if (!p) {
436 /* No separator. */
437 archive_set_error(&a->archive, ENAMETOOLONG,
438 "Pathname too long");
439 ret = ARCHIVE_FAILED;
440 } else if (p[1] == '\0') {
441 /*
442 * The only feasible separator is a final '/';
443 * this would result in a non-empty prefix and
444 * an empty name, which POSIX doesn't
445 * explicitly forbid, but it just feels wrong.
446 */
447 archive_set_error(&a->archive, ENAMETOOLONG,
448 "Pathname too long");
449 ret = ARCHIVE_FAILED;
450 } else if (p > pp + USTAR_prefix_size) {
451 /* Prefix is too long. */
452 archive_set_error(&a->archive, ENAMETOOLONG,
453 "Pathname too long");
454 ret = ARCHIVE_FAILED;
455 } else {
456 /* Copy prefix and remainder to appropriate places */
457 memcpy(h + USTAR_prefix_offset, pp, p - pp);
458 memcpy(h + USTAR_name_offset, p + 1,
459 pp + copy_length - p - 1);
460 }
461 }
462
463 r = archive_entry_hardlink_l(entry, &p, ©_length, sconv);
464 if (r != 0) {
465 if (errno == ENOMEM) {
466 archive_set_error(&a->archive, ENOMEM,
467 "Can't allocate memory for Linkname");
468 return (ARCHIVE_FATAL);
469 }
470 archive_set_error(&a->archive,
471 ARCHIVE_ERRNO_FILE_FORMAT,
472 "Can't translate linkname '%s' to %s",
473 p, archive_string_conversion_charset_name(sconv));
474 ret = ARCHIVE_WARN;
475 }
476 if (copy_length > 0)
477 mytartype = '1';
478 else {
479 r = archive_entry_symlink_l(entry, &p, ©_length, sconv);
480 if (r != 0) {
481 if (errno == ENOMEM) {
482 archive_set_error(&a->archive, ENOMEM,
483 "Can't allocate memory for Linkname");
484 return (ARCHIVE_FATAL);
485 }
486 archive_set_error(&a->archive,
487 ARCHIVE_ERRNO_FILE_FORMAT,
488 "Can't translate linkname '%s' to %s",
489 p, archive_string_conversion_charset_name(sconv));
490 ret = ARCHIVE_WARN;
491 }
492 }
493 if (copy_length > 0) {
494 if (copy_length > USTAR_linkname_size) {
495 archive_set_error(&a->archive, ENAMETOOLONG,
496 "Link contents too long");
497 ret = ARCHIVE_FAILED;
498 copy_length = USTAR_linkname_size;
499 }
500 memcpy(h + USTAR_linkname_offset, p, copy_length);
501 }
502
503 r = archive_entry_uname_l(entry, &p, ©_length, sconv);
504 if (r != 0) {
505 if (errno == ENOMEM) {
506 archive_set_error(&a->archive, ENOMEM,
507 "Can't allocate memory for Uname");
508 return (ARCHIVE_FATAL);
509 }
510 archive_set_error(&a->archive,
511 ARCHIVE_ERRNO_FILE_FORMAT,
512 "Can't translate uname '%s' to %s",
513 p, archive_string_conversion_charset_name(sconv));
514 ret = ARCHIVE_WARN;
515 }
516 if (copy_length > 0) {
517 if (copy_length > USTAR_uname_size) {
518 if (tartype != 'x') {
519 archive_set_error(&a->archive,
520 ARCHIVE_ERRNO_MISC, "Username too long");
521 ret = ARCHIVE_FAILED;
522 }
523 copy_length = USTAR_uname_size;
524 }
525 memcpy(h + USTAR_uname_offset, p, copy_length);
526 }
527
528 r = archive_entry_gname_l(entry, &p, ©_length, sconv);
529 if (r != 0) {
530 if (errno == ENOMEM) {
531 archive_set_error(&a->archive, ENOMEM,
532 "Can't allocate memory for Gname");
533 return (ARCHIVE_FATAL);
534 }
535 archive_set_error(&a->archive,
536 ARCHIVE_ERRNO_FILE_FORMAT,
537 "Can't translate gname '%s' to %s",
538 p, archive_string_conversion_charset_name(sconv));
539 ret = ARCHIVE_WARN;
540 }
541 if (copy_length > 0) {
542 if (strlen(p) > USTAR_gname_size) {
543 if (tartype != 'x') {
544 archive_set_error(&a->archive,
545 ARCHIVE_ERRNO_MISC, "Group name too long");
546 ret = ARCHIVE_FAILED;
547 }
548 copy_length = USTAR_gname_size;
549 }
550 memcpy(h + USTAR_gname_offset, p, copy_length);
551 }
552
553 if (format_number(archive_entry_mode(entry) & 07777,
554 h + USTAR_mode_offset, USTAR_mode_size, USTAR_mode_max_size, strict)) {
555 archive_set_error(&a->archive, ERANGE,
556 "Numeric mode too large");
557 ret = ARCHIVE_FAILED;
558 }
559
560 if (format_number(archive_entry_uid(entry),
561 h + USTAR_uid_offset, USTAR_uid_size, USTAR_uid_max_size, strict)) {
562 archive_set_error(&a->archive, ERANGE,
563 "Numeric user ID too large");
564 ret = ARCHIVE_FAILED;
565 }
566
567 if (format_number(archive_entry_gid(entry),
568 h + USTAR_gid_offset, USTAR_gid_size, USTAR_gid_max_size, strict)) {
569 archive_set_error(&a->archive, ERANGE,
570 "Numeric group ID too large");
571 ret = ARCHIVE_FAILED;
572 }
573
574 if (format_number(archive_entry_size(entry),
575 h + USTAR_size_offset, USTAR_size_size, USTAR_size_max_size, strict)) {
576 archive_set_error(&a->archive, ERANGE,
577 "File size out of range");
578 ret = ARCHIVE_FAILED;
579 }
580
581 if (format_number(archive_entry_mtime(entry),
582 h + USTAR_mtime_offset, USTAR_mtime_size, USTAR_mtime_max_size, strict)) {
583 archive_set_error(&a->archive, ERANGE,
584 "File modification time too large");
585 ret = ARCHIVE_FAILED;
586 }
587
588 if (archive_entry_filetype(entry) == AE_IFBLK
589 || archive_entry_filetype(entry) == AE_IFCHR) {
590 if (format_number(archive_entry_rdevmajor(entry),
591 h + USTAR_rdevmajor_offset, USTAR_rdevmajor_size,
592 USTAR_rdevmajor_max_size, strict)) {
593 archive_set_error(&a->archive, ERANGE,
594 "Major device number too large");
595 ret = ARCHIVE_FAILED;
596 }
597
598 if (format_number(archive_entry_rdevminor(entry),
599 h + USTAR_rdevminor_offset, USTAR_rdevminor_size,
600 USTAR_rdevminor_max_size, strict)) {
601 archive_set_error(&a->archive, ERANGE,
602 "Minor device number too large");
603 ret = ARCHIVE_FAILED;
604 }
605 }
606
607 if (tartype >= 0) {
608 h[USTAR_typeflag_offset] = tartype;
609 } else if (mytartype >= 0) {
610 h[USTAR_typeflag_offset] = mytartype;
611 } else {
612 switch (archive_entry_filetype(entry)) {
613 case AE_IFREG: h[USTAR_typeflag_offset] = '0' ; break;
614 case AE_IFLNK: h[USTAR_typeflag_offset] = '2' ; break;
615 case AE_IFCHR: h[USTAR_typeflag_offset] = '3' ; break;
616 case AE_IFBLK: h[USTAR_typeflag_offset] = '4' ; break;
617 case AE_IFDIR: h[USTAR_typeflag_offset] = '5' ; break;
618 case AE_IFIFO: h[USTAR_typeflag_offset] = '6' ; break;
619 default: /* AE_IFSOCK and unknown */
620 __archive_write_entry_filetype_unsupported(
621 &a->archive, entry, "ustar");
622 ret = ARCHIVE_FAILED;
623 }
624 }
625
626 checksum = 0;
627 for (i = 0; i < 512; i++)
628 checksum += 255 & (unsigned int)h[i];
629 h[USTAR_checksum_offset + 6] = '\0'; /* Can't be pre-set in the template. */
630 /* h[USTAR_checksum_offset + 7] = ' '; */ /* This is pre-set in the template. */
631 format_octal(checksum, h + USTAR_checksum_offset, 6);
632 return (ret);
633 }
634
635 /*
636 * Format a number into a field, with some intelligence.
637 */
638 static int
639 format_number(int64_t v, char *p, int s, int maxsize, int strict)
640 {
641 int64_t limit;
642
643 limit = ((int64_t)1 << (s*3));
644
645 /* "Strict" only permits octal values with proper termination. */
646 if (strict)
647 return (format_octal(v, p, s));
648
649 /*
650 * In non-strict mode, we allow the number to overwrite one or
651 * more bytes of the field termination. Even old tar
652 * implementations should be able to handle this with no
653 * problem.
654 */
655 if (v >= 0) {
656 while (s <= maxsize) {
657 if (v < limit)
658 return (format_octal(v, p, s));
659 s++;
660 limit <<= 3;
661 }
662 }
663
664 /* Base-256 can handle any number, positive or negative. */
665 return (format_256(v, p, maxsize));
666 }
667
668 /*
669 * Format a number into the specified field using base-256.
670 */
671 static int
672 format_256(int64_t v, char *p, int s)
673 {
674 p += s;
675 while (s-- > 0) {
676 *--p = (char)(v & 0xff);
677 v >>= 8;
678 }
679 *p |= 0x80; /* Set the base-256 marker bit. */
680 return (0);
681 }
682
683 /*
684 * Format a number into the specified field.
685 */
686 static int
687 format_octal(int64_t v, char *p, int s)
688 {
689 int len;
690
691 len = s;
692
693 /* Octal values can't be negative, so use 0. */
694 if (v < 0) {
695 while (len-- > 0)
696 *p++ = '0';
697 return (-1);
698 }
699
700 p += s; /* Start at the end and work backwards. */
701 while (s-- > 0) {
702 *--p = (char)('0' + (v & 7));
703 v >>= 3;
704 }
705
706 if (v == 0)
707 return (0);
708
709 /* If it overflowed, fill field with max value. */
710 while (len-- > 0)
711 *p++ = '7';
712
713 return (-1);
714 }
715
716 static int
717 archive_write_ustar_close(struct archive_write *a)
718 {
719 return (__archive_write_nulls(a, 512*2));
720 }
721
722 static int
723 archive_write_ustar_free(struct archive_write *a)
724 {
725 struct ustar *ustar;
726
727 ustar = (struct ustar *)a->format_data;
728 free(ustar);
729 a->format_data = NULL;
730 return (ARCHIVE_OK);
731 }
732
733 static int
734 archive_write_ustar_finish_entry(struct archive_write *a)
735 {
736 struct ustar *ustar;
737 int ret;
738
739 ustar = (struct ustar *)a->format_data;
740 ret = __archive_write_nulls(a,
741 (size_t)(ustar->entry_bytes_remaining + ustar->entry_padding));
742 ustar->entry_bytes_remaining = ustar->entry_padding = 0;
743 return (ret);
744 }
745
746 static ssize_t
747 archive_write_ustar_data(struct archive_write *a, const void *buff, size_t s)
748 {
749 struct ustar *ustar;
750 int ret;
751
752 ustar = (struct ustar *)a->format_data;
753 if (s > ustar->entry_bytes_remaining)
754 s = (size_t)ustar->entry_bytes_remaining;
755 ret = __archive_write_output(a, buff, s);
756 ustar->entry_bytes_remaining -= s;
757 if (ret != ARCHIVE_OK)
758 return (ret);
759 return (s);
760 }
761