- 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 //! Application identifier entity_id
static const Udf::entity_id kApplicationId(0, "*OpenBeOS makeudfimage"); 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. /*! \brief Creates a new UdfBuilder object.
*/ */
UdfBuilder::UdfBuilder(const char *outputFile, uint32 blockSize, bool doUdf, UdfBuilder::UdfBuilder(const char *outputFile, uint32 blockSize, bool doUdf,
@ -42,6 +48,7 @@ UdfBuilder::UdfBuilder(const char *outputFile, uint32 blockSize, bool doUdf,
, fIsoVolumeName(isoVolumeName) , fIsoVolumeName(isoVolumeName)
, fListener(listener) , fListener(listener)
, fAllocator(blockSize) , fAllocator(blockSize)
, fPartitionAllocator(0, 257, fAllocator)
, fBuildTime(0) // set at start of Build() , fBuildTime(0) // set at start of Build()
{ {
DEBUG_INIT_ETC("UdfBuilder", ("blockSize: %ld, doUdf: %s, doIso: %s", DEBUG_INIT_ETC("UdfBuilder", ("blockSize: %ld, doUdf: %s, doIso: %s",
@ -127,6 +134,16 @@ UdfBuilder::Build()
// _SetBuildTime(real_time_clock()); // _SetBuildTime(real_time_clock());
_SetBuildTime(timer); _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); _OutputFile().Seek(0, SEEK_SET);
_PrintUpdate(VERBOSITY_LOW, "Output file: `%s'", fOutputFilename.c_str()); _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()) { if (!error && _DoUdf()) {
// reserve anchor_256 // reserve anchor256
_PrintUpdate(VERBOSITY_MEDIUM, "udf: Reserving space for anchor_256 at block 256"); _PrintUpdate(VERBOSITY_MEDIUM, "udf: Reserving space for anchor256 at block 256");
error = _Allocator().GetBlock(256); error = _Allocator().GetBlock(256);
// reserve primary vds (min length = 16 blocks, which is plenty for us) // reserve primary vds (min length = 16 blocks, which is plenty for us)
Udf::extent_address primaryExtent; Udf::extent_address primaryExtent;
@ -242,22 +259,21 @@ UdfBuilder::Build()
} }
// write anchor_256 // write anchor_256
if (!error) { if (!error) {
_PrintUpdate(VERBOSITY_MEDIUM, "udf: Writing anchor_256"); _PrintUpdate(VERBOSITY_MEDIUM, "udf: Writing anchor256");
Udf::anchor_volume_descriptor anchor; anchor256.main_vds() = primaryExtent;
anchor.main_vds() = primaryExtent; anchor256.reserve_vds() = reserveExtent;
anchor.reserve_vds() = reserveExtent; Udf::descriptor_tag &tag = anchor256.tag();
Udf::descriptor_tag &tag = anchor.tag();
tag.set_id(Udf::TAGID_ANCHOR_VOLUME_DESCRIPTOR_POINTER); tag.set_id(Udf::TAGID_ANCHOR_VOLUME_DESCRIPTOR_POINTER);
tag.set_version(3); tag.set_version(3);
tag.set_serial_number(0); tag.set_serial_number(0);
tag.set_location(256); tag.set_location(256);
tag.set_checksums(anchor); tag.set_checksums(anchor256);
_OutputFile().Seek(256 << _BlockShift(), SEEK_SET); _OutputFile().Seek(256 << _BlockShift(), SEEK_SET);
ssize_t bytes = _OutputFile().Write(&anchor, sizeof(anchor)); ssize_t bytes = _OutputFile().Write(&anchor256, sizeof(anchor256));
error = check_size_error(bytes, sizeof(anchor)); error = check_size_error(bytes, sizeof(anchor256));
if (!error && bytes < ssize_t(_BlockSize())) { if (!error && bytes < ssize_t(_BlockSize())) {
bytes = _OutputFile().Zero(_BlockSize()-sizeof(anchor)); bytes = _OutputFile().Zero(_BlockSize()-sizeof(anchor256));
error = check_size_error(bytes, _BlockSize()-sizeof(anchor)); error = check_size_error(bytes, _BlockSize()-sizeof(anchor256));
} }
} }
uint32 vdsNumber = 0; uint32 vdsNumber = 0;
@ -265,7 +281,6 @@ UdfBuilder::Build()
if (!error) { if (!error) {
_PrintUpdate(VERBOSITY_MEDIUM, "udf: Writing primary volume descriptor"); _PrintUpdate(VERBOSITY_MEDIUM, "udf: Writing primary volume descriptor");
// build primary_vd // build primary_vd
Udf::primary_volume_descriptor primary;
primary.set_vds_number(vdsNumber); primary.set_vds_number(vdsNumber);
primary.set_primary_volume_descriptor_number(0); primary.set_primary_volume_descriptor_number(0);
uint32 nameLength = _UdfVolumeName().Cs0Length(); uint32 nameLength = _UdfVolumeName().Cs0Length();
@ -277,6 +292,8 @@ UdfBuilder::Build()
nameLength); nameLength);
nameLength = 32; nameLength = 32;
} }
memset(primary.volume_identifier().data, 0,
primary.volume_identifier().size());
memcpy(primary.volume_identifier().data, _UdfVolumeName().Cs0(), memcpy(primary.volume_identifier().data, _UdfVolumeName().Cs0(),
nameLength); nameLength);
primary.set_volume_sequence_number(1); primary.set_volume_sequence_number(1);
@ -292,6 +309,8 @@ UdfBuilder::Build()
std::string volumeSetId(timestamp); std::string volumeSetId(timestamp);
volumeSetId = volumeSetId + "--------" + "(unnamed volume set)"; volumeSetId = volumeSetId + "--------" + "(unnamed volume set)";
Udf::String Cs0VolumeSetId(volumeSetId.c_str()); 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(), memcpy(primary.volume_set_identifier().data, Cs0VolumeSetId.Cs0(),
Cs0VolumeSetId.Cs0Length()); Cs0VolumeSetId.Cs0Length());
primary.descriptor_character_set() = Udf::kCs0CharacterSet; primary.descriptor_character_set() = Udf::kCs0CharacterSet;
@ -348,8 +367,6 @@ UdfBuilder::Build()
_PrintUpdate(VERBOSITY_MEDIUM, "udf: Writing partition descriptor"); _PrintUpdate(VERBOSITY_MEDIUM, "udf: Writing partition descriptor");
// build partition descriptor // build partition descriptor
vdsNumber++; vdsNumber++;
uint16 partitionNumber = 0;
Udf::partition_descriptor partition;
partition.set_vds_number(vdsNumber); partition.set_vds_number(vdsNumber);
partition.set_partition_flags(1); partition.set_partition_flags(1);
partition.set_partition_number(partitionNumber); 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 // Build the rest of the image
// Udf::logical_volume_descriptor logical;
// 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 // Error check
if (error) { if (error) {

View File

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