1228753Smm/*- 2228753Smm * Copyright (c) 2003-2007 Tim Kientzle 3228753Smm * All rights reserved. 4228753Smm * 5228753Smm * Redistribution and use in source and binary forms, with or without 6228753Smm * modification, are permitted provided that the following conditions 7228753Smm * are met: 8228753Smm * 1. Redistributions of source code must retain the above copyright 9228753Smm * notice, this list of conditions and the following disclaimer. 10228753Smm * 2. Redistributions in binary form must reproduce the above copyright 11228753Smm * notice, this list of conditions and the following disclaimer in the 12228753Smm * documentation and/or other materials provided with the distribution. 13228753Smm * 14228753Smm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 15228753Smm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16228753Smm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17228753Smm * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 18228753Smm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19228753Smm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20228753Smm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21228753Smm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22228753Smm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23228753Smm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24228753Smm */ 25228753Smm 26228753Smm#include "archive_platform.h" 27229592Smm__FBSDID("$FreeBSD$"); 28228753Smm 29228753Smm#ifdef HAVE_ERRNO_H 30228753Smm#include <errno.h> 31228753Smm#endif 32228753Smm/* #include <stdint.h> */ /* See archive_platform.h */ 33228753Smm#ifdef HAVE_STDLIB_H 34228753Smm#include <stdlib.h> 35228753Smm#endif 36228753Smm#ifdef HAVE_STRING_H 37228753Smm#include <string.h> 38228753Smm#endif 39228753Smm 40228753Smm#include "archive.h" 41228753Smm#include "archive_entry.h" 42228753Smm#include "archive_private.h" 43228753Smm#include "archive_read_private.h" 44228753Smm 45229592Smm#ifdef _MSC_VER 46229592Smm#define __packed 47229592Smm#pragma pack(push, 1) 48229592Smm#endif 49228753Smmstruct cpio_bin_header { 50228753Smm unsigned char c_magic[2]; 51228753Smm unsigned char c_dev[2]; 52228753Smm unsigned char c_ino[2]; 53228753Smm unsigned char c_mode[2]; 54228753Smm unsigned char c_uid[2]; 55228753Smm unsigned char c_gid[2]; 56228753Smm unsigned char c_nlink[2]; 57228753Smm unsigned char c_rdev[2]; 58228753Smm unsigned char c_mtime[4]; 59228753Smm unsigned char c_namesize[2]; 60228753Smm unsigned char c_filesize[4]; 61229592Smm} __packed; 62228753Smm 63228753Smmstruct cpio_odc_header { 64228753Smm char c_magic[6]; 65228753Smm char c_dev[6]; 66228753Smm char c_ino[6]; 67228753Smm char c_mode[6]; 68228753Smm char c_uid[6]; 69228753Smm char c_gid[6]; 70228753Smm char c_nlink[6]; 71228753Smm char c_rdev[6]; 72228753Smm char c_mtime[11]; 73228753Smm char c_namesize[6]; 74228753Smm char c_filesize[11]; 75229592Smm} __packed; 76228753Smm 77228753Smmstruct cpio_newc_header { 78228753Smm char c_magic[6]; 79228753Smm char c_ino[8]; 80228753Smm char c_mode[8]; 81228753Smm char c_uid[8]; 82228753Smm char c_gid[8]; 83228753Smm char c_nlink[8]; 84228753Smm char c_mtime[8]; 85228753Smm char c_filesize[8]; 86228753Smm char c_devmajor[8]; 87228753Smm char c_devminor[8]; 88228753Smm char c_rdevmajor[8]; 89228753Smm char c_rdevminor[8]; 90228753Smm char c_namesize[8]; 91228753Smm char c_crc[8]; 92229592Smm} __packed; 93228753Smm 94229592Smm#ifdef _MSC_VER 95229592Smm#undef __packed 96229592Smm#pragma pack(pop) 97229592Smm#endif 98229592Smm 99228753Smmstruct links_entry { 100228753Smm struct links_entry *next; 101228753Smm struct links_entry *previous; 102228753Smm int links; 103228753Smm dev_t dev; 104228753Smm int64_t ino; 105228753Smm char *name; 106228753Smm}; 107228753Smm 108228753Smm#define CPIO_MAGIC 0x13141516 109228753Smmstruct cpio { 110228753Smm int magic; 111228753Smm int (*read_header)(struct archive_read *, struct cpio *, 112228753Smm struct archive_entry *, size_t *, size_t *); 113228753Smm struct links_entry *links_head; 114228753Smm struct archive_string entry_name; 115228753Smm struct archive_string entry_linkname; 116228753Smm off_t entry_bytes_remaining; 117228753Smm off_t entry_offset; 118228753Smm off_t entry_padding; 119228753Smm}; 120228753Smm 121228753Smmstatic int64_t atol16(const char *, unsigned); 122228753Smmstatic int64_t atol8(const char *, unsigned); 123228753Smmstatic int archive_read_format_cpio_bid(struct archive_read *); 124228753Smmstatic int archive_read_format_cpio_cleanup(struct archive_read *); 125228753Smmstatic int archive_read_format_cpio_read_data(struct archive_read *, 126228753Smm const void **, size_t *, off_t *); 127228753Smmstatic int archive_read_format_cpio_read_header(struct archive_read *, 128228753Smm struct archive_entry *); 129228753Smmstatic int be4(const unsigned char *); 130228753Smmstatic int find_odc_header(struct archive_read *); 131228753Smmstatic int find_newc_header(struct archive_read *); 132228753Smmstatic int header_bin_be(struct archive_read *, struct cpio *, 133228753Smm struct archive_entry *, size_t *, size_t *); 134228753Smmstatic int header_bin_le(struct archive_read *, struct cpio *, 135228753Smm struct archive_entry *, size_t *, size_t *); 136228753Smmstatic int header_newc(struct archive_read *, struct cpio *, 137228753Smm struct archive_entry *, size_t *, size_t *); 138228753Smmstatic int header_odc(struct archive_read *, struct cpio *, 139228753Smm struct archive_entry *, size_t *, size_t *); 140228753Smmstatic int is_octal(const char *, size_t); 141228753Smmstatic int is_hex(const char *, size_t); 142228753Smmstatic int le4(const unsigned char *); 143228753Smmstatic void record_hardlink(struct cpio *cpio, struct archive_entry *entry); 144228753Smm 145228753Smmint 146228753Smmarchive_read_support_format_cpio(struct archive *_a) 147228753Smm{ 148228753Smm struct archive_read *a = (struct archive_read *)_a; 149228753Smm struct cpio *cpio; 150228753Smm int r; 151228753Smm 152228753Smm cpio = (struct cpio *)malloc(sizeof(*cpio)); 153228753Smm if (cpio == NULL) { 154228753Smm archive_set_error(&a->archive, ENOMEM, "Can't allocate cpio data"); 155228753Smm return (ARCHIVE_FATAL); 156228753Smm } 157228753Smm memset(cpio, 0, sizeof(*cpio)); 158228753Smm cpio->magic = CPIO_MAGIC; 159228753Smm 160228753Smm r = __archive_read_register_format(a, 161228753Smm cpio, 162228753Smm "cpio", 163228753Smm archive_read_format_cpio_bid, 164228753Smm NULL, 165228753Smm archive_read_format_cpio_read_header, 166228753Smm archive_read_format_cpio_read_data, 167228753Smm NULL, 168228753Smm archive_read_format_cpio_cleanup); 169228753Smm 170228753Smm if (r != ARCHIVE_OK) 171228753Smm free(cpio); 172228753Smm return (ARCHIVE_OK); 173228753Smm} 174228753Smm 175228753Smm 176228753Smmstatic int 177228753Smmarchive_read_format_cpio_bid(struct archive_read *a) 178228753Smm{ 179228753Smm const void *h; 180228753Smm const unsigned char *p; 181228753Smm struct cpio *cpio; 182228753Smm int bid; 183228753Smm 184228753Smm cpio = (struct cpio *)(a->format->data); 185228753Smm 186228753Smm if ((h = __archive_read_ahead(a, 6, NULL)) == NULL) 187228753Smm return (-1); 188228753Smm 189228753Smm p = (const unsigned char *)h; 190228753Smm bid = 0; 191228753Smm if (memcmp(p, "070707", 6) == 0) { 192228753Smm /* ASCII cpio archive (odc, POSIX.1) */ 193228753Smm cpio->read_header = header_odc; 194228753Smm bid += 48; 195228753Smm /* 196228753Smm * XXX TODO: More verification; Could check that only octal 197228753Smm * digits appear in appropriate header locations. XXX 198228753Smm */ 199228753Smm } else if (memcmp(p, "070701", 6) == 0) { 200228753Smm /* ASCII cpio archive (SVR4 without CRC) */ 201228753Smm cpio->read_header = header_newc; 202228753Smm bid += 48; 203228753Smm /* 204228753Smm * XXX TODO: More verification; Could check that only hex 205228753Smm * digits appear in appropriate header locations. XXX 206228753Smm */ 207228753Smm } else if (memcmp(p, "070702", 6) == 0) { 208228753Smm /* ASCII cpio archive (SVR4 with CRC) */ 209228753Smm /* XXX TODO: Flag that we should check the CRC. XXX */ 210228753Smm cpio->read_header = header_newc; 211228753Smm bid += 48; 212228753Smm /* 213228753Smm * XXX TODO: More verification; Could check that only hex 214228753Smm * digits appear in appropriate header locations. XXX 215228753Smm */ 216228753Smm } else if (p[0] * 256 + p[1] == 070707) { 217228753Smm /* big-endian binary cpio archives */ 218228753Smm cpio->read_header = header_bin_be; 219228753Smm bid += 16; 220228753Smm /* Is more verification possible here? */ 221228753Smm } else if (p[0] + p[1] * 256 == 070707) { 222228753Smm /* little-endian binary cpio archives */ 223228753Smm cpio->read_header = header_bin_le; 224228753Smm bid += 16; 225228753Smm /* Is more verification possible here? */ 226228753Smm } else 227228753Smm return (ARCHIVE_WARN); 228228753Smm 229228753Smm return (bid); 230228753Smm} 231228753Smm 232228753Smmstatic int 233228753Smmarchive_read_format_cpio_read_header(struct archive_read *a, 234228753Smm struct archive_entry *entry) 235228753Smm{ 236228753Smm struct cpio *cpio; 237228753Smm const void *h; 238228753Smm size_t namelength; 239228753Smm size_t name_pad; 240228753Smm int r; 241228753Smm 242228753Smm cpio = (struct cpio *)(a->format->data); 243228753Smm r = (cpio->read_header(a, cpio, entry, &namelength, &name_pad)); 244228753Smm 245228753Smm if (r < ARCHIVE_WARN) 246228753Smm return (r); 247228753Smm 248228753Smm /* Read name from buffer. */ 249228753Smm h = __archive_read_ahead(a, namelength + name_pad, NULL); 250228753Smm if (h == NULL) 251228753Smm return (ARCHIVE_FATAL); 252228753Smm __archive_read_consume(a, namelength + name_pad); 253228753Smm archive_strncpy(&cpio->entry_name, (const char *)h, namelength); 254228753Smm archive_entry_set_pathname(entry, cpio->entry_name.s); 255228753Smm cpio->entry_offset = 0; 256228753Smm 257228753Smm /* If this is a symlink, read the link contents. */ 258228753Smm if (archive_entry_filetype(entry) == AE_IFLNK) { 259228753Smm h = __archive_read_ahead(a, cpio->entry_bytes_remaining, NULL); 260228753Smm if (h == NULL) 261228753Smm return (ARCHIVE_FATAL); 262228753Smm __archive_read_consume(a, cpio->entry_bytes_remaining); 263228753Smm archive_strncpy(&cpio->entry_linkname, (const char *)h, 264228753Smm cpio->entry_bytes_remaining); 265228753Smm archive_entry_set_symlink(entry, cpio->entry_linkname.s); 266228753Smm cpio->entry_bytes_remaining = 0; 267228753Smm } 268228753Smm 269228753Smm /* XXX TODO: If the full mode is 0160200, then this is a Solaris 270228753Smm * ACL description for the following entry. Read this body 271228753Smm * and parse it as a Solaris-style ACL, then read the next 272228753Smm * header. XXX */ 273228753Smm 274228753Smm /* Compare name to "TRAILER!!!" to test for end-of-archive. */ 275228753Smm if (namelength == 11 && strcmp((const char *)h, "TRAILER!!!") == 0) { 276228753Smm /* TODO: Store file location of start of block. */ 277228753Smm archive_clear_error(&a->archive); 278228753Smm return (ARCHIVE_EOF); 279228753Smm } 280228753Smm 281228753Smm /* Detect and record hardlinks to previously-extracted entries. */ 282228753Smm record_hardlink(cpio, entry); 283228753Smm 284228753Smm return (r); 285228753Smm} 286228753Smm 287228753Smmstatic int 288228753Smmarchive_read_format_cpio_read_data(struct archive_read *a, 289228753Smm const void **buff, size_t *size, off_t *offset) 290228753Smm{ 291228753Smm ssize_t bytes_read; 292228753Smm struct cpio *cpio; 293228753Smm 294228753Smm cpio = (struct cpio *)(a->format->data); 295228753Smm if (cpio->entry_bytes_remaining > 0) { 296228753Smm *buff = __archive_read_ahead(a, 1, &bytes_read); 297228753Smm if (bytes_read <= 0) 298228753Smm return (ARCHIVE_FATAL); 299228753Smm if (bytes_read > cpio->entry_bytes_remaining) 300228753Smm bytes_read = cpio->entry_bytes_remaining; 301228753Smm *size = bytes_read; 302228753Smm *offset = cpio->entry_offset; 303228753Smm cpio->entry_offset += bytes_read; 304228753Smm cpio->entry_bytes_remaining -= bytes_read; 305228753Smm __archive_read_consume(a, bytes_read); 306228753Smm return (ARCHIVE_OK); 307228753Smm } else { 308228753Smm while (cpio->entry_padding > 0) { 309228753Smm *buff = __archive_read_ahead(a, 1, &bytes_read); 310228753Smm if (bytes_read <= 0) 311228753Smm return (ARCHIVE_FATAL); 312228753Smm if (bytes_read > cpio->entry_padding) 313228753Smm bytes_read = cpio->entry_padding; 314228753Smm __archive_read_consume(a, bytes_read); 315228753Smm cpio->entry_padding -= bytes_read; 316228753Smm } 317228753Smm *buff = NULL; 318228753Smm *size = 0; 319228753Smm *offset = cpio->entry_offset; 320228753Smm return (ARCHIVE_EOF); 321228753Smm } 322228753Smm} 323228753Smm 324228753Smm/* 325228753Smm * Skip forward to the next cpio newc header by searching for the 326228753Smm * 07070[12] string. This should be generalized and merged with 327228753Smm * find_odc_header below. 328228753Smm */ 329228753Smmstatic int 330228753Smmis_hex(const char *p, size_t len) 331228753Smm{ 332228753Smm while (len-- > 0) { 333228753Smm if ((*p >= '0' && *p <= '9') 334228753Smm || (*p >= 'a' && *p <= 'f') 335228753Smm || (*p >= 'A' && *p <= 'F')) 336228753Smm ++p; 337228753Smm else 338228753Smm return (0); 339228753Smm } 340228753Smm return (1); 341228753Smm} 342228753Smm 343228753Smmstatic int 344228753Smmfind_newc_header(struct archive_read *a) 345228753Smm{ 346228753Smm const void *h; 347228753Smm const char *p, *q; 348228753Smm size_t skip, skipped = 0; 349228753Smm ssize_t bytes; 350228753Smm 351228753Smm for (;;) { 352228753Smm h = __archive_read_ahead(a, sizeof(struct cpio_newc_header), &bytes); 353228753Smm if (h == NULL) 354228753Smm return (ARCHIVE_FATAL); 355228753Smm p = h; 356228753Smm q = p + bytes; 357228753Smm 358228753Smm /* Try the typical case first, then go into the slow search.*/ 359228753Smm if (memcmp("07070", p, 5) == 0 360228753Smm && (p[5] == '1' || p[5] == '2') 361228753Smm && is_hex(p, sizeof(struct cpio_newc_header))) 362228753Smm return (ARCHIVE_OK); 363228753Smm 364228753Smm /* 365228753Smm * Scan ahead until we find something that looks 366228753Smm * like an odc header. 367228753Smm */ 368228753Smm while (p + sizeof(struct cpio_newc_header) <= q) { 369228753Smm switch (p[5]) { 370228753Smm case '1': 371228753Smm case '2': 372228753Smm if (memcmp("07070", p, 5) == 0 373228753Smm && is_hex(p, sizeof(struct cpio_newc_header))) { 374228753Smm skip = p - (const char *)h; 375228753Smm __archive_read_consume(a, skip); 376228753Smm skipped += skip; 377228753Smm if (skipped > 0) { 378228753Smm archive_set_error(&a->archive, 379228753Smm 0, 380228753Smm "Skipped %d bytes before " 381228753Smm "finding valid header", 382228753Smm (int)skipped); 383228753Smm return (ARCHIVE_WARN); 384228753Smm } 385228753Smm return (ARCHIVE_OK); 386228753Smm } 387228753Smm p += 2; 388228753Smm break; 389228753Smm case '0': 390228753Smm p++; 391228753Smm break; 392228753Smm default: 393228753Smm p += 6; 394228753Smm break; 395228753Smm } 396228753Smm } 397228753Smm skip = p - (const char *)h; 398228753Smm __archive_read_consume(a, skip); 399228753Smm skipped += skip; 400228753Smm } 401228753Smm} 402228753Smm 403228753Smmstatic int 404228753Smmheader_newc(struct archive_read *a, struct cpio *cpio, 405228753Smm struct archive_entry *entry, size_t *namelength, size_t *name_pad) 406228753Smm{ 407228753Smm const void *h; 408228753Smm const struct cpio_newc_header *header; 409228753Smm int r; 410228753Smm 411228753Smm r = find_newc_header(a); 412228753Smm if (r < ARCHIVE_WARN) 413228753Smm return (r); 414228753Smm 415228753Smm /* Read fixed-size portion of header. */ 416228753Smm h = __archive_read_ahead(a, sizeof(struct cpio_newc_header), NULL); 417228753Smm if (h == NULL) 418228753Smm return (ARCHIVE_FATAL); 419228753Smm __archive_read_consume(a, sizeof(struct cpio_newc_header)); 420228753Smm 421228753Smm /* Parse out hex fields. */ 422228753Smm header = (const struct cpio_newc_header *)h; 423228753Smm 424228753Smm if (memcmp(header->c_magic, "070701", 6) == 0) { 425228753Smm a->archive.archive_format = ARCHIVE_FORMAT_CPIO_SVR4_NOCRC; 426228753Smm a->archive.archive_format_name = "ASCII cpio (SVR4 with no CRC)"; 427228753Smm } else if (memcmp(header->c_magic, "070702", 6) == 0) { 428228753Smm a->archive.archive_format = ARCHIVE_FORMAT_CPIO_SVR4_CRC; 429228753Smm a->archive.archive_format_name = "ASCII cpio (SVR4 with CRC)"; 430228753Smm } else { 431228753Smm /* TODO: Abort here? */ 432228753Smm } 433228753Smm 434228753Smm archive_entry_set_devmajor(entry, atol16(header->c_devmajor, sizeof(header->c_devmajor))); 435228753Smm archive_entry_set_devminor(entry, atol16(header->c_devminor, sizeof(header->c_devminor))); 436228753Smm archive_entry_set_ino(entry, atol16(header->c_ino, sizeof(header->c_ino))); 437228753Smm archive_entry_set_mode(entry, atol16(header->c_mode, sizeof(header->c_mode))); 438228753Smm archive_entry_set_uid(entry, atol16(header->c_uid, sizeof(header->c_uid))); 439228753Smm archive_entry_set_gid(entry, atol16(header->c_gid, sizeof(header->c_gid))); 440228753Smm archive_entry_set_nlink(entry, atol16(header->c_nlink, sizeof(header->c_nlink))); 441228753Smm archive_entry_set_rdevmajor(entry, atol16(header->c_rdevmajor, sizeof(header->c_rdevmajor))); 442228753Smm archive_entry_set_rdevminor(entry, atol16(header->c_rdevminor, sizeof(header->c_rdevminor))); 443228753Smm archive_entry_set_mtime(entry, atol16(header->c_mtime, sizeof(header->c_mtime)), 0); 444228753Smm *namelength = atol16(header->c_namesize, sizeof(header->c_namesize)); 445228753Smm /* Pad name to 2 more than a multiple of 4. */ 446228753Smm *name_pad = (2 - *namelength) & 3; 447228753Smm 448228753Smm /* 449228753Smm * Note: entry_bytes_remaining is at least 64 bits and 450228753Smm * therefore guaranteed to be big enough for a 33-bit file 451228753Smm * size. 452228753Smm */ 453228753Smm cpio->entry_bytes_remaining = 454228753Smm atol16(header->c_filesize, sizeof(header->c_filesize)); 455228753Smm archive_entry_set_size(entry, cpio->entry_bytes_remaining); 456228753Smm /* Pad file contents to a multiple of 4. */ 457228753Smm cpio->entry_padding = 3 & -cpio->entry_bytes_remaining; 458228753Smm return (r); 459228753Smm} 460228753Smm 461228753Smm/* 462228753Smm * Skip forward to the next cpio odc header by searching for the 463228753Smm * 070707 string. This is a hand-optimized search that could 464228753Smm * probably be easily generalized to handle all character-based 465228753Smm * cpio variants. 466228753Smm */ 467228753Smmstatic int 468228753Smmis_octal(const char *p, size_t len) 469228753Smm{ 470228753Smm while (len-- > 0) { 471228753Smm if (*p < '0' || *p > '7') 472228753Smm return (0); 473228753Smm ++p; 474228753Smm } 475228753Smm return (1); 476228753Smm} 477228753Smm 478228753Smmstatic int 479228753Smmfind_odc_header(struct archive_read *a) 480228753Smm{ 481228753Smm const void *h; 482228753Smm const char *p, *q; 483228753Smm size_t skip, skipped = 0; 484228753Smm ssize_t bytes; 485228753Smm 486228753Smm for (;;) { 487228753Smm h = __archive_read_ahead(a, sizeof(struct cpio_odc_header), &bytes); 488228753Smm if (h == NULL) 489228753Smm return (ARCHIVE_FATAL); 490228753Smm p = h; 491228753Smm q = p + bytes; 492228753Smm 493228753Smm /* Try the typical case first, then go into the slow search.*/ 494228753Smm if (memcmp("070707", p, 6) == 0 495228753Smm && is_octal(p, sizeof(struct cpio_odc_header))) 496228753Smm return (ARCHIVE_OK); 497228753Smm 498228753Smm /* 499228753Smm * Scan ahead until we find something that looks 500228753Smm * like an odc header. 501228753Smm */ 502228753Smm while (p + sizeof(struct cpio_odc_header) <= q) { 503228753Smm switch (p[5]) { 504228753Smm case '7': 505228753Smm if (memcmp("070707", p, 6) == 0 506228753Smm && is_octal(p, sizeof(struct cpio_odc_header))) { 507228753Smm skip = p - (const char *)h; 508228753Smm __archive_read_consume(a, skip); 509228753Smm skipped += skip; 510228753Smm if (skipped > 0) { 511228753Smm archive_set_error(&a->archive, 512228753Smm 0, 513228753Smm "Skipped %d bytes before " 514228753Smm "finding valid header", 515228753Smm (int)skipped); 516228753Smm return (ARCHIVE_WARN); 517228753Smm } 518228753Smm return (ARCHIVE_OK); 519228753Smm } 520228753Smm p += 2; 521228753Smm break; 522228753Smm case '0': 523228753Smm p++; 524228753Smm break; 525228753Smm default: 526228753Smm p += 6; 527228753Smm break; 528228753Smm } 529228753Smm } 530228753Smm skip = p - (const char *)h; 531228753Smm __archive_read_consume(a, skip); 532228753Smm skipped += skip; 533228753Smm } 534228753Smm} 535228753Smm 536228753Smmstatic int 537228753Smmheader_odc(struct archive_read *a, struct cpio *cpio, 538228753Smm struct archive_entry *entry, size_t *namelength, size_t *name_pad) 539228753Smm{ 540228753Smm const void *h; 541228753Smm int r; 542228753Smm const struct cpio_odc_header *header; 543228753Smm 544228753Smm a->archive.archive_format = ARCHIVE_FORMAT_CPIO_POSIX; 545228753Smm a->archive.archive_format_name = "POSIX octet-oriented cpio"; 546228753Smm 547228753Smm /* Find the start of the next header. */ 548228753Smm r = find_odc_header(a); 549228753Smm if (r < ARCHIVE_WARN) 550228753Smm return (r); 551228753Smm 552228753Smm /* Read fixed-size portion of header. */ 553228753Smm h = __archive_read_ahead(a, sizeof(struct cpio_odc_header), NULL); 554228753Smm if (h == NULL) 555228753Smm return (ARCHIVE_FATAL); 556228753Smm __archive_read_consume(a, sizeof(struct cpio_odc_header)); 557228753Smm 558228753Smm /* Parse out octal fields. */ 559228753Smm header = (const struct cpio_odc_header *)h; 560228753Smm 561228753Smm archive_entry_set_dev(entry, atol8(header->c_dev, sizeof(header->c_dev))); 562228753Smm archive_entry_set_ino(entry, atol8(header->c_ino, sizeof(header->c_ino))); 563228753Smm archive_entry_set_mode(entry, atol8(header->c_mode, sizeof(header->c_mode))); 564228753Smm archive_entry_set_uid(entry, atol8(header->c_uid, sizeof(header->c_uid))); 565228753Smm archive_entry_set_gid(entry, atol8(header->c_gid, sizeof(header->c_gid))); 566228753Smm archive_entry_set_nlink(entry, atol8(header->c_nlink, sizeof(header->c_nlink))); 567228753Smm archive_entry_set_rdev(entry, atol8(header->c_rdev, sizeof(header->c_rdev))); 568228753Smm archive_entry_set_mtime(entry, atol8(header->c_mtime, sizeof(header->c_mtime)), 0); 569228753Smm *namelength = atol8(header->c_namesize, sizeof(header->c_namesize)); 570228753Smm *name_pad = 0; /* No padding of filename. */ 571228753Smm 572228753Smm /* 573228753Smm * Note: entry_bytes_remaining is at least 64 bits and 574228753Smm * therefore guaranteed to be big enough for a 33-bit file 575228753Smm * size. 576228753Smm */ 577228753Smm cpio->entry_bytes_remaining = 578228753Smm atol8(header->c_filesize, sizeof(header->c_filesize)); 579228753Smm archive_entry_set_size(entry, cpio->entry_bytes_remaining); 580228753Smm cpio->entry_padding = 0; 581228753Smm return (r); 582228753Smm} 583228753Smm 584228753Smmstatic int 585228753Smmheader_bin_le(struct archive_read *a, struct cpio *cpio, 586228753Smm struct archive_entry *entry, size_t *namelength, size_t *name_pad) 587228753Smm{ 588228753Smm const void *h; 589228753Smm const struct cpio_bin_header *header; 590228753Smm 591228753Smm a->archive.archive_format = ARCHIVE_FORMAT_CPIO_BIN_LE; 592228753Smm a->archive.archive_format_name = "cpio (little-endian binary)"; 593228753Smm 594228753Smm /* Read fixed-size portion of header. */ 595228753Smm h = __archive_read_ahead(a, sizeof(struct cpio_bin_header), NULL); 596228753Smm if (h == NULL) 597228753Smm return (ARCHIVE_FATAL); 598228753Smm __archive_read_consume(a, sizeof(struct cpio_bin_header)); 599228753Smm 600228753Smm /* Parse out binary fields. */ 601228753Smm header = (const struct cpio_bin_header *)h; 602228753Smm 603228753Smm archive_entry_set_dev(entry, header->c_dev[0] + header->c_dev[1] * 256); 604228753Smm archive_entry_set_ino(entry, header->c_ino[0] + header->c_ino[1] * 256); 605228753Smm archive_entry_set_mode(entry, header->c_mode[0] + header->c_mode[1] * 256); 606228753Smm archive_entry_set_uid(entry, header->c_uid[0] + header->c_uid[1] * 256); 607228753Smm archive_entry_set_gid(entry, header->c_gid[0] + header->c_gid[1] * 256); 608228753Smm archive_entry_set_nlink(entry, header->c_nlink[0] + header->c_nlink[1] * 256); 609228753Smm archive_entry_set_rdev(entry, header->c_rdev[0] + header->c_rdev[1] * 256); 610228753Smm archive_entry_set_mtime(entry, le4(header->c_mtime), 0); 611228753Smm *namelength = header->c_namesize[0] + header->c_namesize[1] * 256; 612228753Smm *name_pad = *namelength & 1; /* Pad to even. */ 613228753Smm 614228753Smm cpio->entry_bytes_remaining = le4(header->c_filesize); 615228753Smm archive_entry_set_size(entry, cpio->entry_bytes_remaining); 616228753Smm cpio->entry_padding = cpio->entry_bytes_remaining & 1; /* Pad to even. */ 617228753Smm return (ARCHIVE_OK); 618228753Smm} 619228753Smm 620228753Smmstatic int 621228753Smmheader_bin_be(struct archive_read *a, struct cpio *cpio, 622228753Smm struct archive_entry *entry, size_t *namelength, size_t *name_pad) 623228753Smm{ 624228753Smm const void *h; 625228753Smm const struct cpio_bin_header *header; 626228753Smm 627228753Smm a->archive.archive_format = ARCHIVE_FORMAT_CPIO_BIN_BE; 628228753Smm a->archive.archive_format_name = "cpio (big-endian binary)"; 629228753Smm 630228753Smm /* Read fixed-size portion of header. */ 631228753Smm h = __archive_read_ahead(a, sizeof(struct cpio_bin_header), NULL); 632228753Smm if (h == NULL) 633228753Smm return (ARCHIVE_FATAL); 634228753Smm __archive_read_consume(a, sizeof(struct cpio_bin_header)); 635228753Smm 636228753Smm /* Parse out binary fields. */ 637228753Smm header = (const struct cpio_bin_header *)h; 638228753Smm archive_entry_set_dev(entry, header->c_dev[0] * 256 + header->c_dev[1]); 639228753Smm archive_entry_set_ino(entry, header->c_ino[0] * 256 + header->c_ino[1]); 640228753Smm archive_entry_set_mode(entry, header->c_mode[0] * 256 + header->c_mode[1]); 641228753Smm archive_entry_set_uid(entry, header->c_uid[0] * 256 + header->c_uid[1]); 642228753Smm archive_entry_set_gid(entry, header->c_gid[0] * 256 + header->c_gid[1]); 643228753Smm archive_entry_set_nlink(entry, header->c_nlink[0] * 256 + header->c_nlink[1]); 644228753Smm archive_entry_set_rdev(entry, header->c_rdev[0] * 256 + header->c_rdev[1]); 645228753Smm archive_entry_set_mtime(entry, be4(header->c_mtime), 0); 646228753Smm *namelength = header->c_namesize[0] * 256 + header->c_namesize[1]; 647228753Smm *name_pad = *namelength & 1; /* Pad to even. */ 648228753Smm 649228753Smm cpio->entry_bytes_remaining = be4(header->c_filesize); 650228753Smm archive_entry_set_size(entry, cpio->entry_bytes_remaining); 651228753Smm cpio->entry_padding = cpio->entry_bytes_remaining & 1; /* Pad to even. */ 652228753Smm return (ARCHIVE_OK); 653228753Smm} 654228753Smm 655228753Smmstatic int 656228753Smmarchive_read_format_cpio_cleanup(struct archive_read *a) 657228753Smm{ 658228753Smm struct cpio *cpio; 659228753Smm 660228753Smm cpio = (struct cpio *)(a->format->data); 661228753Smm /* Free inode->name map */ 662228753Smm while (cpio->links_head != NULL) { 663228753Smm struct links_entry *lp = cpio->links_head->next; 664228753Smm 665228753Smm if (cpio->links_head->name) 666228753Smm free(cpio->links_head->name); 667228753Smm free(cpio->links_head); 668228753Smm cpio->links_head = lp; 669228753Smm } 670228753Smm archive_string_free(&cpio->entry_name); 671228753Smm free(cpio); 672228753Smm (a->format->data) = NULL; 673228753Smm return (ARCHIVE_OK); 674228753Smm} 675228753Smm 676228753Smmstatic int 677228753Smmle4(const unsigned char *p) 678228753Smm{ 679228753Smm return ((p[0]<<16) + (p[1]<<24) + (p[2]<<0) + (p[3]<<8)); 680228753Smm} 681228753Smm 682228753Smm 683228753Smmstatic int 684228753Smmbe4(const unsigned char *p) 685228753Smm{ 686228753Smm return ((p[0]<<24) + (p[1]<<16) + (p[2]<<8) + (p[3])); 687228753Smm} 688228753Smm 689228753Smm/* 690228753Smm * Note that this implementation does not (and should not!) obey 691228753Smm * locale settings; you cannot simply substitute strtol here, since 692228753Smm * it does obey locale. 693228753Smm */ 694228753Smmstatic int64_t 695228753Smmatol8(const char *p, unsigned char_cnt) 696228753Smm{ 697228753Smm int64_t l; 698228753Smm int digit; 699228753Smm 700228753Smm l = 0; 701228753Smm while (char_cnt-- > 0) { 702228753Smm if (*p >= '0' && *p <= '7') 703228753Smm digit = *p - '0'; 704228753Smm else 705228753Smm return (l); 706228753Smm p++; 707228753Smm l <<= 3; 708228753Smm l |= digit; 709228753Smm } 710228753Smm return (l); 711228753Smm} 712228753Smm 713228753Smmstatic int64_t 714228753Smmatol16(const char *p, unsigned char_cnt) 715228753Smm{ 716228753Smm int64_t l; 717228753Smm int digit; 718228753Smm 719228753Smm l = 0; 720228753Smm while (char_cnt-- > 0) { 721228753Smm if (*p >= 'a' && *p <= 'f') 722228753Smm digit = *p - 'a' + 10; 723228753Smm else if (*p >= 'A' && *p <= 'F') 724228753Smm digit = *p - 'A' + 10; 725228753Smm else if (*p >= '0' && *p <= '9') 726228753Smm digit = *p - '0'; 727228753Smm else 728228753Smm return (l); 729228753Smm p++; 730228753Smm l <<= 4; 731228753Smm l |= digit; 732228753Smm } 733228753Smm return (l); 734228753Smm} 735228753Smm 736228753Smmstatic void 737228753Smmrecord_hardlink(struct cpio *cpio, struct archive_entry *entry) 738228753Smm{ 739228753Smm struct links_entry *le; 740228753Smm dev_t dev; 741228753Smm int64_t ino; 742228753Smm 743228753Smm if (archive_entry_nlink(entry) <= 1) 744228753Smm return; 745228753Smm 746228753Smm dev = archive_entry_dev(entry); 747228753Smm ino = archive_entry_ino64(entry); 748228753Smm 749228753Smm /* 750228753Smm * First look in the list of multiply-linked files. If we've 751228753Smm * already dumped it, convert this entry to a hard link entry. 752228753Smm */ 753228753Smm for (le = cpio->links_head; le; le = le->next) { 754228753Smm if (le->dev == dev && le->ino == ino) { 755228753Smm archive_entry_copy_hardlink(entry, le->name); 756228753Smm 757228753Smm if (--le->links <= 0) { 758228753Smm if (le->previous != NULL) 759228753Smm le->previous->next = le->next; 760228753Smm if (le->next != NULL) 761228753Smm le->next->previous = le->previous; 762228753Smm if (cpio->links_head == le) 763228753Smm cpio->links_head = le->next; 764228753Smm free(le->name); 765228753Smm free(le); 766228753Smm } 767228753Smm 768228753Smm return; 769228753Smm } 770228753Smm } 771228753Smm 772228753Smm le = (struct links_entry *)malloc(sizeof(struct links_entry)); 773228753Smm if (le == NULL) 774228753Smm __archive_errx(1, "Out of memory adding file to list"); 775228753Smm if (cpio->links_head != NULL) 776228753Smm cpio->links_head->previous = le; 777228753Smm le->next = cpio->links_head; 778228753Smm le->previous = NULL; 779228753Smm cpio->links_head = le; 780228753Smm le->dev = dev; 781228753Smm le->ino = ino; 782228753Smm le->links = archive_entry_nlink(entry) - 1; 783228753Smm le->name = strdup(archive_entry_pathname(entry)); 784228753Smm if (le->name == NULL) 785228753Smm __archive_errx(1, "Out of memory adding file to list"); 786228753Smm} 787