added name prefix, updated tar header and entry

This commit is contained in:
kamranzafar 2012-11-02 17:19:12 +00:00
parent b509b362c1
commit d8c5b6a9d2
2 changed files with 207 additions and 246 deletions

View File

@ -30,7 +30,7 @@ public class TarEntry {
private TarEntry() {
this.file = null;
this.header = new TarHeader();
header = new TarHeader();
}
public TarEntry(File file, String entryName) {
@ -52,64 +52,67 @@ public class TarEntry {
*
* @param header
*
* @see TarHeader#createFileHeader(String, long, long)
* @see TarHeader#createDirHeader(String, long)
*/
public TarEntry(TarHeader header) {
this.file = null;
this.header = header;
}
public TarEntry(TarHeader header) {
this.file = null;
this.header = header;
}
public boolean equals(TarEntry it) {
return this.header.name.toString().equals(it.header.name.toString());
return header.name.toString().equals(it.header.name.toString());
}
public boolean isDescendent(TarEntry desc) {
return desc.header.name.toString().startsWith(this.header.name.toString());
return desc.header.name.toString().startsWith(header.name.toString());
}
public TarHeader getHeader() {
return this.header;
return header;
}
public String getName() {
return this.header.name.toString();
String name = header.name.toString();
if (header.namePrefix != null && !header.namePrefix.toString().equals("")) {
name = header.namePrefix.toString() + "/" + name;
}
return name;
}
public void setName(String name) {
this.header.name = new StringBuffer(name);
header.name = new StringBuffer(name);
}
public int getUserId() {
return this.header.userId;
return header.userId;
}
public void setUserId(int userId) {
this.header.userId = userId;
header.userId = userId;
}
public int getGroupId() {
return this.header.groupId;
return header.groupId;
}
public void setGroupId(int groupId) {
this.header.groupId = groupId;
header.groupId = groupId;
}
public String getUserName() {
return this.header.userName.toString();
return header.userName.toString();
}
public void setUserName(String userName) {
this.header.userName = new StringBuffer(userName);
header.userName = new StringBuffer(userName);
}
public String getGroupName() {
return this.header.groupName.toString();
return header.groupName.toString();
}
public void setGroupName(String groupName) {
this.header.groupName = new StringBuffer(groupName);
header.groupName = new StringBuffer(groupName);
}
public void setIds(int userId, int groupId) {
@ -118,15 +121,15 @@ public class TarEntry {
}
public void setModTime(long time) {
this.header.modTime = time / 1000;
header.modTime = time / 1000;
}
public void setModTime(Date time) {
this.header.modTime = time.getTime() / 1000;
header.modTime = time.getTime() / 1000;
}
public Date getModTime() {
return new Date(this.header.modTime * 1000);
return new Date(header.modTime * 1000);
}
public File getFile() {
@ -134,11 +137,11 @@ public class TarEntry {
}
public long getSize() {
return this.header.size;
return header.size;
}
public void setSize(long size) {
this.header.size = size;
header.size = size;
}
/**
@ -150,11 +153,11 @@ public class TarEntry {
if (this.file != null)
return this.file.isDirectory();
if (this.header != null) {
if (this.header.linkFlag == TarHeader.LF_DIR)
if (header != null) {
if (header.linkFlag == TarHeader.LF_DIR)
return true;
if (this.header.name.toString().endsWith("/"))
if (header.name.toString().endsWith("/"))
return true;
}
@ -167,34 +170,7 @@ public class TarEntry {
* @param entryName
*/
public void extractTarHeader(String entryName) {
String name = entryName;
name = name.replace(File.separatorChar, '/');
if (name.startsWith("/"))
name = name.substring(1);
header.linkName = new StringBuffer("");
header.name = new StringBuffer(name);
if (file.isDirectory()) {
header.mode = 040755;
header.linkFlag = TarHeader.LF_DIR;
if (header.name.charAt(header.name.length() - 1) != '/') {
header.name.append("/");
}
header.size = 0;
} else {
header.mode = 0100644;
header.linkFlag = TarHeader.LF_NORMAL;
header.size = file.length();
}
header.modTime = file.lastModified() / 1000;
header.checkSum = 0;
header.devMajor = 0;
header.devMinor = 0;
header = TarHeader.createHeader(entryName, file.length(), file.lastModified() / 1000, file.isDirectory());
}
/**
@ -221,28 +197,29 @@ public class TarEntry {
public void writeEntryHeader(byte[] outbuf) {
int offset = 0;
offset = TarHeader.getNameBytes(this.header.name, outbuf, offset, TarHeader.NAMELEN);
offset = Octal.getOctalBytes(this.header.mode, outbuf, offset, TarHeader.MODELEN);
offset = Octal.getOctalBytes(this.header.userId, outbuf, offset, TarHeader.UIDLEN);
offset = Octal.getOctalBytes(this.header.groupId, outbuf, offset, TarHeader.GIDLEN);
offset = TarHeader.getNameBytes(header.name, outbuf, offset, TarHeader.NAMELEN);
offset = Octal.getOctalBytes(header.mode, outbuf, offset, TarHeader.MODELEN);
offset = Octal.getOctalBytes(header.userId, outbuf, offset, TarHeader.UIDLEN);
offset = Octal.getOctalBytes(header.groupId, outbuf, offset, TarHeader.GIDLEN);
long size = this.header.size;
long size = header.size;
offset = Octal.getLongOctalBytes(size, outbuf, offset, TarHeader.SIZELEN);
offset = Octal.getLongOctalBytes(this.header.modTime, outbuf, offset, TarHeader.MODTIMELEN);
offset = Octal.getLongOctalBytes(header.modTime, outbuf, offset, TarHeader.MODTIMELEN);
int csOffset = offset;
for (int c = 0; c < TarHeader.CHKSUMLEN; ++c)
outbuf[offset++] = (byte) ' ';
outbuf[offset++] = this.header.linkFlag;
outbuf[offset++] = header.linkFlag;
offset = TarHeader.getNameBytes(this.header.linkName, outbuf, offset, TarHeader.NAMELEN);
offset = TarHeader.getNameBytes(this.header.magic, outbuf, offset, TarHeader.MAGICLEN);
offset = TarHeader.getNameBytes(this.header.userName, outbuf, offset, TarHeader.UNAMELEN);
offset = TarHeader.getNameBytes(this.header.groupName, outbuf, offset, TarHeader.GNAMELEN);
offset = Octal.getOctalBytes(this.header.devMajor, outbuf, offset, TarHeader.DEVLEN);
offset = Octal.getOctalBytes(this.header.devMinor, outbuf, offset, TarHeader.DEVLEN);
offset = TarHeader.getNameBytes(header.linkName, outbuf, offset, TarHeader.NAMELEN);
offset = TarHeader.getNameBytes(header.magic, outbuf, offset, TarHeader.MAGICLEN);
offset = TarHeader.getNameBytes(header.userName, outbuf, offset, TarHeader.UNAMELEN);
offset = TarHeader.getNameBytes(header.groupName, outbuf, offset, TarHeader.GNAMELEN);
offset = Octal.getOctalBytes(header.devMajor, outbuf, offset, TarHeader.DEVLEN);
offset = Octal.getOctalBytes(header.devMinor, outbuf, offset, TarHeader.DEVLEN);
offset = TarHeader.getNameBytes(header.namePrefix, outbuf, offset, TarHeader.FILENAME_PREFIX);
for (; offset < outbuf.length;)
outbuf[offset++] = 0;
@ -300,5 +277,8 @@ public class TarEntry {
offset += TarHeader.DEVLEN;
header.devMinor = (int) Octal.parseOctal(bh, offset, TarHeader.DEVLEN);
offset += TarHeader.DEVLEN;
header.namePrefix = TarHeader.parseName(bh, offset, TarHeader.FILENAME_PREFIX);
}
}

View File

@ -69,205 +69,186 @@ import java.io.File;
public class TarHeader {
/*
* Header
*/
public static final int NAMELEN = 100;
public static final int MODELEN = 8;
public static final int UIDLEN = 8;
public static final int GIDLEN = 8;
public static final int SIZELEN = 12;
public static final int MODTIMELEN = 12;
public static final int CHKSUMLEN = 8;
public static final byte LF_OLDNORM = 0;
/*
* Header
*/
public static final int NAMELEN = 100;
public static final int MODELEN = 8;
public static final int UIDLEN = 8;
public static final int GIDLEN = 8;
public static final int SIZELEN = 12;
public static final int MODTIMELEN = 12;
public static final int CHKSUMLEN = 8;
public static final byte LF_OLDNORM = 0;
/*
* File Types
*/
public static final byte LF_NORMAL = (byte) '0';
public static final byte LF_LINK = (byte) '1';
public static final byte LF_SYMLINK = (byte) '2';
public static final byte LF_CHR = (byte) '3';
public static final byte LF_BLK = (byte) '4';
public static final byte LF_DIR = (byte) '5';
public static final byte LF_FIFO = (byte) '6';
public static final byte LF_CONTIG = (byte) '7';
/*
* File Types
*/
public static final byte LF_NORMAL = (byte) '0';
public static final byte LF_LINK = (byte) '1';
public static final byte LF_SYMLINK = (byte) '2';
public static final byte LF_CHR = (byte) '3';
public static final byte LF_BLK = (byte) '4';
public static final byte LF_DIR = (byte) '5';
public static final byte LF_FIFO = (byte) '6';
public static final byte LF_CONTIG = (byte) '7';
/*
* Ustar header
*/
/*
* Ustar header
*/
public static final int MAGICLEN = 8;
/**
* The magic tag representing a POSIX tar archive.
*/
public static final String TMAGIC = "ustar";
public static final int MAGICLEN = 8;
/**
* The magic tag representing a POSIX tar archive.
*/
public static final String TMAGIC = "ustar";
/**
* The magic tag representing a GNU tar archive.
*/
public static final String GNU_TMAGIC = "ustar ";
/**
* The magic tag representing a GNU tar archive.
*/
public static final String GNU_TMAGIC = "ustar ";
public static final int UNAMELEN = 32;
public static final int GNAMELEN = 32;
public static final int DEVLEN = 8;
public static final int UNAMELEN = 32;
public static final int GNAMELEN = 32;
public static final int DEVLEN = 8;
public static final int FILENAME_PREFIX = 155;
// Header values
public StringBuffer name;
public int mode;
public int userId;
public int groupId;
public long size;
public long modTime;
public int checkSum;
public byte linkFlag;
public StringBuffer linkName;
public StringBuffer magic;
public StringBuffer userName;
public StringBuffer groupName;
public int devMajor;
public int devMinor;
// Header values
public StringBuffer name;
public int mode;
public int userId;
public int groupId;
public long size;
public long modTime;
public int checkSum;
public byte linkFlag;
public StringBuffer linkName;
public StringBuffer magic; // ustar indicator and version
public StringBuffer userName;
public StringBuffer groupName;
public int devMajor;
public int devMinor;
public StringBuffer namePrefix;
public TarHeader() {
this.magic = new StringBuffer( TarHeader.TMAGIC );
public TarHeader() {
this.magic = new StringBuffer(TarHeader.TMAGIC);
this.name = new StringBuffer();
this.linkName = new StringBuffer();
this.name = new StringBuffer();
this.linkName = new StringBuffer();
String user = System.getProperty( "user.name", "" );
String user = System.getProperty("user.name", "");
if (user.length() > 31)
user = user.substring( 0, 31 );
if (user.length() > 31)
user = user.substring(0, 31);
this.userId = 0;
this.groupId = 0;
this.userName = new StringBuffer( user );
this.groupName = new StringBuffer( "" );
}
this.userId = 0;
this.groupId = 0;
this.userName = new StringBuffer(user);
this.groupName = new StringBuffer("");
this.namePrefix = new StringBuffer();
}
/**
* Parse an entry name from a header buffer.
*
* @param name
* @param header
* The header buffer from which to parse.
* @param offset
* The offset into the buffer from which to parse.
* @param length
* The number of header bytes to parse.
* @return The header's entry name.
*/
public static StringBuffer parseName(byte[] header, int offset, int length) {
StringBuffer result = new StringBuffer( length );
/**
* Parse an entry name from a header buffer.
*
* @param name
* @param header
* The header buffer from which to parse.
* @param offset
* The offset into the buffer from which to parse.
* @param length
* The number of header bytes to parse.
* @return The header's entry name.
*/
public static StringBuffer parseName(byte[] header, int offset, int length) {
StringBuffer result = new StringBuffer(length);
int end = offset + length;
for (int i = offset; i < end; ++i) {
if (header[i] == 0)
break;
result.append( (char) header[i] );
}
int end = offset + length;
for (int i = offset; i < end; ++i) {
if (header[i] == 0)
break;
result.append((char) header[i]);
}
return result;
}
return result;
}
/**
* Determine the number of bytes in an entry name.
*
* @param name
* @param header
* The header buffer from which to parse.
* @param offset
* The offset into the buffer from which to parse.
* @param length
* The number of header bytes to parse.
* @return The number of bytes in a header's entry name.
*/
public static int getNameBytes(StringBuffer name, byte[] buf, int offset, int length) {
int i;
/**
* Determine the number of bytes in an entry name.
*
* @param name
* @param header
* The header buffer from which to parse.
* @param offset
* The offset into the buffer from which to parse.
* @param length
* The number of header bytes to parse.
* @return The number of bytes in a header's entry name.
*/
public static int getNameBytes(StringBuffer name, byte[] buf, int offset, int length) {
int i;
for (i = 0; i < length && i < name.length(); ++i) {
buf[offset + i] = (byte) name.charAt( i );
}
for (i = 0; i < length && i < name.length(); ++i) {
buf[offset + i] = (byte) name.charAt(i);
}
for (; i < length; ++i) {
buf[offset + i] = 0;
}
for (; i < length; ++i) {
buf[offset + i] = 0;
}
return offset + length;
}
return offset + length;
}
/**
* Creates a new header for a file entry.
*
* This method is useful for creating entries that do not correspond to a
* file.
*
* @param fileName File name
* @param fileSize File size in bytes
* @param modTime Last modification time in numeric Unix time format
*
* @return
*/
public static TarHeader createFileHeader(String fileName, long fileSize, long modTime) {
String name = fileName;
TarHeader header = new TarHeader();
name = name.replace(File.separatorChar, '/');
/**
* Creates a new header for a file entry.
*
* This method is useful for creating entries that do not correspond to a
* file.
*
* @param name
* File name
* @param size
* File size in bytes
* @param modTime
* Last modification time in numeric Unix time format
*
* @return
*/
public static TarHeader createHeader(String entryName, long size, long modTime, boolean dir) {
String name = entryName;
name = name.replace(File.separatorChar, '/');
if (name.startsWith("/"))
name = name.substring(1);
if (name.startsWith("/"))
name = name.substring(1);
header.linkName = new StringBuffer("");
TarHeader header = new TarHeader();
header.linkName = new StringBuffer("");
header.name = new StringBuffer(name);
if (name.length() > 100) {
header.namePrefix = new StringBuffer(name.substring(0, name.lastIndexOf('/')));
header.name = new StringBuffer(name.substring(name.lastIndexOf('/') + 1));
} else {
header.name = new StringBuffer(name);
}
header.mode = 0100644;
header.linkFlag = TarHeader.LF_NORMAL;
header.size = fileSize;
if (dir) {
header.mode = 040755;
header.linkFlag = TarHeader.LF_DIR;
if (header.name.charAt(header.name.length() - 1) != '/') {
header.name.append("/");
}
header.size = 0;
} else {
header.mode = 0100644;
header.linkFlag = TarHeader.LF_NORMAL;
header.size = size;
}
header.modTime = modTime;
header.checkSum = 0;
header.devMajor = 0;
header.devMinor = 0;
return header;
}
/**
* Creates a new header for a directory entry.
*
* This method is useful for creating entries that do not correspond to
* a directory in the file system.
*
* @param fileName Directory name
* @param modTime Last modification time in numeric Unix time format
*
* @return
*/
public static TarHeader createDirHeader(String dirName, long modTime) {
String name = dirName;
TarHeader header = new TarHeader();
name = name.replace(File.separatorChar, '/');
if (name.startsWith("/"))
name = name.substring(1);
header.linkName = new StringBuffer("");
header.name = new StringBuffer(name);
header.mode = 040755;
header.linkFlag = TarHeader.LF_DIR;
if (header.name.charAt(header.name.length() - 1) != '/') {
header.name.append("/");
}
header.size = 0;
header.modTime = modTime;
header.checkSum = 0;
header.devMajor = 0;
header.devMinor = 0;
return header;
}
header.modTime = modTime;
header.checkSum = 0;
header.devMajor = 0;
header.devMinor = 0;
return header;
}
}