~ubuntu-branches/ubuntu/maverick/libcommons-compress-java/maverick

« back to all changes in this revision

Viewing changes to src/java/org/apache/commons/compress/archivers/tar/TarEntry.java

  • Committer: Bazaar Package Importer
  • Author(s): Torsten Werner
  • Date: 2007-12-17 15:17:09 UTC
  • Revision ID: james.westby@ubuntu.com-20071217151709-dqfo6iq1zxyssgf6
Tags: upstream-0~svn604876
ImportĀ upstreamĀ versionĀ 0~svn604876

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Licensed to the Apache Software Foundation (ASF) under one
 
3
 * or more contributor license agreements.  See the NOTICE file
 
4
 * distributed with this work for additional information
 
5
 * regarding copyright ownership.  The ASF licenses this file
 
6
 * to you under the Apache License, Version 2.0 (the
 
7
 * "License"); you may not use this file except in compliance
 
8
 * with the License.  You may obtain a copy of the License at
 
9
 *
 
10
 * http://www.apache.org/licenses/LICENSE-2.0
 
11
 *
 
12
 * Unless required by applicable law or agreed to in writing,
 
13
 * software distributed under the License is distributed on an
 
14
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 
15
 * KIND, either express or implied.  See the License for the
 
16
 * specific language governing permissions and limitations
 
17
 * under the License.
 
18
 */
 
19
package org.apache.commons.compress.archivers.tar;
 
20
 
 
21
import java.io.File;
 
22
import java.util.Date;
 
23
import java.util.Locale;
 
24
 
 
25
/**
 
26
 * This class represents an entry in a Tar archive. It consists of the entry's
 
27
 * header, as well as the entry's File. Entries can be instantiated in one of
 
28
 * three ways, depending on how they are to be used. <p>
 
29
 *
 
30
 * TarEntries that are created from the header bytes read from an archive are
 
31
 * instantiated with the TarEntry( byte[] ) constructor. These entries will be
 
32
 * used when extracting from or listing the contents of an archive. These
 
33
 * entries have their header filled in using the header bytes. They also set the
 
34
 * File to null, since they reference an archive entry not a file. <p>
 
35
 *
 
36
 * TarEntries that are created from Files that are to be written into an archive
 
37
 * are instantiated with the TarEntry( File ) constructor. These entries have
 
38
 * their header filled in using the File's information. They also keep a
 
39
 * reference to the File for convenience when writing entries. <p>
 
40
 *
 
41
 * Finally, TarEntries can be constructed from nothing but a name. This allows
 
42
 * the programmer to construct the entry by hand, for instance when only an
 
43
 * InputStream is available for writing to the archive, and the header
 
44
 * information is constructed from other information. In this case the header
 
45
 * fields are set to defaults and the File is set to null. <p>
 
46
 *
 
47
 * The C structure for a Tar Entry's header is: <pre>
 
48
 * struct header {
 
49
 * char name[NAMSIZ];
 
50
 * char mode[8];
 
51
 * char uid[8];
 
52
 * char gid[8];
 
53
 * char size[12];
 
54
 * char mtime[12];
 
55
 * char chksum[8];
 
56
 * char linkflag;
 
57
 * char linkname[NAMSIZ];
 
58
 * char magic[8];
 
59
 * char uname[TUNMLEN];
 
60
 * char gname[TGNMLEN];
 
61
 * char devmajor[8];
 
62
 * char devminor[8];
 
63
 * } header;
 
64
 * </pre>
 
65
 *
 
66
 * @author <a href="mailto:time@ice.com">Timothy Gerard Endres</a>
 
67
 * @author <a href="mailto:stefano@apache.org">Stefano Mazzocchi</a>
 
68
 * @author <a href="mailto:peter@apache.org">Peter Donald</a>
 
69
 * @version $Revision: 155439 $ $Date: 2007-01-09 10:24:33 +0100 (Di, 09 Jan 2007) $
 
70
 * @see TarInputStream
 
71
 * @see TarOutputStream
 
72
 */
 
73
public class TarEntry
 
