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 48 static ssize_t archive_write_newc_data(struct archive_write *, 49 const void *buff, size_t s); 50 static int archive_write_newc_close(struct archive_write *); 51 static int archive_write_newc_free(struct archive_write *); 52 static int archive_write_newc_finish_entry(struct archive_write *); 53 static int archive_write_newc_header(struct archive_write *, 54 struct archive_entry *); 55 static int archive_write_newc_options(struct archive_write *, 56 const char *, const char *); 57 static int format_hex(int64_t, void *, int); 58 static int64_t format_hex_recursive(int64_t, char *, int); 59 static int write_header(struct archive_write *, struct archive_entry *); 60 61 struct cpio { 62 uint64_t entry_bytes_remaining; 63 int padding; 64 65 struct archive_string_conv *opt_sconv; 66 struct archive_string_conv *sconv_default; 67 int init_default_conversion; 68 }; 69 70 #define c_magic_offset 0 71 #define c_magic_size 6 72 #define c_ino_offset 6 73 #define c_ino_size 8 74 #define c_mode_offset 14 75 #define c_mode_size 8 76 #define c_uid_offset 22 77 #define c_uid_size 8 78 #define c_gid_offset 30 79 #define c_gid_size 8 80 #define c_nlink_offset 38 81 #define c_nlink_size 8 82 #define c_mtime_offset 46 83 #define c_mtime_size 8 84 #define c_filesize_offset 54 85 #define c_filesize_size 8 86 #define c_devmajor_offset 62 87 #define c_devmajor_size 8 88 #define c_devminor_offset 70 89 #define c_devminor_size 8 90 #define c_rdevmajor_offset 78 91 #define c_rdevmajor_size 8 92 #define c_rdevminor_offset 86 93 #define c_rdevminor_size 8 94 #define c_namesize_offset 94 95 #define c_namesize_size 8 96 #define c_checksum_offset 102 97 #define c_checksum_size 8 98 #define c_header_size 110 99 100 /* Logic trick: difference between 'n' and next multiple of 4 */ 101 #define PAD4(n) (3 & (1 + ~(n))) 102 103 /* 104 * Set output format to 'cpio' format. 105 */ 106 int 107 archive_write_set_format_cpio_newc(struct archive *_a) 108 { 109 struct archive_write *a = (struct archive_write *)_a; 110 struct cpio *cpio; 111 112 archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, 113 ARCHIVE_STATE_NEW, "archive_write_set_format_cpio_newc"); 114 115 /* If someone else was already registered, unregister them. */ 116 if (a->format_free != NULL) 117 (a->format_free)(a); 118 119 cpio = (struct cpio *)malloc(sizeof(*cpio)); 120 if (cpio == NULL) { 121 archive_set_error(&a->archive, ENOMEM, "Can't allocate cpio data"); 122 return (ARCHIVE_FATAL); 123 } 124 memset(cpio, 0, sizeof(*cpio)); 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 pahtname, 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 if (entry_main) 371 archive_entry_free(entry_main); 372 return (ret_final); 373 } 374 375 static ssize_t 376 archive_write_newc_data(struct archive_write *a, const void *buff, size_t s) 377 { 378 struct cpio *cpio; 379 int ret; 380 381 cpio = (struct cpio *)a->format_data; 382 if (s > cpio->entry_bytes_remaining) 383 s = (size_t)cpio->entry_bytes_remaining; 384 385 ret = __archive_write_output(a, buff, s); 386 cpio->entry_bytes_remaining -= s; 387 if (ret >= 0) 388 return (s); 389 else 390 return (ret); 391 } 392 393 /* 394 * Format a number into the specified field. 395 */ 396 static int 397 format_hex(int64_t v, void *p, int digits) 398 { 399 int64_t max; 400 int ret; 401 402 max = (((int64_t)1) << (digits * 4)) - 1; 403 if (v >= 0 && v <= max) { 404 format_hex_recursive(v, (char *)p, digits); 405 ret = 0; 406 } else { 407 format_hex_recursive(max, (char *)p, digits); 408 ret = -1; 409 } 410 return (ret); 411 } 412 413 static int64_t 414 format_hex_recursive(int64_t v, char *p, int s) 415 { 416 if (s == 0) 417 return (v); 418 v = format_hex_recursive(v, p+1, s-1); 419 *p = "0123456789abcdef"[v & 0xf]; 420 return (v >> 4); 421 } 422 423 static int 424 archive_write_newc_close(struct archive_write *a) 425 { 426 int er; 427 struct archive_entry *trailer; 428 429 trailer = archive_entry_new(); 430 archive_entry_set_nlink(trailer, 1); 431 archive_entry_set_size(trailer, 0); 432 archive_entry_set_pathname(trailer, "TRAILER!!!"); 433 /* Bypass the required data checks. */ 434 er = write_header(a, trailer); 435 archive_entry_free(trailer); 436 return (er); 437 } 438 439 static int 440 archive_write_newc_free(struct archive_write *a) 441 { 442 struct cpio *cpio; 443 444 cpio = (struct cpio *)a->format_data; 445 free(cpio); 446 a->format_data = NULL; 447 return (ARCHIVE_OK); 448 } 449 450 static int 451 archive_write_newc_finish_entry(struct archive_write *a) 452 { 453 struct cpio *cpio; 454 455 cpio = (struct cpio *)a->format_data; 456 return (__archive_write_nulls(a, 457 (size_t)cpio->entry_bytes_remaining + cpio->padding)); 458 } 459