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