001: /*
002: ** Authored by Timothy Gerard Endres
003: ** <mailto:time@gjt.org> <http://www.trustice.com>
004: **
005: ** This work has been placed into the public domain.
006: ** You may use this work in any way and for any purpose you wish.
007: **
008: ** THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND,
009: ** NOT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR
010: ** OF THIS SOFTWARE, ASSUMES _NO_ RESPONSIBILITY FOR ANY
011: ** CONSEQUENCE RESULTING FROM THE USE, MODIFICATION, OR
012: ** REDISTRIBUTION OF THIS SOFTWARE.
013: **
014: */
015:
016: package installer;
017:
018: /**
019: * This class encapsulates the Tar Entry Header used in Tar Archives.
020: * The class also holds a number of tar constants, used mostly in headers.
021: */
022:
023: public class TarHeader extends Object {
024: /**
025: * The length of the name field in a header buffer.
026: */
027: public static final int NAMELEN = 100;
028: /**
029: * The length of the mode field in a header buffer.
030: */
031: public static final int MODELEN = 8;
032: /**
033: * The length of the user id field in a header buffer.
034: */
035: public static final int UIDLEN = 8;
036: /**
037: * The length of the group id field in a header buffer.
038: */
039: public static final int GIDLEN = 8;
040: /**
041: * The length of the checksum field in a header buffer.
042: */
043: public static final int CHKSUMLEN = 8;
044: /**
045: * The length of the size field in a header buffer.
046: */
047: public static final int SIZELEN = 12;
048: /**
049: * The length of the magic field in a header buffer.
050: */
051: public static final int MAGICLEN = 8;
052: /**
053: * The length of the modification time field in a header buffer.
054: */
055: public static final int MODTIMELEN = 12;
056: /**
057: * The length of the user name field in a header buffer.
058: */
059: public static final int UNAMELEN = 32;
060: /**
061: * The length of the group name field in a header buffer.
062: */
063: public static final int GNAMELEN = 32;
064: /**
065: * The length of the devices field in a header buffer.
066: */
067: public static final int DEVLEN = 8;
068:
069: /**
070: * LF_ constants represent the "link flag" of an entry, or more commonly,
071: * the "entry type". This is the "old way" of indicating a normal file.
072: */
073: public static final byte LF_OLDNORM = 0;
074: /**
075: * Normal file type.
076: */
077: public static final byte LF_NORMAL = (byte) '0';
078: /**
079: * Link file type.
080: */
081: public static final byte LF_LINK = (byte) '1';
082: /**
083: * Symbolic link file type.
084: */
085: public static final byte LF_SYMLINK = (byte) '2';
086: /**
087: * Character device file type.
088: */
089: public static final byte LF_CHR = (byte) '3';
090: /**
091: * Block device file type.
092: */
093: public static final byte LF_BLK = (byte) '4';
094: /**
095: * Directory file type.
096: */
097: public static final byte LF_DIR = (byte) '5';
098: /**
099: * FIFO (pipe) file type.
100: */
101: public static final byte LF_FIFO = (byte) '6';
102: /**
103: * Contiguous file type.
104: */
105: public static final byte LF_CONTIG = (byte) '7';
106:
107: /**
108: * The magic tag representing a POSIX tar archive.
109: */
110: public static final String TMAGIC = "ustar";
111:
112: /**
113: * The magic tag representing a GNU tar archive.
114: */
115: public static final String GNU_TMAGIC = "ustar ";
116:
117: /**
118: * The entry's name.
119: */
120: public StringBuffer name;
121: /**
122: * The entry's permission mode.
123: */
124: public int mode;
125: /**
126: * The entry's user id.
127: */
128: public int userId;
129: /**
130: * The entry's group id.
131: */
132: public int groupId;
133: /**
134: * The entry's size.
135: */
136: public long size;
137: /**
138: * The entry's modification time.
139: */
140: public long modTime;
141: /**
142: * The entry's checksum.
143: */
144: public int checkSum;
145: /**
146: * The entry's link flag.
147: */
148: public byte linkFlag;
149: /**
150: * The entry's link name.
151: */
152: public StringBuffer linkName;
153: /**
154: * The entry's magic tag.
155: */
156: public StringBuffer magic;
157: /**
158: * The entry's user name.
159: */
160: public StringBuffer userName;
161: /**
162: * The entry's group name.
163: */
164: public StringBuffer groupName;
165: /**
166: * The entry's major device number.
167: */
168: public int devMajor;
169: /**
170: * The entry's minor device number.
171: */
172: public int devMinor;
173:
174: public TarHeader() {
175: this .magic = new StringBuffer(TarHeader.TMAGIC);
176:
177: this .name = new StringBuffer();
178: this .linkName = new StringBuffer();
179:
180: String user = System.getProperty("user.name", "");
181:
182: if (user.length() > 31)
183: user = user.substring(0, 31);
184:
185: this .userId = 0;
186: this .groupId = 0;
187: this .userName = new StringBuffer(user);
188: this .groupName = new StringBuffer("");
189: }
190:
191: /**
192: * TarHeaders can be cloned.
193: */
194: public Object clone() {
195: TarHeader hdr = null;
196:
197: try {
198: hdr = (TarHeader) super .clone();
199:
200: hdr.name = (this .name == null) ? null : new StringBuffer(
201: this .name.toString());
202: hdr.mode = this .mode;
203: hdr.userId = this .userId;
204: hdr.groupId = this .groupId;
205: hdr.size = this .size;
206: hdr.modTime = this .modTime;
207: hdr.checkSum = this .checkSum;
208: hdr.linkFlag = this .linkFlag;
209: hdr.linkName = (this .linkName == null) ? null
210: : new StringBuffer(this .linkName.toString());
211: hdr.magic = (this .magic == null) ? null : new StringBuffer(
212: this .magic.toString());
213: hdr.userName = (this .userName == null) ? null
214: : new StringBuffer(this .userName.toString());
215: hdr.groupName = (this .groupName == null) ? null
216: : new StringBuffer(this .groupName.toString());
217: hdr.devMajor = this .devMajor;
218: hdr.devMinor = this .devMinor;
219: } catch (CloneNotSupportedException ex) {
220: ex.printStackTrace();
221: }
222:
223: return hdr;
224: }
225:
226: /**
227: * Get the name of this entry.
228: *
229: * @return Teh entry's name.
230: */
231: public String getName() {
232: return this .name.toString();
233: }
234:
235: /**
236: * Parse an octal string from a header buffer. This is used for the
237: * file permission mode value.
238: *
239: * @param header The header buffer from which to parse.
240: * @param offset The offset into the buffer from which to parse.
241: * @param length The number of header bytes to parse.
242: * @return The long value of the octal string.
243: */
244: public static long parseOctal(byte[] header, int offset, int length)
245: throws InvalidHeaderException {
246: long result = 0;
247: boolean stillPadding = true;
248:
249: int end = offset + length;
250: for (int i = offset; i < end; ++i) {
251: if (header[i] == 0)
252: break;
253:
254: if (header[i] == (byte) ' ' || header[i] == '0') {
255: if (stillPadding)
256: continue;
257:
258: if (header[i] == (byte) ' ')
259: break;
260: }
261:
262: stillPadding = false;
263:
264: result = (result << 3) + (header[i] - '0');
265: }
266:
267: return result;
268: }
269:
270: /**
271: * Parse an entry name from a header buffer.
272: *
273: * @param header The header buffer from which to parse.
274: * @param offset The offset into the buffer from which to parse.
275: * @param length The number of header bytes to parse.
276: * @return The header's entry name.
277: */
278: public static StringBuffer parseName(byte[] header, int offset,
279: int length) throws InvalidHeaderException {
280: StringBuffer result = new StringBuffer(length);
281:
282: int end = offset + length;
283: for (int i = offset; i < end; ++i) {
284: if (header[i] == 0)
285: break;
286: result.append((char) header[i]);
287: }
288:
289: return result;
290: }
291:
292: /**
293: * Determine the number of bytes in an entry name.
294: *
295: * @param header The header buffer from which to parse.
296: * @param offset The offset into the buffer from which to parse.
297: * @param length The number of header bytes to parse.
298: * @return The number of bytes in a header's entry name.
299: */
300: public static int getNameBytes(StringBuffer name, byte[] buf,
301: int offset, int length) {
302: int i;
303:
304: for (i = 0; i < length && i < name.length(); ++i) {
305: buf[offset + i] = (byte) name.charAt(i);
306: }
307:
308: for (; i < length; ++i) {
309: buf[offset + i] = 0;
310: }
311:
312: return offset + length;
313: }
314:
315: /**
316: * Parse an octal integer from a header buffer.
317: *
318: * @param header The header buffer from which to parse.
319: * @param offset The offset into the buffer from which to parse.
320: * @param length The number of header bytes to parse.
321: * @return The integer value of the octal bytes.
322: */
323: public static int getOctalBytes(long value, byte[] buf, int offset,
324: int length) {
325: byte[] result = new byte[length];
326:
327: int idx = length - 1;
328:
329: buf[offset + idx] = 0;
330: --idx;
331: buf[offset + idx] = (byte) ' ';
332: --idx;
333:
334: if (value == 0) {
335: buf[offset + idx] = (byte) '0';
336: --idx;
337: } else {
338: for (long val = value; idx >= 0 && val > 0; --idx) {
339: buf[offset + idx] = (byte) ((byte) '0' + (byte) (val & 7));
340: val = val >> 3;
341: }
342: }
343:
344: for (; idx >= 0; --idx) {
345: buf[offset + idx] = (byte) ' ';
346: }
347:
348: return offset + length;
349: }
350:
351: /**
352: * Parse an octal long integer from a header buffer.
353: *
354: * @param header The header buffer from which to parse.
355: * @param offset The offset into the buffer from which to parse.
356: * @param length The number of header bytes to parse.
357: * @return The long value of the octal bytes.
358: */
359: public static int getLongOctalBytes(long value, byte[] buf,
360: int offset, int length) {
361: byte[] temp = new byte[length + 1];
362: TarHeader.getOctalBytes(value, temp, 0, length + 1);
363: System.arraycopy(temp, 0, buf, offset, length);
364: return offset + length;
365: }
366:
367: /**
368: * Parse the checksum octal integer from a header buffer.
369: *
370: * @param header The header buffer from which to parse.
371: * @param offset The offset into the buffer from which to parse.
372: * @param length The number of header bytes to parse.
373: * @return The integer value of the entry's checksum.
374: */
375: public static int getCheckSumOctalBytes(long value, byte[] buf,
376: int offset, int length) {
377: TarHeader.getOctalBytes(value, buf, offset, length);
378: buf[offset + length - 1] = (byte) ' ';
379: buf[offset + length - 2] = 0;
380: return offset + length;
381: }
382:
383: }
|