diff --git a/src/main/java/org/kamranzafar/jtar/TarEntry.java b/src/main/java/org/kamranzafar/jtar/TarEntry.java index ea2a904..e0a6186 100755 --- a/src/main/java/org/kamranzafar/jtar/TarEntry.java +++ b/src/main/java/org/kamranzafar/jtar/TarEntry.java @@ -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); } } \ No newline at end of file diff --git a/src/main/java/org/kamranzafar/jtar/TarHeader.java b/src/main/java/org/kamranzafar/jtar/TarHeader.java index 83cac48..077c6eb 100755 --- a/src/main/java/org/kamranzafar/jtar/TarHeader.java +++ b/src/main/java/org/kamranzafar/jtar/TarHeader.java @@ -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; + } } \ No newline at end of file