1228753Smm/*- 2228753Smm * Copyright (c) 2003-2007 Tim Kientzle 3232153Smm * Copyright (c) 2010-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_read_support_format_cpio.c 344674 2019-02-28 22:57:09Z mm $"); 29228753Smm 30228753Smm#ifdef HAVE_ERRNO_H 31228753Smm#include <errno.h> 32228753Smm#endif 33228753Smm/* #include <stdint.h> */ /* See archive_platform.h */ 34228753Smm#ifdef HAVE_STDLIB_H 35228753Smm#include <stdlib.h> 36228753Smm#endif 37228753Smm#ifdef HAVE_STRING_H 38228753Smm#include <string.h> 39228753Smm#endif 40228753Smm 41228753Smm#include "archive.h" 42228753Smm#include "archive_entry.h" 43232153Smm#include "archive_entry_locale.h" 44228753Smm#include "archive_private.h" 45228753Smm#include "archive_read_private.h" 46228753Smm 47232153Smm#define bin_magic_offset 0 48232153Smm#define bin_magic_size 2 49232153Smm#define bin_dev_offset 2 50232153Smm#define bin_dev_size 2 51232153Smm#define bin_ino_offset 4 52232153Smm#define bin_ino_size 2 53232153Smm#define bin_mode_offset 6 54232153Smm#define bin_mode_size 2 55232153Smm#define bin_uid_offset 8 56232153Smm#define bin_uid_size 2 57232153Smm#define bin_gid_offset 10 58232153Smm#define bin_gid_size 2 59232153Smm#define bin_nlink_offset 12 60232153Smm#define bin_nlink_size 2 61232153Smm#define bin_rdev_offset 14 62232153Smm#define bin_rdev_size 2 63232153Smm#define bin_mtime_offset 16 64232153Smm#define bin_mtime_size 4 65232153Smm#define bin_namesize_offset 20 66232153Smm#define bin_namesize_size 2 67232153Smm#define bin_filesize_offset 22 68232153Smm#define bin_filesize_size 4 69232153Smm#define bin_header_size 26 70228753Smm 71232153Smm#define odc_magic_offset 0 72232153Smm#define odc_magic_size 6 73232153Smm#define odc_dev_offset 6 74232153Smm#define odc_dev_size 6 75232153Smm#define odc_ino_offset 12 76232153Smm#define odc_ino_size 6 77232153Smm#define odc_mode_offset 18 78232153Smm#define odc_mode_size 6 79232153Smm#define odc_uid_offset 24 80232153Smm#define odc_uid_size 6 81232153Smm#define odc_gid_offset 30 82232153Smm#define odc_gid_size 6 83232153Smm#define odc_nlink_offset 36 84232153Smm#define odc_nlink_size 6 85232153Smm#define odc_rdev_offset 42 86232153Smm#define odc_rdev_size 6 87232153Smm#define odc_mtime_offset 48 88232153Smm#define odc_mtime_size 11 89232153Smm#define odc_namesize_offset 59 90232153Smm#define odc_namesize_size 6 91232153Smm#define odc_filesize_offset 65 92232153Smm#define odc_filesize_size 11 93232153Smm#define odc_header_size 76 94228753Smm 95232153Smm#define newc_magic_offset 0 96232153Smm#define newc_magic_size 6 97232153Smm#define newc_ino_offset 6 98232153Smm#define newc_ino_size 8 99232153Smm#define newc_mode_offset 14 100232153Smm#define newc_mode_size 8 101232153Smm#define newc_uid_offset 22 102232153Smm#define newc_uid_size 8 103232153Smm#define newc_gid_offset 30 104232153Smm#define newc_gid_size 8 105232153Smm#define newc_nlink_offset 38 106232153Smm#define newc_nlink_size 8 107232153Smm#define newc_mtime_offset 46 108232153Smm#define newc_mtime_size 8 109232153Smm#define newc_filesize_offset 54 110232153Smm#define newc_filesize_size 8 111232153Smm#define newc_devmajor_offset 62 112232153Smm#define newc_devmajor_size 8 113232153Smm#define newc_devminor_offset 70 114232153Smm#define newc_devminor_size 8 115232153Smm#define newc_rdevmajor_offset 78 116232153Smm#define newc_rdevmajor_size 8 117232153Smm#define newc_rdevminor_offset 86 118232153Smm#define newc_rdevminor_size 8 119232153Smm#define newc_namesize_offset 94 120232153Smm#define newc_namesize_size 8 121232153Smm#define newc_checksum_offset 102 122232153Smm#define newc_checksum_size 8 123232153Smm#define newc_header_size 110 124228753Smm 125232153Smm/* 126232153Smm * An afio large ASCII header, which they named itself. 127232153Smm * afio utility uses this header, if a file size is larger than 2G bytes 128232153Smm * or inode/uid/gid is bigger than 65535(0xFFFF) or mtime is bigger than 129232153Smm * 0x7fffffff, which we cannot record to odc header because of its limit. 130232153Smm * If not, uses odc header. 131232153Smm */ 132232153Smm#define afiol_magic_offset 0 133232153Smm#define afiol_magic_size 6 134232153Smm#define afiol_dev_offset 6 135232153Smm#define afiol_dev_size 8 /* hex */ 136232153Smm#define afiol_ino_offset 14 137232153Smm#define afiol_ino_size 16 /* hex */ 138232153Smm#define afiol_ino_m_offset 30 /* 'm' */ 139232153Smm#define afiol_mode_offset 31 140232153Smm#define afiol_mode_size 6 /* oct */ 141232153Smm#define afiol_uid_offset 37 142232153Smm#define afiol_uid_size 8 /* hex */ 143232153Smm#define afiol_gid_offset 45 144232153Smm#define afiol_gid_size 8 /* hex */ 145232153Smm#define afiol_nlink_offset 53 146232153Smm#define afiol_nlink_size 8 /* hex */ 147232153Smm#define afiol_rdev_offset 61 148232153Smm#define afiol_rdev_size 8 /* hex */ 149232153Smm#define afiol_mtime_offset 69 150232153Smm#define afiol_mtime_size 16 /* hex */ 151232153Smm#define afiol_mtime_n_offset 85 /* 'n' */ 152232153Smm#define afiol_namesize_offset 86 153232153Smm#define afiol_namesize_size 4 /* hex */ 154232153Smm#define afiol_flag_offset 90 155232153Smm#define afiol_flag_size 4 /* hex */ 156232153Smm#define afiol_xsize_offset 94 157232153Smm#define afiol_xsize_size 4 /* hex */ 158232153Smm#define afiol_xsize_s_offset 98 /* 's' */ 159232153Smm#define afiol_filesize_offset 99 160232153Smm#define afiol_filesize_size 16 /* hex */ 161232153Smm#define afiol_filesize_c_offset 115 /* ':' */ 162232153Smm#define afiol_header_size 116 163228911Smm 164232153Smm 165228753Smmstruct links_entry { 166228753Smm struct links_entry *next; 167228753Smm struct links_entry *previous; 168318483Smm unsigned int links; 169228753Smm dev_t dev; 170228753Smm int64_t ino; 171228753Smm char *name; 172228753Smm}; 173228753Smm 174228753Smm#define CPIO_MAGIC 0x13141516 175228753Smmstruct cpio { 176228753Smm int magic; 177228753Smm int (*read_header)(struct archive_read *, struct cpio *, 178228753Smm struct archive_entry *, size_t *, size_t *); 179228753Smm struct links_entry *links_head; 180232153Smm int64_t entry_bytes_remaining; 181232153Smm int64_t entry_bytes_unconsumed; 182232153Smm int64_t entry_offset; 183232153Smm int64_t entry_padding; 184232153Smm 185232153Smm struct archive_string_conv *opt_sconv; 186232153Smm struct archive_string_conv *sconv_default; 187232153Smm int init_default_conversion; 188228753Smm}; 189228753Smm 190228753Smmstatic int64_t atol16(const char *, unsigned); 191228753Smmstatic int64_t atol8(const char *, unsigned); 192232153Smmstatic int archive_read_format_cpio_bid(struct archive_read *, int); 193232153Smmstatic int archive_read_format_cpio_options(struct archive_read *, 194232153Smm const char *, const char *); 195228753Smmstatic int archive_read_format_cpio_cleanup(struct archive_read *); 196228753Smmstatic int archive_read_format_cpio_read_data(struct archive_read *, 197232153Smm const void **, size_t *, int64_t *); 198228753Smmstatic int archive_read_format_cpio_read_header(struct archive_read *, 199228753Smm struct archive_entry *); 200232153Smmstatic int archive_read_format_cpio_skip(struct archive_read *); 201283259Sdelphijstatic int64_t be4(const unsigned char *); 202228753Smmstatic int find_odc_header(struct archive_read *); 203228753Smmstatic int find_newc_header(struct archive_read *); 204228753Smmstatic int header_bin_be(struct archive_read *, struct cpio *, 205228753Smm struct archive_entry *, size_t *, size_t *); 206228753Smmstatic int header_bin_le(struct archive_read *, struct cpio *, 207228753Smm struct archive_entry *, size_t *, size_t *); 208228753Smmstatic int header_newc(struct archive_read *, struct cpio *, 209228753Smm struct archive_entry *, size_t *, size_t *); 210228753Smmstatic int header_odc(struct archive_read *, struct cpio *, 211228753Smm struct archive_entry *, size_t *, size_t *); 212232153Smmstatic int header_afiol(struct archive_read *, struct cpio *, 213232153Smm struct archive_entry *, size_t *, size_t *); 214228753Smmstatic int is_octal(const char *, size_t); 215228753Smmstatic int is_hex(const char *, size_t); 216283259Sdelphijstatic int64_t le4(const unsigned char *); 217232153Smmstatic int record_hardlink(struct archive_read *a, 218232153Smm struct cpio *cpio, struct archive_entry *entry); 219228753Smm 220228753Smmint 221228753Smmarchive_read_support_format_cpio(struct archive *_a) 222228753Smm{ 223228753Smm struct archive_read *a = (struct archive_read *)_a; 224228753Smm struct cpio *cpio; 225228753Smm int r; 226228753Smm 227232153Smm archive_check_magic(_a, ARCHIVE_READ_MAGIC, 228232153Smm ARCHIVE_STATE_NEW, "archive_read_support_format_cpio"); 229232153Smm 230232153Smm cpio = (struct cpio *)calloc(1, sizeof(*cpio)); 231228753Smm if (cpio == NULL) { 232228753Smm archive_set_error(&a->archive, ENOMEM, "Can't allocate cpio data"); 233228753Smm return (ARCHIVE_FATAL); 234228753Smm } 235228753Smm cpio->magic = CPIO_MAGIC; 236228753Smm 237228753Smm r = __archive_read_register_format(a, 238228753Smm cpio, 239228753Smm "cpio", 240228753Smm archive_read_format_cpio_bid, 241232153Smm archive_read_format_cpio_options, 242228753Smm archive_read_format_cpio_read_header, 243228753Smm archive_read_format_cpio_read_data, 244232153Smm archive_read_format_cpio_skip, 245248616Smm NULL, 246302001Smm archive_read_format_cpio_cleanup, 247302001Smm NULL, 248302001Smm NULL); 249228753Smm 250228753Smm if (r != ARCHIVE_OK) 251228753Smm free(cpio); 252228753Smm return (ARCHIVE_OK); 253228753Smm} 254228753Smm 255228753Smm 256228753Smmstatic int 257232153Smmarchive_read_format_cpio_bid(struct archive_read *a, int best_bid) 258228753Smm{ 259228753Smm const unsigned char *p; 260228753Smm struct cpio *cpio; 261228753Smm int bid; 262228753Smm 263232153Smm (void)best_bid; /* UNUSED */ 264232153Smm 265228753Smm cpio = (struct cpio *)(a->format->data); 266228753Smm 267232153Smm if ((p = __archive_read_ahead(a, 6, NULL)) == NULL) 268228753Smm return (-1); 269228753Smm 270228753Smm bid = 0; 271228753Smm if (memcmp(p, "070707", 6) == 0) { 272228753Smm /* ASCII cpio archive (odc, POSIX.1) */ 273228753Smm cpio->read_header = header_odc; 274228753Smm bid += 48; 275228753Smm /* 276228753Smm * XXX TODO: More verification; Could check that only octal 277228753Smm * digits appear in appropriate header locations. XXX 278228753Smm */ 279232153Smm } else if (memcmp(p, "070727", 6) == 0) { 280232153Smm /* afio large ASCII cpio archive */ 281232153Smm cpio->read_header = header_odc; 282232153Smm bid += 48; 283232153Smm /* 284232153Smm * XXX TODO: More verification; Could check that almost hex 285232153Smm * digits appear in appropriate header locations. XXX 286232153Smm */ 287228753Smm } else if (memcmp(p, "070701", 6) == 0) { 288228753Smm /* ASCII cpio archive (SVR4 without CRC) */ 289228753Smm cpio->read_header = header_newc; 290228753Smm bid += 48; 291228753Smm /* 292228753Smm * XXX TODO: More verification; Could check that only hex 293228753Smm * digits appear in appropriate header locations. XXX 294228753Smm */ 295228753Smm } else if (memcmp(p, "070702", 6) == 0) { 296228753Smm /* ASCII cpio archive (SVR4 with CRC) */ 297228753Smm /* XXX TODO: Flag that we should check the CRC. XXX */ 298228753Smm cpio->read_header = header_newc; 299228753Smm bid += 48; 300228753Smm /* 301228753Smm * XXX TODO: More verification; Could check that only hex 302228753Smm * digits appear in appropriate header locations. XXX 303228753Smm */ 304228753Smm } else if (p[0] * 256 + p[1] == 070707) { 305228753Smm /* big-endian binary cpio archives */ 306228753Smm cpio->read_header = header_bin_be; 307228753Smm bid += 16; 308228753Smm /* Is more verification possible here? */ 309228753Smm } else if (p[0] + p[1] * 256 == 070707) { 310228753Smm /* little-endian binary cpio archives */ 311228753Smm cpio->read_header = header_bin_le; 312228753Smm bid += 16; 313228753Smm /* Is more verification possible here? */ 314228753Smm } else 315228753Smm return (ARCHIVE_WARN); 316228753Smm 317228753Smm return (bid); 318228753Smm} 319228753Smm 320228753Smmstatic int 321232153Smmarchive_read_format_cpio_options(struct archive_read *a, 322232153Smm const char *key, const char *val) 323232153Smm{ 324232153Smm struct cpio *cpio; 325232153Smm int ret = ARCHIVE_FAILED; 326232153Smm 327232153Smm cpio = (struct cpio *)(a->format->data); 328232153Smm if (strcmp(key, "compat-2x") == 0) { 329311042Smm /* Handle filenames as libarchive 2.x */ 330232153Smm cpio->init_default_conversion = (val != NULL)?1:0; 331232153Smm return (ARCHIVE_OK); 332232153Smm } else if (strcmp(key, "hdrcharset") == 0) { 333232153Smm if (val == NULL || val[0] == 0) 334232153Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 335232153Smm "cpio: hdrcharset option needs a character-set name"); 336232153Smm else { 337232153Smm cpio->opt_sconv = 338232153Smm archive_string_conversion_from_charset( 339232153Smm &a->archive, val, 0); 340232153Smm if (cpio->opt_sconv != NULL) 341232153Smm ret = ARCHIVE_OK; 342232153Smm else 343232153Smm ret = ARCHIVE_FATAL; 344232153Smm } 345232153Smm return (ret); 346232153Smm } 347232153Smm 348232153Smm /* Note: The "warn" return is just to inform the options 349232153Smm * supervisor that we didn't handle it. It will generate 350232153Smm * a suitable error if no one used this option. */ 351232153Smm return (ARCHIVE_WARN); 352232153Smm} 353232153Smm 354232153Smmstatic int 355228753Smmarchive_read_format_cpio_read_header(struct archive_read *a, 356228753Smm struct archive_entry *entry) 357228753Smm{ 358228753Smm struct cpio *cpio; 359313929Smm const void *h, *hl; 360232153Smm struct archive_string_conv *sconv; 361228753Smm size_t namelength; 362228753Smm size_t name_pad; 363228753Smm int r; 364228753Smm 365228753Smm cpio = (struct cpio *)(a->format->data); 366232153Smm sconv = cpio->opt_sconv; 367232153Smm if (sconv == NULL) { 368232153Smm if (!cpio->init_default_conversion) { 369232153Smm cpio->sconv_default = 370232153Smm archive_string_default_conversion_for_read( 371232153Smm &(a->archive)); 372232153Smm cpio->init_default_conversion = 1; 373232153Smm } 374232153Smm sconv = cpio->sconv_default; 375232153Smm } 376232153Smm 377228753Smm r = (cpio->read_header(a, cpio, entry, &namelength, &name_pad)); 378228753Smm 379228753Smm if (r < ARCHIVE_WARN) 380228753Smm return (r); 381228753Smm 382228753Smm /* Read name from buffer. */ 383228753Smm h = __archive_read_ahead(a, namelength + name_pad, NULL); 384228753Smm if (h == NULL) 385228753Smm return (ARCHIVE_FATAL); 386232153Smm if (archive_entry_copy_pathname_l(entry, 387232153Smm (const char *)h, namelength, sconv) != 0) { 388232153Smm if (errno == ENOMEM) { 389232153Smm archive_set_error(&a->archive, ENOMEM, 390232153Smm "Can't allocate memory for Pathname"); 391232153Smm return (ARCHIVE_FATAL); 392232153Smm } 393232153Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 394232153Smm "Pathname can't be converted from %s to current locale.", 395232153Smm archive_string_conversion_charset_name(sconv)); 396232153Smm r = ARCHIVE_WARN; 397232153Smm } 398228753Smm cpio->entry_offset = 0; 399228753Smm 400232153Smm __archive_read_consume(a, namelength + name_pad); 401232153Smm 402228753Smm /* If this is a symlink, read the link contents. */ 403228753Smm if (archive_entry_filetype(entry) == AE_IFLNK) { 404302001Smm if (cpio->entry_bytes_remaining > 1024 * 1024) { 405302001Smm archive_set_error(&a->archive, ENOMEM, 406302001Smm "Rejecting malformed cpio archive: symlink contents exceed 1 megabyte"); 407302001Smm return (ARCHIVE_FATAL); 408302001Smm } 409313929Smm hl = __archive_read_ahead(a, 410238856Smm (size_t)cpio->entry_bytes_remaining, NULL); 411313929Smm if (hl == NULL) 412228753Smm return (ARCHIVE_FATAL); 413313929Smm if (archive_entry_copy_symlink_l(entry, (const char *)hl, 414238856Smm (size_t)cpio->entry_bytes_remaining, sconv) != 0) { 415232153Smm if (errno == ENOMEM) { 416232153Smm archive_set_error(&a->archive, ENOMEM, 417232153Smm "Can't allocate memory for Linkname"); 418232153Smm return (ARCHIVE_FATAL); 419232153Smm } 420232153Smm archive_set_error(&a->archive, 421232153Smm ARCHIVE_ERRNO_FILE_FORMAT, 422232153Smm "Linkname can't be converted from %s to " 423232153Smm "current locale.", 424232153Smm archive_string_conversion_charset_name(sconv)); 425232153Smm r = ARCHIVE_WARN; 426232153Smm } 427228753Smm __archive_read_consume(a, cpio->entry_bytes_remaining); 428228753Smm cpio->entry_bytes_remaining = 0; 429228753Smm } 430228753Smm 431228753Smm /* XXX TODO: If the full mode is 0160200, then this is a Solaris 432228753Smm * ACL description for the following entry. Read this body 433228753Smm * and parse it as a Solaris-style ACL, then read the next 434228753Smm * header. XXX */ 435228753Smm 436228753Smm /* Compare name to "TRAILER!!!" to test for end-of-archive. */ 437313929Smm if (namelength == 11 && strncmp((const char *)h, "TRAILER!!!", 438313571Smm 11) == 0) { 439228753Smm /* TODO: Store file location of start of block. */ 440228753Smm archive_clear_error(&a->archive); 441228753Smm return (ARCHIVE_EOF); 442228753Smm } 443228753Smm 444228753Smm /* Detect and record hardlinks to previously-extracted entries. */ 445232153Smm if (record_hardlink(a, cpio, entry) != ARCHIVE_OK) { 446232153Smm return (ARCHIVE_FATAL); 447232153Smm } 448228753Smm 449228753Smm return (r); 450228753Smm} 451228753Smm 452228753Smmstatic int 453228753Smmarchive_read_format_cpio_read_data(struct archive_read *a, 454232153Smm const void **buff, size_t *size, int64_t *offset) 455228753Smm{ 456228753Smm ssize_t bytes_read; 457228753Smm struct cpio *cpio; 458228753Smm 459228753Smm cpio = (struct cpio *)(a->format->data); 460232153Smm 461232153Smm if (cpio->entry_bytes_unconsumed) { 462232153Smm __archive_read_consume(a, cpio->entry_bytes_unconsumed); 463232153Smm cpio->entry_bytes_unconsumed = 0; 464232153Smm } 465232153Smm 466228753Smm if (cpio->entry_bytes_remaining > 0) { 467228753Smm *buff = __archive_read_ahead(a, 1, &bytes_read); 468228753Smm if (bytes_read <= 0) 469228753Smm return (ARCHIVE_FATAL); 470228753Smm if (bytes_read > cpio->entry_bytes_remaining) 471238856Smm bytes_read = (ssize_t)cpio->entry_bytes_remaining; 472228753Smm *size = bytes_read; 473232153Smm cpio->entry_bytes_unconsumed = bytes_read; 474228753Smm *offset = cpio->entry_offset; 475228753Smm cpio->entry_offset += bytes_read; 476228753Smm cpio->entry_bytes_remaining -= bytes_read; 477228753Smm return (ARCHIVE_OK); 478228753Smm } else { 479232153Smm if (cpio->entry_padding != 480232153Smm __archive_read_consume(a, cpio->entry_padding)) { 481232153Smm return (ARCHIVE_FATAL); 482228753Smm } 483232153Smm cpio->entry_padding = 0; 484228753Smm *buff = NULL; 485228753Smm *size = 0; 486228753Smm *offset = cpio->entry_offset; 487228753Smm return (ARCHIVE_EOF); 488228753Smm } 489228753Smm} 490228753Smm 491232153Smmstatic int 492232153Smmarchive_read_format_cpio_skip(struct archive_read *a) 493232153Smm{ 494232153Smm struct cpio *cpio = (struct cpio *)(a->format->data); 495232153Smm int64_t to_skip = cpio->entry_bytes_remaining + cpio->entry_padding + 496232153Smm cpio->entry_bytes_unconsumed; 497232153Smm 498232153Smm if (to_skip != __archive_read_consume(a, to_skip)) { 499232153Smm return (ARCHIVE_FATAL); 500232153Smm } 501232153Smm cpio->entry_bytes_remaining = 0; 502232153Smm cpio->entry_padding = 0; 503232153Smm cpio->entry_bytes_unconsumed = 0; 504232153Smm return (ARCHIVE_OK); 505232153Smm} 506232153Smm 507228753Smm/* 508228753Smm * Skip forward to the next cpio newc header by searching for the 509228753Smm * 07070[12] string. This should be generalized and merged with 510228753Smm * find_odc_header below. 511228753Smm */ 512228753Smmstatic int 513228753Smmis_hex(const char *p, size_t len) 514228753Smm{ 515228753Smm while (len-- > 0) { 516228753Smm if ((*p >= '0' && *p <= '9') 517228753Smm || (*p >= 'a' && *p <= 'f') 518228753Smm || (*p >= 'A' && *p <= 'F')) 519228753Smm ++p; 520228753Smm else 521228753Smm return (0); 522228753Smm } 523228753Smm return (1); 524228753Smm} 525228753Smm 526228753Smmstatic int 527228753Smmfind_newc_header(struct archive_read *a) 528228753Smm{ 529228753Smm const void *h; 530228753Smm const char *p, *q; 531228753Smm size_t skip, skipped = 0; 532228753Smm ssize_t bytes; 533228753Smm 534228753Smm for (;;) { 535232153Smm h = __archive_read_ahead(a, newc_header_size, &bytes); 536228753Smm if (h == NULL) 537228753Smm return (ARCHIVE_FATAL); 538228753Smm p = h; 539228753Smm q = p + bytes; 540228753Smm 541228753Smm /* Try the typical case first, then go into the slow search.*/ 542228753Smm if (memcmp("07070", p, 5) == 0 543228753Smm && (p[5] == '1' || p[5] == '2') 544232153Smm && is_hex(p, newc_header_size)) 545228753Smm return (ARCHIVE_OK); 546228753Smm 547228753Smm /* 548228753Smm * Scan ahead until we find something that looks 549232153Smm * like a newc header. 550228753Smm */ 551232153Smm while (p + newc_header_size <= q) { 552228753Smm switch (p[5]) { 553228753Smm case '1': 554228753Smm case '2': 555228753Smm if (memcmp("07070", p, 5) == 0 556232153Smm && is_hex(p, newc_header_size)) { 557228753Smm skip = p - (const char *)h; 558228753Smm __archive_read_consume(a, skip); 559228753Smm skipped += skip; 560228753Smm if (skipped > 0) { 561228753Smm archive_set_error(&a->archive, 562228753Smm 0, 563228753Smm "Skipped %d bytes before " 564228753Smm "finding valid header", 565228753Smm (int)skipped); 566228753Smm return (ARCHIVE_WARN); 567228753Smm } 568228753Smm return (ARCHIVE_OK); 569228753Smm } 570228753Smm p += 2; 571228753Smm break; 572228753Smm case '0': 573228753Smm p++; 574228753Smm break; 575228753Smm default: 576228753Smm p += 6; 577228753Smm break; 578228753Smm } 579228753Smm } 580228753Smm skip = p - (const char *)h; 581228753Smm __archive_read_consume(a, skip); 582228753Smm skipped += skip; 583228753Smm } 584228753Smm} 585228753Smm 586228753Smmstatic int 587228753Smmheader_newc(struct archive_read *a, struct cpio *cpio, 588228753Smm struct archive_entry *entry, size_t *namelength, size_t *name_pad) 589228753Smm{ 590228753Smm const void *h; 591232153Smm const char *header; 592228753Smm int r; 593228753Smm 594228753Smm r = find_newc_header(a); 595228753Smm if (r < ARCHIVE_WARN) 596228753Smm return (r); 597228753Smm 598228753Smm /* Read fixed-size portion of header. */ 599232153Smm h = __archive_read_ahead(a, newc_header_size, NULL); 600228753Smm if (h == NULL) 601228753Smm return (ARCHIVE_FATAL); 602228753Smm 603228753Smm /* Parse out hex fields. */ 604232153Smm header = (const char *)h; 605228753Smm 606232153Smm if (memcmp(header + newc_magic_offset, "070701", 6) == 0) { 607228753Smm a->archive.archive_format = ARCHIVE_FORMAT_CPIO_SVR4_NOCRC; 608228753Smm a->archive.archive_format_name = "ASCII cpio (SVR4 with no CRC)"; 609232153Smm } else if (memcmp(header + newc_magic_offset, "070702", 6) == 0) { 610228753Smm a->archive.archive_format = ARCHIVE_FORMAT_CPIO_SVR4_CRC; 611228753Smm a->archive.archive_format_name = "ASCII cpio (SVR4 with CRC)"; 612228753Smm } else { 613228753Smm /* TODO: Abort here? */ 614228753Smm } 615228753Smm 616238856Smm archive_entry_set_devmajor(entry, 617238856Smm (dev_t)atol16(header + newc_devmajor_offset, newc_devmajor_size)); 618238856Smm archive_entry_set_devminor(entry, 619238856Smm (dev_t)atol16(header + newc_devminor_offset, newc_devminor_size)); 620232153Smm archive_entry_set_ino(entry, atol16(header + newc_ino_offset, newc_ino_size)); 621238856Smm archive_entry_set_mode(entry, 622238856Smm (mode_t)atol16(header + newc_mode_offset, newc_mode_size)); 623232153Smm archive_entry_set_uid(entry, atol16(header + newc_uid_offset, newc_uid_size)); 624232153Smm archive_entry_set_gid(entry, atol16(header + newc_gid_offset, newc_gid_size)); 625238856Smm archive_entry_set_nlink(entry, 626238856Smm (unsigned int)atol16(header + newc_nlink_offset, newc_nlink_size)); 627238856Smm archive_entry_set_rdevmajor(entry, 628238856Smm (dev_t)atol16(header + newc_rdevmajor_offset, newc_rdevmajor_size)); 629238856Smm archive_entry_set_rdevminor(entry, 630238856Smm (dev_t)atol16(header + newc_rdevminor_offset, newc_rdevminor_size)); 631232153Smm archive_entry_set_mtime(entry, atol16(header + newc_mtime_offset, newc_mtime_size), 0); 632238856Smm *namelength = (size_t)atol16(header + newc_namesize_offset, newc_namesize_size); 633228753Smm /* Pad name to 2 more than a multiple of 4. */ 634228753Smm *name_pad = (2 - *namelength) & 3; 635228753Smm 636324418Smm /* Make sure that the padded name length fits into size_t. */ 637324418Smm if (*name_pad > SIZE_MAX - *namelength) { 638324418Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 639324418Smm "cpio archive has invalid namelength"); 640324418Smm return (ARCHIVE_FATAL); 641324418Smm } 642324418Smm 643228753Smm /* 644228753Smm * Note: entry_bytes_remaining is at least 64 bits and 645228753Smm * therefore guaranteed to be big enough for a 33-bit file 646228753Smm * size. 647228753Smm */ 648228753Smm cpio->entry_bytes_remaining = 649232153Smm atol16(header + newc_filesize_offset, newc_filesize_size); 650228753Smm archive_entry_set_size(entry, cpio->entry_bytes_remaining); 651228753Smm /* Pad file contents to a multiple of 4. */ 652228753Smm cpio->entry_padding = 3 & -cpio->entry_bytes_remaining; 653232153Smm __archive_read_consume(a, newc_header_size); 654228753Smm return (r); 655228753Smm} 656228753Smm 657228753Smm/* 658228753Smm * Skip forward to the next cpio odc header by searching for the 659228753Smm * 070707 string. This is a hand-optimized search that could 660228753Smm * probably be easily generalized to handle all character-based 661228753Smm * cpio variants. 662228753Smm */ 663228753Smmstatic int 664228753Smmis_octal(const char *p, size_t len) 665228753Smm{ 666228753Smm while (len-- > 0) { 667228753Smm if (*p < '0' || *p > '7') 668228753Smm return (0); 669228753Smm ++p; 670228753Smm } 671228753Smm return (1); 672228753Smm} 673228753Smm 674228753Smmstatic int 675232153Smmis_afio_large(const char *h, size_t len) 676232153Smm{ 677232153Smm if (len < afiol_header_size) 678232153Smm return (0); 679232153Smm if (h[afiol_ino_m_offset] != 'm' 680232153Smm || h[afiol_mtime_n_offset] != 'n' 681232153Smm || h[afiol_xsize_s_offset] != 's' 682232153Smm || h[afiol_filesize_c_offset] != ':') 683232153Smm return (0); 684232153Smm if (!is_hex(h + afiol_dev_offset, afiol_ino_m_offset - afiol_dev_offset)) 685232153Smm return (0); 686232153Smm if (!is_hex(h + afiol_mode_offset, afiol_mtime_n_offset - afiol_mode_offset)) 687232153Smm return (0); 688232153Smm if (!is_hex(h + afiol_namesize_offset, afiol_xsize_s_offset - afiol_namesize_offset)) 689232153Smm return (0); 690232153Smm if (!is_hex(h + afiol_filesize_offset, afiol_filesize_size)) 691232153Smm return (0); 692232153Smm return (1); 693232153Smm} 694232153Smm 695232153Smmstatic int 696228753Smmfind_odc_header(struct archive_read *a) 697228753Smm{ 698228753Smm const void *h; 699228753Smm const char *p, *q; 700228753Smm size_t skip, skipped = 0; 701228753Smm ssize_t bytes; 702228753Smm 703228753Smm for (;;) { 704232153Smm h = __archive_read_ahead(a, odc_header_size, &bytes); 705228753Smm if (h == NULL) 706228753Smm return (ARCHIVE_FATAL); 707228753Smm p = h; 708228753Smm q = p + bytes; 709228753Smm 710228753Smm /* Try the typical case first, then go into the slow search.*/ 711232153Smm if (memcmp("070707", p, 6) == 0 && is_octal(p, odc_header_size)) 712228753Smm return (ARCHIVE_OK); 713232153Smm if (memcmp("070727", p, 6) == 0 && is_afio_large(p, bytes)) { 714232153Smm a->archive.archive_format = ARCHIVE_FORMAT_CPIO_AFIO_LARGE; 715232153Smm return (ARCHIVE_OK); 716232153Smm } 717228753Smm 718228753Smm /* 719228753Smm * Scan ahead until we find something that looks 720228753Smm * like an odc header. 721228753Smm */ 722232153Smm while (p + odc_header_size <= q) { 723228753Smm switch (p[5]) { 724228753Smm case '7': 725232153Smm if ((memcmp("070707", p, 6) == 0 726232153Smm && is_octal(p, odc_header_size)) 727232153Smm || (memcmp("070727", p, 6) == 0 728232153Smm && is_afio_large(p, q - p))) { 729228753Smm skip = p - (const char *)h; 730228753Smm __archive_read_consume(a, skip); 731228753Smm skipped += skip; 732232153Smm if (p[4] == '2') 733232153Smm a->archive.archive_format = 734232153Smm ARCHIVE_FORMAT_CPIO_AFIO_LARGE; 735228753Smm if (skipped > 0) { 736228753Smm archive_set_error(&a->archive, 737228753Smm 0, 738228753Smm "Skipped %d bytes before " 739228753Smm "finding valid header", 740228753Smm (int)skipped); 741228753Smm return (ARCHIVE_WARN); 742228753Smm } 743228753Smm return (ARCHIVE_OK); 744228753Smm } 745228753Smm p += 2; 746228753Smm break; 747228753Smm case '0': 748228753Smm p++; 749228753Smm break; 750228753Smm default: 751228753Smm p += 6; 752228753Smm break; 753228753Smm } 754228753Smm } 755228753Smm skip = p - (const char *)h; 756228753Smm __archive_read_consume(a, skip); 757228753Smm skipped += skip; 758228753Smm } 759228753Smm} 760228753Smm 761228753Smmstatic int 762228753Smmheader_odc(struct archive_read *a, struct cpio *cpio, 763228753Smm struct archive_entry *entry, size_t *namelength, size_t *name_pad) 764228753Smm{ 765228753Smm const void *h; 766228753Smm int r; 767232153Smm const char *header; 768228753Smm 769228753Smm a->archive.archive_format = ARCHIVE_FORMAT_CPIO_POSIX; 770228753Smm a->archive.archive_format_name = "POSIX octet-oriented cpio"; 771228753Smm 772228753Smm /* Find the start of the next header. */ 773228753Smm r = find_odc_header(a); 774228753Smm if (r < ARCHIVE_WARN) 775228753Smm return (r); 776228753Smm 777232153Smm if (a->archive.archive_format == ARCHIVE_FORMAT_CPIO_AFIO_LARGE) { 778232153Smm int r2 = (header_afiol(a, cpio, entry, namelength, name_pad)); 779232153Smm if (r2 == ARCHIVE_OK) 780232153Smm return (r); 781232153Smm else 782232153Smm return (r2); 783232153Smm } 784232153Smm 785228753Smm /* Read fixed-size portion of header. */ 786232153Smm h = __archive_read_ahead(a, odc_header_size, NULL); 787228753Smm if (h == NULL) 788228753Smm return (ARCHIVE_FATAL); 789228753Smm 790228753Smm /* Parse out octal fields. */ 791232153Smm header = (const char *)h; 792228753Smm 793238856Smm archive_entry_set_dev(entry, 794238856Smm (dev_t)atol8(header + odc_dev_offset, odc_dev_size)); 795232153Smm archive_entry_set_ino(entry, atol8(header + odc_ino_offset, odc_ino_size)); 796238856Smm archive_entry_set_mode(entry, 797238856Smm (mode_t)atol8(header + odc_mode_offset, odc_mode_size)); 798232153Smm archive_entry_set_uid(entry, atol8(header + odc_uid_offset, odc_uid_size)); 799232153Smm archive_entry_set_gid(entry, atol8(header + odc_gid_offset, odc_gid_size)); 800238856Smm archive_entry_set_nlink(entry, 801238856Smm (unsigned int)atol8(header + odc_nlink_offset, odc_nlink_size)); 802238856Smm archive_entry_set_rdev(entry, 803238856Smm (dev_t)atol8(header + odc_rdev_offset, odc_rdev_size)); 804232153Smm archive_entry_set_mtime(entry, atol8(header + odc_mtime_offset, odc_mtime_size), 0); 805238856Smm *namelength = (size_t)atol8(header + odc_namesize_offset, odc_namesize_size); 806228753Smm *name_pad = 0; /* No padding of filename. */ 807228753Smm 808228753Smm /* 809228753Smm * Note: entry_bytes_remaining is at least 64 bits and 810228753Smm * therefore guaranteed to be big enough for a 33-bit file 811228753Smm * size. 812228753Smm */ 813228753Smm cpio->entry_bytes_remaining = 814232153Smm atol8(header + odc_filesize_offset, odc_filesize_size); 815228753Smm archive_entry_set_size(entry, cpio->entry_bytes_remaining); 816228753Smm cpio->entry_padding = 0; 817232153Smm __archive_read_consume(a, odc_header_size); 818228753Smm return (r); 819228753Smm} 820228753Smm 821232153Smm/* 822232153Smm * NOTE: if a filename suffix is ".z", it is the file gziped by afio. 823232153Smm * it would be nice that we can show uncompressed file size and we can 824232153Smm * uncompressed file contents automatically, unfortunately we have nothing 825311042Smm * to get a uncompressed file size while reading each header. It means 826311042Smm * we also cannot uncompress file contents under our framework. 827232153Smm */ 828228753Smmstatic int 829232153Smmheader_afiol(struct archive_read *a, struct cpio *cpio, 830232153Smm struct archive_entry *entry, size_t *namelength, size_t *name_pad) 831232153Smm{ 832232153Smm const void *h; 833232153Smm const char *header; 834232153Smm 835232153Smm a->archive.archive_format = ARCHIVE_FORMAT_CPIO_AFIO_LARGE; 836232153Smm a->archive.archive_format_name = "afio large ASCII"; 837232153Smm 838232153Smm /* Read fixed-size portion of header. */ 839232153Smm h = __archive_read_ahead(a, afiol_header_size, NULL); 840232153Smm if (h == NULL) 841232153Smm return (ARCHIVE_FATAL); 842232153Smm 843232153Smm /* Parse out octal fields. */ 844232153Smm header = (const char *)h; 845232153Smm 846238856Smm archive_entry_set_dev(entry, 847238856Smm (dev_t)atol16(header + afiol_dev_offset, afiol_dev_size)); 848232153Smm archive_entry_set_ino(entry, atol16(header + afiol_ino_offset, afiol_ino_size)); 849238856Smm archive_entry_set_mode(entry, 850238856Smm (mode_t)atol8(header + afiol_mode_offset, afiol_mode_size)); 851232153Smm archive_entry_set_uid(entry, atol16(header + afiol_uid_offset, afiol_uid_size)); 852232153Smm archive_entry_set_gid(entry, atol16(header + afiol_gid_offset, afiol_gid_size)); 853238856Smm archive_entry_set_nlink(entry, 854238856Smm (unsigned int)atol16(header + afiol_nlink_offset, afiol_nlink_size)); 855238856Smm archive_entry_set_rdev(entry, 856238856Smm (dev_t)atol16(header + afiol_rdev_offset, afiol_rdev_size)); 857232153Smm archive_entry_set_mtime(entry, atol16(header + afiol_mtime_offset, afiol_mtime_size), 0); 858238856Smm *namelength = (size_t)atol16(header + afiol_namesize_offset, afiol_namesize_size); 859232153Smm *name_pad = 0; /* No padding of filename. */ 860232153Smm 861232153Smm cpio->entry_bytes_remaining = 862232153Smm atol16(header + afiol_filesize_offset, afiol_filesize_size); 863232153Smm archive_entry_set_size(entry, cpio->entry_bytes_remaining); 864232153Smm cpio->entry_padding = 0; 865232153Smm __archive_read_consume(a, afiol_header_size); 866232153Smm return (ARCHIVE_OK); 867232153Smm} 868232153Smm 869232153Smm 870232153Smmstatic int 871228753Smmheader_bin_le(struct archive_read *a, struct cpio *cpio, 872228753Smm struct archive_entry *entry, size_t *namelength, size_t *name_pad) 873228753Smm{ 874228753Smm const void *h; 875232153Smm const unsigned char *header; 876228753Smm 877228753Smm a->archive.archive_format = ARCHIVE_FORMAT_CPIO_BIN_LE; 878228753Smm a->archive.archive_format_name = "cpio (little-endian binary)"; 879228753Smm 880228753Smm /* Read fixed-size portion of header. */ 881232153Smm h = __archive_read_ahead(a, bin_header_size, NULL); 882283259Sdelphij if (h == NULL) { 883283259Sdelphij archive_set_error(&a->archive, 0, 884283259Sdelphij "End of file trying to read next cpio header"); 885228753Smm return (ARCHIVE_FATAL); 886283259Sdelphij } 887228753Smm 888228753Smm /* Parse out binary fields. */ 889232153Smm header = (const unsigned char *)h; 890228753Smm 891232153Smm archive_entry_set_dev(entry, header[bin_dev_offset] + header[bin_dev_offset + 1] * 256); 892232153Smm archive_entry_set_ino(entry, header[bin_ino_offset] + header[bin_ino_offset + 1] * 256); 893232153Smm archive_entry_set_mode(entry, header[bin_mode_offset] + header[bin_mode_offset + 1] * 256); 894232153Smm archive_entry_set_uid(entry, header[bin_uid_offset] + header[bin_uid_offset + 1] * 256); 895232153Smm archive_entry_set_gid(entry, header[bin_gid_offset] + header[bin_gid_offset + 1] * 256); 896232153Smm archive_entry_set_nlink(entry, header[bin_nlink_offset] + header[bin_nlink_offset + 1] * 256); 897232153Smm archive_entry_set_rdev(entry, header[bin_rdev_offset] + header[bin_rdev_offset + 1] * 256); 898232153Smm archive_entry_set_mtime(entry, le4(header + bin_mtime_offset), 0); 899232153Smm *namelength = header[bin_namesize_offset] + header[bin_namesize_offset + 1] * 256; 900228753Smm *name_pad = *namelength & 1; /* Pad to even. */ 901228753Smm 902232153Smm cpio->entry_bytes_remaining = le4(header + bin_filesize_offset); 903228753Smm archive_entry_set_size(entry, cpio->entry_bytes_remaining); 904228753Smm cpio->entry_padding = cpio->entry_bytes_remaining & 1; /* Pad to even. */ 905232153Smm __archive_read_consume(a, bin_header_size); 906228753Smm return (ARCHIVE_OK); 907228753Smm} 908228753Smm 909228753Smmstatic int 910228753Smmheader_bin_be(struct archive_read *a, struct cpio *cpio, 911228753Smm struct archive_entry *entry, size_t *namelength, size_t *name_pad) 912228753Smm{ 913228753Smm const void *h; 914232153Smm const unsigned char *header; 915228753Smm 916228753Smm a->archive.archive_format = ARCHIVE_FORMAT_CPIO_BIN_BE; 917228753Smm a->archive.archive_format_name = "cpio (big-endian binary)"; 918228753Smm 919228753Smm /* Read fixed-size portion of header. */ 920232153Smm h = __archive_read_ahead(a, bin_header_size, NULL); 921283259Sdelphij if (h == NULL) { 922283259Sdelphij archive_set_error(&a->archive, 0, 923283259Sdelphij "End of file trying to read next cpio header"); 924228753Smm return (ARCHIVE_FATAL); 925283259Sdelphij } 926228753Smm 927228753Smm /* Parse out binary fields. */ 928232153Smm header = (const unsigned char *)h; 929232153Smm 930232153Smm archive_entry_set_dev(entry, header[bin_dev_offset] * 256 + header[bin_dev_offset + 1]); 931232153Smm archive_entry_set_ino(entry, header[bin_ino_offset] * 256 + header[bin_ino_offset + 1]); 932232153Smm archive_entry_set_mode(entry, header[bin_mode_offset] * 256 + header[bin_mode_offset + 1]); 933232153Smm archive_entry_set_uid(entry, header[bin_uid_offset] * 256 + header[bin_uid_offset + 1]); 934232153Smm archive_entry_set_gid(entry, header[bin_gid_offset] * 256 + header[bin_gid_offset + 1]); 935232153Smm archive_entry_set_nlink(entry, header[bin_nlink_offset] * 256 + header[bin_nlink_offset + 1]); 936232153Smm archive_entry_set_rdev(entry, header[bin_rdev_offset] * 256 + header[bin_rdev_offset + 1]); 937232153Smm archive_entry_set_mtime(entry, be4(header + bin_mtime_offset), 0); 938232153Smm *namelength = header[bin_namesize_offset] * 256 + header[bin_namesize_offset + 1]; 939228753Smm *name_pad = *namelength & 1; /* Pad to even. */ 940228753Smm 941232153Smm cpio->entry_bytes_remaining = be4(header + bin_filesize_offset); 942228753Smm archive_entry_set_size(entry, cpio->entry_bytes_remaining); 943228753Smm cpio->entry_padding = cpio->entry_bytes_remaining & 1; /* Pad to even. */ 944232153Smm __archive_read_consume(a, bin_header_size); 945228753Smm return (ARCHIVE_OK); 946228753Smm} 947228753Smm 948228753Smmstatic int 949228753Smmarchive_read_format_cpio_cleanup(struct archive_read *a) 950228753Smm{ 951228753Smm struct cpio *cpio; 952228753Smm 953228753Smm cpio = (struct cpio *)(a->format->data); 954228753Smm /* Free inode->name map */ 955228753Smm while (cpio->links_head != NULL) { 956228753Smm struct links_entry *lp = cpio->links_head->next; 957228753Smm 958344674Smm free(cpio->links_head->name); 959228753Smm free(cpio->links_head); 960228753Smm cpio->links_head = lp; 961228753Smm } 962228753Smm free(cpio); 963228753Smm (a->format->data) = NULL; 964228753Smm return (ARCHIVE_OK); 965228753Smm} 966228753Smm 967283259Sdelphijstatic int64_t 968228753Smmle4(const unsigned char *p) 969228753Smm{ 970283259Sdelphij return ((p[0] << 16) + (((int64_t)p[1]) << 24) + (p[2] << 0) + (p[3] << 8)); 971228753Smm} 972228753Smm 973228753Smm 974283259Sdelphijstatic int64_t 975228753Smmbe4(const unsigned char *p) 976228753Smm{ 977283259Sdelphij return ((((int64_t)p[0]) << 24) + (p[1] << 16) + (p[2] << 8) + (p[3])); 978228753Smm} 979228753Smm 980228753Smm/* 981228753Smm * Note that this implementation does not (and should not!) obey 982228753Smm * locale settings; you cannot simply substitute strtol here, since 983228753Smm * it does obey locale. 984228753Smm */ 985228753Smmstatic int64_t 986228753Smmatol8(const char *p, unsigned char_cnt) 987228753Smm{ 988228753Smm int64_t l; 989228753Smm int digit; 990228753Smm 991228753Smm l = 0; 992228753Smm while (char_cnt-- > 0) { 993228753Smm if (*p >= '0' && *p <= '7') 994228753Smm digit = *p - '0'; 995228753Smm else 996228753Smm return (l); 997228753Smm p++; 998228753Smm l <<= 3; 999228753Smm l |= digit; 1000228753Smm } 1001228753Smm return (l); 1002228753Smm} 1003228753Smm 1004228753Smmstatic int64_t 1005228753Smmatol16(const char *p, unsigned char_cnt) 1006228753Smm{ 1007228753Smm int64_t l; 1008228753Smm int digit; 1009228753Smm 1010228753Smm l = 0; 1011228753Smm while (char_cnt-- > 0) { 1012228753Smm if (*p >= 'a' && *p <= 'f') 1013228753Smm digit = *p - 'a' + 10; 1014228753Smm else if (*p >= 'A' && *p <= 'F') 1015228753Smm digit = *p - 'A' + 10; 1016228753Smm else if (*p >= '0' && *p <= '9') 1017228753Smm digit = *p - '0'; 1018228753Smm else 1019228753Smm return (l); 1020228753Smm p++; 1021228753Smm l <<= 4; 1022228753Smm l |= digit; 1023228753Smm } 1024228753Smm return (l); 1025228753Smm} 1026228753Smm 1027232153Smmstatic int 1028232153Smmrecord_hardlink(struct archive_read *a, 1029232153Smm struct cpio *cpio, struct archive_entry *entry) 1030228753Smm{ 1031228753Smm struct links_entry *le; 1032228753Smm dev_t dev; 1033228753Smm int64_t ino; 1034228753Smm 1035228753Smm if (archive_entry_nlink(entry) <= 1) 1036232153Smm return (ARCHIVE_OK); 1037228753Smm 1038228753Smm dev = archive_entry_dev(entry); 1039228753Smm ino = archive_entry_ino64(entry); 1040228753Smm 1041228753Smm /* 1042228753Smm * First look in the list of multiply-linked files. If we've 1043228753Smm * already dumped it, convert this entry to a hard link entry. 1044228753Smm */ 1045228753Smm for (le = cpio->links_head; le; le = le->next) { 1046228753Smm if (le->dev == dev && le->ino == ino) { 1047228753Smm archive_entry_copy_hardlink(entry, le->name); 1048228753Smm 1049228753Smm if (--le->links <= 0) { 1050228753Smm if (le->previous != NULL) 1051228753Smm le->previous->next = le->next; 1052228753Smm if (le->next != NULL) 1053228753Smm le->next->previous = le->previous; 1054228753Smm if (cpio->links_head == le) 1055228753Smm cpio->links_head = le->next; 1056228753Smm free(le->name); 1057228753Smm free(le); 1058228753Smm } 1059228753Smm 1060232153Smm return (ARCHIVE_OK); 1061228753Smm } 1062228753Smm } 1063228753Smm 1064228753Smm le = (struct links_entry *)malloc(sizeof(struct links_entry)); 1065232153Smm if (le == NULL) { 1066232153Smm archive_set_error(&a->archive, 1067232153Smm ENOMEM, "Out of memory adding file to list"); 1068232153Smm return (ARCHIVE_FATAL); 1069232153Smm } 1070228753Smm if (cpio->links_head != NULL) 1071228753Smm cpio->links_head->previous = le; 1072228753Smm le->next = cpio->links_head; 1073228753Smm le->previous = NULL; 1074228753Smm cpio->links_head = le; 1075228753Smm le->dev = dev; 1076228753Smm le->ino = ino; 1077228753Smm le->links = archive_entry_nlink(entry) - 1; 1078228753Smm le->name = strdup(archive_entry_pathname(entry)); 1079232153Smm if (le->name == NULL) { 1080232153Smm archive_set_error(&a->archive, 1081232153Smm ENOMEM, "Out of memory adding file to list"); 1082232153Smm return (ARCHIVE_FATAL); 1083232153Smm } 1084232153Smm 1085232153Smm return (ARCHIVE_OK); 1086228753Smm} 1087