]> WPIA git - gigi.git/blob - lib/jtar/org/kamranzafar/jtar/TarHeader.java
Adding jtar
[gigi.git] / lib / jtar / org / kamranzafar / jtar / TarHeader.java
1 /**
2  * Copyright 2012 Kamran Zafar 
3  * 
4  * Licensed under the Apache License, Version 2.0 (the "License"); 
5  * you may not use this file except in compliance with the License. 
6  * You may obtain a copy of the License at 
7  * 
8  *      http://www.apache.org/licenses/LICENSE-2.0 
9  * 
10  * Unless required by applicable law or agreed to in writing, software 
11  * distributed under the License is distributed on an "AS IS" BASIS, 
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
13  * See the License for the specific language governing permissions and 
14  * limitations under the License. 
15  * 
16  */
17
18 package org.kamranzafar.jtar;
19
20 import java.io.File;
21
22 /**
23  * Header
24  * 
25  * <pre>
26  * Offset  Size     Field
27  * 0       100      File name
28  * 100     8        File mode
29  * 108     8        Owner's numeric user ID
30  * 116     8        Group's numeric user ID
31  * 124     12       File size in bytes
32  * 136     12       Last modification time in numeric Unix time format
33  * 148     8        Checksum for header block
34  * 156     1        Link indicator (file type)
35  * 157     100      Name of linked file
36  * </pre>
37  * 
38  * 
39  * File Types
40  * 
41  * <pre>
42  * Value        Meaning
43  * '0'          Normal file
44  * (ASCII NUL)  Normal file (now obsolete)
45  * '1'          Hard link
46  * '2'          Symbolic link
47  * '3'          Character special
48  * '4'          Block special
49  * '5'          Directory
50  * '6'          FIFO
51  * '7'          Contigous
52  * </pre>
53  * 
54  * 
55  * 
56  * Ustar header
57  * 
58  * <pre>
59  * Offset  Size    Field
60  * 257     6       UStar indicator "ustar"
61  * 263     2       UStar version "00"
62  * 265     32      Owner user name
63  * 297     32      Owner group name
64  * 329     8       Device major number
65  * 337     8       Device minor number
66  * 345     155     Filename prefix
67  * </pre>
68  */
69
70 public class TarHeader {
71
72         /*
73          * Header
74          */
75         public static final int NAMELEN = 100;
76         public static final int MODELEN = 8;
77         public static final int UIDLEN = 8;
78         public static final int GIDLEN = 8;
79         public static final int SIZELEN = 12;
80         public static final int MODTIMELEN = 12;
81         public static final int CHKSUMLEN = 8;
82         public static final byte LF_OLDNORM = 0;
83
84         /*
85          * File Types
86          */
87         public static final byte LF_NORMAL = (byte) '0';
88         public static final byte LF_LINK = (byte) '1';
89         public static final byte LF_SYMLINK = (byte) '2';
90         public static final byte LF_CHR = (byte) '3';
91         public static final byte LF_BLK = (byte) '4';
92         public static final byte LF_DIR = (byte) '5';
93         public static final byte LF_FIFO = (byte) '6';
94         public static final byte LF_CONTIG = (byte) '7';
95
96         /*
97          * Ustar header
98          */
99
100         public static final String USTAR_MAGIC = "ustar"; // POSIX
101
102         public static final int USTAR_MAGICLEN = 8;
103         public static final int USTAR_USER_NAMELEN = 32;
104         public static final int USTAR_GROUP_NAMELEN = 32;
105         public static final int USTAR_DEVLEN = 8;
106         public static final int USTAR_FILENAME_PREFIX = 155;
107
108         // Header values
109         public StringBuffer name;
110         public int mode;
111         public int userId;
112         public int groupId;
113         public long size;
114         public long modTime;
115         public int checkSum;
116         public byte linkFlag;
117         public StringBuffer linkName;
118         public StringBuffer magic; // ustar indicator and version
119         public StringBuffer userName;
120         public StringBuffer groupName;
121         public int devMajor;
122         public int devMinor;
123         public StringBuffer namePrefix;
124
125         public TarHeader() {
126                 this.magic = new StringBuffer(TarHeader.USTAR_MAGIC);
127
128                 this.name = new StringBuffer();
129                 this.linkName = new StringBuffer();
130
131                 String user = System.getProperty("user.name", "");
132
133                 if (user.length() > 31)
134                         user = user.substring(0, 31);
135
136                 this.userId = 0;
137                 this.groupId = 0;
138                 this.userName = new StringBuffer(user);
139                 this.groupName = new StringBuffer("");
140                 this.namePrefix = new StringBuffer();
141         }
142
143         /**
144          * Parse an entry name from a header buffer.
145          * 
146          * @param name
147          * @param header
148          *            The header buffer from which to parse.
149          * @param offset
150          *            The offset into the buffer from which to parse.
151          * @param length
152          *            The number of header bytes to parse.
153          * @return The header's entry name.
154          */
155         public static StringBuffer parseName(byte[] header, int offset, int length) {
156                 StringBuffer result = new StringBuffer(length);
157
158                 int end = offset + length;
159                 for (int i = offset; i < end; ++i) {
160                         if (header[i] == 0)
161                                 break;
162                         result.append((char) header[i]);
163                 }
164
165                 return result;
166         }
167
168         /**
169          * Determine the number of bytes in an entry name.
170          * 
171          * @param name
172          * @param header
173          *            The header buffer from which to parse.
174          * @param offset
175          *            The offset into the buffer from which to parse.
176          * @param length
177          *            The number of header bytes to parse.
178          * @return The number of bytes in a header's entry name.
179          */
180         public static int getNameBytes(StringBuffer name, byte[] buf, int offset, int length) {
181                 int i;
182
183                 for (i = 0; i < length && i < name.length(); ++i) {
184                         buf[offset + i] = (byte) name.charAt(i);
185                 }
186
187                 for (; i < length; ++i) {
188                         buf[offset + i] = 0;
189                 }
190
191                 return offset + length;
192         }
193
194         /**
195          * Creates a new header for a file/directory entry.
196          * 
197          * 
198          * @param name
199          *            File name
200          * @param size
201          *            File size in bytes
202          * @param modTime
203          *            Last modification time in numeric Unix time format
204          * @param dir
205          *            Is directory
206          * 
207          * @return
208          */
209         public static TarHeader createHeader(String entryName, long size, long modTime, boolean dir) {
210                 String name = entryName;
211                 name = TarUtils.trim(name.replace(File.separatorChar, '/'), '/');
212
213                 TarHeader header = new TarHeader();
214                 header.linkName = new StringBuffer("");
215
216                 if (name.length() > 100) {
217                         header.namePrefix = new StringBuffer(name.substring(0, name.lastIndexOf('/')));
218                         header.name = new StringBuffer(name.substring(name.lastIndexOf('/') + 1));
219                 } else {
220                         header.name = new StringBuffer(name);
221                 }
222
223                 if (dir) {
224                         header.mode = 040755;
225                         header.linkFlag = TarHeader.LF_DIR;
226                         if (header.name.charAt(header.name.length() - 1) != '/') {
227                                 header.name.append("/");
228                         }
229                         header.size = 0;
230                 } else {
231                         header.mode = 0100644;
232                         header.linkFlag = TarHeader.LF_NORMAL;
233                         header.size = size;
234                 }
235
236                 header.modTime = modTime;
237                 header.checkSum = 0;
238                 header.devMajor = 0;
239                 header.devMinor = 0;
240
241                 return header;
242         }
243 }