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