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