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