From: <ga...@us...> - 2009-01-03 21:05:23
|
Revision: 4821 http://jnode.svn.sourceforge.net/jnode/?rev=4821&view=rev Author: galatnm Date: 2009-01-03 21:05:14 +0000 (Sat, 03 Jan 2009) Log Message: ----------- Intermediate checkins for HFS+ formatter and read/Write support. Modified Paths: -------------- trunk/fs/src/fs/org/jnode/fs/hfsplus/HFSPlusDirectory.java trunk/fs/src/fs/org/jnode/fs/hfsplus/HFSPlusForkData.java trunk/fs/src/fs/org/jnode/fs/hfsplus/HFSPlusObject.java trunk/fs/src/fs/org/jnode/fs/hfsplus/HFSUnicodeString.java trunk/fs/src/fs/org/jnode/fs/hfsplus/HFSUtils.java trunk/fs/src/fs/org/jnode/fs/hfsplus/HfsPlusConstants.java trunk/fs/src/fs/org/jnode/fs/hfsplus/HfsPlusFileSystem.java trunk/fs/src/fs/org/jnode/fs/hfsplus/HfsPlusFileSystemFormatter.java trunk/fs/src/fs/org/jnode/fs/hfsplus/Superblock.java trunk/fs/src/fs/org/jnode/fs/hfsplus/catalog/CatalogFile.java trunk/fs/src/fs/org/jnode/fs/hfsplus/catalog/CatalogFolder.java trunk/fs/src/fs/org/jnode/fs/hfsplus/catalog/CatalogKey.java trunk/fs/src/fs/org/jnode/fs/hfsplus/catalog/CatalogNodeId.java trunk/fs/src/fs/org/jnode/fs/hfsplus/catalog/CatalogThread.java trunk/fs/src/fs/org/jnode/fs/hfsplus/extent/ExtentDescriptor.java trunk/fs/src/fs/org/jnode/fs/hfsplus/tree/LeafNode.java trunk/fs/src/fs/org/jnode/fs/hfsplus/tree/LeafRecord.java Added Paths: ----------- trunk/fs/src/fs/org/jnode/fs/hfsplus/command/ trunk/fs/src/fs/org/jnode/fs/hfsplus/command/FormatHfsPlusCommand.java Modified: trunk/fs/src/fs/org/jnode/fs/hfsplus/HFSPlusDirectory.java =================================================================== --- trunk/fs/src/fs/org/jnode/fs/hfsplus/HFSPlusDirectory.java 2009-01-03 15:15:07 UTC (rev 4820) +++ trunk/fs/src/fs/org/jnode/fs/hfsplus/HFSPlusDirectory.java 2009-01-03 21:05:14 UTC (rev 4821) @@ -9,6 +9,7 @@ import org.jnode.fs.ReadOnlyFileSystemException; import org.jnode.fs.hfsplus.catalog.CatalogFolder; import org.jnode.fs.hfsplus.catalog.CatalogKey; +import org.jnode.fs.hfsplus.catalog.CatalogNodeId; import org.jnode.fs.hfsplus.tree.LeafRecord; import org.jnode.fs.spi.AbstractFSDirectory; import org.jnode.fs.spi.FSEntryTable; @@ -32,7 +33,20 @@ @Override protected final FSEntry createDirectoryEntry(final String name) throws IOException { - throw new ReadOnlyFileSystemException(); + if(!canWrite()){ + throw new ReadOnlyFileSystemException(); + } + Superblock volumeHeader = ((HfsPlusFileSystem) getFileSystem()).getVolumeHeader(); + CatalogFolder newFolder = new CatalogFolder(new CatalogNodeId(volumeHeader.getNextCatalogId())); + log.debug("New catalog folder :\n" + newFolder.toString()); + CatalogKey key = new CatalogKey(this.folder.getFolderId(),new HFSUnicodeString(name)); + log.debug("New catalog key :\n" + key.toString()); + LeafRecord folderRecord = new LeafRecord(key,newFolder.getBytes()); + log.debug("New record folder :\n" + folderRecord.toString()); + HFSPlusEntry newEntry = new HFSPlusEntry( (HfsPlusFileSystem) getFileSystem(),null,this,name,folderRecord); + volumeHeader.setFolderCount(volumeHeader.getFolderCount() + 1); + log.debug("New volume header :\n" + volumeHeader.toString()); + return newEntry; } @Override @@ -54,7 +68,7 @@ rec.getType() == HfsPlusConstants.RECORD_TYPE_FILE) { String name = ((CatalogKey) rec.getKey()).getNodeName().getUnicodeString(); HFSPlusEntry e = - new HFSPlusEntry((HfsPlusFileSystem) getFileSystem(), null, null, name, rec); + new HFSPlusEntry((HfsPlusFileSystem) getFileSystem(), null, this, name, rec); pathList.add(e); } } Modified: trunk/fs/src/fs/org/jnode/fs/hfsplus/HFSPlusForkData.java =================================================================== --- trunk/fs/src/fs/org/jnode/fs/hfsplus/HFSPlusForkData.java 2009-01-03 15:15:07 UTC (rev 4820) +++ trunk/fs/src/fs/org/jnode/fs/hfsplus/HFSPlusForkData.java 2009-01-03 21:05:14 UTC (rev 4821) @@ -8,24 +8,53 @@ private static final int EXTENT_OFFSET = 16; private byte[] data; - + + /** + * + * @param src + * @param offset + */ public HFSPlusForkData(final byte[] src, final int offset) { data = new byte[FORK_DATA_LENGTH]; System.arraycopy(src, offset, data, 0, FORK_DATA_LENGTH); } + + /** + * + * Create a new empty fork data object. + * + * @param totalSize + * @param clumpSize + * @param totalBock + */ + public HFSPlusForkData(){ + data = new byte[FORK_DATA_LENGTH]; + } public final long getTotalSize() { return BigEndian.getInt64(data, 0); } + public final void setTotalSize(long totalSize){ + BigEndian.setInt64(data, 0, totalSize); + } + public final int getClumpSize() { return BigEndian.getInt32(data, 8); } + public final void setClumpSize(int clumpSize){ + BigEndian.setInt32(data, 8, clumpSize); + } + public final int getTotalBlocks() { return BigEndian.getInt32(data, 12); } + public final void setTotalBlocks(int totalBlock){ + BigEndian.setInt32(data, 12, totalBlock); + } + public final ExtentDescriptor[] getExtents() { ExtentDescriptor[] list = new ExtentDescriptor[8]; for (int i = 0; i < 8; i++) { @@ -34,6 +63,15 @@ } return list; } + + public final void setExtentDescriptor(int position, ExtentDescriptor desc){ + int offset = EXTENT_OFFSET + (position * ExtentDescriptor.EXTENT_DESCRIPTOR_LENGTH); + System.arraycopy(desc.getBytes(), 0, data, offset, ExtentDescriptor.EXTENT_DESCRIPTOR_LENGTH); + } + + public byte[] getBytes(){ + return data; + } public final String toString() { StringBuffer s = new StringBuffer(); Modified: trunk/fs/src/fs/org/jnode/fs/hfsplus/HFSPlusObject.java =================================================================== --- trunk/fs/src/fs/org/jnode/fs/hfsplus/HFSPlusObject.java 2009-01-03 15:15:07 UTC (rev 4820) +++ trunk/fs/src/fs/org/jnode/fs/hfsplus/HFSPlusObject.java 2009-01-03 21:05:14 UTC (rev 4821) @@ -3,7 +3,7 @@ import org.jnode.fs.FSObject; public class HFSPlusObject implements FSObject { - private HfsPlusFileSystem fs; + protected HfsPlusFileSystem fs; public HFSPlusObject(final HfsPlusFileSystem fileSystem) { this.fs = fileSystem; Modified: trunk/fs/src/fs/org/jnode/fs/hfsplus/HFSUnicodeString.java =================================================================== --- trunk/fs/src/fs/org/jnode/fs/hfsplus/HFSUnicodeString.java 2009-01-03 15:15:07 UTC (rev 4820) +++ trunk/fs/src/fs/org/jnode/fs/hfsplus/HFSUnicodeString.java 2009-01-03 21:05:14 UTC (rev 4821) @@ -8,9 +8,14 @@ private int length; private String string; - + /** + * + * @param src + * @param offset + */ public HFSUnicodeString(final byte[] src, final int offset) { - byte[] data = new byte[2]; + length = BigEndian.getInt16(src, offset); + byte[] data = new byte[2 + length * 2]; System.arraycopy(src, offset, data, 0, 2); length = BigEndian.getInt16(data, 0); data = new byte[length * 2]; @@ -21,6 +26,15 @@ } string = new String(result); } + + /** + * + * @param string + */ + public HFSUnicodeString(String string){ + this.string = string; + this.length = string.length(); + } public final int getLength() { return length; @@ -29,5 +43,9 @@ public final String getUnicodeString() { return string; } + + public final byte[] getBytes(){ + return (length + "" + string).getBytes() ; + } } Modified: trunk/fs/src/fs/org/jnode/fs/hfsplus/HFSUtils.java =================================================================== --- trunk/fs/src/fs/org/jnode/fs/hfsplus/HFSUtils.java 2009-01-03 15:15:07 UTC (rev 4820) +++ trunk/fs/src/fs/org/jnode/fs/hfsplus/HFSUtils.java 2009-01-03 21:05:14 UTC (rev 4821) @@ -1,29 +1,40 @@ package org.jnode.fs.hfsplus; import java.text.SimpleDateFormat; -import java.util.Date; +import java.util.Calendar; public class HFSUtils { - public static final long DIFF_TO_JAVA_DATE_IN_MILLIS = 2082844800000L; + + /** + * Difference in second between 01/01/1970 00:00:00 (java reference time) + * and 01/01/1904 00:00:00 (HFS reference time). + */ + public static final long MAC_DATE_CONVERTION = 2082844800L; /** + * Convert time from/to java time to/from mac time. + * + * @param time in seconds since reference date. + * @param encode if set to true, convert from java to mac. If set to false, + * convert from mac to java. * - * @param time time in second since midnight, January 1, 1904, GMT. * @return */ - public static Date decodeDate(final int time) { - return new Date(time * 1000 - DIFF_TO_JAVA_DATE_IN_MILLIS); + public static long getDate(long time, boolean encode){ + time = (encode)? time + MAC_DATE_CONVERTION:time - MAC_DATE_CONVERTION; + return time; } - + /** * * @param time * @param dateFormat * @return */ - public static String printDate(final int time, final String dateFormat) { - Date date = decodeDate(time); + public static String printDate(final long time, final String dateFormat) { + Calendar cal = Calendar.getInstance(); + cal.setTimeInMillis(getDate(time, false)*1000); SimpleDateFormat sdf = new SimpleDateFormat(dateFormat); - return sdf.format(date.getTime()); + return sdf.format(cal.getTime()); } } Modified: trunk/fs/src/fs/org/jnode/fs/hfsplus/HfsPlusConstants.java =================================================================== --- trunk/fs/src/fs/org/jnode/fs/hfsplus/HfsPlusConstants.java 2009-01-03 15:15:07 UTC (rev 4820) +++ trunk/fs/src/fs/org/jnode/fs/hfsplus/HfsPlusConstants.java 2009-01-03 21:05:14 UTC (rev 4821) @@ -3,7 +3,7 @@ public class HfsPlusConstants { public static final int HFSPLUS_SUPER_MAGIC = 0x482b; - public static final int HFSPLUS_MIN_VERSION = 4; /* HFS+ */ + public static final int HFSPLUS_MIN_VERSION = 0x0004; /* HFS+ */ public static final int HFSPLUS_CURRENT_VERSION = 5; /* HFSX */ /* HFS+ volume attributes */ @@ -32,4 +32,10 @@ public static final byte EK_DATA_FORK = (byte) 0x00; public static final byte EK_RESOURCE_FORK = (byte) 0xFF; + + public static final int MINIMAL_BLOCK_SIZE = 512; + public static final int OPTIMAL_BLOCK_SIZE = 4096; + + public static final int DATA_CLUMP_FACTOR = 16; + public static final int RESOURCE_CLUMP_FACTOR = 16; } Modified: trunk/fs/src/fs/org/jnode/fs/hfsplus/HfsPlusFileSystem.java =================================================================== --- trunk/fs/src/fs/org/jnode/fs/hfsplus/HfsPlusFileSystem.java 2009-01-03 15:15:07 UTC (rev 4820) +++ trunk/fs/src/fs/org/jnode/fs/hfsplus/HfsPlusFileSystem.java 2009-01-03 21:05:14 UTC (rev 4821) @@ -1,8 +1,10 @@ package org.jnode.fs.hfsplus; import java.io.IOException; +import java.nio.ByteBuffer; import org.apache.log4j.Logger; +import org.jnode.driver.ApiNotFoundException; import org.jnode.driver.Device; import org.jnode.fs.FSDirectory; import org.jnode.fs.FSEntry; @@ -35,13 +37,7 @@ super(device, readOnly, type); } - /** - * - * @throws FileSystemException - */ - public void create() throws FileSystemException { - // TODO implements file system creation. - } + /** * @@ -114,4 +110,21 @@ public final Superblock getVolumeHeader() { return sb; } + + /** + * + * @throws FileSystemException + */ + public void create(int blockSize) throws FileSystemException { + sb = new Superblock(); + try { + sb.create(this,blockSize, false); + this.getApi().write(1024, ByteBuffer.wrap(sb.getBytes())); + flush(); + } catch (IOException e) { + throw new FileSystemException("Unable to create HFS+ filesystem", e); + } catch (ApiNotFoundException e) { + throw new FileSystemException("Unable to create HFS+ filesystem", e); + } + } } Modified: trunk/fs/src/fs/org/jnode/fs/hfsplus/HfsPlusFileSystemFormatter.java =================================================================== --- trunk/fs/src/fs/org/jnode/fs/hfsplus/HfsPlusFileSystemFormatter.java 2009-01-03 15:15:07 UTC (rev 4820) +++ trunk/fs/src/fs/org/jnode/fs/hfsplus/HfsPlusFileSystemFormatter.java 2009-01-03 21:05:14 UTC (rev 4821) @@ -17,10 +17,10 @@ @Override public final HfsPlusFileSystem format(final Device device) throws FileSystemException { try { - FileSystemService fSS = InitialNaming.lookup(FileSystemService.NAME); - HfsPlusFileSystemType type = fSS.getFileSystemType(HfsPlusFileSystemType.ID); + FileSystemService fss = InitialNaming.lookup(FileSystemService.NAME); + HfsPlusFileSystemType type = fss.getFileSystemType(HfsPlusFileSystemType.ID); HfsPlusFileSystem fs = type.create(device, false); - fs.create(); + fs.create(HfsPlusConstants.OPTIMAL_BLOCK_SIZE); return fs; } catch (NameNotFoundException e) { throw new FileSystemException(e); Modified: trunk/fs/src/fs/org/jnode/fs/hfsplus/Superblock.java =================================================================== --- trunk/fs/src/fs/org/jnode/fs/hfsplus/Superblock.java 2009-01-03 15:15:07 UTC (rev 4820) +++ trunk/fs/src/fs/org/jnode/fs/hfsplus/Superblock.java 2009-01-03 21:05:14 UTC (rev 4821) @@ -7,10 +7,15 @@ import java.io.IOException; import java.nio.ByteBuffer; +import java.util.Calendar; +import java.util.Date; import org.apache.log4j.Level; import org.apache.log4j.Logger; +import org.jnode.driver.ApiNotFoundException; import org.jnode.fs.FileSystemException; +import org.jnode.fs.hfsplus.catalog.CatalogNodeId; +import org.jnode.fs.hfsplus.extent.ExtentDescriptor; import org.jnode.util.BigEndian; import org.jnode.util.NumberUtils; @@ -62,7 +67,229 @@ throw new FileSystemException(e); } } + + + + /** + * Create a new volume header. + * + * @param fs + * @param blockSize + * @throws ApiNotFoundException + */ + public void create(HfsPlusFileSystem fs, int blockSize,boolean journaled) throws IOException, ApiNotFoundException, FileSystemException { + + this.fs = fs; + int burnedBlocksBeforeVH = 0; + int burnedBlocksAfterAltVH = 0; + /* + * Volume header is located at sector 2. Block before this position + * must be invalidated. + */ + if ( blockSize == 512 ) { + burnedBlocksBeforeVH = 2; + burnedBlocksAfterAltVH = 1; + } else if ( blockSize == 1024 ) { + burnedBlocksBeforeVH = 1; + } + long size = fs.getApi().getLength(); + long sectorCount = size / fs.getFSApi().getSectorSize(); + long blocks = size / blockSize; + long allocationClumpSize = getClumpSize(blocks); + long bitmapBlocks = allocationClumpSize/blockSize; + long blockUsed = 2+ burnedBlocksBeforeVH + burnedBlocksAfterAltVH + bitmapBlocks; + // Populate volume header. + this.setMagic(HfsPlusConstants.HFSPLUS_SUPER_MAGIC); + this.setVersion(HfsPlusConstants.HFSPLUS_MIN_VERSION); + //Set attributes. + this.setAttribute(HFSPLUS_VOL_UNMNT_BIT); + this.setLastMountedVersion(0x446534a); + //TODO Put correct dates. + Calendar now = Calendar.getInstance(); + now.setTime(new Date()); + int macDate = (int)HFSUtils.getDate(now.getTimeInMillis()/1000, true); + this.setCreateDate(macDate); + this.setModifyDate(macDate); + this.setBackupDate(0); + this.setCheckedDate(macDate); + //--- + this.setFileCount(0); + this.setFolderCount(0); + this.setBlockSize(blockSize); + this.setTotalBlocks((int)blocks); + this.setFreeBlocks((int)blocks); + this.setRsrcClumpSize(HfsPlusConstants.RESOURCE_CLUMP_FACTOR * blockSize); + this.setDataClumpSize(HfsPlusConstants.DATA_CLUMP_FACTOR * blockSize); + this.setNextCatalogId(CatalogNodeId.HFSPLUS_FIRSTUSER_CNID.getId()); + // Allocation file creation + initAllocationFile((int)allocationClumpSize, (int)bitmapBlocks, burnedBlocksBeforeVH); + int nextBlock = 0; + // Journal creation + ExtentDescriptor desc = this.getAllocationFile().getExtents()[0]; + if(journaled){ + int journalSize = 8*1024*1024; + this.setFileCount(2); + this.setAttribute(HFSPLUS_VOL_JOURNALED_BIT); + this.setNextCatalogId(this.getNextCatalogId() + 2); + this.setJournalInfoBlock(desc.getStartBlock() + desc.getBlockCount()); + blockUsed = blockUsed + 1 + (journalSize / blockSize); + } else { + this.setJournalInfoBlock(0); + nextBlock = desc.getStartBlock() + desc.getBlockCount(); + } + blockUsed += initExtents(0,blockSize,nextBlock, (int)sectorCount, blockUsed); + blockUsed += initCatalog(0,blockSize,nextBlock, (int)sectorCount, blockUsed); + this.setFreeBlocks(this.getFreeBlocks() - (int)blockUsed); + this.setNextAllocation((int)blockUsed - 1 - burnedBlocksAfterAltVH + 10 * (this.getCatalogFile().getClumpSize() / this.getBlockSize())); + } + + /** + * + * @param clumpSize + * @param bitmapBlocks + * @param burnedBlocksBeforeVH + * @return + */ + private void initAllocationFile(int clumpSize, int bitmapBlocks, int burnedBlocksBeforeVH){ + HFSPlusForkData forkdata = new HFSPlusForkData(); + forkdata.setTotalSize(clumpSize); + forkdata.setClumpSize(clumpSize); + forkdata.setTotalBlocks(bitmapBlocks); + ExtentDescriptor desc = new ExtentDescriptor(); + desc.setStartBlock(1 + burnedBlocksBeforeVH); + desc.setBlockCount(0); + forkdata.setExtentDescriptor(0, desc); + System.arraycopy(forkdata.getBytes(), 0, data, 112, forkdata.FORK_DATA_LENGTH); + } + + /** + * + * @param extentsClumpBlock + * @param blockSize + * @param nextBlock + * @return + */ + private long initExtents(int extentsClumpBlock, int blockSize, int nextBlock, int sectorCount, long blockUsed){ + int extentNodeSize = 4096; + long clumpSize = 0; + if(extentsClumpBlock == 0){ + clumpSize = getBTreeClumpSize(blockSize, extentNodeSize, sectorCount, false); + } else { + clumpSize = clumpSizeCalculation(extentsClumpBlock, blockSize); + } + HFSPlusForkData forkdata = new HFSPlusForkData(); + forkdata.setTotalSize(clumpSize); + forkdata.setClumpSize((int)clumpSize); + forkdata.setTotalBlocks((int)(clumpSize/blockSize)); + ExtentDescriptor desc = new ExtentDescriptor(); + desc.setStartBlock(nextBlock); + desc.setBlockCount(forkdata.getTotalBlocks()); + forkdata.setExtentDescriptor(0, desc); + System.arraycopy(forkdata.getBytes(), 0, data, 192, forkdata.FORK_DATA_LENGTH); + return blockUsed + forkdata.getTotalBlocks(); + } + + /** + * + * @param extentsClumpBlock + * @param blockSize + * @param nextBlock + * @param sectorCount + * @param blockUsed + * @return + * @throws IOException + */ + private long initCatalog(int catalogClumpBlock, int blockSize, int nextBlock, int sectorCount, long blockUsed) throws FileSystemException{ + int catalogNodeSize = 8192; + try{ + if(blockSize < HfsPlusConstants.OPTIMAL_BLOCK_SIZE || fs.getApi().getLength() < 0x40000000){ + catalogNodeSize = 4096; + } + long clumpSize = 0; + if(catalogClumpBlock == 0){ + clumpSize = getBTreeClumpSize(blockSize, catalogNodeSize, sectorCount, true); + } else { + clumpSize = clumpSizeCalculation(catalogClumpBlock, blockSize); + if(clumpSize % catalogNodeSize != 0){ + throw new FileSystemException("clump size is not a multiple of node size"); + } + } + + HFSPlusForkData forkdata = new HFSPlusForkData(); + forkdata.setTotalSize(clumpSize); + forkdata.setClumpSize((int)clumpSize); + forkdata.setTotalBlocks((int)(clumpSize/blockSize)); + ExtentDescriptor desc = new ExtentDescriptor(); + desc.setStartBlock(this.getExtentsFile().getExtents()[0].getStartBlock() + this.getExtentsFile().getExtents()[0].getBlockCount()); + desc.setBlockCount(forkdata.getTotalBlocks()); + forkdata.setExtentDescriptor(0, desc); + System.arraycopy(forkdata.getBytes(), 0, data, 272, forkdata.FORK_DATA_LENGTH); + return blockUsed + forkdata.getTotalBlocks(); + } catch(IOException e){ + throw new FileSystemException(e); + } + } + + /** + * Calculate the number of blocks needed for bitmap. + * + * @param totalBlocks Total of blocks found in the device. + * + * @return long - Number of blocks. + * + * @throws IOException + */ + private long getClumpSize(long totalBlocks) throws IOException { + long clumpSize; + long minClumpSize = totalBlocks >> 3; + if ((totalBlocks & 7) == 0){ + ++minClumpSize; + } + clumpSize = minClumpSize; + return clumpSize; + } + /** + * + * @param blockSize + * @param nodeSize + * @param sectors + * @param catalog + * @return + */ + private int[] extentClumpTable = new int[]{4,4,4,5,5,6,7,8,9,11,14,16,20,25,32}; + private int[] catalogClumpTable = new int[]{4,6,8,11,14,19,25,34,45,60,80,107,144,192,256}; + private long getBTreeClumpSize(int blockSize, int nodeSize, long sectors, boolean catalog){ + long clumpSize = 0; + if(sectors < 0x200000){ + clumpSize = (sectors << 2); + if(clumpSize < (8*nodeSize)){ + clumpSize = (8*nodeSize); + } + } else { + sectors = sectors >> 22; + for(int i=0;sectors != 0 && (i < 14);++i){ + if(catalog){ + clumpSize = catalogClumpTable[i] * 1024 * 1024; + } else { + clumpSize = extentClumpTable[i] * 1024 * 1024; + } + sectors = sectors >> 1; + } + } + + return clumpSize; + } + + private int clumpSizeCalculation(long clumpBlocks, int blockSize){ + long clumpSize = clumpBlocks * blockSize; + if((clumpSize & 0XFFFFFFFF00000000L) == 0){ + //ERROR + } + return (int)clumpSize; + } + // Getters/setters + public final int getMagic() { return BigEndian.getInt16(data, 0); } @@ -82,31 +309,14 @@ // public final int getAttributes() { + return BigEndian.getInt32(data, 4); } - - /** - * Get string representation of attribute. - * - * @return - */ - public final String getAttributesAsString() { - return ((isAttribute(HFSPLUS_VOL_UNMNT_BIT)) ? " kHFSVolumeUnmountedBit" : "") + - ((isAttribute(HFSPLUS_VOL_INCNSTNT_BIT)) ? " kHFSBootVolumeInconsistentBit" : "") + - ((isAttribute(HFSPLUS_VOL_JOURNALED_BIT)) ? " kHFSVolumeJournaledBit" : ""); + + public final void setAttribute(final int attributeMaskBit) { + BigEndian.setInt32(data, 4,(getAttributes() >> attributeMaskBit) | 0x1); } - /** - * Check if the attribute corresponding to maskBit parameter is set. - * - * @param maskBit See constants. - * - * @return true if attribute is set. - */ - public final boolean isAttribute(final int maskBit) { - return (((getAttributes() >> maskBit) & 0x1) != 0); - } - // public final int getLastMountedVersion() { return BigEndian.getInt32(data, 8); @@ -126,32 +336,32 @@ } // - public final int getCreateDate() { - return BigEndian.getInt32(data, 16); + public final long getCreateDate() { + return BigEndian.getUInt32(data, 16); } public final void setCreateDate(final int value) { BigEndian.setInt32(data, 16, value); } - public final int getModifyDate() { - return BigEndian.getInt32(data, 20); + public final long getModifyDate() { + return BigEndian.getUInt32(data, 20); } public final void setModifyDate(final int value) { BigEndian.setInt32(data, 20, value); } - public final int getBackupDate() { - return BigEndian.getInt32(data, 24); + public final long getBackupDate() { + return BigEndian.getUInt32(data, 24); } public final void setBackupDate(final int value) { BigEndian.setInt32(data, 24, value); } - public final int getCheckedDate() { - return BigEndian.getInt32(data, 28); + public final long getCheckedDate() { + return BigEndian.getUInt32(data, 28); } public final void setCheckedDate(final int value) { @@ -277,7 +487,33 @@ public final HFSPlusForkData getStartupFile() { return new HFSPlusForkData(data, 432); } + + /** + * Get string representation of attribute. + * + * @return + */ + public final String getAttributesAsString() { + return ((isAttribute(HFSPLUS_VOL_UNMNT_BIT)) ? " kHFSVolumeUnmountedBit" : "") + + ((isAttribute(HFSPLUS_VOL_INCNSTNT_BIT)) ? " kHFSBootVolumeInconsistentBit" : "") + + ((isAttribute(HFSPLUS_VOL_JOURNALED_BIT)) ? " kHFSVolumeJournaledBit" : ""); + } + /** + * Check if the corresponding attribute corresponding is set. + * + * @param maskBit Bit position of the attribute. See constants. + * + * @return true if attribute is set. + */ + public final boolean isAttribute(final int maskBit) { + return (((getAttributes() >> maskBit) & 0x1) != 0); + } + + public byte[] getBytes(){ + return data; + } + /* * (non-Javadoc) * @see java.lang.Object#toString() @@ -286,7 +522,7 @@ StringBuffer buffer = new StringBuffer(); buffer.append("Magic: 0x").append(NumberUtils.hex(getMagic(), 4)).append("\n"); buffer.append("Version: ").append(getVersion()).append("\n").append("\n"); - buffer.append("Attributes: ").append(getAttributesAsString()).append("\n").append("\n"); + buffer.append("Attributes: ").append(getAttributesAsString()).append(" (").append(getAttributes()).append(")").append("\n").append("\n"); buffer.append("Create date: ").append( HFSUtils.printDate(getCreateDate(), "EEE MMM d HH:mm:ss yyyy")).append("\n"); buffer.append("Modify date: ").append( @@ -305,7 +541,7 @@ buffer.append("Write count: ").append(getWriteCount()).append("\n"); buffer.append("Encoding bmp: ").append(getEncodingsBmp()).append("\n"); buffer.append("Finder Infos: ").append(getFinderInfo()).append("\n").append("\n"); - buffer.append("Finder Infos: ").append(getJournalInfoBlock()).append("\n").append("\n"); + buffer.append("Journal block: ").append(getJournalInfoBlock()).append("\n").append("\n"); buffer.append("Allocation file").append("\n"); buffer.append(getAllocationFile().toString()).append("\n"); buffer.append("Extents file").append("\n"); Modified: trunk/fs/src/fs/org/jnode/fs/hfsplus/catalog/CatalogFile.java =================================================================== --- trunk/fs/src/fs/org/jnode/fs/hfsplus/catalog/CatalogFile.java 2009-01-03 15:15:07 UTC (rev 4820) +++ trunk/fs/src/fs/org/jnode/fs/hfsplus/catalog/CatalogFile.java 2009-01-03 21:05:14 UTC (rev 4821) @@ -1,6 +1,7 @@ package org.jnode.fs.hfsplus.catalog; import org.jnode.fs.hfsplus.HFSPlusForkData; +import org.jnode.fs.hfsplus.HFSUtils; import org.jnode.util.BigEndian; public class CatalogFile { @@ -14,10 +15,26 @@ public final int getRecordType() { return BigEndian.getInt16(data, 0); } + + public final int getFlags() { + return BigEndian.getInt16(data, 2); + } public final CatalogNodeId getFileId() { return new CatalogNodeId(data, 8); } + + public final int getCreateDate() { + return BigEndian.getInt32(data, 12); + } + + public final int getContentModDate() { + return BigEndian.getInt32(data, 16); + } + + public final int getAttrModDate() { + return BigEndian.getInt32(data, 20); + } public final HFSPlusForkData getDataFork() { return new HFSPlusForkData(data, 88); @@ -31,6 +48,9 @@ StringBuffer s = new StringBuffer(); s.append("Record type:").append(getRecordType()).append("\t"); s.append("File ID :").append(getFileId().getId()).append("\n"); + s.append("Creation Date :").append(HFSUtils.printDate(getCreateDate(), "EEE MMM d HH:mm:ss yyyy")).append("\n"); + s.append("Content Mod Date :").append(HFSUtils.printDate(getContentModDate(), "EEE MMM d HH:mm:ss yyyy")).append("\n"); + s.append("Attr Mod Date :").append(HFSUtils.printDate(getAttrModDate(), "EEE MMM d HH:mm:ss yyyy")).append("\n"); return s.toString(); } } Modified: trunk/fs/src/fs/org/jnode/fs/hfsplus/catalog/CatalogFolder.java =================================================================== --- trunk/fs/src/fs/org/jnode/fs/hfsplus/catalog/CatalogFolder.java 2009-01-03 15:15:07 UTC (rev 4820) +++ trunk/fs/src/fs/org/jnode/fs/hfsplus/catalog/CatalogFolder.java 2009-01-03 21:05:14 UTC (rev 4821) @@ -1,5 +1,7 @@ package org.jnode.fs.hfsplus.catalog; +import org.jnode.fs.hfsplus.HFSUtils; +import org.jnode.fs.hfsplus.HfsPlusConstants; import org.jnode.util.BigEndian; public class CatalogFolder { @@ -9,6 +11,19 @@ data = new byte[88]; System.arraycopy(src, 0, data, 0, 88); } + + /** + * Create a new catalog folder. + * + * @param folderId + * + */ + public CatalogFolder(CatalogNodeId folderId){ + data = new byte[88]; + BigEndian.setInt16(data, 0, HfsPlusConstants.RECORD_TYPE_FOLDER); + BigEndian.setInt32(data, 4, 0); + System.arraycopy(folderId.getBytes(), 0, data, 8, folderId.getBytes().length); + } public final int getRecordType() { return BigEndian.getInt16(data, 0); @@ -21,12 +36,31 @@ public final CatalogNodeId getFolderId() { return new CatalogNodeId(data, 8); } + + public final int getCreateDate() { + return BigEndian.getInt32(data, 12); + } + + public final int getContentModDate() { + return BigEndian.getInt32(data, 16); + } + + public final int getAttrModDate() { + return BigEndian.getInt32(data, 20); + } + + public byte[] getBytes(){ + return data; + } public final String toString() { StringBuffer s = new StringBuffer(); s.append("Record type: ").append(getRecordType()).append("\n"); s.append("Valence: ").append(getValence()).append("\n"); s.append("Folder ID: ").append(getFolderId().getId()).append("\n"); + s.append("Creation Date :").append(HFSUtils.printDate(getCreateDate(), "EEE MMM d HH:mm:ss yyyy")).append("\n"); + s.append("Content Mod Date :").append(HFSUtils.printDate(getContentModDate(), "EEE MMM d HH:mm:ss yyyy")).append("\n"); + s.append("Attr Mod Date :").append(HFSUtils.printDate(getAttrModDate(), "EEE MMM d HH:mm:ss yyyy")).append("\n"); return s.toString(); } } Modified: trunk/fs/src/fs/org/jnode/fs/hfsplus/catalog/CatalogKey.java =================================================================== --- trunk/fs/src/fs/org/jnode/fs/hfsplus/catalog/CatalogKey.java 2009-01-03 15:15:07 UTC (rev 4820) +++ trunk/fs/src/fs/org/jnode/fs/hfsplus/catalog/CatalogKey.java 2009-01-03 21:05:14 UTC (rev 4821) @@ -35,6 +35,7 @@ public CatalogKey(final CatalogNodeId parentID, final HFSUnicodeString name) { this.parentID = parentID; this.nodeName = name; + this.keyLength = 6 + name.getLength(); } public final int getKeyLength() { Modified: trunk/fs/src/fs/org/jnode/fs/hfsplus/catalog/CatalogNodeId.java =================================================================== --- trunk/fs/src/fs/org/jnode/fs/hfsplus/catalog/CatalogNodeId.java 2009-01-03 15:15:07 UTC (rev 4820) +++ trunk/fs/src/fs/org/jnode/fs/hfsplus/catalog/CatalogNodeId.java 2009-01-03 21:05:14 UTC (rev 4821) @@ -39,5 +39,9 @@ public final int getId() { return BigEndian.getInt32(cnid, 0); } + + public final byte[] getBytes(){ + return cnid; + } } Modified: trunk/fs/src/fs/org/jnode/fs/hfsplus/catalog/CatalogThread.java =================================================================== --- trunk/fs/src/fs/org/jnode/fs/hfsplus/catalog/CatalogThread.java 2009-01-03 15:15:07 UTC (rev 4820) +++ trunk/fs/src/fs/org/jnode/fs/hfsplus/catalog/CatalogThread.java 2009-01-03 21:05:14 UTC (rev 4821) @@ -11,6 +11,20 @@ System.arraycopy(src, 0, data, 0, 512); } + /** + * Create a new catalog thread. + * + * @param type + * @param parent + * @param name + */ + public CatalogThread(int type, CatalogNodeId parent, HFSUnicodeString name){ + BigEndian.setInt16(data, 0, type); + BigEndian.setInt32(data, 4, parent.getId()); + System.arraycopy(parent.getBytes(), 0, data, 4, 4); + System.arraycopy(name.getBytes(), 0, data, 8, name.getBytes().length); + } + public final int getRecordType() { return BigEndian.getInt16(data, 0); } Added: trunk/fs/src/fs/org/jnode/fs/hfsplus/command/FormatHfsPlusCommand.java =================================================================== --- trunk/fs/src/fs/org/jnode/fs/hfsplus/command/FormatHfsPlusCommand.java (rev 0) +++ trunk/fs/src/fs/org/jnode/fs/hfsplus/command/FormatHfsPlusCommand.java 2009-01-03 21:05:14 UTC (rev 4821) @@ -0,0 +1,19 @@ +package org.jnode.fs.hfsplus.command; + +import org.jnode.fs.Formatter; +import org.jnode.fs.command.AbstractFormatCommand; +import org.jnode.fs.hfsplus.HfsPlusFileSystem; + +public class FormatHfsPlusCommand extends AbstractFormatCommand<HfsPlusFileSystem> { + + public FormatHfsPlusCommand() { + super("Format a block device with HFS+ filesystem"); + } + + @Override + protected Formatter<HfsPlusFileSystem> getFormatter() { + // TODO implement it. + return null; + } + +} Modified: trunk/fs/src/fs/org/jnode/fs/hfsplus/extent/ExtentDescriptor.java =================================================================== --- trunk/fs/src/fs/org/jnode/fs/hfsplus/extent/ExtentDescriptor.java 2009-01-03 15:15:07 UTC (rev 4820) +++ trunk/fs/src/fs/org/jnode/fs/hfsplus/extent/ExtentDescriptor.java 2009-01-03 21:05:14 UTC (rev 4821) @@ -8,6 +8,13 @@ private byte[] data; + /** + * Create empty extent descriptor. + */ + public ExtentDescriptor() { + data = new byte[EXTENT_DESCRIPTOR_LENGTH]; + } + public ExtentDescriptor(final byte[] src, final int offset) { data = new byte[EXTENT_DESCRIPTOR_LENGTH]; System.arraycopy(src, offset, data, 0, EXTENT_DESCRIPTOR_LENGTH); @@ -17,10 +24,22 @@ return BigEndian.getInt32(data, 0); } + public final void setStartBlock(int start){ + BigEndian.setInt32(data, 0, start); + } + public final int getBlockCount() { return BigEndian.getInt32(data, 4); } + + public final void setBlockCount(int count){ + BigEndian.setInt32(data, 4, count); + } + public final byte[] getBytes(){ + return data; + } + public final String toString() { return "Start block : " + getStartBlock() + "\tBlock count : " + getBlockCount() + "\n"; } Modified: trunk/fs/src/fs/org/jnode/fs/hfsplus/tree/LeafNode.java =================================================================== --- trunk/fs/src/fs/org/jnode/fs/hfsplus/tree/LeafNode.java 2009-01-03 15:15:07 UTC (rev 4820) +++ trunk/fs/src/fs/org/jnode/fs/hfsplus/tree/LeafNode.java 2009-01-03 21:05:14 UTC (rev 4821) @@ -14,11 +14,5 @@ records = new LeafRecord[offsets.length - 1]; } - /** - * - * @return - */ - public final LeafRecord[] getRecords() { - return records; - } + } Modified: trunk/fs/src/fs/org/jnode/fs/hfsplus/tree/LeafRecord.java =================================================================== --- trunk/fs/src/fs/org/jnode/fs/hfsplus/tree/LeafRecord.java 2009-01-03 15:15:07 UTC (rev 4820) +++ trunk/fs/src/fs/org/jnode/fs/hfsplus/tree/LeafRecord.java 2009-01-03 21:05:14 UTC (rev 4821) @@ -13,6 +13,17 @@ System.arraycopy(nodeData, offset + key.getKeyLength() + 2, recordData, 0, recordDataSize); } + /** + * + * @param key + * @param recordData + */ + public LeafRecord(final Key key, final byte[] recordData){ + this.key = key; + this.recordData = new byte[recordData.length]; + System.arraycopy(recordData,0, this.recordData, 0, recordData.length); + } + public final Key getKey() { return key; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |