1228753Smm/*- 2228753Smm * Copyright (c) 2003-2007 Tim Kientzle 3232153Smm * Copyright (c) 2011-2012 Michihiro NAKAJIMA 4228753Smm * All rights reserved. 5228753Smm * 6228753Smm * Redistribution and use in source and binary forms, with or without 7228753Smm * modification, are permitted provided that the following conditions 8228753Smm * are met: 9228753Smm * 1. Redistributions of source code must retain the above copyright 10228753Smm * notice, this list of conditions and the following disclaimer. 11228753Smm * 2. Redistributions in binary form must reproduce the above copyright 12228753Smm * notice, this list of conditions and the following disclaimer in the 13228753Smm * documentation and/or other materials provided with the distribution. 14228753Smm * 15228753Smm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 16228753Smm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17228753Smm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18228753Smm * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 19228753Smm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20228753Smm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21228753Smm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22228753Smm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23228753Smm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24228753Smm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25228753Smm */ 26228753Smm 27228753Smm#include "archive_platform.h" 28228763Smm__FBSDID("$FreeBSD: stable/10/contrib/libarchive/libarchive/archive_write_set_format_ustar.c 358090 2020-02-19 01:51:44Z mm $"); 29228753Smm 30228753Smm 31228753Smm#ifdef HAVE_ERRNO_H 32228753Smm#include <errno.h> 33228753Smm#endif 34228753Smm#include <stdio.h> 35228753Smm#ifdef HAVE_STDLIB_H 36228753Smm#include <stdlib.h> 37228753Smm#endif 38228753Smm#ifdef HAVE_STRING_H 39228753Smm#include <string.h> 40228753Smm#endif 41228753Smm 42228753Smm#include "archive.h" 43228753Smm#include "archive_entry.h" 44232153Smm#include "archive_entry_locale.h" 45228753Smm#include "archive_private.h" 46228753Smm#include "archive_write_private.h" 47358090Smm#include "archive_write_set_format_private.h" 48228753Smm 49228753Smmstruct ustar { 50228753Smm uint64_t entry_bytes_remaining; 51228753Smm uint64_t entry_padding; 52232153Smm 53232153Smm struct archive_string_conv *opt_sconv; 54232153Smm struct archive_string_conv *sconv_default; 55232153Smm int init_default_conversion; 56228753Smm}; 57228753Smm 58228753Smm/* 59228753Smm * Define structure of POSIX 'ustar' tar header. 60228753Smm */ 61228753Smm#define USTAR_name_offset 0 62228753Smm#define USTAR_name_size 100 63228753Smm#define USTAR_mode_offset 100 64228753Smm#define USTAR_mode_size 6 65228753Smm#define USTAR_mode_max_size 8 66228753Smm#define USTAR_uid_offset 108 67228753Smm#define USTAR_uid_size 6 68228753Smm#define USTAR_uid_max_size 8 69228753Smm#define USTAR_gid_offset 116 70228753Smm#define USTAR_gid_size 6 71228753Smm#define USTAR_gid_max_size 8 72228753Smm#define USTAR_size_offset 124 73228753Smm#define USTAR_size_size 11 74228753Smm#define USTAR_size_max_size 12 75228753Smm#define USTAR_mtime_offset 136 76228753Smm#define USTAR_mtime_size 11 77228753Smm#define USTAR_mtime_max_size 11 78228753Smm#define USTAR_checksum_offset 148 79228753Smm#define USTAR_checksum_size 8 80228753Smm#define USTAR_typeflag_offset 156 81228753Smm#define USTAR_typeflag_size 1 82228753Smm#define USTAR_linkname_offset 157 83228753Smm#define USTAR_linkname_size 100 84228753Smm#define USTAR_magic_offset 257 85228753Smm#define USTAR_magic_size 6 86228753Smm#define USTAR_version_offset 263 87228753Smm#define USTAR_version_size 2 88228753Smm#define USTAR_uname_offset 265 89228753Smm#define USTAR_uname_size 32 90228753Smm#define USTAR_gname_offset 297 91228753Smm#define USTAR_gname_size 32 92228753Smm#define USTAR_rdevmajor_offset 329 93228753Smm#define USTAR_rdevmajor_size 6 94228753Smm#define USTAR_rdevmajor_max_size 8 95228753Smm#define USTAR_rdevminor_offset 337 96228753Smm#define USTAR_rdevminor_size 6 97228753Smm#define USTAR_rdevminor_max_size 8 98228753Smm#define USTAR_prefix_offset 345 99228753Smm#define USTAR_prefix_size 155 100228753Smm#define USTAR_padding_offset 500 101228753Smm#define USTAR_padding_size 12 102228753Smm 103228753Smm/* 104228753Smm * A filled-in copy of the header for initialization. 105228753Smm */ 106228753Smmstatic const char template_header[] = { 107228753Smm /* name: 100 bytes */ 108228753Smm 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 109228753Smm 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 110228753Smm 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 111228753Smm 0,0,0,0, 112228753Smm /* Mode, space-null termination: 8 bytes */ 113228753Smm '0','0','0','0','0','0', ' ','\0', 114228753Smm /* uid, space-null termination: 8 bytes */ 115228753Smm '0','0','0','0','0','0', ' ','\0', 116228753Smm /* gid, space-null termination: 8 bytes */ 117228753Smm '0','0','0','0','0','0', ' ','\0', 118311042Smm /* size, space termination: 12 bytes */ 119228753Smm '0','0','0','0','0','0','0','0','0','0','0', ' ', 120311042Smm /* mtime, space termination: 12 bytes */ 121228753Smm '0','0','0','0','0','0','0','0','0','0','0', ' ', 122228753Smm /* Initial checksum value: 8 spaces */ 123228753Smm ' ',' ',' ',' ',' ',' ',' ',' ', 124228753Smm /* Typeflag: 1 byte */ 125228753Smm '0', /* '0' = regular file */ 126228753Smm /* Linkname: 100 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 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 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 0,0,0,0, 131228753Smm /* Magic: 6 bytes, Version: 2 bytes */ 132228753Smm 'u','s','t','a','r','\0', '0','0', 133228753Smm /* Uname: 32 bytes */ 134228753Smm 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 135228753Smm /* Gname: 32 bytes */ 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 /* rdevmajor + space/null padding: 8 bytes */ 138228753Smm '0','0','0','0','0','0', ' ','\0', 139228753Smm /* rdevminor + space/null padding: 8 bytes */ 140228753Smm '0','0','0','0','0','0', ' ','\0', 141228753Smm /* Prefix: 155 bytes */ 142228753Smm 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 143228753Smm 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 144228753Smm 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 145228753Smm 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 146228753Smm 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0, 147228753Smm /* Padding: 12 bytes */ 148228753Smm 0,0,0,0,0,0,0,0, 0,0,0,0 149228753Smm}; 150228753Smm 151228753Smmstatic ssize_t archive_write_ustar_data(struct archive_write *a, const void *buff, 152228753Smm size_t s); 153232153Smmstatic int archive_write_ustar_free(struct archive_write *); 154232153Smmstatic int archive_write_ustar_close(struct archive_write *); 155228753Smmstatic int archive_write_ustar_finish_entry(struct archive_write *); 156228753Smmstatic int archive_write_ustar_header(struct archive_write *, 157228753Smm struct archive_entry *entry); 158232153Smmstatic int archive_write_ustar_options(struct archive_write *, 159232153Smm const char *, const char *); 160228753Smmstatic int format_256(int64_t, char *, int); 161228753Smmstatic int format_number(int64_t, char *, int size, int max, int strict); 162228753Smmstatic int format_octal(int64_t, char *, int); 163228753Smm 164228753Smm/* 165228753Smm * Set output format to 'ustar' format. 166228753Smm */ 167228753Smmint 168228753Smmarchive_write_set_format_ustar(struct archive *_a) 169228753Smm{ 170228753Smm struct archive_write *a = (struct archive_write *)_a; 171228753Smm struct ustar *ustar; 172228753Smm 173232153Smm archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, 174232153Smm ARCHIVE_STATE_NEW, "archive_write_set_format_ustar"); 175232153Smm 176228753Smm /* If someone else was already registered, unregister them. */ 177232153Smm if (a->format_free != NULL) 178232153Smm (a->format_free)(a); 179228753Smm 180228753Smm /* Basic internal sanity test. */ 181228753Smm if (sizeof(template_header) != 512) { 182232153Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 183232153Smm "Internal: template_header wrong size: %zu should be 512", 184232153Smm sizeof(template_header)); 185228753Smm return (ARCHIVE_FATAL); 186228753Smm } 187228753Smm 188311042Smm ustar = (struct ustar *)calloc(1, sizeof(*ustar)); 189228753Smm if (ustar == NULL) { 190232153Smm archive_set_error(&a->archive, ENOMEM, 191232153Smm "Can't allocate ustar data"); 192228753Smm return (ARCHIVE_FATAL); 193228753Smm } 194228753Smm a->format_data = ustar; 195228753Smm a->format_name = "ustar"; 196232153Smm a->format_options = archive_write_ustar_options; 197228753Smm a->format_write_header = archive_write_ustar_header; 198228753Smm a->format_write_data = archive_write_ustar_data; 199232153Smm a->format_close = archive_write_ustar_close; 200232153Smm a->format_free = archive_write_ustar_free; 201228753Smm a->format_finish_entry = archive_write_ustar_finish_entry; 202228753Smm a->archive.archive_format = ARCHIVE_FORMAT_TAR_USTAR; 203228753Smm a->archive.archive_format_name = "POSIX ustar"; 204228753Smm return (ARCHIVE_OK); 205228753Smm} 206228753Smm 207228753Smmstatic int 208232153Smmarchive_write_ustar_options(struct archive_write *a, const char *key, 209232153Smm const char *val) 210232153Smm{ 211232153Smm struct ustar *ustar = (struct ustar *)a->format_data; 212232153Smm int ret = ARCHIVE_FAILED; 213232153Smm 214232153Smm if (strcmp(key, "hdrcharset") == 0) { 215232153Smm if (val == NULL || val[0] == 0) 216232153Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 217232153Smm "%s: hdrcharset option needs a character-set name", 218232153Smm a->format_name); 219232153Smm else { 220232153Smm ustar->opt_sconv = archive_string_conversion_to_charset( 221232153Smm &a->archive, val, 0); 222232153Smm if (ustar->opt_sconv != NULL) 223232153Smm ret = ARCHIVE_OK; 224232153Smm else 225232153Smm ret = ARCHIVE_FATAL; 226232153Smm } 227232153Smm return (ret); 228232153Smm } 229232153Smm 230232153Smm /* Note: The "warn" return is just to inform the options 231232153Smm * supervisor that we didn't handle it. It will generate 232232153Smm * a suitable error if no one used this option. */ 233232153Smm return (ARCHIVE_WARN); 234232153Smm} 235232153Smm 236232153Smmstatic int 237228753Smmarchive_write_ustar_header(struct archive_write *a, struct archive_entry *entry) 238228753Smm{ 239228753Smm char buff[512]; 240228753Smm int ret, ret2; 241228753Smm struct ustar *ustar; 242232153Smm struct archive_entry *entry_main; 243232153Smm struct archive_string_conv *sconv; 244228753Smm 245228753Smm ustar = (struct ustar *)a->format_data; 246228753Smm 247232153Smm /* Setup default string conversion. */ 248232153Smm if (ustar->opt_sconv == NULL) { 249232153Smm if (!ustar->init_default_conversion) { 250232153Smm ustar->sconv_default = 251232153Smm archive_string_default_conversion_for_write(&(a->archive)); 252232153Smm ustar->init_default_conversion = 1; 253232153Smm } 254232153Smm sconv = ustar->sconv_default; 255232153Smm } else 256232153Smm sconv = ustar->opt_sconv; 257232153Smm 258232153Smm /* Sanity check. */ 259232153Smm if (archive_entry_pathname(entry) == NULL) { 260232153Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 261232153Smm "Can't record entry in tar file without pathname"); 262232153Smm return (ARCHIVE_FAILED); 263232153Smm } 264232153Smm 265228753Smm /* Only regular files (not hardlinks) have data. */ 266228753Smm if (archive_entry_hardlink(entry) != NULL || 267228753Smm archive_entry_symlink(entry) != NULL || 268228753Smm !(archive_entry_filetype(entry) == AE_IFREG)) 269228753Smm archive_entry_set_size(entry, 0); 270228753Smm 271228753Smm if (AE_IFDIR == archive_entry_filetype(entry)) { 272228753Smm const char *p; 273232153Smm size_t path_length; 274228753Smm /* 275228753Smm * Ensure a trailing '/'. Modify the entry so 276228753Smm * the client sees the change. 277228753Smm */ 278232153Smm#if defined(_WIN32) && !defined(__CYGWIN__) 279232153Smm const wchar_t *wp; 280232153Smm 281232153Smm wp = archive_entry_pathname_w(entry); 282232153Smm if (wp != NULL && wp[wcslen(wp) -1] != L'/') { 283232153Smm struct archive_wstring ws; 284232153Smm 285232153Smm archive_string_init(&ws); 286232153Smm path_length = wcslen(wp); 287232153Smm if (archive_wstring_ensure(&ws, 288232153Smm path_length + 2) == NULL) { 289228753Smm archive_set_error(&a->archive, ENOMEM, 290232153Smm "Can't allocate ustar data"); 291232153Smm archive_wstring_free(&ws); 292228753Smm return(ARCHIVE_FATAL); 293228753Smm } 294232153Smm /* Should we keep '\' ? */ 295232153Smm if (wp[path_length -1] == L'\\') 296232153Smm path_length--; 297232153Smm archive_wstrncpy(&ws, wp, path_length); 298232153Smm archive_wstrappend_wchar(&ws, L'/'); 299232153Smm archive_entry_copy_pathname_w(entry, ws.s); 300232153Smm archive_wstring_free(&ws); 301232153Smm p = NULL; 302232153Smm } else 303232153Smm#endif 304232153Smm p = archive_entry_pathname(entry); 305232153Smm /* 306232153Smm * On Windows, this is a backup operation just in 307232153Smm * case getting WCS failed. On POSIX, this is a 308232153Smm * normal operation. 309232153Smm */ 310305192Smm if (p != NULL && p[0] != '\0' && p[strlen(p) - 1] != '/') { 311232153Smm struct archive_string as; 312232153Smm 313232153Smm archive_string_init(&as); 314232153Smm path_length = strlen(p); 315232153Smm if (archive_string_ensure(&as, 316232153Smm path_length + 2) == NULL) { 317232153Smm archive_set_error(&a->archive, ENOMEM, 318232153Smm "Can't allocate ustar data"); 319232153Smm archive_string_free(&as); 320232153Smm return(ARCHIVE_FATAL); 321232153Smm } 322232153Smm#if defined(_WIN32) && !defined(__CYGWIN__) 323232153Smm /* NOTE: This might break the pathname 324232153Smm * if the current code page is CP932 and 325232153Smm * the pathname includes a character '\' 326232153Smm * as a part of its multibyte pathname. */ 327232153Smm if (p[strlen(p) -1] == '\\') 328232153Smm path_length--; 329232153Smm else 330232153Smm#endif 331232153Smm archive_strncpy(&as, p, path_length); 332232153Smm archive_strappend_char(&as, '/'); 333232153Smm archive_entry_copy_pathname(entry, as.s); 334232153Smm archive_string_free(&as); 335228753Smm } 336228753Smm } 337228753Smm 338232153Smm#if defined(_WIN32) && !defined(__CYGWIN__) 339311042Smm /* Make sure the path separators in pathname, hardlink and symlink 340232153Smm * are all slash '/', not the Windows path separator '\'. */ 341232153Smm entry_main = __la_win_entry_in_posix_pathseparator(entry); 342232153Smm if (entry_main == NULL) { 343232153Smm archive_set_error(&a->archive, ENOMEM, 344232153Smm "Can't allocate ustar data"); 345232153Smm return(ARCHIVE_FATAL); 346232153Smm } 347232153Smm if (entry != entry_main) 348232153Smm entry = entry_main; 349232153Smm else 350232153Smm entry_main = NULL; 351232153Smm#else 352232153Smm entry_main = NULL; 353232153Smm#endif 354232153Smm ret = __archive_write_format_header_ustar(a, buff, entry, -1, 1, sconv); 355232153Smm if (ret < ARCHIVE_WARN) { 356344674Smm archive_entry_free(entry_main); 357228753Smm return (ret); 358232153Smm } 359232153Smm ret2 = __archive_write_output(a, buff, 512); 360232153Smm if (ret2 < ARCHIVE_WARN) { 361344674Smm archive_entry_free(entry_main); 362228753Smm return (ret2); 363232153Smm } 364228753Smm if (ret2 < ret) 365228753Smm ret = ret2; 366228753Smm 367228753Smm ustar->entry_bytes_remaining = archive_entry_size(entry); 368228753Smm ustar->entry_padding = 0x1ff & (-(int64_t)ustar->entry_bytes_remaining); 369344674Smm archive_entry_free(entry_main); 370228753Smm return (ret); 371228753Smm} 372228753Smm 373228753Smm/* 374228753Smm * Format a basic 512-byte "ustar" header. 375228753Smm * 376228753Smm * Returns -1 if format failed (due to field overflow). 377228753Smm * Note that this always formats as much of the header as possible. 378228753Smm * If "strict" is set to zero, it will extend numeric fields as 379228753Smm * necessary (overwriting terminators or using base-256 extensions). 380228753Smm * 381228753Smm * This is exported so that other 'tar' formats can use it. 382228753Smm */ 383228753Smmint 384228753Smm__archive_write_format_header_ustar(struct archive_write *a, char h[512], 385232153Smm struct archive_entry *entry, int tartype, int strict, 386232153Smm struct archive_string_conv *sconv) 387228753Smm{ 388228753Smm unsigned int checksum; 389232153Smm int i, r, ret; 390228753Smm size_t copy_length; 391228753Smm const char *p, *pp; 392228753Smm int mytartype; 393228753Smm 394228753Smm ret = 0; 395228753Smm mytartype = -1; 396228753Smm /* 397228753Smm * The "template header" already includes the "ustar" 398228753Smm * signature, various end-of-field markers and other required 399228753Smm * elements. 400228753Smm */ 401228753Smm memcpy(h, &template_header, 512); 402228753Smm 403228753Smm /* 404228753Smm * Because the block is already null-filled, and strings 405228753Smm * are allowed to exactly fill their destination (without null), 406228753Smm * I use memcpy(dest, src, strlen()) here a lot to copy strings. 407228753Smm */ 408232153Smm r = archive_entry_pathname_l(entry, &pp, ©_length, sconv); 409232153Smm if (r != 0) { 410232153Smm if (errno == ENOMEM) { 411232153Smm archive_set_error(&a->archive, ENOMEM, 412232153Smm "Can't allocate memory for Pathname"); 413232153Smm return (ARCHIVE_FATAL); 414232153Smm } 415232153Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 416232153Smm "Can't translate pathname '%s' to %s", 417232153Smm pp, archive_string_conversion_charset_name(sconv)); 418232153Smm ret = ARCHIVE_WARN; 419232153Smm } 420232153Smm if (copy_length <= USTAR_name_size) 421232153Smm memcpy(h + USTAR_name_offset, pp, copy_length); 422228753Smm else { 423228753Smm /* Store in two pieces, splitting at a '/'. */ 424232153Smm p = strchr(pp + copy_length - USTAR_name_size - 1, '/'); 425228753Smm /* 426228753Smm * Look for the next '/' if we chose the first character 427228753Smm * as the separator. (ustar format doesn't permit 428228753Smm * an empty prefix.) 429228753Smm */ 430228753Smm if (p == pp) 431228753Smm p = strchr(p + 1, '/'); 432228753Smm /* Fail if the name won't fit. */ 433228753Smm if (!p) { 434228753Smm /* No separator. */ 435228753Smm archive_set_error(&a->archive, ENAMETOOLONG, 436228753Smm "Pathname too long"); 437228753Smm ret = ARCHIVE_FAILED; 438228753Smm } else if (p[1] == '\0') { 439228753Smm /* 440228753Smm * The only feasible separator is a final '/'; 441228753Smm * this would result in a non-empty prefix and 442228753Smm * an empty name, which POSIX doesn't 443232153Smm * explicitly forbid, but it just feels wrong. 444228753Smm */ 445228753Smm archive_set_error(&a->archive, ENAMETOOLONG, 446228753Smm "Pathname too long"); 447228753Smm ret = ARCHIVE_FAILED; 448228753Smm } else if (p > pp + USTAR_prefix_size) { 449228753Smm /* Prefix is too long. */ 450228753Smm archive_set_error(&a->archive, ENAMETOOLONG, 451228753Smm "Pathname too long"); 452228753Smm ret = ARCHIVE_FAILED; 453228753Smm } else { 454228753Smm /* Copy prefix and remainder to appropriate places */ 455228753Smm memcpy(h + USTAR_prefix_offset, pp, p - pp); 456232153Smm memcpy(h + USTAR_name_offset, p + 1, 457232153Smm pp + copy_length - p - 1); 458228753Smm } 459228753Smm } 460228753Smm 461232153Smm r = archive_entry_hardlink_l(entry, &p, ©_length, sconv); 462232153Smm if (r != 0) { 463232153Smm if (errno == ENOMEM) { 464232153Smm archive_set_error(&a->archive, ENOMEM, 465232153Smm "Can't allocate memory for Linkname"); 466232153Smm return (ARCHIVE_FATAL); 467232153Smm } 468232153Smm archive_set_error(&a->archive, 469232153Smm ARCHIVE_ERRNO_FILE_FORMAT, 470232153Smm "Can't translate linkname '%s' to %s", 471232153Smm p, archive_string_conversion_charset_name(sconv)); 472232153Smm ret = ARCHIVE_WARN; 473232153Smm } 474232153Smm if (copy_length > 0) 475228753Smm mytartype = '1'; 476232153Smm else { 477232153Smm r = archive_entry_symlink_l(entry, &p, ©_length, sconv); 478232153Smm if (r != 0) { 479232153Smm if (errno == ENOMEM) { 480232153Smm archive_set_error(&a->archive, ENOMEM, 481232153Smm "Can't allocate memory for Linkname"); 482232153Smm return (ARCHIVE_FATAL); 483232153Smm } 484232153Smm archive_set_error(&a->archive, 485232153Smm ARCHIVE_ERRNO_FILE_FORMAT, 486232153Smm "Can't translate linkname '%s' to %s", 487232153Smm p, archive_string_conversion_charset_name(sconv)); 488232153Smm ret = ARCHIVE_WARN; 489232153Smm } 490232153Smm } 491232153Smm if (copy_length > 0) { 492228753Smm if (copy_length > USTAR_linkname_size) { 493228753Smm archive_set_error(&a->archive, ENAMETOOLONG, 494228753Smm "Link contents too long"); 495228753Smm ret = ARCHIVE_FAILED; 496228753Smm copy_length = USTAR_linkname_size; 497228753Smm } 498228753Smm memcpy(h + USTAR_linkname_offset, p, copy_length); 499228753Smm } 500228753Smm 501232153Smm r = archive_entry_uname_l(entry, &p, ©_length, sconv); 502232153Smm if (r != 0) { 503232153Smm if (errno == ENOMEM) { 504232153Smm archive_set_error(&a->archive, ENOMEM, 505232153Smm "Can't allocate memory for Uname"); 506232153Smm return (ARCHIVE_FATAL); 507232153Smm } 508232153Smm archive_set_error(&a->archive, 509232153Smm ARCHIVE_ERRNO_FILE_FORMAT, 510232153Smm "Can't translate uname '%s' to %s", 511232153Smm p, archive_string_conversion_charset_name(sconv)); 512232153Smm ret = ARCHIVE_WARN; 513232153Smm } 514232153Smm if (copy_length > 0) { 515228753Smm if (copy_length > USTAR_uname_size) { 516358090Smm if (tartype != 'x') { 517358090Smm archive_set_error(&a->archive, 518358090Smm ARCHIVE_ERRNO_MISC, "Username too long"); 519358090Smm ret = ARCHIVE_FAILED; 520358090Smm } 521228753Smm copy_length = USTAR_uname_size; 522228753Smm } 523228753Smm memcpy(h + USTAR_uname_offset, p, copy_length); 524228753Smm } 525228753Smm 526232153Smm r = archive_entry_gname_l(entry, &p, ©_length, sconv); 527232153Smm if (r != 0) { 528232153Smm if (errno == ENOMEM) { 529232153Smm archive_set_error(&a->archive, ENOMEM, 530232153Smm "Can't allocate memory for Gname"); 531232153Smm return (ARCHIVE_FATAL); 532232153Smm } 533232153Smm archive_set_error(&a->archive, 534232153Smm ARCHIVE_ERRNO_FILE_FORMAT, 535232153Smm "Can't translate gname '%s' to %s", 536232153Smm p, archive_string_conversion_charset_name(sconv)); 537232153Smm ret = ARCHIVE_WARN; 538232153Smm } 539232153Smm if (copy_length > 0) { 540228753Smm if (strlen(p) > USTAR_gname_size) { 541358090Smm if (tartype != 'x') { 542358090Smm archive_set_error(&a->archive, 543358090Smm ARCHIVE_ERRNO_MISC, "Group name too long"); 544358090Smm ret = ARCHIVE_FAILED; 545358090Smm } 546228753Smm copy_length = USTAR_gname_size; 547228753Smm } 548228753Smm memcpy(h + USTAR_gname_offset, p, copy_length); 549228753Smm } 550228753Smm 551232153Smm if (format_number(archive_entry_mode(entry) & 07777, 552232153Smm h + USTAR_mode_offset, USTAR_mode_size, USTAR_mode_max_size, strict)) { 553232153Smm archive_set_error(&a->archive, ERANGE, 554232153Smm "Numeric mode too large"); 555228753Smm ret = ARCHIVE_FAILED; 556228753Smm } 557228753Smm 558232153Smm if (format_number(archive_entry_uid(entry), 559232153Smm h + USTAR_uid_offset, USTAR_uid_size, USTAR_uid_max_size, strict)) { 560232153Smm archive_set_error(&a->archive, ERANGE, 561232153Smm "Numeric user ID too large"); 562228753Smm ret = ARCHIVE_FAILED; 563228753Smm } 564228753Smm 565232153Smm if (format_number(archive_entry_gid(entry), 566232153Smm h + USTAR_gid_offset, USTAR_gid_size, USTAR_gid_max_size, strict)) { 567232153Smm archive_set_error(&a->archive, ERANGE, 568232153Smm "Numeric group ID too large"); 569228753Smm ret = ARCHIVE_FAILED; 570228753Smm } 571228753Smm 572232153Smm if (format_number(archive_entry_size(entry), 573232153Smm h + USTAR_size_offset, USTAR_size_size, USTAR_size_max_size, strict)) { 574232153Smm archive_set_error(&a->archive, ERANGE, 575232153Smm "File size out of range"); 576228753Smm ret = ARCHIVE_FAILED; 577228753Smm } 578228753Smm 579232153Smm if (format_number(archive_entry_mtime(entry), 580232153Smm h + USTAR_mtime_offset, USTAR_mtime_size, USTAR_mtime_max_size, strict)) { 581228753Smm archive_set_error(&a->archive, ERANGE, 582228753Smm "File modification time too large"); 583228753Smm ret = ARCHIVE_FAILED; 584228753Smm } 585228753Smm 586228753Smm if (archive_entry_filetype(entry) == AE_IFBLK 587228753Smm || archive_entry_filetype(entry) == AE_IFCHR) { 588232153Smm if (format_number(archive_entry_rdevmajor(entry), 589232153Smm h + USTAR_rdevmajor_offset, USTAR_rdevmajor_size, 590232153Smm USTAR_rdevmajor_max_size, strict)) { 591228753Smm archive_set_error(&a->archive, ERANGE, 592228753Smm "Major device number too large"); 593228753Smm ret = ARCHIVE_FAILED; 594228753Smm } 595228753Smm 596232153Smm if (format_number(archive_entry_rdevminor(entry), 597232153Smm h + USTAR_rdevminor_offset, USTAR_rdevminor_size, 598232153Smm USTAR_rdevminor_max_size, strict)) { 599228753Smm archive_set_error(&a->archive, ERANGE, 600228753Smm "Minor device number too large"); 601228753Smm ret = ARCHIVE_FAILED; 602228753Smm } 603228753Smm } 604228753Smm 605228753Smm if (tartype >= 0) { 606228753Smm h[USTAR_typeflag_offset] = tartype; 607228753Smm } else if (mytartype >= 0) { 608228753Smm h[USTAR_typeflag_offset] = mytartype; 609228753Smm } else { 610228753Smm switch (archive_entry_filetype(entry)) { 611228753Smm case AE_IFREG: h[USTAR_typeflag_offset] = '0' ; break; 612228753Smm case AE_IFLNK: h[USTAR_typeflag_offset] = '2' ; break; 613228753Smm case AE_IFCHR: h[USTAR_typeflag_offset] = '3' ; break; 614228753Smm case AE_IFBLK: h[USTAR_typeflag_offset] = '4' ; break; 615228753Smm case AE_IFDIR: h[USTAR_typeflag_offset] = '5' ; break; 616228753Smm case AE_IFIFO: h[USTAR_typeflag_offset] = '6' ; break; 617358090Smm default: /* AE_IFSOCK and unknown */ 618358090Smm __archive_write_entry_filetype_unsupported( 619358090Smm &a->archive, entry, "ustar"); 620228753Smm ret = ARCHIVE_FAILED; 621228753Smm } 622228753Smm } 623228753Smm 624228753Smm checksum = 0; 625228753Smm for (i = 0; i < 512; i++) 626228753Smm checksum += 255 & (unsigned int)h[i]; 627228753Smm h[USTAR_checksum_offset + 6] = '\0'; /* Can't be pre-set in the template. */ 628228753Smm /* h[USTAR_checksum_offset + 7] = ' '; */ /* This is pre-set in the template. */ 629228753Smm format_octal(checksum, h + USTAR_checksum_offset, 6); 630228753Smm return (ret); 631228753Smm} 632228753Smm 633228753Smm/* 634228753Smm * Format a number into a field, with some intelligence. 635228753Smm */ 636228753Smmstatic int 637228753Smmformat_number(int64_t v, char *p, int s, int maxsize, int strict) 638228753Smm{ 639228753Smm int64_t limit; 640228753Smm 641228753Smm limit = ((int64_t)1 << (s*3)); 642228753Smm 643228753Smm /* "Strict" only permits octal values with proper termination. */ 644228753Smm if (strict) 645228753Smm return (format_octal(v, p, s)); 646228753Smm 647228753Smm /* 648228753Smm * In non-strict mode, we allow the number to overwrite one or 649228753Smm * more bytes of the field termination. Even old tar 650228753Smm * implementations should be able to handle this with no 651228753Smm * problem. 652228753Smm */ 653228753Smm if (v >= 0) { 654228753Smm while (s <= maxsize) { 655228753Smm if (v < limit) 656228753Smm return (format_octal(v, p, s)); 657228753Smm s++; 658228753Smm limit <<= 3; 659228753Smm } 660228753Smm } 661228753Smm 662228753Smm /* Base-256 can handle any number, positive or negative. */ 663228753Smm return (format_256(v, p, maxsize)); 664228753Smm} 665228753Smm 666228753Smm/* 667228753Smm * Format a number into the specified field using base-256. 668228753Smm */ 669228753Smmstatic int 670228753Smmformat_256(int64_t v, char *p, int s) 671228753Smm{ 672228753Smm p += s; 673228753Smm while (s-- > 0) { 674228753Smm *--p = (char)(v & 0xff); 675228753Smm v >>= 8; 676228753Smm } 677228753Smm *p |= 0x80; /* Set the base-256 marker bit. */ 678228753Smm return (0); 679228753Smm} 680228753Smm 681228753Smm/* 682228753Smm * Format a number into the specified field. 683228753Smm */ 684228753Smmstatic int 685228753Smmformat_octal(int64_t v, char *p, int s) 686228753Smm{ 687228753Smm int len; 688228753Smm 689228753Smm len = s; 690228753Smm 691228753Smm /* Octal values can't be negative, so use 0. */ 692228753Smm if (v < 0) { 693228753Smm while (len-- > 0) 694228753Smm *p++ = '0'; 695228753Smm return (-1); 696228753Smm } 697228753Smm 698228753Smm p += s; /* Start at the end and work backwards. */ 699228753Smm while (s-- > 0) { 700228753Smm *--p = (char)('0' + (v & 7)); 701228753Smm v >>= 3; 702228753Smm } 703228753Smm 704228753Smm if (v == 0) 705228753Smm return (0); 706228753Smm 707228753Smm /* If it overflowed, fill field with max value. */ 708228753Smm while (len-- > 0) 709228753Smm *p++ = '7'; 710228753Smm 711228753Smm return (-1); 712228753Smm} 713228753Smm 714228753Smmstatic int 715232153Smmarchive_write_ustar_close(struct archive_write *a) 716228753Smm{ 717232153Smm return (__archive_write_nulls(a, 512*2)); 718228753Smm} 719228753Smm 720228753Smmstatic int 721232153Smmarchive_write_ustar_free(struct archive_write *a) 722228753Smm{ 723228753Smm struct ustar *ustar; 724228753Smm 725228753Smm ustar = (struct ustar *)a->format_data; 726228753Smm free(ustar); 727228753Smm a->format_data = NULL; 728228753Smm return (ARCHIVE_OK); 729228753Smm} 730228753Smm 731228753Smmstatic int 732228753Smmarchive_write_ustar_finish_entry(struct archive_write *a) 733228753Smm{ 734228753Smm struct ustar *ustar; 735228753Smm int ret; 736228753Smm 737228753Smm ustar = (struct ustar *)a->format_data; 738232153Smm ret = __archive_write_nulls(a, 739238856Smm (size_t)(ustar->entry_bytes_remaining + ustar->entry_padding)); 740228753Smm ustar->entry_bytes_remaining = ustar->entry_padding = 0; 741228753Smm return (ret); 742228753Smm} 743228753Smm 744228753Smmstatic ssize_t 745228753Smmarchive_write_ustar_data(struct archive_write *a, const void *buff, size_t s) 746228753Smm{ 747228753Smm struct ustar *ustar; 748228753Smm int ret; 749228753Smm 750228753Smm ustar = (struct ustar *)a->format_data; 751228753Smm if (s > ustar->entry_bytes_remaining) 752238856Smm s = (size_t)ustar->entry_bytes_remaining; 753232153Smm ret = __archive_write_output(a, buff, s); 754228753Smm ustar->entry_bytes_remaining -= s; 755228753Smm if (ret != ARCHIVE_OK) 756228753Smm return (ret); 757228753Smm return (s); 758228753Smm} 759