diff --git a/src/apps/bin/makeudfimage/UdfBuilder.cpp b/src/apps/bin/makeudfimage/UdfBuilder.cpp index 331de14045..c950513562 100644 --- a/src/apps/bin/makeudfimage/UdfBuilder.cpp +++ b/src/apps/bin/makeudfimage/UdfBuilder.cpp @@ -15,27 +15,159 @@ #include #include "UdfDebug.h" +#include "Utils.h" -UdfBuilder::UdfBuilder(const ProgressListener &listener) - : fListener(listener) +using Udf::check_size_error; + +/*! \brief Creates a new UdfBuilder object. +*/ +UdfBuilder::UdfBuilder(const char *outputFile, uint32 blockSize, bool doUdf, + bool doIso, const ProgressListener &listener) + : fInitStatus(B_NO_INIT) + , fOutputFile(outputFile, B_READ_WRITE | B_CREATE_FILE) + , fOutputFilename(outputFile) + , fBlockSize(blockSize) + , fBlockShift(0) + , fDoUdf(doUdf) + , fDoIso(doIso) + , fListener(listener) + , fAllocator(blockSize) { + DEBUG_INIT_ETC("UdfBuilder", ("blockSize: %ld, doUdf: %s, doIso: %s", + blockSize, bool_to_string(doUdf), bool_to_string(doIso))); + + // Check the output file + status_t error = _OutputFile().InitCheck(); + if (!error) { + // Check the allocator + error = _Allocator().InitCheck(); + if (!error) { + // Check the block size + if (!error) + error = Udf::get_block_shift(_BlockSize(), fBlockShift); + if (!error) + error = _BlockSize() >= 512 ? B_OK : B_BAD_VALUE; + if (!error) { + // Check that at least one type of filesystem has + // been requested + error = _DoUdf() || _DoIso() ? B_OK : B_BAD_VALUE; + if (error) { + _PrintError("No filesystems requested."); + } + } else { + _PrintError("Invalid block size: %ld", blockSize); + } + } else { + _PrintError("Error creating block allocator: 0x%lx, `%s'", error, + strerror(error)); + } + } else { + _PrintError("Error opening output file: 0x%lx, `%s'", error, + strerror(error)); + } + + if (!error) { + fInitStatus = B_OK; + } } status_t UdfBuilder::InitCheck() const { - return B_OK; + return fInitStatus; } +/*! \brief Builds the disc image. +*/ status_t -UdfBuilder::Build() const +UdfBuilder::Build() { DEBUG_INIT("UdfBuilder"); - _PrintError("This is an error."); - _PrintWarning("This is a warning."); - _PrintUpdate(VERBOSITY_LOW, "This is a VERBOSITY_LOW update."); - _PrintUpdate(VERBOSITY_HIGH, "This is a VERBOSITY_HIGH update."); - RETURN(B_ERROR); + status_t error = InitCheck(); + if (error) + RETURN(error); + + _OutputFile().Seek(0, SEEK_SET); + _PrintUpdate(VERBOSITY_LOW, "Output file: `%s'", fOutputFilename.c_str()); + + // Reserve the first 32KB and zero them out. + if (!error) { + const int reservedAreaSize = 32 * 1024; + Udf::extent_address extent(0, reservedAreaSize); + error = _Allocator().GetExtent(extent); + if (!error) { + ssize_t bytes = _OutputFile().Zero(reservedAreaSize); + error = check_size_error(bytes, reservedAreaSize); + } + // Error check + if (error) { + _PrintError("Error creating reserved area: 0x%lx, `%s'", + error, strerror(error)); + } + } + + const int vrsBlockSize = 2048; + + // Write the iso portion of the vrs + if (!error && _DoIso()) { + _PrintUpdate(VERBOSITY_LOW, "Writing iso portion of volume recognition sequence..."); + + // Error check + if (error) { + _PrintError("Error writing iso vrs: 0x%lx, `%s'", + error, strerror(error)); + } + } + + // Write the udf portion of the vrs + if (!error && _DoUdf()) { + _PrintUpdate(VERBOSITY_LOW, "Writing udf portion of volume recognition sequence..."); + Udf::extent_address extent; + // Bea + Udf::volume_structure_descriptor_header bea(0, Udf::kVSDID_BEA, 1); + error = _Allocator().GetNextExtent(vrsBlockSize, true, extent); + if (!error) { + ssize_t bytes = _OutputFile().Write(&bea, sizeof(bea)); + error = check_size_error(bytes, sizeof(bea)); + if (!error) { + bytes = _OutputFile().Zero(vrsBlockSize-sizeof(bea)); + error = check_size_error(bytes, vrsBlockSize-sizeof(bea)); + } + } + // Nsr + Udf::volume_structure_descriptor_header nsr(0, Udf::kVSDID_ECMA167_3, 1); + if (!error) + error = _Allocator().GetNextExtent(vrsBlockSize, true, extent); + if (!error) { + ssize_t bytes = _OutputFile().Write(&nsr, sizeof(nsr)); + error = check_size_error(bytes, sizeof(nsr)); + if (!error) { + bytes = _OutputFile().Zero(vrsBlockSize-sizeof(nsr)); + error = check_size_error(bytes, vrsBlockSize-sizeof(nsr)); + } + } + // Tea + Udf::volume_structure_descriptor_header tea(0, Udf::kVSDID_TEA, 1); + if (!error) + error = _Allocator().GetNextExtent(vrsBlockSize, true, extent); + if (!error) { + ssize_t bytes = _OutputFile().Write(&tea, sizeof(tea)); + error = check_size_error(bytes, sizeof(tea)); + if (!error) { + bytes = _OutputFile().Zero(vrsBlockSize-sizeof(tea)); + error = check_size_error(bytes, vrsBlockSize-sizeof(tea)); + } + } + // Error check + if (error) { + _PrintError("Error writing udf vrs: 0x%lx, `%s'", + error, strerror(error)); + } + } + + if (!error) + _PrintUpdate(VERBOSITY_LOW, "Finished."); + RETURN(error); } /*! \brief Uses vsprintf() to output the given format string and arguments diff --git a/src/apps/bin/makeudfimage/UdfBuilder.h b/src/apps/bin/makeudfimage/UdfBuilder.h index 5befd6b53b..84d212a330 100644 --- a/src/apps/bin/makeudfimage/UdfBuilder.h +++ b/src/apps/bin/makeudfimage/UdfBuilder.h @@ -17,23 +17,40 @@ #include #include +#include "Allocator.h" +#include "OutputFile.h" #include "ProgressListener.h" class UdfBuilder { public: - UdfBuilder(const ProgressListener &listener); + UdfBuilder(const char *outputFile, uint32 blockSize, bool doUdf, + bool doIso, const ProgressListener &listener); status_t InitCheck() const; - status_t Build() const; + status_t Build(); private: //! Maximum length of string generated by calls to any _Print*() functions static const int kMaxUpdateStringLength = 1024; + OutputFile& _OutputFile() { return fOutputFile; } + uint32 _BlockSize() const { return fBlockSize; } + bool _DoUdf() const { return fDoUdf; } + bool _DoIso() const { return fDoIso; } + Allocator& _Allocator() { return fAllocator; } + status_t _FormatString(char *message, const char *formatString, va_list arguments) const; void _PrintError(const char *formatString, ...) const; void _PrintWarning(const char *formatString, ...) const; void _PrintUpdate(VerbosityLevel level, const char *formatString, ...) const; + status_t fInitStatus; + OutputFile fOutputFile; + string fOutputFilename; + uint32 fBlockSize; + uint32 fBlockShift; + bool fDoUdf; + bool fDoIso; const ProgressListener &fListener; + Allocator fAllocator; };