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: releng/10.3/contrib/libarchive/libarchive/archive_read_support_format_cpio.c 283259 2015-05-21 19:05:47Z delphij $"); 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; 168228753Smm 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, 246228753Smm archive_read_format_cpio_cleanup); 247228753Smm 248228753Smm if (r != ARCHIVE_OK) 249228753Smm free(cpio); 250228753Smm return (ARCHIVE_OK); 251228753Smm} 252228753Smm 253228753Smm 254228753Smmstatic int 255232153Smmarchive_read_format_cpio_bid(struct archive_read *a, int best_bid) 256228753Smm{ 257228753Smm const unsigned char *p; 258228753Smm struct cpio *cpio; 259228753Smm int bid; 260228753Smm 261232153Smm (void)best_bid; /* UNUSED */ 262232153Smm 263228753Smm cpio = (struct cpio *)(a->format->data); 264228753Smm 265232153Smm if ((p = __archive_read_ahead(a, 6, NULL)) == NULL) 266228753Smm return (-1); 267228753Smm 268228753Smm bid = 0; 269228753Smm if (memcmp(p, "070707", 6) == 0) { 270228753Smm /* ASCII cpio archive (odc, POSIX.1) */ 271228753Smm cpio->read_header = header_odc; 272228753Smm bid += 48; 273228753Smm /* 274228753Smm * XXX TODO: More verification; Could check that only octal 275228753Smm * digits appear in appropriate header locations. XXX 276228753Smm */ 277232153Smm } else if (memcmp(p, "070727", 6) == 0) { 278232153Smm /* afio large ASCII cpio archive */ 279232153Smm cpio->read_header = header_odc; 280232153Smm bid += 48; 281232153Smm /* 282232153Smm * XXX TODO: More verification; Could check that almost hex 283232153Smm * digits appear in appropriate header locations. XXX 284232153Smm */ 285228753Smm } else if (memcmp(p, "070701", 6) == 0) { 286228753Smm /* ASCII cpio archive (SVR4 without CRC) */ 287228753Smm cpio->read_header = header_newc; 288228753Smm bid += 48; 289228753Smm /* 290228753Smm * XXX TODO: More verification; Could check that only hex 291228753Smm * digits appear in appropriate header locations. XXX 292228753Smm */ 293228753Smm } else if (memcmp(p, "070702", 6) == 0) { 294228753Smm /* ASCII cpio archive (SVR4 with CRC) */ 295228753Smm /* XXX TODO: Flag that we should check the CRC. XXX */ 296228753Smm cpio->read_header = header_newc; 297228753Smm bid += 48; 298228753Smm /* 299228753Smm * XXX TODO: More verification; Could check that only hex 300228753Smm * digits appear in appropriate header locations. XXX 301228753Smm */ 302228753Smm } else if (p[0] * 256 + p[1] == 070707) { 303228753Smm /* big-endian binary cpio archives */ 304228753Smm cpio->read_header = header_bin_be; 305228753Smm bid += 16; 306228753Smm /* Is more verification possible here? */ 307228753Smm } else if (p[0] + p[1] * 256 == 070707) { 308228753Smm /* little-endian binary cpio archives */ 309228753Smm cpio->read_header = header_bin_le; 310228753Smm bid += 16; 311228753Smm /* Is more verification possible here? */ 312228753Smm } else 313228753Smm return (ARCHIVE_WARN); 314228753Smm 315228753Smm return (bid); 316228753Smm} 317228753Smm 318228753Smmstatic int 319232153Smmarchive_read_format_cpio_options(struct archive_read *a, 320232153Smm const char *key, const char *val) 321232153Smm{ 322232153Smm struct cpio *cpio; 323232153Smm int ret = ARCHIVE_FAILED; 324232153Smm 325232153Smm cpio = (struct cpio *)(a->format->data); 326232153Smm if (strcmp(key, "compat-2x") == 0) { 327232153Smm /* Handle filnames as libarchive 2.x */ 328232153Smm cpio->init_default_conversion = (val != NULL)?1:0; 329232153Smm return (ARCHIVE_OK); 330232153Smm } else if (strcmp(key, "hdrcharset") == 0) { 331232153Smm if (val == NULL || val[0] == 0) 332232153Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 333232153Smm "cpio: hdrcharset option needs a character-set name"); 334232153Smm else { 335232153Smm cpio->opt_sconv = 336232153Smm archive_string_conversion_from_charset( 337232153Smm &a->archive, val, 0); 338232153Smm if (cpio->opt_sconv != NULL) 339232153Smm ret = ARCHIVE_OK; 340232153Smm else 341232153Smm ret = ARCHIVE_FATAL; 342232153Smm } 343232153Smm return (ret); 344232153Smm } 345232153Smm 346232153Smm /* Note: The "warn" return is just to inform the options 347232153Smm * supervisor that we didn't handle it. It will generate 348232153Smm * a suitable error if no one used this option. */ 349232153Smm return (ARCHIVE_WARN); 350232153Smm} 351232153Smm 352232153Smmstatic int 353228753Smmarchive_read_format_cpio_read_header(struct archive_read *a, 354228753Smm struct archive_entry *entry) 355228753Smm{ 356228753Smm struct cpio *cpio; 357228753Smm const void *h; 358232153Smm struct archive_string_conv *sconv; 359228753Smm size_t namelength; 360228753Smm size_t name_pad; 361228753Smm int r; 362228753Smm 363228753Smm cpio = (struct cpio *)(a->format->data); 364232153Smm sconv = cpio->opt_sconv; 365232153Smm if (sconv == NULL) { 366232153Smm if (!cpio->init_default_conversion) { 367232153Smm cpio->sconv_default = 368232153Smm archive_string_default_conversion_for_read( 369232153Smm &(a->archive)); 370232153Smm cpio->init_default_conversion = 1; 371232153Smm } 372232153Smm sconv = cpio->sconv_default; 373232153Smm } 374232153Smm 375228753Smm r = (cpio->read_header(a, cpio, entry, &namelength, &name_pad)); 376228753Smm 377228753Smm if (r < ARCHIVE_WARN) 378228753Smm return (r); 379228753Smm 380228753Smm /* Read name from buffer. */ 381228753Smm h = __archive_read_ahead(a, namelength + name_pad, NULL); 382228753Smm if (h == NULL) 383228753Smm return (ARCHIVE_FATAL); 384232153Smm if (archive_entry_copy_pathname_l(entry, 385232153Smm (const char *)h, namelength, sconv) != 0) { 386232153Smm if (errno == ENOMEM) { 387232153Smm archive_set_error(&a->archive, ENOMEM, 388232153Smm "Can't allocate memory for Pathname"); 389232153Smm return (ARCHIVE_FATAL); 390232153Smm } 391232153Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 392232153Smm "Pathname can't be converted from %s to current locale.", 393232153Smm archive_string_conversion_charset_name(sconv)); 394232153Smm r = ARCHIVE_WARN; 395232153Smm } 396228753Smm cpio->entry_offset = 0; 397228753Smm 398232153Smm __archive_read_consume(a, namelength + name_pad); 399232153Smm 400228753Smm /* If this is a symlink, read the link contents. */ 401228753Smm if (archive_entry_filetype(entry) == AE_IFLNK) { 402238856Smm h = __archive_read_ahead(a, 403238856Smm (size_t)cpio->entry_bytes_remaining, NULL); 404228753Smm if (h == NULL) 405228753Smm return (ARCHIVE_FATAL); 406232153Smm if (archive_entry_copy_symlink_l(entry, (const char *)h, 407238856Smm (size_t)cpio->entry_bytes_remaining, sconv) != 0) { 408232153Smm if (errno == ENOMEM) { 409232153Smm archive_set_error(&a->archive, ENOMEM, 410232153Smm "Can't allocate memory for Linkname"); 411232153Smm return (ARCHIVE_FATAL); 412232153Smm } 413232153Smm archive_set_error(&a->archive, 414232153Smm ARCHIVE_ERRNO_FILE_FORMAT, 415232153Smm "Linkname can't be converted from %s to " 416232153Smm "current locale.", 417232153Smm archive_string_conversion_charset_name(sconv)); 418232153Smm r = ARCHIVE_WARN; 419232153Smm } 420228753Smm __archive_read_consume(a, cpio->entry_bytes_remaining); 421228753Smm cpio->entry_bytes_remaining = 0; 422228753Smm } 423228753Smm 424228753Smm /* XXX TODO: If the full mode is 0160200, then this is a Solaris 425228753Smm * ACL description for the following entry. Read this body 426228753Smm * and parse it as a Solaris-style ACL, then read the next 427228753Smm * header. XXX */ 428228753Smm 429228753Smm /* Compare name to "TRAILER!!!" to test for end-of-archive. */ 430228753Smm if (namelength == 11 && strcmp((const char *)h, "TRAILER!!!") == 0) { 431228753Smm /* TODO: Store file location of start of block. */ 432228753Smm archive_clear_error(&a->archive); 433228753Smm return (ARCHIVE_EOF); 434228753Smm } 435228753Smm 436228753Smm /* Detect and record hardlinks to previously-extracted entries. */ 437232153Smm if (record_hardlink(a, cpio, entry) != ARCHIVE_OK) { 438232153Smm return (ARCHIVE_FATAL); 439232153Smm } 440228753Smm 441228753Smm return (r); 442228753Smm} 443228753Smm 444228753Smmstatic int 445228753Smmarchive_read_format_cpio_read_data(struct archive_read *a, 446232153Smm const void **buff, size_t *size, int64_t *offset) 447228753Smm{ 448228753Smm ssize_t bytes_read; 449228753Smm struct cpio *cpio; 450228753Smm 451228753Smm cpio = (struct cpio *)(a->format->data); 452232153Smm 453232153Smm if (cpio->entry_bytes_unconsumed) { 454232153Smm __archive_read_consume(a, cpio->entry_bytes_unconsumed); 455232153Smm cpio->entry_bytes_unconsumed = 0; 456232153Smm } 457232153Smm 458228753Smm if (cpio->entry_bytes_remaining > 0) { 459228753Smm *buff = __archive_read_ahead(a, 1, &bytes_read); 460228753Smm if (bytes_read <= 0) 461228753Smm return (ARCHIVE_FATAL); 462228753Smm if (bytes_read > cpio->entry_bytes_remaining) 463238856Smm bytes_read = (ssize_t)cpio->entry_bytes_remaining; 464228753Smm *size = bytes_read; 465232153Smm cpio->entry_bytes_unconsumed = bytes_read; 466228753Smm *offset = cpio->entry_offset; 467228753Smm cpio->entry_offset += bytes_read; 468228753Smm cpio->entry_bytes_remaining -= bytes_read; 469228753Smm return (ARCHIVE_OK); 470228753Smm } else { 471232153Smm if (cpio->entry_padding != 472232153Smm __archive_read_consume(a, cpio->entry_padding)) { 473232153Smm return (ARCHIVE_FATAL); 474228753Smm } 475232153Smm cpio->entry_padding = 0; 476228753Smm *buff = NULL; 477228753Smm *size = 0; 478228753Smm *offset = cpio->entry_offset; 479228753Smm return (ARCHIVE_EOF); 480228753Smm } 481228753Smm} 482228753Smm 483232153Smmstatic int 484232153Smmarchive_read_format_cpio_skip(struct archive_read *a) 485232153Smm{ 486232153Smm struct cpio *cpio = (struct cpio *)(a->format->data); 487232153Smm int64_t to_skip = cpio->entry_bytes_remaining + cpio->entry_padding + 488232153Smm cpio->entry_bytes_unconsumed; 489232153Smm 490232153Smm if (to_skip != __archive_read_consume(a, to_skip)) { 491232153Smm return (ARCHIVE_FATAL); 492232153Smm } 493232153Smm cpio->entry_bytes_remaining = 0; 494232153Smm cpio->entry_padding = 0; 495232153Smm cpio->entry_bytes_unconsumed = 0; 496232153Smm return (ARCHIVE_OK); 497232153Smm} 498232153Smm 499228753Smm/* 500228753Smm * Skip forward to the next cpio newc header by searching for the 501228753Smm * 07070[12] string. This should be generalized and merged with 502228753Smm * find_odc_header below. 503228753Smm */ 504228753Smmstatic int 505228753Smmis_hex(const char *p, size_t len) 506228753Smm{ 507228753Smm while (len-- > 0) { 508228753Smm if ((*p >= '0' && *p <= '9') 509228753Smm || (*p >= 'a' && *p <= 'f') 510228753Smm || (*p >= 'A' && *p <= 'F')) 511228753Smm ++p; 512228753Smm else 513228753Smm return (0); 514228753Smm } 515228753Smm return (1); 516228753Smm} 517228753Smm 518228753Smmstatic int 519228753Smmfind_newc_header(struct archive_read *a) 520228753Smm{ 521228753Smm const void *h; 522228753Smm const char *p, *q; 523228753Smm size_t skip, skipped = 0; 524228753Smm ssize_t bytes; 525228753Smm 526228753Smm for (;;) { 527232153Smm h = __archive_read_ahead(a, newc_header_size, &bytes); 528228753Smm if (h == NULL) 529228753Smm return (ARCHIVE_FATAL); 530228753Smm p = h; 531228753Smm q = p + bytes; 532228753Smm 533228753Smm /* Try the typical case first, then go into the slow search.*/ 534228753Smm if (memcmp("07070", p, 5) == 0 535228753Smm && (p[5] == '1' || p[5] == '2') 536232153Smm && is_hex(p, newc_header_size)) 537228753Smm return (ARCHIVE_OK); 538228753Smm 539228753Smm /* 540228753Smm * Scan ahead until we find something that looks 541232153Smm * like a newc header. 542228753Smm */ 543232153Smm while (p + newc_header_size <= q) { 544228753Smm switch (p[5]) { 545228753Smm case '1': 546228753Smm case '2': 547228753Smm if (memcmp("07070", p, 5) == 0 548232153Smm && is_hex(p, newc_header_size)) { 549228753Smm skip = p - (const char *)h; 550228753Smm __archive_read_consume(a, skip); 551228753Smm skipped += skip; 552228753Smm if (skipped > 0) { 553228753Smm archive_set_error(&a->archive, 554228753Smm 0, 555228753Smm "Skipped %d bytes before " 556228753Smm "finding valid header", 557228753Smm (int)skipped); 558228753Smm return (ARCHIVE_WARN); 559228753Smm } 560228753Smm return (ARCHIVE_OK); 561228753Smm } 562228753Smm p += 2; 563228753Smm break; 564228753Smm case '0': 565228753Smm p++; 566228753Smm break; 567228753Smm default: 568228753Smm p += 6; 569228753Smm break; 570228753Smm } 571228753Smm } 572228753Smm skip = p - (const char *)h; 573228753Smm __archive_read_consume(a, skip); 574228753Smm skipped += skip; 575228753Smm } 576228753Smm} 577228753Smm 578228753Smmstatic int 579228753Smmheader_newc(struct archive_read *a, struct cpio *cpio, 580228753Smm struct archive_entry *entry, size_t *namelength, size_t *name_pad) 581228753Smm{ 582228753Smm const void *h; 583232153Smm const char *header; 584228753Smm int r; 585228753Smm 586228753Smm r = find_newc_header(a); 587228753Smm if (r < ARCHIVE_WARN) 588228753Smm return (r); 589228753Smm 590228753Smm /* Read fixed-size portion of header. */ 591232153Smm h = __archive_read_ahead(a, newc_header_size, NULL); 592228753Smm if (h == NULL) 593228753Smm return (ARCHIVE_FATAL); 594228753Smm 595228753Smm /* Parse out hex fields. */ 596232153Smm header = (const char *)h; 597228753Smm 598232153Smm if (memcmp(header + newc_magic_offset, "070701", 6) == 0) { 599228753Smm a->archive.archive_format = ARCHIVE_FORMAT_CPIO_SVR4_NOCRC; 600228753Smm a->archive.archive_format_name = "ASCII cpio (SVR4 with no CRC)"; 601232153Smm } else if (memcmp(header + newc_magic_offset, "070702", 6) == 0) { 602228753Smm a->archive.archive_format = ARCHIVE_FORMAT_CPIO_SVR4_CRC; 603228753Smm a->archive.archive_format_name = "ASCII cpio (SVR4 with CRC)"; 604228753Smm } else { 605228753Smm /* TODO: Abort here? */ 606228753Smm } 607228753Smm 608238856Smm archive_entry_set_devmajor(entry, 609238856Smm (dev_t)atol16(header + newc_devmajor_offset, newc_devmajor_size)); 610238856Smm archive_entry_set_devminor(entry, 611238856Smm (dev_t)atol16(header + newc_devminor_offset, newc_devminor_size)); 612232153Smm archive_entry_set_ino(entry, atol16(header + newc_ino_offset, newc_ino_size)); 613238856Smm archive_entry_set_mode(entry, 614238856Smm (mode_t)atol16(header + newc_mode_offset, newc_mode_size)); 615232153Smm archive_entry_set_uid(entry, atol16(header + newc_uid_offset, newc_uid_size)); 616232153Smm archive_entry_set_gid(entry, atol16(header + newc_gid_offset, newc_gid_size)); 617238856Smm archive_entry_set_nlink(entry, 618238856Smm (unsigned int)atol16(header + newc_nlink_offset, newc_nlink_size)); 619238856Smm archive_entry_set_rdevmajor(entry, 620238856Smm (dev_t)atol16(header + newc_rdevmajor_offset, newc_rdevmajor_size)); 621238856Smm archive_entry_set_rdevminor(entry, 622238856Smm (dev_t)atol16(header + newc_rdevminor_offset, newc_rdevminor_size)); 623232153Smm archive_entry_set_mtime(entry, atol16(header + newc_mtime_offset, newc_mtime_size), 0); 624238856Smm *namelength = (size_t)atol16(header + newc_namesize_offset, newc_namesize_size); 625228753Smm /* Pad name to 2 more than a multiple of 4. */ 626228753Smm *name_pad = (2 - *namelength) & 3; 627228753Smm 628228753Smm /* 629228753Smm * Note: entry_bytes_remaining is at least 64 bits and 630228753Smm * therefore guaranteed to be big enough for a 33-bit file 631228753Smm * size. 632228753Smm */ 633228753Smm cpio->entry_bytes_remaining = 634232153Smm atol16(header + newc_filesize_offset, newc_filesize_size); 635228753Smm archive_entry_set_size(entry, cpio->entry_bytes_remaining); 636228753Smm /* Pad file contents to a multiple of 4. */ 637228753Smm cpio->entry_padding = 3 & -cpio->entry_bytes_remaining; 638232153Smm __archive_read_consume(a, newc_header_size); 639228753Smm return (r); 640228753Smm} 641228753Smm 642228753Smm/* 643228753Smm * Skip forward to the next cpio odc header by searching for the 644228753Smm * 070707 string. This is a hand-optimized search that could 645228753Smm * probably be easily generalized to handle all character-based 646228753Smm * cpio variants. 647228753Smm */ 648228753Smmstatic int 649228753Smmis_octal(const char *p, size_t len) 650228753Smm{ 651228753Smm while (len-- > 0) { 652228753Smm if (*p < '0' || *p > '7') 653228753Smm return (0); 654228753Smm ++p; 655228753Smm } 656228753Smm return (1); 657228753Smm} 658228753Smm 659228753Smmstatic int 660232153Smmis_afio_large(const char *h, size_t len) 661232153Smm{ 662232153Smm if (len < afiol_header_size) 663232153Smm return (0); 664232153Smm if (h[afiol_ino_m_offset] != 'm' 665232153Smm || h[afiol_mtime_n_offset] != 'n' 666232153Smm || h[afiol_xsize_s_offset] != 's' 667232153Smm || h[afiol_filesize_c_offset] != ':') 668232153Smm return (0); 669232153Smm if (!is_hex(h + afiol_dev_offset, afiol_ino_m_offset - afiol_dev_offset)) 670232153Smm return (0); 671232153Smm if (!is_hex(h + afiol_mode_offset, afiol_mtime_n_offset - afiol_mode_offset)) 672232153Smm return (0); 673232153Smm if (!is_hex(h + afiol_namesize_offset, afiol_xsize_s_offset - afiol_namesize_offset)) 674232153Smm return (0); 675232153Smm if (!is_hex(h + afiol_filesize_offset, afiol_filesize_size)) 676232153Smm return (0); 677232153Smm return (1); 678232153Smm} 679232153Smm 680232153Smmstatic int 681228753Smmfind_odc_header(struct archive_read *a) 682228753Smm{ 683228753Smm const void *h; 684228753Smm const char *p, *q; 685228753Smm size_t skip, skipped = 0; 686228753Smm ssize_t bytes; 687228753Smm 688228753Smm for (;;) { 689232153Smm h = __archive_read_ahead(a, odc_header_size, &bytes); 690228753Smm if (h == NULL) 691228753Smm return (ARCHIVE_FATAL); 692228753Smm p = h; 693228753Smm q = p + bytes; 694228753Smm 695228753Smm /* Try the typical case first, then go into the slow search.*/ 696232153Smm if (memcmp("070707", p, 6) == 0 && is_octal(p, odc_header_size)) 697228753Smm return (ARCHIVE_OK); 698232153Smm if (memcmp("070727", p, 6) == 0 && is_afio_large(p, bytes)) { 699232153Smm a->archive.archive_format = ARCHIVE_FORMAT_CPIO_AFIO_LARGE; 700232153Smm return (ARCHIVE_OK); 701232153Smm } 702228753Smm 703228753Smm /* 704228753Smm * Scan ahead until we find something that looks 705228753Smm * like an odc header. 706228753Smm */ 707232153Smm while (p + odc_header_size <= q) { 708228753Smm switch (p[5]) { 709228753Smm case '7': 710232153Smm if ((memcmp("070707", p, 6) == 0 711232153Smm && is_octal(p, odc_header_size)) 712232153Smm || (memcmp("070727", p, 6) == 0 713232153Smm && is_afio_large(p, q - p))) { 714228753Smm skip = p - (const char *)h; 715228753Smm __archive_read_consume(a, skip); 716228753Smm skipped += skip; 717232153Smm if (p[4] == '2') 718232153Smm a->archive.archive_format = 719232153Smm ARCHIVE_FORMAT_CPIO_AFIO_LARGE; 720228753Smm if (skipped > 0) { 721228753Smm archive_set_error(&a->archive, 722228753Smm 0, 723228753Smm "Skipped %d bytes before " 724228753Smm "finding valid header", 725228753Smm (int)skipped); 726228753Smm return (ARCHIVE_WARN); 727228753Smm } 728228753Smm return (ARCHIVE_OK); 729228753Smm } 730228753Smm p += 2; 731228753Smm break; 732228753Smm case '0': 733228753Smm p++; 734228753Smm break; 735228753Smm default: 736228753Smm p += 6; 737228753Smm break; 738228753Smm } 739228753Smm } 740228753Smm skip = p - (const char *)h; 741228753Smm __archive_read_consume(a, skip); 742228753Smm skipped += skip; 743228753Smm } 744228753Smm} 745228753Smm 746228753Smmstatic int 747228753Smmheader_odc(struct archive_read *a, struct cpio *cpio, 748228753Smm struct archive_entry *entry, size_t *namelength, size_t *name_pad) 749228753Smm{ 750228753Smm const void *h; 751228753Smm int r; 752232153Smm const char *header; 753228753Smm 754228753Smm a->archive.archive_format = ARCHIVE_FORMAT_CPIO_POSIX; 755228753Smm a->archive.archive_format_name = "POSIX octet-oriented cpio"; 756228753Smm 757228753Smm /* Find the start of the next header. */ 758228753Smm r = find_odc_header(a); 759228753Smm if (r < ARCHIVE_WARN) 760228753Smm return (r); 761228753Smm 762232153Smm if (a->archive.archive_format == ARCHIVE_FORMAT_CPIO_AFIO_LARGE) { 763232153Smm int r2 = (header_afiol(a, cpio, entry, namelength, name_pad)); 764232153Smm if (r2 == ARCHIVE_OK) 765232153Smm return (r); 766232153Smm else 767232153Smm return (r2); 768232153Smm } 769232153Smm 770228753Smm /* Read fixed-size portion of header. */ 771232153Smm h = __archive_read_ahead(a, odc_header_size, NULL); 772228753Smm if (h == NULL) 773228753Smm return (ARCHIVE_FATAL); 774228753Smm 775228753Smm /* Parse out octal fields. */ 776232153Smm header = (const char *)h; 777228753Smm 778238856Smm archive_entry_set_dev(entry, 779238856Smm (dev_t)atol8(header + odc_dev_offset, odc_dev_size)); 780232153Smm archive_entry_set_ino(entry, atol8(header + odc_ino_offset, odc_ino_size)); 781238856Smm archive_entry_set_mode(entry, 782238856Smm (mode_t)atol8(header + odc_mode_offset, odc_mode_size)); 783232153Smm archive_entry_set_uid(entry, atol8(header + odc_uid_offset, odc_uid_size)); 784232153Smm archive_entry_set_gid(entry, atol8(header + odc_gid_offset, odc_gid_size)); 785238856Smm archive_entry_set_nlink(entry, 786238856Smm (unsigned int)atol8(header + odc_nlink_offset, odc_nlink_size)); 787238856Smm archive_entry_set_rdev(entry, 788238856Smm (dev_t)atol8(header + odc_rdev_offset, odc_rdev_size)); 789232153Smm archive_entry_set_mtime(entry, atol8(header + odc_mtime_offset, odc_mtime_size), 0); 790238856Smm *namelength = (size_t)atol8(header + odc_namesize_offset, odc_namesize_size); 791228753Smm *name_pad = 0; /* No padding of filename. */ 792228753Smm 793228753Smm /* 794228753Smm * Note: entry_bytes_remaining is at least 64 bits and 795228753Smm * therefore guaranteed to be big enough for a 33-bit file 796228753Smm * size. 797228753Smm */ 798228753Smm cpio->entry_bytes_remaining = 799232153Smm atol8(header + odc_filesize_offset, odc_filesize_size); 800228753Smm archive_entry_set_size(entry, cpio->entry_bytes_remaining); 801228753Smm cpio->entry_padding = 0; 802232153Smm __archive_read_consume(a, odc_header_size); 803228753Smm return (r); 804228753Smm} 805228753Smm 806232153Smm/* 807232153Smm * NOTE: if a filename suffix is ".z", it is the file gziped by afio. 808232153Smm * it would be nice that we can show uncompressed file size and we can 809232153Smm * uncompressed file contents automatically, unfortunately we have nothing 810232153Smm * to get a uncompressed file size while reading each header. it means 811232153Smm * we also cannot uncompressed file contens under the our framework. 812232153Smm */ 813228753Smmstatic int 814232153Smmheader_afiol(struct archive_read *a, struct cpio *cpio, 815232153Smm struct archive_entry *entry, size_t *namelength, size_t *name_pad) 816232153Smm{ 817232153Smm const void *h; 818232153Smm const char *header; 819232153Smm 820232153Smm a->archive.archive_format = ARCHIVE_FORMAT_CPIO_AFIO_LARGE; 821232153Smm a->archive.archive_format_name = "afio large ASCII"; 822232153Smm 823232153Smm /* Read fixed-size portion of header. */ 824232153Smm h = __archive_read_ahead(a, afiol_header_size, NULL); 825232153Smm if (h == NULL) 826232153Smm return (ARCHIVE_FATAL); 827232153Smm 828232153Smm /* Parse out octal fields. */ 829232153Smm header = (const char *)h; 830232153Smm 831238856Smm archive_entry_set_dev(entry, 832238856Smm (dev_t)atol16(header + afiol_dev_offset, afiol_dev_size)); 833232153Smm archive_entry_set_ino(entry, atol16(header + afiol_ino_offset, afiol_ino_size)); 834238856Smm archive_entry_set_mode(entry, 835238856Smm (mode_t)atol8(header + afiol_mode_offset, afiol_mode_size)); 836232153Smm archive_entry_set_uid(entry, atol16(header + afiol_uid_offset, afiol_uid_size)); 837232153Smm archive_entry_set_gid(entry, atol16(header + afiol_gid_offset, afiol_gid_size)); 838238856Smm archive_entry_set_nlink(entry, 839238856Smm (unsigned int)atol16(header + afiol_nlink_offset, afiol_nlink_size)); 840238856Smm archive_entry_set_rdev(entry, 841238856Smm (dev_t)atol16(header + afiol_rdev_offset, afiol_rdev_size)); 842232153Smm archive_entry_set_mtime(entry, atol16(header + afiol_mtime_offset, afiol_mtime_size), 0); 843238856Smm *namelength = (size_t)atol16(header + afiol_namesize_offset, afiol_namesize_size); 844232153Smm *name_pad = 0; /* No padding of filename. */ 845232153Smm 846232153Smm cpio->entry_bytes_remaining = 847232153Smm atol16(header + afiol_filesize_offset, afiol_filesize_size); 848232153Smm archive_entry_set_size(entry, cpio->entry_bytes_remaining); 849232153Smm cpio->entry_padding = 0; 850232153Smm __archive_read_consume(a, afiol_header_size); 851232153Smm return (ARCHIVE_OK); 852232153Smm} 853232153Smm 854232153Smm 855232153Smmstatic int 856228753Smmheader_bin_le(struct archive_read *a, struct cpio *cpio, 857228753Smm struct archive_entry *entry, size_t *namelength, size_t *name_pad) 858228753Smm{ 859228753Smm const void *h; 860232153Smm const unsigned char *header; 861228753Smm 862228753Smm a->archive.archive_format = ARCHIVE_FORMAT_CPIO_BIN_LE; 863228753Smm a->archive.archive_format_name = "cpio (little-endian binary)"; 864228753Smm 865228753Smm /* Read fixed-size portion of header. */ 866232153Smm h = __archive_read_ahead(a, bin_header_size, NULL); 867283259Sdelphij if (h == NULL) { 868283259Sdelphij archive_set_error(&a->archive, 0, 869283259Sdelphij "End of file trying to read next cpio header"); 870228753Smm return (ARCHIVE_FATAL); 871283259Sdelphij } 872228753Smm 873228753Smm /* Parse out binary fields. */ 874232153Smm header = (const unsigned char *)h; 875228753Smm 876232153Smm archive_entry_set_dev(entry, header[bin_dev_offset] + header[bin_dev_offset + 1] * 256); 877232153Smm archive_entry_set_ino(entry, header[bin_ino_offset] + header[bin_ino_offset + 1] * 256); 878232153Smm archive_entry_set_mode(entry, header[bin_mode_offset] + header[bin_mode_offset + 1] * 256); 879232153Smm archive_entry_set_uid(entry, header[bin_uid_offset] + header[bin_uid_offset + 1] * 256); 880232153Smm archive_entry_set_gid(entry, header[bin_gid_offset] + header[bin_gid_offset + 1] * 256); 881232153Smm archive_entry_set_nlink(entry, header[bin_nlink_offset] + header[bin_nlink_offset + 1] * 256); 882232153Smm archive_entry_set_rdev(entry, header[bin_rdev_offset] + header[bin_rdev_offset + 1] * 256); 883232153Smm archive_entry_set_mtime(entry, le4(header + bin_mtime_offset), 0); 884232153Smm *namelength = header[bin_namesize_offset] + header[bin_namesize_offset + 1] * 256; 885228753Smm *name_pad = *namelength & 1; /* Pad to even. */ 886228753Smm 887232153Smm cpio->entry_bytes_remaining = le4(header + bin_filesize_offset); 888228753Smm archive_entry_set_size(entry, cpio->entry_bytes_remaining); 889228753Smm cpio->entry_padding = cpio->entry_bytes_remaining & 1; /* Pad to even. */ 890232153Smm __archive_read_consume(a, bin_header_size); 891228753Smm return (ARCHIVE_OK); 892228753Smm} 893228753Smm 894228753Smmstatic int 895228753Smmheader_bin_be(struct archive_read *a, struct cpio *cpio, 896228753Smm struct archive_entry *entry, size_t *namelength, size_t *name_pad) 897228753Smm{ 898228753Smm const void *h; 899232153Smm const unsigned char *header; 900228753Smm 901228753Smm a->archive.archive_format = ARCHIVE_FORMAT_CPIO_BIN_BE; 902228753Smm a->archive.archive_format_name = "cpio (big-endian binary)"; 903228753Smm 904228753Smm /* Read fixed-size portion of header. */ 905232153Smm h = __archive_read_ahead(a, bin_header_size, NULL); 906283259Sdelphij if (h == NULL) { 907283259Sdelphij archive_set_error(&a->archive, 0, 908283259Sdelphij "End of file trying to read next cpio header"); 909228753Smm return (ARCHIVE_FATAL); 910283259Sdelphij } 911228753Smm 912228753Smm /* Parse out binary fields. */ 913232153Smm header = (const unsigned char *)h; 914232153Smm 915232153Smm archive_entry_set_dev(entry, header[bin_dev_offset] * 256 + header[bin_dev_offset + 1]); 916232153Smm archive_entry_set_ino(entry, header[bin_ino_offset] * 256 + header[bin_ino_offset + 1]); 917232153Smm archive_entry_set_mode(entry, header[bin_mode_offset] * 256 + header[bin_mode_offset + 1]); 918232153Smm archive_entry_set_uid(entry, header[bin_uid_offset] * 256 + header[bin_uid_offset + 1]); 919232153Smm archive_entry_set_gid(entry, header[bin_gid_offset] * 256 + header[bin_gid_offset + 1]); 920232153Smm archive_entry_set_nlink(entry, header[bin_nlink_offset] * 256 + header[bin_nlink_offset + 1]); 921232153Smm archive_entry_set_rdev(entry, header[bin_rdev_offset] * 256 + header[bin_rdev_offset + 1]); 922232153Smm archive_entry_set_mtime(entry, be4(header + bin_mtime_offset), 0); 923232153Smm *namelength = header[bin_namesize_offset] * 256 + header[bin_namesize_offset + 1]; 924228753Smm *name_pad = *namelength & 1; /* Pad to even. */ 925228753Smm 926232153Smm cpio->entry_bytes_remaining = be4(header + bin_filesize_offset); 927228753Smm archive_entry_set_size(entry, cpio->entry_bytes_remaining); 928228753Smm cpio->entry_padding = cpio->entry_bytes_remaining & 1; /* Pad to even. */ 929232153Smm __archive_read_consume(a, bin_header_size); 930228753Smm return (ARCHIVE_OK); 931228753Smm} 932228753Smm 933228753Smmstatic int 934228753Smmarchive_read_format_cpio_cleanup(struct archive_read *a) 935228753Smm{ 936228753Smm struct cpio *cpio; 937228753Smm 938228753Smm cpio = (struct cpio *)(a->format->data); 939228753Smm /* Free inode->name map */ 940228753Smm while (cpio->links_head != NULL) { 941228753Smm struct links_entry *lp = cpio->links_head->next; 942228753Smm 943228753Smm if (cpio->links_head->name) 944228753Smm free(cpio->links_head->name); 945228753Smm free(cpio->links_head); 946228753Smm cpio->links_head = lp; 947228753Smm } 948228753Smm free(cpio); 949228753Smm (a->format->data) = NULL; 950228753Smm return (ARCHIVE_OK); 951228753Smm} 952228753Smm 953283259Sdelphijstatic int64_t 954228753Smmle4(const unsigned char *p) 955228753Smm{ 956283259Sdelphij return ((p[0] << 16) + (((int64_t)p[1]) << 24) + (p[2] << 0) + (p[3] << 8)); 957228753Smm} 958228753Smm 959228753Smm 960283259Sdelphijstatic int64_t 961228753Smmbe4(const unsigned char *p) 962228753Smm{ 963283259Sdelphij return ((((int64_t)p[0]) << 24) + (p[1] << 16) + (p[2] << 8) + (p[3])); 964228753Smm} 965228753Smm 966228753Smm/* 967228753Smm * Note that this implementation does not (and should not!) obey 968228753Smm * locale settings; you cannot simply substitute strtol here, since 969228753Smm * it does obey locale. 970228753Smm */ 971228753Smmstatic int64_t 972228753Smmatol8(const char *p, unsigned char_cnt) 973228753Smm{ 974228753Smm int64_t l; 975228753Smm int digit; 976228753Smm 977228753Smm l = 0; 978228753Smm while (char_cnt-- > 0) { 979228753Smm if (*p >= '0' && *p <= '7') 980228753Smm digit = *p - '0'; 981228753Smm else 982228753Smm return (l); 983228753Smm p++; 984228753Smm l <<= 3; 985228753Smm l |= digit; 986228753Smm } 987228753Smm return (l); 988228753Smm} 989228753Smm 990228753Smmstatic int64_t 991228753Smmatol16(const char *p, unsigned char_cnt) 992228753Smm{ 993228753Smm int64_t l; 994228753Smm int digit; 995228753Smm 996228753Smm l = 0; 997228753Smm while (char_cnt-- > 0) { 998228753Smm if (*p >= 'a' && *p <= 'f') 999228753Smm digit = *p - 'a' + 10; 1000228753Smm else if (*p >= 'A' && *p <= 'F') 1001228753Smm digit = *p - 'A' + 10; 1002228753Smm else if (*p >= '0' && *p <= '9') 1003228753Smm digit = *p - '0'; 1004228753Smm else 1005228753Smm return (l); 1006228753Smm p++; 1007228753Smm l <<= 4; 1008228753Smm l |= digit; 1009228753Smm } 1010228753Smm return (l); 1011228753Smm} 1012228753Smm 1013232153Smmstatic int 1014232153Smmrecord_hardlink(struct archive_read *a, 1015232153Smm struct cpio *cpio, struct archive_entry *entry) 1016228753Smm{ 1017228753Smm struct links_entry *le; 1018228753Smm dev_t dev; 1019228753Smm int64_t ino; 1020228753Smm 1021228753Smm if (archive_entry_nlink(entry) <= 1) 1022232153Smm return (ARCHIVE_OK); 1023228753Smm 1024228753Smm dev = archive_entry_dev(entry); 1025228753Smm ino = archive_entry_ino64(entry); 1026228753Smm 1027228753Smm /* 1028228753Smm * First look in the list of multiply-linked files. If we've 1029228753Smm * already dumped it, convert this entry to a hard link entry. 1030228753Smm */ 1031228753Smm for (le = cpio->links_head; le; le = le->next) { 1032228753Smm if (le->dev == dev && le->ino == ino) { 1033228753Smm archive_entry_copy_hardlink(entry, le->name); 1034228753Smm 1035228753Smm if (--le->links <= 0) { 1036228753Smm if (le->previous != NULL) 1037228753Smm le->previous->next = le->next; 1038228753Smm if (le->next != NULL) 1039228753Smm le->next->previous = le->previous; 1040228753Smm if (cpio->links_head == le) 1041228753Smm cpio->links_head = le->next; 1042228753Smm free(le->name); 1043228753Smm free(le); 1044228753Smm } 1045228753Smm 1046232153Smm return (ARCHIVE_OK); 1047228753Smm } 1048228753Smm } 1049228753Smm 1050228753Smm le = (struct links_entry *)malloc(sizeof(struct links_entry)); 1051232153Smm if (le == NULL) { 1052232153Smm archive_set_error(&a->archive, 1053232153Smm ENOMEM, "Out of memory adding file to list"); 1054232153Smm return (ARCHIVE_FATAL); 1055232153Smm } 1056228753Smm if (cpio->links_head != NULL) 1057228753Smm cpio->links_head->previous = le; 1058228753Smm le->next = cpio->links_head; 1059228753Smm le->previous = NULL; 1060228753Smm cpio->links_head = le; 1061228753Smm le->dev = dev; 1062228753Smm le->ino = ino; 1063228753Smm le->links = archive_entry_nlink(entry) - 1; 1064228753Smm le->name = strdup(archive_entry_pathname(entry)); 1065232153Smm if (le->name == NULL) { 1066232153Smm archive_set_error(&a->archive, 1067232153Smm ENOMEM, "Out of memory adding file to list"); 1068232153Smm return (ARCHIVE_FATAL); 1069232153Smm } 1070232153Smm 1071232153Smm return (ARCHIVE_OK); 1072228753Smm} 1073