1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, 13 * software distributed under the License is distributed on an 14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 * KIND, either express or implied. See the License for the 16 * specific language governing permissions and limitations 17 * under the License. 18 */ 19 package org.apache.commons.compress.archivers.cpio; 20 21 import java.io.File; 22 import java.io.IOException; 23 import java.nio.charset.Charset; 24 import java.nio.file.Files; 25 import java.nio.file.LinkOption; 26 import java.nio.file.Path; 27 import java.nio.file.attribute.FileTime; 28 import java.util.Date; 29 import java.util.Objects; 30 31 import org.apache.commons.compress.archivers.ArchiveEntry; 32 import org.apache.commons.compress.utils.ExactMath; 33 import org.apache.commons.compress.utils.TimeUtils; 34 35 /** 36 * A cpio archive consists of a sequence of files. There are several types of headers defined in two categories of new and old format. The headers are 37 * recognized by magic numbers: 38 * 39 * <ul> 40 * <li>"070701" ASCII for new portable format</li> 41 * <li>"070702" ASCII for new portable format with CRC</li> 42 * <li>"070707" ASCII for old ASCII (also known as Portable ASCII, odc or old character format</li> 43 * <li>070707 binary for old binary</li> 44 * </ul> 45 * 46 * <p> 47 * The old binary format is limited to 16 bits for user id, group id, device, and inode numbers. It is limited to 4 gigabyte file sizes. 48 * 49 * The old ASCII format is limited to 18 bits for the user id, group id, device, and inode numbers. It is limited to 8 gigabyte file sizes. 50 * 51 * The new ASCII format is limited to 4 gigabyte file sizes. 52 * 53 * CPIO 2.5 knows also about tar, but it is not recognized here. 54 * </p> 55 * 56 * 57 * <h2>OLD FORMAT</h2> 58 * 59 * <p> 60 * Each file has a 76 (ascii) / 26 (binary) byte header, a variable length, NUL terminated file name, and variable length file data. A header for a file name 61 * "TRAILER!!!" indicates the end of the archive. 62 * </p> 63 * 64 * <p> 65 * All the fields in the header are ISO 646 (approximately ASCII) strings of octal numbers, left padded, not NUL terminated. 66 * </p> 67 * 68 * <pre> 69 * FIELDNAME NOTES 70 * c_magic The integer value octal 070707. This value can be used to deter- 71 * mine whether this archive is written with little-endian or big- 72 * endian integers. 73 * c_dev Device that contains a directory entry for this file 74 * c_ino I-node number that identifies the input file to the file system 75 * c_mode The mode specifies both the regular permissions and the file type. 76 * c_uid Numeric User ID of the owner of the input file 77 * c_gid Numeric Group ID of the owner of the input file 78 * c_nlink Number of links that are connected to the input file 79 * c_rdev For block special and character special entries, this field 80 * contains the associated device number. For all other entry types, 81 * it should be set to zero by writers and ignored by readers. 82 * c_mtime[2] Modification time of the file, indicated as the number of seconds 83 * since the start of the epoch, 00:00:00 UTC January 1, 1970. The 84 * four-byte integer is stored with the most-significant 16 bits 85 * first followed by the least-significant 16 bits. Each of the two 86 * 16 bit values are stored in machine-native byte order. 87 * c_namesize Length of the path name, including the terminating null byte 88 * c_filesize[2] Length of the file in bytes. This is the length of the data 89 * section that follows the header structure. Must be 0 for 90 * FIFOs and directories 91 * 92 * All fields are unsigned short fields with 16-bit integer values 93 * apart from c_mtime and c_filesize which are 32-bit integer values 94 * </pre> 95 * 96 * <p> 97 * If necessary, the file name and file data are padded with a NUL byte to an even length 98 * </p> 99 * 100 * <p> 101 * Special files, directories, and the trailer are recorded with the h_filesize field equal to 0. 102 * </p> 103 * 104 * <p> 105 * In the ASCII version of this format, the 16-bit entries are represented as 6-byte octal numbers, and the 32-bit entries are represented as 11-byte octal 106 * numbers. No padding is added. 107 * </p> 108 * 109 * <h3>NEW FORMAT</h3> 110 * 111 * <p> 112 * Each file has a 110 byte header, a variable length, NUL terminated file name, and variable length file data. A header for a file name "TRAILER!!!" indicates 113 * the end of the archive. All the fields in the header are ISO 646 (approximately ASCII) strings of hexadecimal numbers, left padded, not NUL terminated. 114 * </p> 115 * 116 * <pre> 117 * FIELDNAME NOTES 118 * c_magic[6] The string 070701 for new ASCII, the string 070702 for new ASCII with CRC 119 * c_ino[8] 120 * c_mode[8] 121 * c_uid[8] 122 * c_gid[8] 123 * c_nlink[8] 124 * c_mtim[8] 125 * c_filesize[8] must be 0 for FIFOs and directories 126 * c_maj[8] 127 * c_min[8] 128 * c_rmaj[8] only valid for chr and blk special files 129 * c_rmin[8] only valid for chr and blk special files 130 * c_namesize[8] count includes terminating NUL in path name 131 * c_check[8] 0 for "new" portable format; for CRC format 132 * the sum of all the bytes in the file 133 * </pre> 134 * 135 * <p> 136 * New ASCII Format The "new" ASCII format uses 8-byte hexadecimal fields for all numbers and separates device numbers into separate fields for major and minor 137 * numbers. 138 * </p> 139 * 140 * <p> 141 * The path name is followed by NUL bytes so that the total size of the fixed header plus path name is a multiple of four. Likewise, the file data is padded to 142 * a multiple of four bytes. 143 * </p> 144 * 145 * <p> 146 * This class uses mutable fields and is not considered to be threadsafe. 147 * </p> 148 * 149 * <p> 150 * Based on code from the jRPM project (https://jrpm.sourceforge.net). 151 * </p> 152 * 153 * <p> 154 * The MAGIC numbers and other constants are defined in {@link CpioConstants} 155 * </p> 156 * 157 * <p> 158 * N.B. does not handle the cpio "tar" format 159 * </p> 160 * 161 * @NotThreadSafe 162 * @see <a href="https://people.freebsd.org/~kientzle/libarchive/man/cpio.5.txt">https://people.freebsd.org/~kientzle/libarchive/man/cpio.5.txt</a> 163 */ 164 public class CpioArchiveEntry implements CpioConstants, ArchiveEntry { 165 166 // Header description fields - should be same throughout an archive 167 168 /** 169 * See {@link #CpioArchiveEntry(short)} for possible values. 170 */ 171 private final short fileFormat; 172 173 /** The number of bytes in each header record; depends on the file format */ 174 private final int headerSize; 175 176 /** The boundary to which the header and data elements are aligned: 0, 2 or 4 bytes */ 177 private final int alignmentBoundary; 178 179 // Header fields 180 181 private long chksum; 182 183 /** Number of bytes in the file */ 184 private long filesize; 185 186 private long gid; 187 188 private long inode; 189 190 private long maj; 191 192 private long min; 193 194 private long mode; 195 196 private long mtime; 197 198 private String name; 199 200 private long nlink; 201 202 private long rmaj; 203 204 private long rmin; 205 206 private long uid; 207 208 /** 209 * Creates a CpioArchiveEntry with a specified name for a specified file. The format of this entry will be the new format. 210 * 211 * @param inputFile The file to gather information from. 212 * @param entryName The name of this entry. 213 */ 214 public CpioArchiveEntry(final File inputFile, final String entryName) { 215 this(FORMAT_NEW, inputFile, entryName); 216 } 217 218 /** 219 * Creates a CpioArchiveEntry with a specified name for a specified file. The format of this entry will be the new format. 220 * 221 * @param inputPath The file to gather information from. 222 * @param entryName The name of this entry. 223 * @param options options indicating how symbolic links are handled. 224 * @throws IOException if an I/O error occurs 225 * @since 1.21 226 */ 227 public CpioArchiveEntry(final Path inputPath, final String entryName, final LinkOption... options) throws IOException { 228 this(FORMAT_NEW, inputPath, entryName, options); 229 } 230 231 /** 232 * Creates a CpioArchiveEntry with a specified format. 233 * 234 * @param format The cpio format for this entry. 235 * <p> 236 * Possible format values are: 237 * 238 * <pre> 239 * CpioConstants.FORMAT_NEW 240 * CpioConstants.FORMAT_NEW_CRC 241 * CpioConstants.FORMAT_OLD_BINARY 242 * CpioConstants.FORMAT_OLD_ASCII 243 * </pre> 244 */ 245 public CpioArchiveEntry(final short format) { 246 switch (format) { 247 case FORMAT_NEW: 248 this.headerSize = 110; 249 this.alignmentBoundary = 4; 250 break; 251 case FORMAT_NEW_CRC: 252 this.headerSize = 110; 253 this.alignmentBoundary = 4; 254 break; 255 case FORMAT_OLD_ASCII: 256 this.headerSize = 76; 257 this.alignmentBoundary = 0; 258 break; 259 case FORMAT_OLD_BINARY: 260 this.headerSize = 26; 261 this.alignmentBoundary = 2; 262 break; 263 default: 264 throw new IllegalArgumentException("Unknown header type " + format); 265 } 266 this.fileFormat = format; 267 } 268 269 /** 270 * Creates a CpioArchiveEntry with a specified name for a specified file. 271 * 272 * @param format The cpio format for this entry. 273 * @param inputFile The file to gather information from. 274 * @param entryName The name of this entry. 275 * <p> 276 * Possible format values are: 277 * 278 * <pre> 279 * CpioConstants.FORMAT_NEW 280 * CpioConstants.FORMAT_NEW_CRC 281 * CpioConstants.FORMAT_OLD_BINARY 282 * CpioConstants.FORMAT_OLD_ASCII 283 * </pre> 284 * 285 * @since 1.1 286 */ 287 public CpioArchiveEntry(final short format, final File inputFile, final String entryName) { 288 this(format, entryName, inputFile.isFile() ? inputFile.length() : 0); 289 if (inputFile.isDirectory()) { 290 setMode(C_ISDIR); 291 } else if (inputFile.isFile()) { 292 setMode(C_ISREG); 293 } else { 294 throw new IllegalArgumentException("Cannot determine type of file " + inputFile.getName()); 295 } 296 // TODO set other fields as needed 297 setTime(inputFile.lastModified() / 1000); 298 } 299 300 /** 301 * Creates a CpioArchiveEntry with a specified name for a specified path. 302 * 303 * @param format The cpio format for this entry. 304 * @param inputPath The file to gather information from. 305 * @param entryName The name of this entry. 306 * <p> 307 * Possible format values are: 308 * 309 * <pre> 310 * CpioConstants.FORMAT_NEW 311 * CpioConstants.FORMAT_NEW_CRC 312 * CpioConstants.FORMAT_OLD_BINARY 313 * CpioConstants.FORMAT_OLD_ASCII 314 * </pre> 315 * 316 * @param options options indicating how symbolic links are handled. 317 * 318 * @throws IOException if an I/O error occurs 319 * @since 1.21 320 */ 321 public CpioArchiveEntry(final short format, final Path inputPath, final String entryName, final LinkOption... options) throws IOException { 322 this(format, entryName, Files.isRegularFile(inputPath, options) ? Files.size(inputPath) : 0); 323 if (Files.isDirectory(inputPath, options)) { 324 setMode(C_ISDIR); 325 } else if (Files.isRegularFile(inputPath, options)) { 326 setMode(C_ISREG); 327 } else { 328 throw new IllegalArgumentException("Cannot determine type of file " + inputPath); 329 } 330 // TODO set other fields as needed 331 setTime(Files.getLastModifiedTime(inputPath, options)); 332 } 333 334 /** 335 * Creates a CpioArchiveEntry with a specified name. 336 * 337 * @param format The cpio format for this entry. 338 * @param name The name of this entry. 339 * <p> 340 * Possible format values are: 341 * 342 * <pre> 343 * CpioConstants.FORMAT_NEW 344 * CpioConstants.FORMAT_NEW_CRC 345 * CpioConstants.FORMAT_OLD_BINARY 346 * CpioConstants.FORMAT_OLD_ASCII 347 * </pre> 348 * 349 * @since 1.1 350 */ 351 public CpioArchiveEntry(final short format, final String name) { 352 this(format); 353 this.name = name; 354 } 355 356 /** 357 * Creates a CpioArchiveEntry with a specified name. 358 * 359 * @param format The cpio format for this entry. 360 * @param name The name of this entry. 361 * @param size The size of this entry 362 * <p> 363 * Possible format values are: 364 * 365 * <pre> 366 * CpioConstants.FORMAT_NEW 367 * CpioConstants.FORMAT_NEW_CRC 368 * CpioConstants.FORMAT_OLD_BINARY 369 * CpioConstants.FORMAT_OLD_ASCII 370 * </pre> 371 * 372 * @since 1.1 373 */ 374 public CpioArchiveEntry(final short format, final String name, final long size) { 375 this(format, name); 376 setSize(size); 377 } 378 379 /** 380 * Creates a CpioArchiveEntry with a specified name. The format of this entry will be the new format. 381 * 382 * @param name The name of this entry. 383 */ 384 public CpioArchiveEntry(final String name) { 385 this(FORMAT_NEW, name); 386 } 387 388 /** 389 * Creates a CpioArchiveEntry with a specified name. The format of this entry will be the new format. 390 * 391 * @param name The name of this entry. 392 * @param size The size of this entry 393 */ 394 public CpioArchiveEntry(final String name, final long size) { 395 this(name); 396 setSize(size); 397 } 398 399 /** 400 * Checks if the method is allowed for the defined format. 401 */ 402 private void checkNewFormat() { 403 if ((this.fileFormat & FORMAT_NEW_MASK) == 0) { 404 throw new UnsupportedOperationException(); 405 } 406 } 407 408 /** 409 * Checks if the method is allowed for the defined format. 410 */ 411 private void checkOldFormat() { 412 if ((this.fileFormat & FORMAT_OLD_MASK) == 0) { 413 throw new UnsupportedOperationException(); 414 } 415 } 416 417 /* 418 * (non-Javadoc) 419 * 420 * @see Object#equals(Object) 421 */ 422 @Override 423 public boolean equals(final Object obj) { 424 if (this == obj) { 425 return true; 426 } 427 if (obj == null || getClass() != obj.getClass()) { 428 return false; 429 } 430 final CpioArchiveEntry other = (CpioArchiveEntry) obj; 431 return Objects.equals(name, other.name); 432 } 433 434 /** 435 * Gets the alignment boundary for this CPIO format 436 * 437 * @return the alignment boundary (0, 2, 4) in bytes 438 */ 439 public int getAlignmentBoundary() { 440 return this.alignmentBoundary; 441 } 442 443 /** 444 * Gets the checksum. Only supported for the new formats. 445 * 446 * @return the checksum. 447 * @throws UnsupportedOperationException if the format is not a new format 448 */ 449 public long getChksum() { 450 checkNewFormat(); 451 return this.chksum & 0xFFFFFFFFL; 452 } 453 454 /** 455 * Gets the number of bytes needed to pad the data to the alignment boundary. 456 * 457 * @return the number of bytes needed to pad the data (0,1,2,3) 458 */ 459 public int getDataPadCount() { 460 if (this.alignmentBoundary == 0) { 461 return 0; 462 } 463 final long size = this.filesize; 464 final int remain = (int) (size % this.alignmentBoundary); 465 if (remain > 0) { 466 return this.alignmentBoundary - remain; 467 } 468 return 0; 469 } 470 471 /** 472 * Gets the device id. 473 * 474 * @return the device id. 475 * @throws UnsupportedOperationException if this method is called for a CpioArchiveEntry with a new format. 476 */ 477 public long getDevice() { 478 checkOldFormat(); 479 return this.min; 480 } 481 482 /** 483 * Gets the major device id. 484 * 485 * @return the major device id. 486 * @throws UnsupportedOperationException if this method is called for a CpioArchiveEntry with an old format. 487 */ 488 public long getDeviceMaj() { 489 checkNewFormat(); 490 return this.maj; 491 } 492 493 /** 494 * Gets the minor device id 495 * 496 * @return the minor device id. 497 * @throws UnsupportedOperationException if format is not a new format 498 */ 499 public long getDeviceMin() { 500 checkNewFormat(); 501 return this.min; 502 } 503 504 /** 505 * Gets the format for this entry. 506 * 507 * @return the format. 508 */ 509 public short getFormat() { 510 return this.fileFormat; 511 } 512 513 /** 514 * Gets the group id. 515 * 516 * @return the group id. 517 */ 518 public long getGID() { 519 return this.gid; 520 } 521 522 /** 523 * Gets the number of bytes needed to pad the header to the alignment boundary. 524 * 525 * @deprecated This method doesn't properly work for multi-byte encodings. And creates corrupt archives. Use {@link #getHeaderPadCount(Charset)} or 526 * {@link #getHeaderPadCount(long)} in any case. 527 * @return the number of bytes needed to pad the header (0,1,2,3) 528 */ 529 @Deprecated 530 public int getHeaderPadCount() { 531 return getHeaderPadCount(null); 532 } 533 534 /** 535 * Gets the number of bytes needed to pad the header to the alignment boundary. 536 * 537 * @param charset The character set used to encode the entry name in the stream. 538 * @return the number of bytes needed to pad the header (0,1,2,3) 539 * @since 1.18 540 */ 541 public int getHeaderPadCount(final Charset charset) { 542 if (name == null) { 543 return 0; 544 } 545 if (charset == null) { 546 return getHeaderPadCount(name.length()); 547 } 548 return getHeaderPadCount(name.getBytes(charset).length); 549 } 550 551 /** 552 * Gets the number of bytes needed to pad the header to the alignment boundary. 553 * 554 * @param nameSize The length of the name in bytes, as read in the stream. Without the trailing zero byte. 555 * @return the number of bytes needed to pad the header (0,1,2,3) 556 * 557 * @since 1.18 558 */ 559 public int getHeaderPadCount(final long nameSize) { 560 if (this.alignmentBoundary == 0) { 561 return 0; 562 } 563 int size = this.headerSize + 1; // Name has terminating null 564 if (name != null) { 565 size = ExactMath.add(size, nameSize); 566 } 567 final int remain = size % this.alignmentBoundary; 568 if (remain > 0) { 569 return this.alignmentBoundary - remain; 570 } 571 return 0; 572 } 573 574 /** 575 * Gets the header size for this CPIO format 576 * 577 * @return the header size in bytes. 578 */ 579 public int getHeaderSize() { 580 return this.headerSize; 581 } 582 583 /** 584 * Sets the inode. 585 * 586 * @return the inode. 587 */ 588 public long getInode() { 589 return this.inode; 590 } 591 592 @Override 593 public Date getLastModifiedDate() { 594 return new Date(1000 * getTime()); 595 } 596 597 /** 598 * Gets the mode of this entry (e.g. directory, regular file). 599 * 600 * @return the mode. 601 */ 602 public long getMode() { 603 return mode == 0 && !CPIO_TRAILER.equals(name) ? C_ISREG : mode; 604 } 605 606 /** 607 * Gets the name. 608 * 609 * <p> 610 * This method returns the raw name as it is stored inside of the archive. 611 * </p> 612 * 613 * @return the name. 614 */ 615 @Override 616 public String getName() { 617 return this.name; 618 } 619 620 /** 621 * Gets the number of links. 622 * 623 * @return the number of links. 624 */ 625 public long getNumberOfLinks() { 626 return nlink == 0 ? isDirectory() ? 2 : 1 : nlink; 627 } 628 629 /** 630 * Gets the remote device id. 631 * 632 * @return the remote device id. 633 * @throws UnsupportedOperationException if this method is called for a CpioArchiveEntry with a new format. 634 */ 635 public long getRemoteDevice() { 636 checkOldFormat(); 637 return this.rmin; 638 } 639 640 /** 641 * Gets the remote major device id. 642 * 643 * @return the remote major device id. 644 * @throws UnsupportedOperationException if this method is called for a CpioArchiveEntry with an old format. 645 */ 646 public long getRemoteDeviceMaj() { 647 checkNewFormat(); 648 return this.rmaj; 649 } 650 651 /** 652 * Gets the remote minor device id. 653 * 654 * @return the remote minor device id. 655 * @throws UnsupportedOperationException if this method is called for a CpioArchiveEntry with an old format. 656 */ 657 public long getRemoteDeviceMin() { 658 checkNewFormat(); 659 return this.rmin; 660 } 661 662 /** 663 * Gets the filesize. 664 * 665 * @return the filesize. 666 * @see org.apache.commons.compress.archivers.ArchiveEntry#getSize() 667 */ 668 @Override 669 public long getSize() { 670 return this.filesize; 671 } 672 673 /** 674 * Gets the time in seconds. 675 * 676 * @return the time. 677 */ 678 public long getTime() { 679 return this.mtime; 680 } 681 682 /** 683 * Gets the user id. 684 * 685 * @return the user id. 686 */ 687 public long getUID() { 688 return this.uid; 689 } 690 691 /* 692 * (non-Javadoc) 693 * 694 * @see Object#hashCode() 695 */ 696 @Override 697 public int hashCode() { 698 return Objects.hash(name); 699 } 700 701 /** 702 * Checks if this entry represents a block device. 703 * 704 * @return TRUE if this entry is a block device. 705 */ 706 public boolean isBlockDevice() { 707 return CpioUtil.fileType(mode) == C_ISBLK; 708 } 709 710 /** 711 * Checks if this entry represents a character device. 712 * 713 * @return TRUE if this entry is a character device. 714 */ 715 public boolean isCharacterDevice() { 716 return CpioUtil.fileType(mode) == C_ISCHR; 717 } 718 719 /** 720 * Checks if this entry represents a directory. 721 * 722 * @return TRUE if this entry is a directory. 723 */ 724 @Override 725 public boolean isDirectory() { 726 return CpioUtil.fileType(mode) == C_ISDIR; 727 } 728 729 /** 730 * Checks if this entry represents a network device. 731 * 732 * @return TRUE if this entry is a network device. 733 */ 734 public boolean isNetwork() { 735 return CpioUtil.fileType(mode) == C_ISNWK; 736 } 737 738 /** 739 * Checks if this entry represents a pipe. 740 * 741 * @return TRUE if this entry is a pipe. 742 */ 743 public boolean isPipe() { 744 return CpioUtil.fileType(mode) == C_ISFIFO; 745 } 746 747 /** 748 * Checks if this entry represents a regular file. 749 * 750 * @return TRUE if this entry is a regular file. 751 */ 752 public boolean isRegularFile() { 753 return CpioUtil.fileType(mode) == C_ISREG; 754 } 755 756 /** 757 * Checks if this entry represents a socket. 758 * 759 * @return TRUE if this entry is a socket. 760 */ 761 public boolean isSocket() { 762 return CpioUtil.fileType(mode) == C_ISSOCK; 763 } 764 765 /** 766 * Checks if this entry represents a symbolic link. 767 * 768 * @return TRUE if this entry is a symbolic link. 769 */ 770 public boolean isSymbolicLink() { 771 return CpioUtil.fileType(mode) == C_ISLNK; 772 } 773 774 /** 775 * Sets the checksum. The checksum is calculated by adding all bytes of a file to transfer (crc += buf[pos] & 0xFF). 776 * 777 * @param chksum The checksum to set. 778 */ 779 public void setChksum(final long chksum) { 780 checkNewFormat(); 781 this.chksum = chksum & 0xFFFFFFFFL; 782 } 783 784 /** 785 * Sets the device id. 786 * 787 * @param device The device id to set. 788 * @throws UnsupportedOperationException if this method is called for a CpioArchiveEntry with a new format. 789 */ 790 public void setDevice(final long device) { 791 checkOldFormat(); 792 this.min = device; 793 } 794 795 /** 796 * Sets major device id. 797 * 798 * @param maj The major device id to set. 799 */ 800 public void setDeviceMaj(final long maj) { 801 checkNewFormat(); 802 this.maj = maj; 803 } 804 805 /** 806 * Sets the minor device id 807 * 808 * @param min The minor device id to set. 809 */ 810 public void setDeviceMin(final long min) { 811 checkNewFormat(); 812 this.min = min; 813 } 814 815 /** 816 * Sets the group id. 817 * 818 * @param gid The group id to set. 819 */ 820 public void setGID(final long gid) { 821 this.gid = gid; 822 } 823 824 /** 825 * Sets the inode. 826 * 827 * @param inode The inode to set. 828 */ 829 public void setInode(final long inode) { 830 this.inode = inode; 831 } 832 833 /** 834 * Sets the mode of this entry (e.g. directory, regular file). 835 * 836 * @param mode The mode to set. 837 */ 838 public void setMode(final long mode) { 839 final long maskedMode = mode & S_IFMT; 840 switch ((int) maskedMode) { 841 case C_ISDIR: 842 case C_ISLNK: 843 case C_ISREG: 844 case C_ISFIFO: 845 case C_ISCHR: 846 case C_ISBLK: 847 case C_ISSOCK: 848 case C_ISNWK: 849 break; 850 default: 851 throw new IllegalArgumentException("Unknown mode. " + "Full: " + Long.toHexString(mode) + " Masked: " + Long.toHexString(maskedMode)); 852 } 853 854 this.mode = mode; 855 } 856 857 /** 858 * Sets the name. 859 * 860 * @param name The name to set. 861 */ 862 public void setName(final String name) { 863 this.name = name; 864 } 865 866 /** 867 * Sets the number of links. 868 * 869 * @param nlink The number of links to set. 870 */ 871 public void setNumberOfLinks(final long nlink) { 872 this.nlink = nlink; 873 } 874 875 /** 876 * Sets the remote device id. 877 * 878 * @param device The remote device id to set. 879 * @throws UnsupportedOperationException if this method is called for a CpioArchiveEntry with a new format. 880 */ 881 public void setRemoteDevice(final long device) { 882 checkOldFormat(); 883 this.rmin = device; 884 } 885 886 /** 887 * Sets the remote major device id. 888 * 889 * @param rmaj The remote major device id to set. 890 * @throws UnsupportedOperationException if this method is called for a CpioArchiveEntry with an old format. 891 */ 892 public void setRemoteDeviceMaj(final long rmaj) { 893 checkNewFormat(); 894 this.rmaj = rmaj; 895 } 896 897 /** 898 * Sets the remote minor device id. 899 * 900 * @param rmin The remote minor device id to set. 901 * @throws UnsupportedOperationException if this method is called for a CpioArchiveEntry with an old format. 902 */ 903 public void setRemoteDeviceMin(final long rmin) { 904 checkNewFormat(); 905 this.rmin = rmin; 906 } 907 908 /** 909 * Sets the filesize. 910 * 911 * @param size The filesize to set. 912 */ 913 public void setSize(final long size) { 914 if (size < 0 || size > 0xFFFFFFFFL) { 915 throw new IllegalArgumentException("Invalid entry size <" + size + ">"); 916 } 917 this.filesize = size; 918 } 919 920 /** 921 * Sets the time. 922 * 923 * @param time The time to set. 924 */ 925 public void setTime(final FileTime time) { 926 this.mtime = TimeUtils.toUnixTime(time); 927 } 928 929 /** 930 * Sets the time in seconds. 931 * 932 * @param time The time to set. 933 */ 934 public void setTime(final long time) { 935 this.mtime = time; 936 } 937 938 /** 939 * Sets the user id. 940 * 941 * @param uid The user id to set. 942 */ 943 public void setUID(final long uid) { 944 this.uid = uid; 945 } 946 }