/* Copyright (c) 2001-2009, The HSQL Development Group
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the HSQL Development Group nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.hsqldb.lib.tar;
import java.util.HashMap;
import java.util.Map;
/**
* Purely static structure defining our interface to the Tar Entry Header.
*
* The fields controlled here are fields for the individual tar file entries
* in an archive. There is no such thing as a Header Field at the top archive
* level.
* <P>
* We use header field names as they are specified in the FreeBSD man page for
* tar in section 5 (Solaris and Linux have no such page in section 5).
* Where we use a constant, the constant name is just the FreeBSD field name
* capitalized.
* Since a single field is known as either "linkflag" or "typeflag", we are
* going with the UStar name typeflag for this field.
* <P>
* We purposefully define no variable for this list of fields, since
* we DO NOT WANT TO access or change these values, due to application
* goals or JVM limitations:<UL>
* <LI>gid
* <LI>uid
* <LI>linkname
* <LI>magic (UStar ID),
* <LI>magic version
* <LI>group name
* <LI>device major num
* <LI>device minor num
* </UL>
* Our application has no use for these, or Java has no ability to
* work with them.
* <P>
* This class will be very elegant when refactored as an enum with enumMap(s)
* and using generics with auto-boxing instead of the ugly and non-validating
* casts.
*
* @author Blaine Simpson (blaine dot simpson at admc dot com)
*/
public class TarHeaderFields {
final static int NAME = 1;
final static int MODE = 2;
final static int UID = 3;
final static int GID = 4;
final static int SIZE = 5;
final static int MTIME = 6; // (File.lastModified()|*.getTime())/1000
final static int CHECKSUM = 7;
final static int TYPEFLAG = 8;
// The remaining are from UStar format:
final static int MAGIC = 9;
final static int UNAME = 10;
final static int GNAME = 11;
final static int PREFIX = 12;
// Replace these contants with proper enum once we require Java 1.5.
static Map labels = new HashMap(); // String identifier
// (this supplied automatically by enums)
static Map starts = new HashMap(); // Starting positions
static Map stops = new HashMap();
// 1 PAST last position (in normal Java substring fashion).
/* Note that (with one exception), there is always 1 byte
* between a numeric field stop and the next start. This is
* because null byte must occupy the intervening position.
* This is not true for non-numeric fields (which includes the
* link-indicator/type-flag field, which is used as a code,
* and is not necessarily numeric with UStar format).
*
* As a consequence, there may be NO DELIMITER after
* non-numerics, which may occupy the entire field segment.
*
* Arg. man page for "pax" says that both original and ustar
* headers must be <= 100 chars. INCLUDING the trailing \0
* character. ??? GNU tar certainly does not honor this.
*/
static {
labels.put(new Integer(NAME), "name");
starts.put(new Integer(NAME), new Integer(0));
stops.put(new Integer(NAME), new Integer(100));
labels.put(new Integer(MODE), "mode");
starts.put(new Integer(MODE), new Integer(100));
stops.put(new Integer(MODE), new Integer(107));
labels.put(new Integer(UID), "uid");
starts.put(new Integer(UID), new Integer(108));
stops.put(new Integer(UID), new Integer(115));
labels.put(new Integer(GID), "gid");
starts.put(new Integer(GID), new Integer(116));
stops.put(new Integer(GID), new Integer(123));
labels.put(new Integer(SIZE), "size");
starts.put(new Integer(SIZE), new Integer(124));
stops.put(new Integer(SIZE), new Integer(135));
labels.put(new Integer(MTIME), "mtime");
starts.put(new Integer(MTIME), new Integer(136));
stops.put(new Integer(MTIME), new Integer(147));
labels.put(new Integer(CHECKSUM), "checksum"); // Queer terminator.
// Pax UStore does not follow spec and delimits this field like
// any other numeric, skipping the space byte.
starts.put(new Integer(CHECKSUM), new Integer(148)); // Special fmt.
stops.put(new Integer(CHECKSUM), new Integer(156)); // Queer terminator.
labels.put(new Integer(TYPEFLAG), "typeflag");
starts.put(new Integer(TYPEFLAG), new Integer(156)); // 1-byte CODE
// With current version, we are never doing anything with this
// field. In future, we will support x and/or g type here.
stops.put(new Integer(TYPEFLAG), new Integer(157));
labels.put(new Integer(MAGIC), "magic");
// N.b. Gnu Tar does not honor this Stop.
starts.put(new Integer(MAGIC), new Integer(257));
stops.put(new Integer(MAGIC), new Integer(263));
labels.put(new Integer(UNAME), "uname");
starts.put(new Integer(UNAME), new Integer(265));
stops.put(new Integer(UNAME), new Integer(296));
labels.put(new Integer(GNAME), "gname");
starts.put(new Integer(GNAME), new Integer(297));
stops.put(new Integer(GNAME), new Integer(328));
labels.put(new Integer(PREFIX), "prefix");
starts.put(new Integer(PREFIX), new Integer(345));
stops.put(new Integer(PREFIX), new Integer(399));
}
// The getters below throw RuntimExceptions instead of
// TarMalformatExceptions because these errors indicate a dev problem,
// not some problem with a Header, or generating or reading a Header.
static public int getStart(int field) {
Integer iObject = (Integer) starts.get(new Integer(field));
if (iObject == null) {
throw new IllegalArgumentException(
RB.singleton.getString(RB.UNEXPECTED_HEADER_KEY, field));
}
return iObject.intValue();
}
static public int getStop(int field) {
Integer iObject = (Integer) stops.get(new Integer(field));
if (iObject == null) {
throw new IllegalArgumentException(
RB.singleton.getString(RB.UNEXPECTED_HEADER_KEY, field));
}
return iObject.intValue();
}
static public String toString(int field) {
String s = (String) labels.get(new Integer(field));
if (s == null) {
throw new IllegalArgumentException(
RB.singleton.getString(RB.UNEXPECTED_HEADER_KEY, field));
}
return s;
}
}