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