- Added physical partition allocator.

- Build() now writes logical volume descriptor and updates
  the partition descriptor to have the proper partition length.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@5649 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Tyler Dauwalder 2003-12-11 06:11:39 +00:00
parent aff8ada4dd
commit bf757e6cca
2 changed files with 154 additions and 20 deletions

View File

@ -25,6 +25,12 @@ using Udf::check_size_error;
//! Application identifier entity_id
static const Udf::entity_id kApplicationId(0, "*OpenBeOS makeudfimage");
//! Domain identifier
static const Udf::entity_id kDomainId(0, "*OSTA UDF Compliant",
Udf::domain_id_suffix(0x0201,
Udf::DF_HARD_WRITE_PROTECT));
/*! \brief Creates a new UdfBuilder object.
*/
UdfBuilder::UdfBuilder(const char *outputFile, uint32 blockSize, bool doUdf,
@ -42,6 +48,7 @@ UdfBuilder::UdfBuilder(const char *outputFile, uint32 blockSize, bool doUdf,
, fIsoVolumeName(isoVolumeName)
, fListener(listener)
, fAllocator(blockSize)
, fPartitionAllocator(0, 257, fAllocator)
, fBuildTime(0) // set at start of Build()
{
DEBUG_INIT_ETC("UdfBuilder", ("blockSize: %ld, doUdf: %s, doIso: %s",
@ -127,6 +134,16 @@ UdfBuilder::Build()
// _SetBuildTime(real_time_clock());
_SetBuildTime(timer);
// Variables of particular interest
uint16 partitionNumber = 0;
Udf::anchor_volume_descriptor anchor256;
// Udf::anchor_volume_descriptor anchorN;
Udf::primary_volume_descriptor primary;
Udf::partition_descriptor partition;
Udf::logical_volume_descriptor logical;
Udf::long_address fileSetAddress;
Udf::extent_address integrityExtent;
_OutputFile().Seek(0, SEEK_SET);
_PrintUpdate(VERBOSITY_LOW, "Output file: `%s'", fOutputFilename.c_str());
@ -210,10 +227,10 @@ UdfBuilder::Build()
}
}
// Write the udf anchor_256 and volume descriptor sequences
// Write the udf anchor256 and volume descriptor sequences
if (!error && _DoUdf()) {
// reserve anchor_256
_PrintUpdate(VERBOSITY_MEDIUM, "udf: Reserving space for anchor_256 at block 256");
// reserve anchor256
_PrintUpdate(VERBOSITY_MEDIUM, "udf: Reserving space for anchor256 at block 256");
error = _Allocator().GetBlock(256);
// reserve primary vds (min length = 16 blocks, which is plenty for us)
Udf::extent_address primaryExtent;
@ -242,22 +259,21 @@ UdfBuilder::Build()
}
// write anchor_256
if (!error) {
_PrintUpdate(VERBOSITY_MEDIUM, "udf: Writing anchor_256");
Udf::anchor_volume_descriptor anchor;
anchor.main_vds() = primaryExtent;
anchor.reserve_vds() = reserveExtent;
Udf::descriptor_tag &tag = anchor.tag();
_PrintUpdate(VERBOSITY_MEDIUM, "udf: Writing anchor256");
anchor256.main_vds() = primaryExtent;
anchor256.reserve_vds() = reserveExtent;
Udf::descriptor_tag &tag = anchor256.tag();
tag.set_id(Udf::TAGID_ANCHOR_VOLUME_DESCRIPTOR_POINTER);
tag.set_version(3);
tag.set_serial_number(0);
tag.set_location(256);
tag.set_checksums(anchor);
tag.set_checksums(anchor256);
_OutputFile().Seek(256 << _BlockShift(), SEEK_SET);
ssize_t bytes = _OutputFile().Write(&anchor, sizeof(anchor));
error = check_size_error(bytes, sizeof(anchor));
ssize_t bytes = _OutputFile().Write(&anchor256, sizeof(anchor256));
error = check_size_error(bytes, sizeof(anchor256));
if (!error && bytes < ssize_t(_BlockSize())) {
bytes = _OutputFile().Zero(_BlockSize()-sizeof(anchor));
error = check_size_error(bytes, _BlockSize()-sizeof(anchor));
bytes = _OutputFile().Zero(_BlockSize()-sizeof(anchor256));
error = check_size_error(bytes, _BlockSize()-sizeof(anchor256));
}
}
uint32 vdsNumber = 0;
@ -265,7 +281,6 @@ UdfBuilder::Build()
if (!error) {
_PrintUpdate(VERBOSITY_MEDIUM, "udf: Writing primary volume descriptor");
// build primary_vd
Udf::primary_volume_descriptor primary;
primary.set_vds_number(vdsNumber);
primary.set_primary_volume_descriptor_number(0);
uint32 nameLength = _UdfVolumeName().Cs0Length();
@ -277,6 +292,8 @@ UdfBuilder::Build()
nameLength);
nameLength = 32;
}
memset(primary.volume_identifier().data, 0,
primary.volume_identifier().size());
memcpy(primary.volume_identifier().data, _UdfVolumeName().Cs0(),
nameLength);
primary.set_volume_sequence_number(1);
@ -292,6 +309,8 @@ UdfBuilder::Build()
std::string volumeSetId(timestamp);
volumeSetId = volumeSetId + "--------" + "(unnamed volume set)";
Udf::String Cs0VolumeSetId(volumeSetId.c_str());
memset(primary.volume_set_identifier().data, 0,
primary.volume_set_identifier().size());
memcpy(primary.volume_set_identifier().data, Cs0VolumeSetId.Cs0(),
Cs0VolumeSetId.Cs0Length());
primary.descriptor_character_set() = Udf::kCs0CharacterSet;
@ -348,8 +367,6 @@ UdfBuilder::Build()
_PrintUpdate(VERBOSITY_MEDIUM, "udf: Writing partition descriptor");
// build partition descriptor
vdsNumber++;
uint16 partitionNumber = 0;
Udf::partition_descriptor partition;
partition.set_vds_number(vdsNumber);
partition.set_partition_flags(1);
partition.set_partition_number(partitionNumber);
@ -403,11 +420,125 @@ UdfBuilder::Build()
}
}
// write logical_vd
if (!error) {
_PrintUpdate(VERBOSITY_MEDIUM, "udf: Writing logical volume descriptor");
// build logical_vd
vdsNumber++;
logical.set_vds_number(vdsNumber);
logical.character_set() = Udf::kCs0CharacterSet;
error = (_UdfVolumeName().Cs0Length() <=
logical.logical_volume_identifier().size())
? B_OK : B_ERROR;
// We check the length in the constructor, so this should never
// trigger an error, but just to be safe...
if (!error) {
memset(logical.logical_volume_identifier().data, 0,
logical.logical_volume_identifier().size());
memcpy(logical.logical_volume_identifier().data,
_UdfVolumeName().Cs0(), _UdfVolumeName().Cs0Length());
logical.set_logical_block_size(_BlockSize());
logical.domain_id() = kDomainId;
memset(logical.logical_volume_contents_use().data, 0,
logical.logical_volume_contents_use().size());
// Allocate a block for the file set descriptor
Udf::extent_address temp;
error = _PartitionAllocator().GetNextExtent(_BlockSize(), true,
fileSetAddress, temp);
}
if (!error) {
logical.file_set_address() = fileSetAddress;
logical.set_map_table_length(sizeof(Udf::physical_partition_map));
logical.set_partition_map_count(1);
logical.implementation_id() = Udf::kImplementationId;
memset(logical.implementation_use().data, 0,
logical.implementation_use().size());
// Allocate a couple of blocks for the integrity sequence
error = _Allocator().GetNextExtent(_BlockSize()*2, true,
integrityExtent);
}
if (!error) {
logical.integrity_sequence_extent() = integrityExtent;
Udf::physical_partition_map map;
map.set_type(1);
map.set_length(6);
map.set_volume_sequence_number(1);
map.set_partition_number(partitionNumber);
memcpy(logical.partition_maps(), &map, sizeof(map));
logical.tag().set_id(Udf::TAGID_LOGICAL_VOLUME_DESCRIPTOR);
logical.tag().set_version(3);
logical.tag().set_serial_number(0);
// note that the checksums haven't been set yet, since the
// location is dependent on which sequence (primary or reserve)
// the descriptor is currently being written to. Thus we have to
// recalculate the checksums for each sequence.
DUMP(logical);
// write partition descriptor to primary vds
uint32 logicalSize = Udf::kLogicalVolumeDescriptorBaseSize + sizeof(map);
logical.tag().set_location(primaryExtent.location()+vdsNumber);
logical.tag().set_checksums(logical, logicalSize);
ssize_t bytes = _OutputFile().WriteAt(logical.tag().location() << _BlockShift(),
&logical, sizeof(logical));
error = check_size_error(bytes, sizeof(logical));
if (!error && bytes < ssize_t(_BlockSize())) {
ssize_t bytesLeft = _BlockSize() - bytes;
bytes = _OutputFile().ZeroAt((logical.tag().location() << _BlockShift())
+ bytes, bytesLeft);
error = check_size_error(bytes, bytesLeft);
}
// write logical descriptor to reserve vds
if (!error) {
logical.tag().set_location(reserveExtent.location()+vdsNumber);
logical.tag().set_checksums(logical, logicalSize);
ssize_t bytes = _OutputFile().WriteAt(logical.tag().location() << _BlockShift(),
&logical, sizeof(logical));
error = check_size_error(bytes, sizeof(logical));
if (!error && bytes < ssize_t(_BlockSize())) {
ssize_t bytesLeft = _BlockSize() - bytes;
bytes = _OutputFile().ZeroAt((logical.tag().location() << _BlockShift())
+ bytes, bytesLeft);
error = check_size_error(bytes, bytesLeft);
}
}
}
}
// write logical vds
// Udf::logical_volume_descriptor logical;
// Build the rest of the image
// Set the partition length and rewrite the partition descriptor
if (!error) {
_PrintUpdate(VERBOSITY_MEDIUM, "udf: Finalizing partition descriptor");
partition.set_length(_PartitionAllocator().Length());
DUMP(partition);
// write partition descriptor to primary vds
partition.tag().set_location(primaryExtent.location()+partition.vds_number());
partition.tag().set_checksums(partition);
ssize_t bytes = _OutputFile().WriteAt(partition.tag().location() << _BlockShift(),
&partition, sizeof(partition));
error = check_size_error(bytes, sizeof(partition));
if (!error && bytes < ssize_t(_BlockSize())) {
ssize_t bytesLeft = _BlockSize() - bytes;
bytes = _OutputFile().ZeroAt((partition.tag().location() << _BlockShift())
+ bytes, bytesLeft);
error = check_size_error(bytes, bytesLeft);
}
// write partition descriptor to reserve vds
if (!error) {
partition.tag().set_location(reserveExtent.location()+partition.vds_number());
partition.tag().set_checksums(partition);
ssize_t bytes = _OutputFile().WriteAt(partition.tag().location() << _BlockShift(),
&partition, sizeof(partition));
error = check_size_error(bytes, sizeof(partition));
if (!error && bytes < ssize_t(_BlockSize())) {
ssize_t bytesLeft = _BlockSize() - bytes;
bytes = _OutputFile().ZeroAt((partition.tag().location() << _BlockShift())
+ bytes, bytesLeft);
error = check_size_error(bytes, bytesLeft);
}
}
}
// Error check
if (error) {

View File

@ -19,6 +19,7 @@
#include "Allocator.h"
#include "OutputFile.h"
#include "PhysicalPartitionAllocator.h"
#include "ProgressListener.h"
#include "UdfString.h"
@ -41,6 +42,7 @@ private:
Udf::String& _UdfVolumeName() { return fUdfVolumeName; }
Udf::String& _IsoVolumeName() { return fIsoVolumeName; }
Allocator& _Allocator() { return fAllocator; }
PhysicalPartitionAllocator& _PartitionAllocator() { return fPartitionAllocator; }
time_t _BuildTime() const { return fBuildTime; }
Udf::timestamp& _BuildTimeStamp() { return fBuildTimeStamp; }
@ -62,6 +64,7 @@ private:
Udf::String fIsoVolumeName;
const ProgressListener &fListener;
Allocator fAllocator;
PhysicalPartitionAllocator fPartitionAllocator;
time_t fBuildTime;
Udf::timestamp fBuildTimeStamp;
};