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