int blockSize, int serialNumberForTags,
UDFImageBuilderFile currentUDFImageBuilderFile, long currentBlock,
FileEntry parentFileEntry, long uniqueID, boolean writeExtendedFileEntries,
int descriptorVersion)
throws Exception {
FileEntry myFileEntry = null;
if (!writeExtendedFileEntries) {
myFileEntry = new FileEntry();
} else {
myFileEntry = new ExtendedFileEntry();
}
myFileEntry.DescriptorTag.TagSerialNumber = serialNumberForTags;
myFileEntry.DescriptorTag.DescriptorVersion = descriptorVersion;
myFileEntry.DescriptorTag.TagLocation = currentBlock - partitionStartingBlock;
myFileEntry.Uid = 0xFFFFFFFF; // TODO: get current uid and gid if java supports it
myFileEntry.Gid = 0xFFFFFFFF;
// TODO: get real file permission if java supports it
myFileEntry.Permissions = Permissions.OTHER_Read | Permissions.GROUP_Read | Permissions.OWNER_Read;
myFileEntry.FileLinkCount = currentUDFImageBuilderFile.getFileLinkCount();
myFileEntry.RecordFormat = 0;
myFileEntry.RecordDisplayAttributes = 0;
myFileEntry.RecordLength = 0;
myFileEntry.AccessTime = new Timestamp(currentUDFImageBuilderFile.getAccessTime());
myFileEntry.ModificationTime = new Timestamp(currentUDFImageBuilderFile.getModificationTime());
myFileEntry.AttributeTime = new Timestamp(currentUDFImageBuilderFile.getAttributeTime());
myFileEntry.Checkpoint = 1;
myFileEntry.ImplementationIdentifier.setIdentifier(applicationIdentifier);
myFileEntry.ImplementationIdentifier.IdentifierSuffix = applicationIdentifierSuffix;
myFileEntry.ICBTag.PriorRecordedNumberofDirectEntries = 0;
myFileEntry.ICBTag.NumberofEntries = 1;
myFileEntry.ICBTag.StrategyType = 4;
myFileEntry.UniqueID = uniqueID;
long nextFreeBlock = currentBlock + 1;
/*
* if file is a directory
*/
if (currentUDFImageBuilderFile.getFileType() == UDFImageBuilderFile.FileType.Directory) {
myFileEntry.ICBTag.FileType = 4; // directory
myFileEntry.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 = currentBlock - partitionStartingBlock;
parentDirectoryFileIdentifierDescriptor.DescriptorTag.TagSerialNumber = serialNumberForTags;
parentDirectoryFileIdentifierDescriptor.DescriptorTag.DescriptorVersion = descriptorVersion;
parentDirectoryFileIdentifierDescriptor.ICB.ExtentLength = blockSize;
parentDirectoryFileIdentifierDescriptor.ICB.ExtentLocation.part_num = 0;
parentDirectoryFileIdentifierDescriptor.FileVersionNumber = 1;
parentDirectoryFileIdentifierDescriptor.FileCharacteristics = 10; // file is directory and parent
// if root directory
if (parentFileEntry == null) {
parentDirectoryFileIdentifierDescriptor.ICB.ExtentLocation.lb_num =
currentBlock - partitionStartingBlock;
}
// 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 = currentBlock - partitionStartingBlock;
childFileIdentifierDescriptor.DescriptorTag.TagSerialNumber = serialNumberForTags;
childFileIdentifierDescriptor.DescriptorTag.DescriptorVersion = descriptorVersion;
childFileIdentifierDescriptor.ICB.ExtentLength = blockSize;
childFileIdentifierDescriptor.ICB.ExtentLocation.lb_num = nextFreeBlock - partitionStartingBlock;
childFileIdentifierDescriptor.ICB.ExtentLocation.part_num = 0;
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);
nextFreeBlock = recursiveWriteFilesystem(myRandomAccessFile, partitionStartingBlock, blockSize,
serialNumberForTags, childUDFImageBuilderFiles[i], nextFreeBlock, myFileEntry,
childFileUniqueID, writeExtendedFileEntries, descriptorVersion);
}
// get directory file data length
int directoryFileDataLength = 0;
for (int i = 0; i < childFileIdentifierDescriptors.size(); ++i) {
directoryFileDataLength += childFileIdentifierDescriptors.get(i).getLength();
}
myFileEntry.InformationLength = directoryFileDataLength;
if ((writeExtendedFileEntries && directoryFileDataLength <= blockSize - ExtendedFileEntry.fixedPartLength)
||
(!writeExtendedFileEntries && directoryFileDataLength <= blockSize - FileEntry.fixedPartLength)) {
// inline embedded file data
myFileEntry.ICBTag.Flags = 3; // storage type inline
myFileEntry.LogicalBlocksRecorded = 0;
myFileEntry.LengthofAllocationDescriptors = directoryFileDataLength;
myFileEntry.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, myFileEntry.AllocationDescriptors, pos,
childFileIdentifierDescriptorBytes.length);
pos += childFileIdentifierDescriptorBytes.length;
}
} else {
// store as exernal file data with Short_ad
myFileEntry.ICBTag.Flags = 0; // storage type short_ad
myFileEntry.LogicalBlocksRecorded = (long) (directoryFileDataLength / blockSize);
if (directoryFileDataLength % blockSize != 0) {
myFileEntry.LogicalBlocksRecorded++;
}
Short_ad allocationDescriptor = new Short_ad();
allocationDescriptor.ExtentLength = directoryFileDataLength;
allocationDescriptor.ExtentPosition = nextFreeBlock - partitionStartingBlock;
long currentRealPosition = nextFreeBlock * blockSize;
myRandomAccessFile.seek(currentRealPosition);
for (int i = 0; i < childFileIdentifierDescriptors.size(); ++i) {
long tagLocationBlock = (long) (currentRealPosition / blockSize) - partitionStartingBlock;
FileIdentifierDescriptor childFileIdentifierDescriptor = childFileIdentifierDescriptors.get(i);
childFileIdentifierDescriptor.DescriptorTag.TagLocation = tagLocationBlock;
byte childFileIdentifierDescriptorBytes[] = childFileIdentifierDescriptors.get(i).getBytes();
myRandomAccessFile.write(childFileIdentifierDescriptorBytes);
currentRealPosition += childFileIdentifierDescriptorBytes.length;
}
nextFreeBlock += myFileEntry.LogicalBlocksRecorded;
myFileEntry.AllocationDescriptors = allocationDescriptor.getBytes();
myFileEntry.LengthofAllocationDescriptors = myFileEntry.AllocationDescriptors.length;
}
}
/*
* if file is a "normal" file
*/
else if (currentUDFImageBuilderFile.getFileType() == UDFImageBuilderFile.FileType.File) {
myFileEntry.ICBTag.FileType = 5; // normal file
long fileSize = currentUDFImageBuilderFile.getFileLength();
myFileEntry.InformationLength = fileSize;
if ((writeExtendedFileEntries && fileSize <= (blockSize - ExtendedFileEntry.fixedPartLength))
|| (!writeExtendedFileEntries && fileSize <= (blockSize - FileEntry.fixedPartLength))) {
// store as inline embedded file data
myFileEntry.ICBTag.Flags = 3; // storage type inline
myFileEntry.LogicalBlocksRecorded = 0;
myFileEntry.LengthofAllocationDescriptors = fileSize;
myFileEntry.AllocationDescriptors = new byte[(int) fileSize];
currentUDFImageBuilderFile.readFileData(myFileEntry.AllocationDescriptors);
} else {
// store as exernal file data with Long_ad
myFileEntry.ICBTag.Flags = 1; // storage type long_ad
myFileEntry.LogicalBlocksRecorded = (long) (fileSize / blockSize);
if (fileSize % blockSize != 0) {
myFileEntry.LogicalBlocksRecorded++;
}
ArrayList<Long_ad> allocationDescriptors = new ArrayList<Long_ad>();
long restFileSize = fileSize;
long currentExtentPosition = nextFreeBlock - 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(nextFreeBlock * blockSize);
writeFileData(myRandomAccessFile, currentUDFImageBuilderFile.getSourceFile());
nextFreeBlock += myFileEntry.LogicalBlocksRecorded;
myFileEntry.AllocationDescriptors = allocationDescriptorBytes;
myFileEntry.LengthofAllocationDescriptors = allocationDescriptorBytes.length;
}
}
if (writeExtendedFileEntries) {
ExtendedFileEntry myExtendedFileEntry = (ExtendedFileEntry) myFileEntry;
myExtendedFileEntry.ObjectSize = myFileEntry.InformationLength;
myExtendedFileEntry.CreationTime = new Timestamp(currentUDFImageBuilderFile.getCreationTime());
}
myRandomAccessFile.seek(currentBlock * blockSize);
myFileEntry.write(myRandomAccessFile, blockSize);
return nextFreeBlock;
}