long currentMetadataBlock, long currentFiledataBlock,
FileEntry parentFileEntry, long uniqueID, int descriptorVersion)
throws Exception {
long[] nextFreeBlocks = new long[2];
ExtendedFileEntry myExtendedFileEntry = new ExtendedFileEntry();
myExtendedFileEntry.DescriptorTag.TagSerialNumber = serialNumberForTags;
myExtendedFileEntry.DescriptorTag.DescriptorVersion = descriptorVersion;
myExtendedFileEntry.DescriptorTag.TagLocation = currentMetadataBlock - metadataPartitionStartingBlock;
myExtendedFileEntry.Uid = 0xFFFFFFFF; // TODO: get current uid and gid if java supports it
myExtendedFileEntry.Gid = 0xFFFFFFFF;
// TODO: get real file permission if java supports it
myExtendedFileEntry.Permissions = Permissions.OTHER_Read | Permissions.GROUP_Read | Permissions.OWNER_Read;
myExtendedFileEntry.FileLinkCount = currentUDFImageBuilderFile.getFileLinkCount();
myExtendedFileEntry.RecordFormat = 0;
myExtendedFileEntry.RecordDisplayAttributes = 0;
myExtendedFileEntry.RecordLength = 0;
myExtendedFileEntry.AccessTime = new Timestamp(currentUDFImageBuilderFile.getAccessTime());
myExtendedFileEntry.ModificationTime = new Timestamp(currentUDFImageBuilderFile.getModificationTime());
myExtendedFileEntry.AttributeTime = new Timestamp(currentUDFImageBuilderFile.getAttributeTime());
myExtendedFileEntry.Checkpoint = 1;
myExtendedFileEntry.ImplementationIdentifier.setIdentifier(applicationIdentifier);
myExtendedFileEntry.ImplementationIdentifier.IdentifierSuffix = applicationIdentifierSuffix;
myExtendedFileEntry.ICBTag.PriorRecordedNumberofDirectEntries = 0;
myExtendedFileEntry.ICBTag.NumberofEntries = 1;
myExtendedFileEntry.ICBTag.StrategyType = 4;
myExtendedFileEntry.UniqueID = uniqueID;
nextFreeBlocks[0] = currentMetadataBlock + 1;
nextFreeBlocks[1] = currentFiledataBlock;
/*
* if file is a directory
*/
if (currentUDFImageBuilderFile.getFileType() == UDFImageBuilderFile.FileType.Directory) {
myExtendedFileEntry.ICBTag.FileType = 4; // directory
myExtendedFileEntry.Permissions |=
Permissions.OTHER_Execute | Permissions.GROUP_Execute | Permissions.OWNER_Execute;
// create file identifier descriptors for all child files
UDFImageBuilderFile childUDFImageBuilderFiles[] = currentUDFImageBuilderFile.getChilds();
ArrayList<FileIdentifierDescriptor> childFileIdentifierDescriptors =
new ArrayList<FileIdentifierDescriptor>();
// parent directory FID
FileIdentifierDescriptor parentDirectoryFileIdentifierDescriptor = new FileIdentifierDescriptor();
parentDirectoryFileIdentifierDescriptor.DescriptorTag.TagLocation =
currentMetadataBlock - metadataPartitionStartingBlock;
parentDirectoryFileIdentifierDescriptor.DescriptorTag.TagSerialNumber = serialNumberForTags;
parentDirectoryFileIdentifierDescriptor.DescriptorTag.DescriptorVersion = descriptorVersion;
parentDirectoryFileIdentifierDescriptor.ICB.ExtentLength = blockSize;
parentDirectoryFileIdentifierDescriptor.ICB.ExtentLocation.part_num = 1;
parentDirectoryFileIdentifierDescriptor.FileVersionNumber = 1;
parentDirectoryFileIdentifierDescriptor.FileCharacteristics = 10; // file is directory and parent
// if root directory
if (parentFileEntry == null) {
parentDirectoryFileIdentifierDescriptor.ICB.ExtentLocation.lb_num =
currentMetadataBlock - metadataPartitionStartingBlock;
}
// if non root directory
else {
parentDirectoryFileIdentifierDescriptor.ICB.ExtentLocation.lb_num =
parentFileEntry.DescriptorTag.TagLocation;
parentDirectoryFileIdentifierDescriptor.ICB.implementationUse = new byte[6];
parentDirectoryFileIdentifierDescriptor.ICB.implementationUse[2] =
(byte) (parentFileEntry.UniqueID & 0xFF);
parentDirectoryFileIdentifierDescriptor.ICB.implementationUse[3] =
(byte) ((parentFileEntry.UniqueID >> 8) & 0xFF);
parentDirectoryFileIdentifierDescriptor.ICB.implementationUse[4] =
(byte) ((parentFileEntry.UniqueID >> 16) & 0xFF);
parentDirectoryFileIdentifierDescriptor.ICB.implementationUse[5] =
(byte) ((parentFileEntry.UniqueID >> 32) & 0xFF);
}
childFileIdentifierDescriptors.add(parentDirectoryFileIdentifierDescriptor);
// child file FIDs
for (int i = 0; i < childUDFImageBuilderFiles.length; ++i) {
long childFileUniqueID = myUniqueIdDisposer.getNextUniqueId();
FileIdentifierDescriptor childFileIdentifierDescriptor = new FileIdentifierDescriptor();
childFileIdentifierDescriptor.DescriptorTag.TagLocation =
currentMetadataBlock - metadataPartitionStartingBlock;
childFileIdentifierDescriptor.DescriptorTag.TagSerialNumber = serialNumberForTags;
childFileIdentifierDescriptor.DescriptorTag.DescriptorVersion = descriptorVersion;
childFileIdentifierDescriptor.ICB.ExtentLength = blockSize;
childFileIdentifierDescriptor.ICB.ExtentLocation.lb_num =
nextFreeBlocks[0] - metadataPartitionStartingBlock;
childFileIdentifierDescriptor.ICB.ExtentLocation.part_num = 1;
childFileIdentifierDescriptor.ICB.implementationUse = new byte[6];
childFileIdentifierDescriptor.ICB.implementationUse[2] = (byte) (childFileUniqueID & 0xFF);
childFileIdentifierDescriptor.ICB.implementationUse[3] = (byte) ((childFileUniqueID >> 8) & 0xFF);
childFileIdentifierDescriptor.ICB.implementationUse[4] = (byte) ((childFileUniqueID >> 16) & 0xFF);
childFileIdentifierDescriptor.ICB.implementationUse[5] = (byte) ((childFileUniqueID >> 32) & 0xFF);
childFileIdentifierDescriptor.FileVersionNumber = 1;
childFileIdentifierDescriptor.setFileIdentifier(childUDFImageBuilderFiles[i].getIdentifier());
if (childUDFImageBuilderFiles[i].getFileType() == UDFImageBuilderFile.FileType.Directory) {
childFileIdentifierDescriptor.FileCharacteristics = 2;
}
childFileIdentifierDescriptors.add(childFileIdentifierDescriptor);
nextFreeBlocks = recursiveWriteFilesystemWithMetadata(myRandomAccessFile, partitionStartingBlock,
metadataPartitionStartingBlock, blockSize, serialNumberForTags, childUDFImageBuilderFiles[i],
nextFreeBlocks[0], nextFreeBlocks[1], myExtendedFileEntry, childFileUniqueID,
descriptorVersion);
}
// get directory file data length
int directoryFileDataLength = 0;
for (int i = 0; i < childFileIdentifierDescriptors.size(); ++i) {
directoryFileDataLength += childFileIdentifierDescriptors.get(i).getLength();
}
myExtendedFileEntry.InformationLength = directoryFileDataLength;
if (directoryFileDataLength <= blockSize - ExtendedFileEntry.fixedPartLength) {
// inline embedded file data
myExtendedFileEntry.ICBTag.Flags = 3; // storage type inline
myExtendedFileEntry.LogicalBlocksRecorded = 0;
myExtendedFileEntry.LengthofAllocationDescriptors = directoryFileDataLength;
myExtendedFileEntry.AllocationDescriptors = new byte[directoryFileDataLength];
int pos = 0;
for (int i = 0; i < childFileIdentifierDescriptors.size(); ++i) {
byte childFileIdentifierDescriptorBytes[] = childFileIdentifierDescriptors.get(i).getBytes();
System.arraycopy(childFileIdentifierDescriptorBytes, 0, myExtendedFileEntry.AllocationDescriptors,
pos, childFileIdentifierDescriptorBytes.length);
pos += childFileIdentifierDescriptorBytes.length;
}
} else {
// store as exernal file data with Short_ad
myExtendedFileEntry.ICBTag.Flags = 0; // storage type short_ad
myExtendedFileEntry.LogicalBlocksRecorded = (long) (directoryFileDataLength / blockSize);
if (directoryFileDataLength % blockSize != 0) {
myExtendedFileEntry.LogicalBlocksRecorded++;
}
Short_ad allocationDescriptor = new Short_ad();
allocationDescriptor.ExtentLength = directoryFileDataLength;
allocationDescriptor.ExtentPosition = nextFreeBlocks[0] - metadataPartitionStartingBlock;
long currentRealPosition = nextFreeBlocks[0] * blockSize;
myRandomAccessFile.seek(currentRealPosition);
for (int i = 0; i < childFileIdentifierDescriptors.size(); ++i) {
long tagLocationBlock = (long) (currentRealPosition / blockSize) - metadataPartitionStartingBlock;
FileIdentifierDescriptor childFileIdentifierDescriptor = childFileIdentifierDescriptors.get(i);
childFileIdentifierDescriptor.DescriptorTag.TagLocation = tagLocationBlock;
byte childFileIdentifierDescriptorBytes[] = childFileIdentifierDescriptors.get(i).getBytes();
myRandomAccessFile.write(childFileIdentifierDescriptorBytes);
currentRealPosition += childFileIdentifierDescriptorBytes.length;
}
nextFreeBlocks[0] += myExtendedFileEntry.LogicalBlocksRecorded;
myExtendedFileEntry.AllocationDescriptors = allocationDescriptor.getBytes();
myExtendedFileEntry.LengthofAllocationDescriptors = myExtendedFileEntry.AllocationDescriptors.length;
}
}
/*
* if file is a "normal" file
*/
else if (currentUDFImageBuilderFile.getFileType() == UDFImageBuilderFile.FileType.File) {
myExtendedFileEntry.ICBTag.FileType = 5; // normal file
long fileSize = currentUDFImageBuilderFile.getFileLength();
myExtendedFileEntry.InformationLength = fileSize;
if (fileSize <= (blockSize - ExtendedFileEntry.fixedPartLength)) {
// store as inline embedded file data
myExtendedFileEntry.ICBTag.Flags = 3; // storage type inline
myExtendedFileEntry.LogicalBlocksRecorded = 0;
myExtendedFileEntry.LengthofAllocationDescriptors = fileSize;
myExtendedFileEntry.AllocationDescriptors = new byte[(int) fileSize];
currentUDFImageBuilderFile.readFileData(myExtendedFileEntry.AllocationDescriptors);
} else {
// store as exernal file data with Long_ad
myExtendedFileEntry.ICBTag.Flags = 1; // storage type long_ad
myExtendedFileEntry.LogicalBlocksRecorded = (long) (fileSize / blockSize);
if (fileSize % blockSize != 0) {
myExtendedFileEntry.LogicalBlocksRecorded++;
}
ArrayList<Long_ad> allocationDescriptors = new ArrayList<Long_ad>();
long restFileSize = fileSize;
long currentExtentPosition = nextFreeBlocks[1] - partitionStartingBlock;
while (restFileSize > 0) {
Long_ad allocationDescriptor = new Long_ad();
if (restFileSize < maximumAllocationLength) {
allocationDescriptor.ExtentLength = restFileSize;
} else {
allocationDescriptor.ExtentLength = maximumAllocationLength;
}
allocationDescriptor.ExtentLocation.part_num = 0;
allocationDescriptor.ExtentLocation.lb_num = currentExtentPosition;
allocationDescriptors.add(allocationDescriptor);
restFileSize -= maximumAllocationLength;
currentExtentPosition += (maximumAllocationLength / blockSize);
if (maximumAllocationLength % blockSize != 0) {
currentExtentPosition++;
}
}
byte allocationDescriptorBytes[] = new byte[allocationDescriptors.size() * 16];
int allocationDescriptorBytesPosition = 0;
for (int i = 0; i < allocationDescriptors.size(); ++i) {
byte singleAllocationDescriptorBytes[] = allocationDescriptors.get(i).getBytes();
System.arraycopy(singleAllocationDescriptorBytes, 0, allocationDescriptorBytes,
allocationDescriptorBytesPosition, singleAllocationDescriptorBytes.length);
allocationDescriptorBytesPosition += singleAllocationDescriptorBytes.length;
}
myRandomAccessFile.seek(nextFreeBlocks[1] * blockSize);
writeFileData(myRandomAccessFile, currentUDFImageBuilderFile.getSourceFile());
nextFreeBlocks[1] += myExtendedFileEntry.LogicalBlocksRecorded;
myExtendedFileEntry.AllocationDescriptors = allocationDescriptorBytes;
myExtendedFileEntry.LengthofAllocationDescriptors = allocationDescriptorBytes.length;
}
}
myExtendedFileEntry.ObjectSize = myExtendedFileEntry.InformationLength;
myExtendedFileEntry.CreationTime = new Timestamp(currentUDFImageBuilderFile.getCreationTime());
myRandomAccessFile.seek(currentMetadataBlock * blockSize);
myExtendedFileEntry.write(myRandomAccessFile, blockSize);
return nextFreeBlocks;
}