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