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.util.Date;
023
024import 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</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 <a href="http://people.freebsd.org/~kientzle/libarchive/man/cpio.5.txt">http://people.freebsd.org/~kientzle/libarchive/man/cpio.5.txt</a>
145 */
146public 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     * <p>
196     * Possible format values are:
197     * <pre>
198     * CpioConstants.FORMAT_NEW
199     * CpioConstants.FORMAT_NEW_CRC
200     * CpioConstants.FORMAT_OLD_BINARY
201     * CpioConstants.FORMAT_OLD_ASCII
202     * </pre>
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     * <p>
247     * Possible format values are:
248     * <pre>
249     * CpioConstants.FORMAT_NEW
250     * CpioConstants.FORMAT_NEW_CRC
251     * CpioConstants.FORMAT_OLD_BINARY
252     * CpioConstants.FORMAT_OLD_ASCII
253     * </pre>
254     * 
255     * @since 1.1
256     */
257    public CpioArchiveEntry(final short format, final String name) {
258        this(format);
259        this.name = name;
260    }
261
262    /**
263     * Creates a CPIOArchiveEntry with a specified name. The format of
264     * this entry will be the new format.
265     * 
266     * @param name
267     *            The name of this entry.
268     * @param size
269     *            The size of this entry
270     */
271    public CpioArchiveEntry(final String name, final long size) {
272        this(name);
273        this.setSize(size);
274    }
275
276    /**
277     * Creates a CPIOArchiveEntry with a specified name.
278     * 
279     * @param format
280     *            The cpio format for this entry.
281     * @param name
282     *            The name of this entry.
283     * @param size
284     *            The size of this entry
285     * <p>
286     * Possible format values are:
287     * <pre>
288     * CpioConstants.FORMAT_NEW
289     * CpioConstants.FORMAT_NEW_CRC
290     * CpioConstants.FORMAT_OLD_BINARY
291     * CpioConstants.FORMAT_OLD_ASCII
292     * </pre>
293     * 
294     * @since 1.1
295     */
296    public CpioArchiveEntry(final short format, final String name,
297                            final long size) {
298        this(format, name);
299        this.setSize(size);
300    }
301
302    /**
303     * Creates a CPIOArchiveEntry with a specified name for a
304     * specified file. The format of this entry will be the new
305     * format.
306     * 
307     * @param inputFile
308     *            The file to gather information from.
309     * @param entryName
310     *            The name of this entry.
311     */
312    public CpioArchiveEntry(File inputFile, String entryName) {
313        this(FORMAT_NEW, inputFile, entryName);
314    }
315
316    /**
317     * Creates a CPIOArchiveEntry with a specified name for a
318     * specified file.
319     * 
320     * @param format
321     *            The cpio format for this entry.
322     * @param inputFile
323     *            The file to gather information from.
324     * @param entryName
325     *            The name of this entry.
326     * <p>
327     * Possible format values are:
328     * <pre>
329     * CpioConstants.FORMAT_NEW
330     * CpioConstants.FORMAT_NEW_CRC
331     * CpioConstants.FORMAT_OLD_BINARY
332     * CpioConstants.FORMAT_OLD_ASCII
333     * </pre>
334     * 
335     * @since 1.1
336     */
337    public CpioArchiveEntry(final short format, File inputFile,
338                            String entryName) {
339        this(format, entryName, inputFile.isFile() ? inputFile.length() : 0);
340        if (inputFile.isDirectory()){
341            setMode(C_ISDIR);
342        } else if (inputFile.isFile()){
343            setMode(C_ISREG);
344        } else {
345            throw new IllegalArgumentException("Cannot determine type of file "
346                                               + inputFile.getName());
347        }
348        // TODO set other fields as needed
349        setTime(inputFile.lastModified() / 1000);
350    }
351
352    /**
353     * Check if the method is allowed for the defined format.
354     */
355    private void checkNewFormat() {
356        if ((this.fileFormat & FORMAT_NEW_MASK) == 0) {
357            throw new UnsupportedOperationException();
358        }
359    }
360
361    /**
362     * Check if the method is allowed for the defined format.
363     */
364    private void checkOldFormat() {
365        if ((this.fileFormat & FORMAT_OLD_MASK) == 0) {
366            throw new UnsupportedOperationException();
367        }
368    }
369
370    /**
371     * Get the checksum.
372     * Only supported for the new formats.
373     * 
374     * @return Returns the checksum.
375     * @throws UnsupportedOperationException if the format is not a new format
376     */
377    public long getChksum() {
378        checkNewFormat();
379        return this.chksum;
380    }
381
382    /**
383     * Get the device id.
384     * 
385     * @return Returns the device id.
386     * @throws UnsupportedOperationException
387     *             if this method is called for a CPIOArchiveEntry with a new
388     *             format.
389     */
390    public long getDevice() {
391        checkOldFormat();
392        return this.min;
393    }
394
395    /**
396     * Get the major device id.
397     * 
398     * @return Returns the major device id.
399     * @throws UnsupportedOperationException
400     *             if this method is called for a CPIOArchiveEntry with an old
401     *             format.
402     */
403    public long getDeviceMaj() {
404        checkNewFormat();
405        return this.maj;
406    }
407
408    /**
409     * Get the minor device id
410     * 
411     * @return Returns the minor device id.
412     * @throws UnsupportedOperationException if format is not a new format
413     */
414    public long getDeviceMin() {
415        checkNewFormat();
416        return this.min;
417    }
418
419    /**
420     * Get the filesize.
421     * 
422     * @return Returns the filesize.
423     * @see org.apache.commons.compress.archivers.ArchiveEntry#getSize()
424     */
425    public long getSize() {
426        return this.filesize;
427    }
428
429    /**
430     * Get the format for this entry.
431     * 
432     * @return Returns the format.
433     */
434    public short getFormat() {
435        return this.fileFormat;
436    }
437
438    /**
439     * Get the group id.
440     * 
441     * @return Returns the group id.
442     */
443    public long getGID() {
444        return this.gid;
445    }
446
447    /**
448     * Get the header size for this CPIO format
449     * 
450     * @return Returns the header size in bytes.
451     */
452    public int getHeaderSize() {
453        return this.headerSize;
454    }
455
456    /**
457     * Get the alignment boundary for this CPIO format
458     * 
459     * @return Returns the aligment boundary (0, 2, 4) in bytes
460     */
461    public int getAlignmentBoundary() {
462        return this.alignmentBoundary;
463    }
464
465    /**
466     * Get the number of bytes needed to pad the header to the alignment boundary.
467     * 
468     * @return the number of bytes needed to pad the header (0,1,2,3)
469     */
470    public int getHeaderPadCount(){
471        if (this.alignmentBoundary == 0) { return 0; }
472        int size = this.headerSize + 1;  // Name has terminating null
473        if (name != null) {
474            size += name.length();
475        }
476        int remain = size % this.alignmentBoundary;
477        if (remain > 0){
478            return this.alignmentBoundary - remain;
479        }
480        return 0;
481    }
482
483    /**
484     * Get the number of bytes needed to pad the data to the alignment boundary.
485     * 
486     * @return the number of bytes needed to pad the data (0,1,2,3)
487     */
488    public int getDataPadCount(){
489        if (this.alignmentBoundary == 0) { return 0; }
490        long size = this.filesize;
491        int remain = (int) (size % this.alignmentBoundary);
492        if (remain > 0){
493            return this.alignmentBoundary - remain;
494        }
495        return 0;
496    }
497
498    /**
499     * Set the inode.
500     * 
501     * @return Returns the inode.
502     */
503    public long getInode() {
504        return this.inode;
505    }
506
507    /**
508     * Get the mode of this entry (e.g. directory, regular file).
509     * 
510     * @return Returns the mode.
511     */
512    public long getMode() {
513        return mode == 0 && !CPIO_TRAILER.equals(name) ? C_ISREG : mode;
514    }
515
516    /**
517     * Get the name.
518     * 
519     * @return Returns the name.
520     */
521    public String getName() {
522        return this.name;
523    }
524
525    /**
526     * Get the number of links.
527     * 
528     * @return Returns the number of links.
529     */
530    public long getNumberOfLinks() {
531        return nlink == 0 ?
532            isDirectory() ? 2 : 1
533            : nlink;
534    }
535
536    /**
537     * Get the remote device id.
538     * 
539     * @return Returns the remote device id.
540     * @throws UnsupportedOperationException
541     *             if this method is called for a CPIOArchiveEntry with a new
542     *             format.
543     */
544    public long getRemoteDevice() {
545        checkOldFormat();
546        return this.rmin;
547    }
548
549    /**
550     * Get the remote major device id.
551     * 
552     * @return Returns the remote major device id.
553     * @throws UnsupportedOperationException
554     *             if this method is called for a CPIOArchiveEntry with an old
555     *             format.
556     */
557    public long getRemoteDeviceMaj() {
558        checkNewFormat();
559        return this.rmaj;
560    }
561
562    /**
563     * Get the remote minor device id.
564     * 
565     * @return Returns the remote minor device id.
566     * @throws UnsupportedOperationException
567     *             if this method is called for a CPIOArchiveEntry with an old
568     *             format.
569     */
570    public long getRemoteDeviceMin() {
571        checkNewFormat();
572        return this.rmin;
573    }
574
575    /**
576     * Get the time in seconds.
577     * 
578     * @return Returns the time.
579     */
580    public long getTime() {
581        return this.mtime;
582    }
583
584    public Date getLastModifiedDate() {
585        return new Date(1000 * getTime());
586    }
587
588    /**
589     * Get the user id.
590     * 
591     * @return Returns the user id.
592     */
593    public long getUID() {
594        return this.uid;
595    }
596
597    /**
598     * Check if this entry represents a block device.
599     * 
600     * @return TRUE if this entry is a block device.
601     */
602    public boolean isBlockDevice() {
603        return CpioUtil.fileType(mode) == C_ISBLK;
604    }
605
606    /**
607     * Check if this entry represents a character device.
608     * 
609     * @return TRUE if this entry is a character device.
610     */
611    public boolean isCharacterDevice() {
612        return CpioUtil.fileType(mode) == C_ISCHR;
613    }
614
615    /**
616     * Check if this entry represents a directory.
617     * 
618     * @return TRUE if this entry is a directory.
619     */
620    public boolean isDirectory() {
621        return CpioUtil.fileType(mode) == C_ISDIR;
622    }
623
624    /**
625     * Check if this entry represents a network device.
626     * 
627     * @return TRUE if this entry is a network device.
628     */
629    public boolean isNetwork() {
630        return CpioUtil.fileType(mode) == C_ISNWK;
631    }
632
633    /**
634     * Check if this entry represents a pipe.
635     * 
636     * @return TRUE if this entry is a pipe.
637     */
638    public boolean isPipe() {
639        return CpioUtil.fileType(mode) == C_ISFIFO;
640    }
641
642    /**
643     * Check if this entry represents a regular file.
644     * 
645     * @return TRUE if this entry is a regular file.
646     */
647    public boolean isRegularFile() {
648        return CpioUtil.fileType(mode) == C_ISREG;
649    }
650
651    /**
652     * Check if this entry represents a socket.
653     * 
654     * @return TRUE if this entry is a socket.
655     */
656    public boolean isSocket() {
657        return CpioUtil.fileType(mode) == C_ISSOCK;
658    }
659
660    /**
661     * Check if this entry represents a symbolic link.
662     * 
663     * @return TRUE if this entry is a symbolic link.
664     */
665    public boolean isSymbolicLink() {
666        return CpioUtil.fileType(mode) == C_ISLNK;
667    }
668
669    /**
670     * Set the checksum. The checksum is calculated by adding all bytes of a
671     * file to transfer (crc += buf[pos] &amp; 0xFF).
672     * 
673     * @param chksum
674     *            The checksum to set.
675     */
676    public void setChksum(final long chksum) {
677        checkNewFormat();
678        this.chksum = chksum;
679    }
680
681    /**
682     * Set the device id.
683     * 
684     * @param device
685     *            The device id to set.
686     * @throws UnsupportedOperationException
687     *             if this method is called for a CPIOArchiveEntry with a new
688     *             format.
689     */
690    public void setDevice(final long device) {
691        checkOldFormat();
692        this.min = device;
693    }
694
695    /**
696     * Set major device id.
697     * 
698     * @param maj
699     *            The major device id to set.
700     */
701    public void setDeviceMaj(final long maj) {
702        checkNewFormat();
703        this.maj = maj;
704    }
705
706    /**
707     * Set the minor device id
708     * 
709     * @param min
710     *            The minor device id to set.
711     */
712    public void setDeviceMin(final long min) {
713        checkNewFormat();
714        this.min = min;
715    }
716
717    /**
718     * Set the filesize.
719     * 
720     * @param size
721     *            The filesize to set.
722     */
723    public void setSize(final long size) {
724        if (size < 0 || size > 0xFFFFFFFFL) {
725            throw new IllegalArgumentException("invalid entry size <" + size
726                                               + ">");
727        }
728        this.filesize = size;
729    }
730
731    /**
732     * Set the group id.
733     * 
734     * @param gid
735     *            The group id to set.
736     */
737    public void setGID(final long gid) {
738        this.gid = gid;
739    }
740
741    /**
742     * Set the inode.
743     * 
744     * @param inode
745     *            The inode to set.
746     */
747    public void setInode(final long inode) {
748        this.inode = inode;
749    }
750
751    /**
752     * Set the mode of this entry (e.g. directory, regular file).
753     * 
754     * @param mode
755     *            The mode to set.
756     */
757    public void setMode(final long mode) {
758        final long maskedMode = mode & S_IFMT;
759        switch ((int) maskedMode) {
760        case C_ISDIR:
761        case C_ISLNK:
762        case C_ISREG:
763        case C_ISFIFO:
764        case C_ISCHR:
765        case C_ISBLK:
766        case C_ISSOCK:
767        case C_ISNWK:
768            break;
769        default:
770            throw new IllegalArgumentException(
771                                               "Unknown mode. "
772                                               + "Full: " + Long.toHexString(mode) 
773                                               + " Masked: " + Long.toHexString(maskedMode));
774        }
775
776        this.mode = mode;
777    }
778
779    /**
780     * Set the name.
781     * 
782     * @param name
783     *            The name to set.
784     */
785    public void setName(final String name) {
786        this.name = name;
787    }
788
789    /**
790     * Set the number of links.
791     * 
792     * @param nlink
793     *            The number of links to set.
794     */
795    public void setNumberOfLinks(final long nlink) {
796        this.nlink = nlink;
797    }
798
799    /**
800     * Set the remote device id.
801     * 
802     * @param device
803     *            The remote device id to set.
804     * @throws UnsupportedOperationException
805     *             if this method is called for a CPIOArchiveEntry with a new
806     *             format.
807     */
808    public void setRemoteDevice(final long device) {
809        checkOldFormat();
810        this.rmin = device;
811    }
812
813    /**
814     * Set the remote major device id.
815     * 
816     * @param rmaj
817     *            The remote major device id to set.
818     * @throws UnsupportedOperationException
819     *             if this method is called for a CPIOArchiveEntry with an old
820     *             format.
821     */
822    public void setRemoteDeviceMaj(final long rmaj) {
823        checkNewFormat();
824        this.rmaj = rmaj;
825    }
826
827    /**
828     * Set the remote minor device id.
829     * 
830     * @param rmin
831     *            The remote minor device id to set.
832     * @throws UnsupportedOperationException
833     *             if this method is called for a CPIOArchiveEntry with an old
834     *             format.
835     */
836    public void setRemoteDeviceMin(final long rmin) {
837        checkNewFormat();
838        this.rmin = rmin;
839    }
840
841    /**
842     * Set the time in seconds.
843     * 
844     * @param time
845     *            The time to set.
846     */
847    public void setTime(final long time) {
848        this.mtime = time;
849    }
850
851    /**
852     * Set the user id.
853     * 
854     * @param uid
855     *            The user id to set.
856     */
857    public void setUID(final long uid) {
858        this.uid = uid;
859    }
860
861    /* (non-Javadoc)
862     * @see java.lang.Object#hashCode()
863     */
864    @Override
865    public int hashCode() {
866        final int prime = 31;
867        int result = 1;
868        result = prime * result + (name == null ? 0 : name.hashCode());
869        return result;
870    }
871
872    /* (non-Javadoc)
873     * @see java.lang.Object#equals(java.lang.Object)
874     */
875    @Override
876    public boolean equals(Object obj) {
877        if (this == obj) {
878            return true;
879        }
880        if (obj == null || getClass() != obj.getClass()) {
881            return false;
882        }
883        CpioArchiveEntry other = (CpioArchiveEntry) obj;
884        if (name == null) {
885            if (other.name != null) {
886                return false;
887            }
888        } else if (!name.equals(other.name)) {
889            return false;
890        }
891        return true;
892    }
893}