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