74
{
 
75
        /**
 
76
     * The length of the mode field in a header buffer.
 
77
     */
 
78
        private final static int MODELEN = 8;
 
79
 
 
80
    /**
 
81
     * The length of the user id field in a header buffer.
 
82
     */
 
83
     private final static int UIDLEN = 8;
 
84
 
 
85
    /**
 
86
     * The length of the group id field in a header buffer.
 
87
     */
 
88
    private final static int GIDLEN = 8;
 
89
 
 
90
    /**
 
91
     * The length of the checksum field in a header buffer.
 
92
     */
 
93
    private final static int CHKSUMLEN = 8;
 
94
 
 
95
    /**
 
96
     * The length of the size field in a header buffer.
 
97
     */
 
98
    private final static int SIZELEN = 12;
 
99
 
 
100
    /**
 
101
     * The length of the magic field in a header buffer.
 
102
     */
 
103
    private final static int MAGICLEN = 8;
 
104
 
 
105
    /**
 
106
     * The length of the modification time field in a header buffer.
 
107
     */
 
108
    private final static int MODTIMELEN = 12;
 
109
 
 
110
    /**
 
111
     * The length of the user name field in a header buffer.
 
112
     */
 
113
    private final static int UNAMELEN = 32;
 
114
 
 
115
    /**
 
116
     * The length of the group name field in a header buffer.
 
117
     */
 
118
    private final static int GNAMELEN = 32;
 
119
 
 
120
    /**
 
121
     * The length of the devices field in a header buffer.
 
122
     */
 
123
    private final static int DEVLEN = 8;
 
124
 
 
125
    /**
 
126
     * LF_ constants represent the "link flag" of an entry, or more commonly,
 
127
     * the "entry type". This is the "old way" of indicating a normal file.
 
128
     */
 
129
    //private final static byte LF_OLDNORM = 0;
 
130
 
 
131
    /**
 
132
     * Normal file type.
 
133
     */
 
134
    private final static byte LF_NORMAL = (byte)'0';
 
135
 
 
136
    /**
 
137
     * Link file type.
 
138
     */
 
139
    //private final static byte LF_LINK = (byte)'1';
 
140
 
 
141
    /**
 
142
     * Symbolic link file type.
 
143
     */
 
144
    //private final static byte LF_SYMLINK = (byte)'2';
 
145
 
 
146
    /**
 
147
     * Character device file type.
 
148
     */
 
149
    //private final static byte LF_CHR = (byte)'3';
 
150
 
 
151
    /**
 
152
     * Block device file type.
 
153
     */
 
154
    //private final static byte LF_BLK = (byte)'4';
 
155
 
 
156
    /**
 
157
     * Directory file type.
 
158
     */
 
159
    private final static byte LF_DIR = (byte)'5';
 
160
 
 
161
    /**
 
162
     * FIFO (pipe) file type.
 
163
     */
 
164
    //private final static byte LF_FIFO = (byte)'6';
 
165
 
 
166
    /**
 
167
     * Contiguous file type.
 
168
     */
 
169
    //private final static byte LF_CONTIG = (byte)'7';
 
170
 
 
171
    /**
 
172
     * The magic tag representing a POSIX tar archive.
 
173
     */
 
174
    private final static String TMAGIC = "ustar";
 
175
 
 
176
    /**
 
177
     * The magic tag representing a GNU tar archive.
 
178
     */
 
179
    //private final static String GNU_TMAGIC = "ustar  ";
 
180
 
 
181
    /**
 
182
     * The name of the GNU tar entry which contains a long name.
 
183
     */
 
184
    static String GNU_LONGLINK = "././@LongLink";
 
185
 
 
186
    /**
 
187
     * Identifies the *next* file on the tape as having a long name.
 
188
     */
 
189
    static byte LF_GNUTYPE_LONGNAME = (byte)'L';
 
190
    
 
191
    
 
192
    
 
193
    /**
 
194
     * The length of the name field in a header buffer.
 
195
     */
 
196
    public static final int NAMELEN = 100;
 
197
 
 
198
    /**
 
199
     * The entry's modification time.
 
200
     */
 
201
    private int m_checkSum;
 
202
 
 
203
    /**
 
204
     * The entry's group name.
 
205
     */
 
206
    private int m_devMajor;
 
207
 
 
208
    /**
 
209
     * The entry's major device number.
 
210
     */
 
211
    private int m_devMinor;
 
212
 
 
213
    /**
 
214
     * The entry's minor device number.
 
215
     */
 
216
    private File m_file;
 
217
 
 
218
    /**
 
219
     * The entry's user id.
 
220
     */
 
221
    private int m_groupID;
 
222
 
 
223
    /**
 
224
     * The entry's user name.
 
225
     */
 
226
    private StringBuffer m_groupName;
 
227
 
 
228
    /**
 
229
     * The entry's checksum.
 
230
     */
 
231
    private byte m_linkFlag;
 
232
 
 
233
    /**
 
234
     * The entry's link flag.
 
235
     */
 
236
    private StringBuffer m_linkName;
 
237
 
 
238
    /**
 
239
     * The entry's link name.
 
240
     */
 
241
    private StringBuffer m_magic;
 
242
 
 
243
    /**
 
244
     * The entry's size.
 
245
     */
 
246
    private long m_modTime;
 
247
 
 
248
    /**
 
249
     * The entry's name.
 
250
     */
 
251
    private int m_mode;
 
252
 
 
253
    private StringBuffer m_name;
 
254
 
 
255
    /**
 
256
     * The entry's group id.
 
257
     */
 
258
    private long m_size;
 
259
 
 
260
    /**
 
261
     * The entry's permission mode.
 
262
     */
 
263
    private int m_userID;
 
264
 
 
265
    /**
 
266
     * The entry's magic tag.
 
267
     */
 
268
    private StringBuffer m_userName;
 
269
 
 
270
    /**
 
271
     * Construct an entry with only a name. This allows the programmer to
 
272
     * construct the entry's header "by hand". File is set to null.
 
273
     *
 
274
     * @param name the name of the entry
 
275
     */
 
276
    public TarEntry( final String name )
 
277
    {
 
278
        this();
 
279
 
 
280
        final boolean isDir = name.endsWith( "/" );
 
281
 
 
282
        m_name = new StringBuffer( name );
 
283
        m_mode = isDir ? 040755 : 0100644;
 
284
        m_linkFlag = isDir ? TarEntry.LF_DIR : TarEntry.LF_NORMAL;
 
285
        m_modTime = ( new Date() ).getTime() / 1000;
 
286
        m_linkName = new StringBuffer( "" );
 
287
        m_userName = new StringBuffer( "" );
 
288
        m_groupName = new StringBuffer( "" );
 
289
    }
 
290
 
 
291
    /**
 
292
     * Construct an entry with a name an a link flag.
 
293
     *
 
294
     * @param name Description of Parameter
 
295
     * @param linkFlag Description of Parameter
 
296
     */
 
297
    public TarEntry( final String name, final byte linkFlag )
 
298
    {
 
299
        this( name );
 
300
        m_linkFlag = linkFlag;
 
301
    }
 
302
 
 
303
    /**
 
304
     * Construct an entry for a file. File is set to file, and the header is
 
305
     * constructed from information from the file.
 
306
     *
 
307
     * @param file The file that the entry represents.
 
308
     */
 
309
    public TarEntry( final File file )
 
310
    {
 
311
        this();
 
312
 
 
313
        m_file = file;
 
314
 
 
315
        String name = file.getPath();
 
316
 
 
317
        // Strip off drive letters!
 
318
        final String osName =
 
319
            System.getProperty( "os.name" ).toLowerCase( Locale.US );
 
320
        if( -1 != osName.indexOf( "netware" ) )
 
321
        {
 
322
            if( name.length() > 2 )
 
323
            {
 
324
                final char ch1 = name.charAt( 0 );
 
325
                final char ch2 = name.charAt( 1 );
 
326
 
 
327
                if( ch2 == ':' &&
 
328
                    ( ( ch1 >= 'a' && ch1 <= 'z' ) ||
 
329
                    ( ch1 >= 'A' && ch1 <= 'Z' ) ) )
 
330
                {
 
331
                    name = name.substring( 2 );
 
332
                }
 
333
            }
 
334
        }
 
335
        else if( -1 != osName.indexOf( "netware" ) )
 
336
        {
 
337
            final int colon = name.indexOf( ':' );
 
338
            if( colon != -1 )
 
339
            {
 
340
                name = name.substring( colon + 1 );
 
341
            }
 
342
        }
 
343
 
 
344
        name = name.replace( File.separatorChar, '/' );
 
345
 
 
346
        // No absolute pathnames
 
347
        // Windows (and Posix?) paths can start with "\\NetworkDrive\",
 
348
        // so we loop on starting /'s.
 
349
        while( name.startsWith( "/" ) )
 
350
        {
 
351
            name = name.substring( 1 );
 
352
        }
 
353
 
 
354
        m_linkName = new StringBuffer( "" );
 
355
        m_name = new StringBuffer( name );
 
356
 
 
357
        if( file.isDirectory() )
 
358
        {
 
359
            m_mode = 040755;
 
360
            m_linkFlag = TarEntry.LF_DIR;
 
361
 
 
362
            if( m_name.charAt( m_name.length() - 1 ) != '/' )
 
363
            {
 
364
                m_name.append( "/" );
 
365
            }
 
366
        }
 
367
        else
 
368
        {
 
369
            m_mode = 0100644;
 
370
            m_linkFlag = TarEntry.LF_NORMAL;
 
371
        }
 
372
 
 
373
        m_size = file.length();
 
374
        m_modTime = file.lastModified() / 1000;
 
375
        m_checkSum = 0;
 
376
        m_devMajor = 0;
 
377
        m_devMinor = 0;
 
378
    }
 
379
 
 
380
    /**
 
381
     * Construct an entry from an archive's header bytes. File is set to null.
 
382
     *
 
383
     * @param header The header bytes from a tar archive entry.
 
384
     */
 
385
    public TarEntry( final byte[] header )
 
386
    {
 
387
        this();
 
388
        parseTarHeader( header );
 
389
    }
 
390
 
 
391
    /**
 
392
     * Construct an empty entry and prepares the header values.
 
393
     */
 
394
    private TarEntry()
 
395
    {
 
396
        m_magic = new StringBuffer( TarEntry.TMAGIC );
 
397
        m_name = new StringBuffer();
 
398
        m_linkName = new StringBuffer();
 
399
 
 
400
        String user = System.getProperty( "user.name", "" );
 
401
        if( user.length() > 31 )
 
402
        {
 
403
            user = user.substring( 0, 31 );
 
404
        }
 
405
 
 
406
        m_userName = new StringBuffer( user );
 
407
        m_groupName = new StringBuffer( "" );
 
408
    }
 
409
 
 
410
    /**
 
411
     * Set this entry's group id.
 
412
     *
 
413
     * @param groupId This entry's new group id.
 
414
     */
 
415
    public void setGroupID( final int groupId )
 
416
    {
 
417
        m_groupID = groupId;
 
418
    }
 
419
 
 
420
    /**
 
421
     * Set this entry's group id.
 
422
     *
 
423
     * @param groupId This entry's new group id.
 
424
     * @deprecated Use setGroupID() instead
 
425
     * @see #setGroupID(int)
 
426
     */
 
427
    public void setGroupId( final int groupId )
 
428
    {
 
429
        m_groupID = groupId;
 
430
    }
 
431
 
 
432
    /**
 
433
     * Set this entry's group name.
 
434
     *
 
435
     * @param groupName This entry's new group name.
 
436
     */
 
437
    public void setGroupName( final String groupName )
 
438
    {
 
439
        m_groupName = new StringBuffer( groupName );
 
440
    }
 
441
 
 
442
    /**
 
443
     * Set this entry's modification time. The parameter passed to this method
 
444
     * is in "Java time".
 
445
     *
 
446
     * @param time This entry's new modification time.
 
447
     */
 
448
    public void setModTime( final long time )
 
449
    {
 
450
        m_modTime = time / 1000;
 
451
    }
 
452
 
 
453
    /**
 
454
     * Set this entry's modification time.
 
455
     *
 
456
     * @param time This entry's new modification time.
 
457
     */
 
458
    public void setModTime( final Date time )
 
459
    {
 
460
        m_modTime = time.getTime() / 1000;
 
461
    }
 
462
 
 
463
    /**
 
464
     * Set the mode for this entry
 
465
     *
 
466
     * @param mode The new Mode value
 
467
     */
 
468
    public void setMode( final int mode )
 
469
    {
 
470
        m_mode = mode;
 
471
    }
 
472
 
 
473
    /**
 
474
     * Set this entry's name.
 
475
     *
 
476
     * @param name This entry's new name.
 
477
     */
 
478
    public void setName( final String name )
 
479
    {
 
480
        m_name = new StringBuffer( name );
 
481
    }
 
482
 
 
483
    /**
 
484
     * Set this entry's file size.
 
485
     *
 
486
     * @param size This entry's new file size.
 
487
     */
 
488
    public void setSize( final long size )
 
489
    {
 
490
        m_size = size;
 
491
    }
 
492
 
 
493
    /**
 
494
     * Set this entry's user id.
 
495
     *
 
496
     * @param userId This entry's new user id.
 
497
     */
 
498
    public void setUserID( final int userId )
 
499
    {
 
500
        m_userID = userId;
 
501
    }
 
502
 
 
503
    /**
 
504
     * Set this entry's user id.
 
505
     *
 
506
     * @param userId This entry's new user id.
 
507
     * @deprecated Use setUserID() instead
 
508
     * @see #setUserID(int)
 
509
     */
 
510
    public void setUserId( final int userId )
 
511
    {
 
512
        m_userID = userId;
 
513
    }
 
514
 
 
515
    /**
 
516
     * Set this entry's user name.
 
517
     *
 
518
     * @param userName This entry's new user name.
 
519
     */
 
520
    public void setUserName( final String userName )
 
521
    {
 
522
        m_userName = new StringBuffer( userName );
 
523
    }
 
524
 
 
525
    /**
 
526
     * If this entry represents a file, and the file is a directory, return an
 
527
     * array of TarEntries for this entry's children.
 
528
     *
 
529
     * @return An array of TarEntry's for this entry's children.
 
530
     */
 
531
    public TarEntry[] getDirectoryEntries()
 
532
    {
 
533
        if( null == m_file || !m_file.isDirectory() )
 
534
        {
 
535
            return new TarEntry[ 0 ];
 
536
        }
 
537
 
 
538
        final String[] list = m_file.list();
 
539
        final TarEntry[] result = new TarEntry[ list.length ];
 
540
 
 
541
        for( int i = 0; i < list.length; ++i )
 
542
        {
 
543
            result[ i ] = new TarEntry( new File( m_file, list[ i ] ) );
 
544
        }
 
545
 
 
546
        return result;
 
547
    }
 
548
 
 
549
    /**
 
550
     * Get this entry's file.
 
551
     *
 
552
     * @return This entry's file.
 
553
     */
 
554
    public File getFile()
 
555
    {
 
556
        return m_file;
 
557
    }
 
558
 
 
559
    /**
 
560
     * Get this entry's group id.
 
561
     *
 
562
     * @return This entry's group id.
 
563
     * @deprecated Use getGroupID() instead
 
564
     * @see #getGroupID()
 
565
     */
 
566
    public int getGroupId()
 
567
    {
 
568
        return m_groupID;
 
569
    }
 
570
 
 
571
    /**
 
572
     * Get this entry's group id.
 
573
     *
 
574
     * @return This entry's group id.
 
575
     */
 
576
    public int getGroupID()
 
577
    {
 
578
        return m_groupID;
 
579
    }
 
580
 
 
581
    /**
 
582
     * Get this entry's group name.
 
583
     *
 
584
     * @return This entry's group name.
 
585
     */
 
586
    public String getGroupName()
 
587
    {
 
588
        return m_groupName.toString();
 
589
    }
 
590
 
 
591
    /**
 
592
     * Set this entry's modification time.
 
593
     *
 
594
     * @return The ModTime value
 
595
     */
 
596
    public Date getModTime()
 
597
    {
 
598
        return new Date( m_modTime * 1000 );
 
599
    }
 
600
 
 
601
    /**
 
602
     * Get this entry's mode.
 
603
     *
 
604
     * @return This entry's mode.
 
605
     */
 
606
    public int getMode()
 
607
    {
 
608
        return m_mode;
 
609
    }
 
610
 
 
611
    /**
 
612
     * Get this entry's name.
 
613
     *
 
614
     * @return This entry's name.
 
615
     */
 
616
    public String getName()
 
617
    {
 
618
        return m_name.toString();
 
619
    }
 
620
 
 
621
    /**
 
622
     * Get this entry's file size.
 
623
     *
 
624
     * @return This entry's file size.
 
625
     */
 
626
    public long getSize()
 
627
    {
 
628
        return m_size;
 
629
    }
 
630
 
 
631
    /**
 
632
     * Get this entry's checksum.
 
633
     *
 
634
     * @return This entry's checksum.
 
635
     */
 
636
    public int getCheckSum()
 
637
    {
 
638
        return m_checkSum;
 
639
    }
 
640
 
 
641
    /**
 
642
     * Get this entry's user id.
 
643
     *
 
644
     * @return This entry's user id.
 
645
     * @deprecated Use getUserID() instead
 
646
     * @see #getUserID()
 
647
     */
 
648
    public int getUserId()
 
649
    {
 
650
        return m_userID;
 
651
    }
 
652
 
 
653
    /**
 
654
     * Get this entry's user id.
 
655
     *
 
656
     * @return This entry's user id.
 
657
     */
 
658
    public int getUserID()
 
659
    {
 
660
        return m_userID;
 
661
    }
 
662
 
 
663
    /**
 
664
     * Get this entry's user name.
 
665
     *
 
666
     * @return This entry's user name.
 
667
     */
 
668
    public String getUserName()
 
669
    {
 
670
        return m_userName.toString();
 
671
    }
 
672
 
 
673
    /**
 
674
     * Determine if the given entry is a descendant of this entry. Descendancy
 
675
     * is determined by the name of the descendant starting with this entry's
 
676
     * name.
 
677
     *
 
678
     * @param desc Entry to be checked as a descendent of
 
679
     * @return True if entry is a descendant of
 
680
     */
 
681
    public boolean isDescendent( final TarEntry desc )
 
682
    {
 
683
        return desc.getName().startsWith( getName() );
 
684
    }
 
685
 
 
686
    /**
 
687
     * Return whether or not this entry represents a directory.
 
688
     *
 
689
     * @return True if this entry is a directory.
 
690
     */
 
691
    public boolean isDirectory()
 
692
    {
 
693
        if( m_file != null )
 
694
        {
 
695
            return m_file.isDirectory();
 
696
        }
 
697
 
 
698
        if( m_linkFlag == TarEntry.LF_DIR )
 
699
        {
 
700
            return true;
 
701
        }
 
702
 
 
703
        if( getName().endsWith( "/" ) )
 
704
        {
 
705
            return true;
 
706
        }
 
707
 
 
708
        return false;
 
709
    }
 
710
 
 
711
    /**
 
712
     * Indicate if this entry is a GNU long name block
 
713
     *
 
714
     * @return true if this is a long name extension provided by GNU tar
 
715
     */
 
716
    public boolean isGNULongNameEntry()
 
717
    {
 
718
        return m_linkFlag == TarEntry.LF_GNUTYPE_LONGNAME &&
 
719
            m_name.toString().equals( TarEntry.GNU_LONGLINK );
 
720
    }
 
721
 
 
722
    /**
 
723
     * Determine if the two entries are equal. Equality is determined by the
 
724
     * header names being equal.
 
725
     *
 
726
     * @param other Entry to be checked for equality.
 
727
     * @return True if the entries are equal.
 
728
     */
 
729
    public boolean equals( final TarEntry other )
 
730
    {
 
731
        return getName().equals( other.getName() );
 
732
    }
 
733
 
 
734
    /**
 
735
     * Parse an entry's header information from a header buffer.
 
736
     *
 
737
     * @param header The tar entry header buffer to get information from.
 
738
     */
 
739
    private void parseTarHeader( final byte[] header )
 
740
    {
 
741
        int offset = 0;
 
742
 
 
743
        m_name = TarUtils.parseName( header, offset, NAMELEN );
 
744
        offset += NAMELEN;
 
745
        m_mode = (int)TarUtils.parseOctal( header, offset, TarEntry.MODELEN );
 
746
        offset += TarEntry.MODELEN;
 
747
        m_userID = (int)TarUtils.parseOctal( header, offset, TarEntry.UIDLEN );
 
748
        offset += TarEntry.UIDLEN;
 
749
        m_groupID = (int)TarUtils.parseOctal( header, offset, TarEntry.GIDLEN );
 
750
        offset += TarEntry.GIDLEN;
 
751
        m_size = TarUtils.parseOctal( header, offset, TarEntry.SIZELEN );
 
752
        offset += TarEntry.SIZELEN;
 
753
        m_modTime = TarUtils.parseOctal( header, offset, TarEntry.MODTIMELEN );
 
754
        offset += TarEntry.MODTIMELEN;
 
755
        m_checkSum = (int)TarUtils.parseOctal( header, offset, TarEntry.CHKSUMLEN );
 
756
        offset += TarEntry.CHKSUMLEN;
 
757
        m_linkFlag = header[ offset++ ];
 
758
        m_linkName = TarUtils.parseName( header, offset, NAMELEN );
 
759
        offset += NAMELEN;
 
760
        m_magic = TarUtils.parseName( header, offset, TarEntry.MAGICLEN );
 
761
        offset += TarEntry.MAGICLEN;
 
762
        m_userName = TarUtils.parseName( header, offset, TarEntry.UNAMELEN );
 
763
        offset += TarEntry.UNAMELEN;
 
764
        m_groupName = TarUtils.parseName( header, offset, TarEntry.GNAMELEN );
 
765
        offset += TarEntry.GNAMELEN;
 
766
        m_devMajor = (int)TarUtils.parseOctal( header, offset, TarEntry.DEVLEN );
 
767
        offset += TarEntry.DEVLEN;
 
768
        m_devMinor = (int)TarUtils.parseOctal( header, offset, TarEntry.DEVLEN );
 
769
    }
 
770
 
 
771
    /**
 
772
     * Write an entry's header information to a header buffer.
 
773
     *
 
774
     * @param buffer The tar entry header buffer to fill in.
 
775
     */
 
776
    public void writeEntryHeader( final byte[] buffer )
 
777
    {
 
778
        int offset = 0;
 
779
 
 
780
        offset = TarUtils.getNameBytes( m_name, buffer, offset, NAMELEN );
 
781
        offset = TarUtils.getOctalBytes( m_mode, buffer, offset, TarEntry.MODELEN );
 
782
        offset = TarUtils.getOctalBytes( m_userID, buffer, offset, TarEntry.UIDLEN );
 
783
        offset = TarUtils.getOctalBytes( m_groupID, buffer, offset, TarEntry.GIDLEN );
 
784
        offset = TarUtils.getLongOctalBytes( m_size, buffer, offset, TarEntry.SIZELEN );
 
785
        offset = TarUtils.getLongOctalBytes( m_modTime, buffer, offset, TarEntry.MODTIMELEN );
 
786
 
 
787
        final int checkSumOffset = offset;
 
788
        for( int i = 0; i < TarEntry.CHKSUMLEN; ++i )
 
789
        {
 
790
            buffer[ offset++ ] = (byte)' ';
 
791
        }
 
792
 
 
793
        buffer[ offset++ ] = m_linkFlag;
 
794
        offset = TarUtils.getNameBytes( m_linkName, buffer, offset, NAMELEN );
 
795
        offset = TarUtils.getNameBytes( m_magic, buffer, offset, TarEntry.MAGICLEN );
 
796
        offset = TarUtils.getNameBytes( m_userName, buffer, offset, TarEntry.UNAMELEN );
 
797
        offset = TarUtils.getNameBytes( m_groupName, buffer, offset, TarEntry.GNAMELEN );
 
798
        offset = TarUtils.getOctalBytes( m_devMajor, buffer, offset, TarEntry.DEVLEN );
 
799
        offset = TarUtils.getOctalBytes( m_devMinor, buffer, offset, TarEntry.DEVLEN );
 
800
 
 
801
        while( offset < buffer.length )
 
802
        {
 
803
            buffer[ offset++ ] = 0;
 
804
        }
 
805
 
 
806
        final long checkSum = TarUtils.computeCheckSum( buffer );
 
807
        TarUtils.getCheckSumOctalBytes( checkSum, buffer, checkSumOffset, TarEntry.CHKSUMLEN );
 
808
    }
 
809
}