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 * https://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.io.file.attribute.FileTimes; 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 * 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 * @throws IOException if an I/O error occurs 318 * @since 1.21 319 */ 320 public CpioArchiveEntry(final short format, final Path inputPath, final String entryName, final LinkOption... options) throws IOException { 321 this(format, entryName, Files.isRegularFile(inputPath, options) ? Files.size(inputPath) : 0); 322 if (Files.isDirectory(inputPath, options)) { 323 setMode(C_ISDIR); 324 } else if (Files.isRegularFile(inputPath, options)) { 325 setMode(C_ISREG); 326 } else { 327 throw new IllegalArgumentException("Cannot determine type of file " + inputPath); 328 } 329 // TODO set other fields as needed 330 setTime(Files.getLastModifiedTime(inputPath, options)); 331 } 332 333 /** 334 * Creates a CpioArchiveEntry with a specified name. 335 * 336 * @param format The cpio format for this entry. 337 * @param name The name of this entry. 338 * <p> 339 * Possible format values are: 340 * 341 * <pre> 342 * CpioConstants.FORMAT_NEW 343 * CpioConstants.FORMAT_NEW_CRC 344 * CpioConstants.FORMAT_OLD_BINARY 345 * CpioConstants.FORMAT_OLD_ASCII 346 * </pre> 347 * 348 * @since 1.1 349 */ 350 public CpioArchiveEntry(final short format, final String name) { 351 this(format); 352 this.name = name; 353 } 354 355 /** 356 * Creates a CpioArchiveEntry with a specified name. 357 * 358 * @param format The cpio format for this entry. 359 * @param name The name of this entry. 360 * @param size The size of this entry 361 * <p> 362 * Possible format values are: 363 * 364 * <pre> 365 * CpioConstants.FORMAT_NEW 366 * CpioConstants.FORMAT_NEW_CRC 367 * CpioConstants.FORMAT_OLD_BINARY 368 * CpioConstants.FORMAT_OLD_ASCII 369 * </pre> 370 * 371 * @since 1.1 372 */ 373 public CpioArchiveEntry(final short format, final String name, final long size) { 374 this(format, name); 375 setSize(size); 376 } 377 378 /** 379 * Creates a CpioArchiveEntry with a specified name. The format of this entry will be the new format. 380 * 381 * @param name The name of this entry. 382 */ 383 public CpioArchiveEntry(final String name) { 384 this(FORMAT_NEW, name); 385 } 386 387 /** 388 * Creates a CpioArchiveEntry with a specified name. The format of this entry will be the new format. 389 * 390 * @param name The name of this entry. 391 * @param size The size of this entry 392 */ 393 public CpioArchiveEntry(final String name, final long size) { 394 this(name); 395 setSize(size); 396 } 397 398 /** 399 * Checks if the method is allowed for the defined format. 400 */ 401 private void checkNewFormat() { 402 if ((this.fileFormat & FORMAT_NEW_MASK) == 0) { 403 throw new UnsupportedOperationException(); 404 } 405 } 406 407 /** 408 * Checks if the method is allowed for the defined format. 409 */ 410 private void checkOldFormat() { 411 if ((this.fileFormat & FORMAT_OLD_MASK) == 0) { 412 throw new UnsupportedOperationException(); 413 } 414 } 415 416 /* 417 * (non-Javadoc) 418 * 419 * @see Object#equals(Object) 420 */ 421 @Override 422 public boolean equals(final Object obj) { 423 if (this == obj) { 424 return true; 425 } 426 if (obj == null || getClass() != obj.getClass()) { 427 return false; 428 } 429 final CpioArchiveEntry other = (CpioArchiveEntry) obj; 430 return Objects.equals(name, other.name); 431 } 432 433 /** 434 * Gets the alignment boundary for this CPIO format 435 * 436 * @return the alignment boundary (0, 2, 4) in bytes 437 */ 438 public int getAlignmentBoundary() { 439 return this.alignmentBoundary; 440 } 441 442 /** 443 * Gets the checksum. Only supported for the new formats. 444 * 445 * @return the checksum. 446 * @throws UnsupportedOperationException if the format is not a new format 447 */ 448 public long getChksum() { 449 checkNewFormat(); 450 return this.chksum & 0xFFFFFFFFL; 451 } 452 453 /** 454 * Gets the number of bytes needed to pad the data to the alignment boundary. 455 * 456 * @return the number of bytes needed to pad the data (0,1,2,3) 457 */ 458 public int getDataPadCount() { 459 if (this.alignmentBoundary == 0) { 460 return 0; 461 } 462 final long size = this.fileSize; 463 final int remain = (int) (size % this.alignmentBoundary); 464 if (remain > 0) { 465 return this.alignmentBoundary - remain; 466 } 467 return 0; 468 } 469 470 /** 471 * Gets the device id. 472 * 473 * @return the device id. 474 * @throws UnsupportedOperationException if this method is called for a CpioArchiveEntry with a new format. 475 */ 476 public long getDevice() { 477 checkOldFormat(); 478 return this.min; 479 } 480 481 /** 482 * Gets the major device id. 483 * 484 * @return the major device id. 485 * @throws UnsupportedOperationException if this method is called for a CpioArchiveEntry with an old format. 486 */ 487 public long getDeviceMaj() { 488 checkNewFormat(); 489 return this.maj; 490 } 491 492 /** 493 * Gets the minor device id 494 * 495 * @return the minor device id. 496 * @throws UnsupportedOperationException if format is not a new format 497 */ 498 public long getDeviceMin() { 499 checkNewFormat(); 500 return this.min; 501 } 502 503 /** 504 * Gets the format for this entry. 505 * 506 * @return the format. 507 */ 508 public short getFormat() { 509 return this.fileFormat; 510 } 511 512 /** 513 * Gets the group id. 514 * 515 * @return the group id. 516 */ 517 public long getGID() { 518 return this.gid; 519 } 520 521 /** 522 * Gets the number of bytes needed to pad the header to the alignment boundary. 523 * 524 * @deprecated This method doesn't properly work for multi-byte encodings. And creates corrupt archives. Use {@link #getHeaderPadCount(Charset)} or 525 * {@link #getHeaderPadCount(long)} in any case. 526 * @return the number of bytes needed to pad the header (0,1,2,3) 527 */ 528 @Deprecated 529 public int getHeaderPadCount() { 530 return getHeaderPadCount(null); 531 } 532 533 /** 534 * Gets the number of bytes needed to pad the header to the alignment boundary. 535 * 536 * @param charset The character set used to encode the entry name in the stream. 537 * @return the number of bytes needed to pad the header (0,1,2,3) 538 * @since 1.18 539 */ 540 public int getHeaderPadCount(final Charset charset) { 541 if (name == null) { 542 return 0; 543 } 544 if (charset == null) { 545 return getHeaderPadCount(name.length()); 546 } 547 return getHeaderPadCount(name.getBytes(charset).length); 548 } 549 550 /** 551 * Gets the number of bytes needed to pad the header to the alignment boundary. 552 * 553 * @param nameSize The length of the name in bytes, as read in the stream. Without the trailing zero byte. 554 * @return the number of bytes needed to pad the header (0,1,2,3) 555 * @since 1.18 556 */ 557 public int getHeaderPadCount(final long nameSize) { 558 if (this.alignmentBoundary == 0) { 559 return 0; 560 } 561 int size = this.headerSize + 1; // Name has terminating null 562 if (name != null) { 563 size = ExactMath.add(size, nameSize); 564 } 565 final int remain = size % this.alignmentBoundary; 566 if (remain > 0) { 567 return this.alignmentBoundary - remain; 568 } 569 return 0; 570 } 571 572 /** 573 * Gets the header size for this CPIO format 574 * 575 * @return the header size in bytes. 576 */ 577 public int getHeaderSize() { 578 return this.headerSize; 579 } 580 581 /** 582 * Sets the inode. 583 * 584 * @return the inode. 585 */ 586 public long getInode() { 587 return this.inode; 588 } 589 590 @Override 591 public Date getLastModifiedDate() { 592 return new Date(1000 * getTime()); 593 } 594 595 /** 596 * Gets the mode of this entry (for example directory, regular file). 597 * 598 * @return the mode. 599 */ 600 public long getMode() { 601 return mode == 0 && !CPIO_TRAILER.equals(name) ? C_ISREG : mode; 602 } 603 604 /** 605 * Gets the name. 606 * 607 * <p> 608 * This method returns the raw name as it is stored inside of the archive. 609 * </p> 610 * 611 * @return the name. 612 */ 613 @Override 614 public String getName() { 615 return this.name; 616 } 617 618 /** 619 * Gets the number of links. 620 * 621 * @return the number of links. 622 */ 623 public long getNumberOfLinks() { 624 return nlink == 0 ? isDirectory() ? 2 : 1 : nlink; 625 } 626 627 /** 628 * Gets the remote device id. 629 * 630 * @return the remote device id. 631 * @throws UnsupportedOperationException if this method is called for a CpioArchiveEntry with a new format. 632 */ 633 public long getRemoteDevice() { 634 checkOldFormat(); 635 return this.rmin; 636 } 637 638 /** 639 * Gets the remote major device id. 640 * 641 * @return the remote major device id. 642 * @throws UnsupportedOperationException if this method is called for a CpioArchiveEntry with an old format. 643 */ 644 public long getRemoteDeviceMaj() { 645 checkNewFormat(); 646 return this.rmaj; 647 } 648 649 /** 650 * Gets the remote minor device id. 651 * 652 * @return the remote minor device id. 653 * @throws UnsupportedOperationException if this method is called for a CpioArchiveEntry with an old format. 654 */ 655 public long getRemoteDeviceMin() { 656 checkNewFormat(); 657 return this.rmin; 658 } 659 660 /** 661 * Gets the file size. 662 * 663 * @return the file size. 664 * @see org.apache.commons.compress.archivers.ArchiveEntry#getSize() 665 */ 666 @Override 667 public long getSize() { 668 return this.fileSize; 669 } 670 671 /** 672 * Gets the time in seconds. 673 * 674 * @return the time. 675 */ 676 public long getTime() { 677 return this.mtime; 678 } 679 680 /** 681 * Gets the user id. 682 * 683 * @return the user id. 684 */ 685 public long getUID() { 686 return this.uid; 687 } 688 689 /* 690 * (non-Javadoc) 691 * 692 * @see Object#hashCode() 693 */ 694 @Override 695 public int hashCode() { 696 return Objects.hash(name); 697 } 698 699 /** 700 * Checks if this entry represents a block device. 701 * 702 * @return TRUE if this entry is a block device. 703 */ 704 public boolean isBlockDevice() { 705 return CpioUtil.fileType(mode) == C_ISBLK; 706 } 707 708 /** 709 * Checks if this entry represents a character device. 710 * 711 * @return TRUE if this entry is a character device. 712 */ 713 public boolean isCharacterDevice() { 714 return CpioUtil.fileType(mode) == C_ISCHR; 715 } 716 717 /** 718 * Checks if this entry represents a directory. 719 * 720 * @return TRUE if this entry is a directory. 721 */ 722 @Override 723 public boolean isDirectory() { 724 return CpioUtil.fileType(mode) == C_ISDIR; 725 } 726 727 /** 728 * Checks if this entry represents a network device. 729 * 730 * @return TRUE if this entry is a network device. 731 */ 732 public boolean isNetwork() { 733 return CpioUtil.fileType(mode) == C_ISNWK; 734 } 735 736 /** 737 * Checks if this entry represents a pipe. 738 * 739 * @return TRUE if this entry is a pipe. 740 */ 741 public boolean isPipe() { 742 return CpioUtil.fileType(mode) == C_ISFIFO; 743 } 744 745 /** 746 * Checks if this entry represents a regular file. 747 * 748 * @return TRUE if this entry is a regular file. 749 */ 750 public boolean isRegularFile() { 751 return CpioUtil.fileType(mode) == C_ISREG; 752 } 753 754 /** 755 * Checks if this entry represents a socket. 756 * 757 * @return TRUE if this entry is a socket. 758 */ 759 public boolean isSocket() { 760 return CpioUtil.fileType(mode) == C_ISSOCK; 761 } 762 763 /** 764 * Checks if this entry represents a symbolic link. 765 * 766 * @return TRUE if this entry is a symbolic link. 767 */ 768 public boolean isSymbolicLink() { 769 return CpioUtil.fileType(mode) == C_ISLNK; 770 } 771 772 /** 773 * Sets the checksum. The checksum is calculated by adding all bytes of a file to transfer (crc += buf[pos] & 0xFF). 774 * 775 * @param chksum The checksum to set. 776 */ 777 public void setChksum(final long chksum) { 778 checkNewFormat(); 779 this.chksum = chksum & 0xFFFFFFFFL; 780 } 781 782 /** 783 * Sets the device id. 784 * 785 * @param device The device id to set. 786 * @throws UnsupportedOperationException if this method is called for a CpioArchiveEntry with a new format. 787 */ 788 public void setDevice(final long device) { 789 checkOldFormat(); 790 this.min = device; 791 } 792 793 /** 794 * Sets major device id. 795 * 796 * @param maj The major device id to set. 797 */ 798 public void setDeviceMaj(final long maj) { 799 checkNewFormat(); 800 this.maj = maj; 801 } 802 803 /** 804 * Sets the minor device id 805 * 806 * @param min The minor device id to set. 807 */ 808 public void setDeviceMin(final long min) { 809 checkNewFormat(); 810 this.min = min; 811 } 812 813 /** 814 * Sets the group id. 815 * 816 * @param gid The group id to set. 817 */ 818 public void setGID(final long gid) { 819 this.gid = gid; 820 } 821 822 /** 823 * Sets the inode. 824 * 825 * @param inode The inode to set. 826 */ 827 public void setInode(final long inode) { 828 this.inode = inode; 829 } 830 831 /** 832 * Sets the mode of this entry (for example directory, regular file). 833 * 834 * @param mode The mode to set. 835 */ 836 public void setMode(final long mode) { 837 final long maskedMode = mode & S_IFMT; 838 switch ((int) maskedMode) { 839 case C_ISDIR: 840 case C_ISLNK: 841 case C_ISREG: 842 case C_ISFIFO: 843 case C_ISCHR: 844 case C_ISBLK: 845 case C_ISSOCK: 846 case C_ISNWK: 847 break; 848 default: 849 throw new IllegalArgumentException("Unknown mode. Full: " + Long.toHexString(mode) + " Masked: " + Long.toHexString(maskedMode)); 850 } 851 852 this.mode = mode; 853 } 854 855 /** 856 * Sets the name. 857 * 858 * @param name The name to set. 859 */ 860 public void setName(final String name) { 861 this.name = name; 862 } 863 864 /** 865 * Sets the number of links. 866 * 867 * @param nlink The number of links to set. 868 */ 869 public void setNumberOfLinks(final long nlink) { 870 this.nlink = nlink; 871 } 872 873 /** 874 * Sets the remote device id. 875 * 876 * @param device The remote device id to set. 877 * @throws UnsupportedOperationException if this method is called for a CpioArchiveEntry with a new format. 878 */ 879 public void setRemoteDevice(final long device) { 880 checkOldFormat(); 881 this.rmin = device; 882 } 883 884 /** 885 * Sets the remote major device id. 886 * 887 * @param rmaj The remote major device id to set. 888 * @throws UnsupportedOperationException if this method is called for a CpioArchiveEntry with an old format. 889 */ 890 public void setRemoteDeviceMaj(final long rmaj) { 891 checkNewFormat(); 892 this.rmaj = rmaj; 893 } 894 895 /** 896 * Sets the remote minor device id. 897 * 898 * @param rmin The remote minor device id to set. 899 * @throws UnsupportedOperationException if this method is called for a CpioArchiveEntry with an old format. 900 */ 901 public void setRemoteDeviceMin(final long rmin) { 902 checkNewFormat(); 903 this.rmin = rmin; 904 } 905 906 /** 907 * Sets the file size. 908 * 909 * @param size The file size to set. 910 */ 911 public void setSize(final long size) { 912 if (size < 0 || size > 0xFFFFFFFFL) { 913 throw new IllegalArgumentException("Invalid entry size <" + size + ">"); 914 } 915 this.fileSize = size; 916 } 917 918 /** 919 * Sets the time. 920 * 921 * @param time The time to set. 922 */ 923 public void setTime(final FileTime time) { 924 this.mtime = FileTimes.toUnixTime(time); 925 } 926 927 /** 928 * Sets the time in seconds. 929 * 930 * @param time The time to set. 931 */ 932 public void setTime(final long time) { 933 this.mtime = time; 934 } 935 936 /** 937 * Sets the user id. 938 * 939 * @param uid The user id to set. 940 */ 941 public void setUID(final long uid) { 942 this.uid = uid; 943 } 944 }