diff --git a/src/bin/Jamfile b/src/bin/Jamfile index d0d3ad190d..b21968ceee 100644 --- a/src/bin/Jamfile +++ b/src/bin/Jamfile @@ -257,7 +257,6 @@ SubInclude HAIKU_TOP src bin listdev ; SubInclude HAIKU_TOP src bin listusb ; SubInclude HAIKU_TOP src bin locale ; SubInclude HAIKU_TOP src bin makebootable ; -#SubInclude HAIKU_TOP src bin makeudfimage ; SubInclude HAIKU_TOP src bin mail_utils ; SubInclude HAIKU_TOP src bin media_client ; SubInclude HAIKU_TOP src bin mkdos ; diff --git a/src/bin/makeudfimage/Allocator.cpp b/src/bin/makeudfimage/Allocator.cpp deleted file mode 100644 index 1a224fc17d..0000000000 --- a/src/bin/makeudfimage/Allocator.cpp +++ /dev/null @@ -1,272 +0,0 @@ -//---------------------------------------------------------------------- -// This software is part of the OpenBeOS distribution and is covered -// by the MIT License. -// -// Copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net -//---------------------------------------------------------------------- - -/*! \file Allocator.cpp - - Physical block allocator class implementation. -*/ - -#include "Allocator.h" - -#include - -#include "Utils.h" - -/*! \brief Creates a new Allocator object. -*/ -Allocator::Allocator(uint32 blockSize) - : fLength(0) - , fBlockSize(blockSize) - , fBlockShift(0) - , fInitStatus(B_NO_INIT) -{ - status_t error = get_block_shift(BlockSize(), fBlockShift); - if (!error) - fInitStatus = B_OK; -} - -status_t -Allocator::InitCheck() const -{ - return fInitStatus; -} - -/*! \brief Allocates the given block, if available. - - \return - - B_OK: Success. - - error code: Failure, the block has already been allocated. -*/ -status_t -Allocator::GetBlock(uint32 block) -{ - extent_address extent(block, BlockSize()); - return GetExtent(extent); -} - -/*! \brief Allocates the given extent, if available. - - \return - - B_OK: Success. - - error code: Failure, the extent (or some portion of it) has already - been allocated. -*/ -status_t -Allocator::GetExtent(extent_address extent) -{ - status_t error = InitCheck(); - if (!error) { - uint32 offset = extent.location(); - uint32 length = BlocksFor(extent.length()); - // First see if the extent is past the allocation tail, - // since we then don't have to do any chunklist traversal - if (offset >= Length()) { - // Add a new chunk to the end of the chunk list if - // necessary - if (offset > Length()) { - extent_address chunk(Length(), (offset-Length())<::iterator i = fChunkList.begin(); - i != fChunkList.end(); - i++) - { - uint32 chunkOffset = i->location(); - uint32 chunkLength = BlocksFor(i->length()); - if (chunkOffset <= offset && (offset+length) <= (chunkOffset+chunkLength)) { - // Found it. Split the chunk. First look for an orphan - // before the block, then after. - if (chunkOffset < offset) { - // Orhpan before; add a new chunk in front - // of the current one - extent_address chunk(chunkOffset, (offset-chunkOffset)<set_location(offset+length); - i->set_length(((chunkOffset+chunkLength)-(offset+length))<::iterator i = fChunkList.begin(); - i != fChunkList.end(); - i++) - { - uint32 chunkOffset = i->location(); - uint32 chunkLength = BlocksFor(i->length()); - if (chunkOffset < minimumStartingBlock) - { - if (minimumStartingBlock < chunkOffset+chunkLength) { - // Start of chunk is below min starting block. See if - // any part of the chunk would make for an acceptable - // allocation - uint32 difference = minimumStartingBlock - chunkOffset; - uint32 newOffset = minimumStartingBlock; - uint32 newLength = chunkLength-difference; - if (length <= newLength) { - // new chunk is still long enough - extent_address newExtent(newOffset, _length); - if (GetExtent(newExtent) == B_OK) { - extent = newExtent; - return B_OK; - } - } else if (!contiguous) { - // new chunk is too short, but we're allowed to - // allocate a shorter extent, so we'll do it. - extent_address newExtent(newOffset, newLength<set_location(chunkOffset+length); - i->set_length((chunkLength-length)< 0 ? B_OK : B_DEVICE_FULL; - if (!error) { - if (minimumStartingBlock > Tail()) - maxLength -= minimumStartingBlock - Tail(); - uint32 tail = minimumStartingBlock > Tail() ? minimumStartingBlock : Tail(); - if (length > maxLength) { - if (contiguous) - error = B_DEVICE_FULL; - else { - isPartial = true; - length = maxLength; - } - } - if (!error) { - extent_address newExtent(tail, isPartial ? length<> BlockShift(); - if (bytes % BlockSize() != 0) - blocks++; - uint64 mask = 0xffffffff; - mask <<= 32; - if (blocks & mask) { - // ToDo: Convert this to actually signal an error - DEBUG_INIT_ETC("Allocator", ("bytes: %ld\n", bytes)); - PRINT(("WARNING: bytes argument too large for corresponding number " - "of blocks to be specified with a uint32! (bytes: %Ld, blocks: %Ld, " - "maxblocks: %ld).\n", bytes, blocks, ULONG_MAX)); - blocks = 0; - } - return blocks; - } -} diff --git a/src/bin/makeudfimage/Allocator.h b/src/bin/makeudfimage/Allocator.h deleted file mode 100644 index 20a8cc44e5..0000000000 --- a/src/bin/makeudfimage/Allocator.h +++ /dev/null @@ -1,53 +0,0 @@ -//---------------------------------------------------------------------- -// This software is part of the OpenBeOS distribution and is covered -// by the MIT License. -// -// Copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net -//---------------------------------------------------------------------- - -/*! \file Allocator.h - - Physical block allocator class declarations. -*/ - -#ifndef _UDF_ALLOCATOR_H -#define _UDF_ALLOCATOR_H - -#include -using std::list; - -#include "UdfStructures.h" - -/*! \brief This class keeps track of allocated and unallocated - blocks in the range of 0 to 2^32. - - By default, all blocks are unallocated. -*/ -class Allocator { -public: - Allocator(uint32 blockSize); - status_t InitCheck() const; - - status_t GetBlock(uint32 block); - status_t GetExtent(extent_address extent); - - status_t GetNextBlock(uint32 &block, uint32 minimumBlock = 0); - status_t GetNextExtent(uint32 length, bool contiguous, - extent_address &extent, - uint32 minimumStartingBlock = 0); - - uint32 Length() const { return fLength; } - uint32 Tail() const { return fLength; } //!< Returns the first unallocated block in the tail - uint32 BlockSize() const { return fBlockSize; } - uint32 BlockShift() const { return fBlockShift; } - - uint32 BlocksFor(off_t bytes); -private: - list fChunkList; - uint32 fLength; //!< Length of allocation so far, in blocks. - uint32 fBlockSize; - uint32 fBlockShift; - status_t fInitStatus; -}; - -#endif // _UDF_ALLOCATOR_H diff --git a/src/bin/makeudfimage/Attribute.cpp b/src/bin/makeudfimage/Attribute.cpp deleted file mode 100644 index 31ccc71d1c..0000000000 --- a/src/bin/makeudfimage/Attribute.cpp +++ /dev/null @@ -1,31 +0,0 @@ -//---------------------------------------------------------------------- -// This software is part of the OpenBeOS distribution and is covered -// by the MIT License. -// -// Copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net -//---------------------------------------------------------------------- - -/*! \file Attribute.h - - BDataIO wrapper around a given attribute for a file. (implementation) -*/ - -#include "Attribute.h" - -Attribute::Attribute(BNode &node, const char *attribute) - : fNode(node) - , fAttribute(attribute) -{ -} - -ssize_t -Attribute::Read(void *buffer, size_t size) -{ - return B_ERROR; -} - -ssize_t -Attribute::Write(const void *buffer, size_t size) -{ - return B_ERROR; -} diff --git a/src/bin/makeudfimage/Attribute.h b/src/bin/makeudfimage/Attribute.h deleted file mode 100644 index 3a1779f37f..0000000000 --- a/src/bin/makeudfimage/Attribute.h +++ /dev/null @@ -1,30 +0,0 @@ -//---------------------------------------------------------------------- -// This software is part of the OpenBeOS distribution and is covered -// by the MIT License. -// -// Copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net -//---------------------------------------------------------------------- - -/*! \file Attribute.h - - BDataIO wrapper around a given attribute for a file. (declarations) -*/ - -#ifndef _ATTRIBUTE_H -#define _ATTRIBUTE_H - -#include -#include -#include - -class Attribute : public BDataIO { -public: - Attribute(BNode &node, const char *attribute); - virtual ssize_t Read(void *buffer, size_t size); - virtual ssize_t Write(const void *buffer, size_t size); -private: - BNode fNode; - string fAttribute; -}; - -#endif // _ATTRIBUTE_H diff --git a/src/bin/makeudfimage/ConsoleListener.cpp b/src/bin/makeudfimage/ConsoleListener.cpp deleted file mode 100644 index 68533f2258..0000000000 --- a/src/bin/makeudfimage/ConsoleListener.cpp +++ /dev/null @@ -1,111 +0,0 @@ -//---------------------------------------------------------------------- -// This software is part of the OpenBeOS distribution and is covered -// by the MIT License. -// -// Copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net -//---------------------------------------------------------------------- - -/*! \file ConsoleListener.cpp - - Console-based implementation of ProgressListener interface. -*/ - -#include "ConsoleListener.h" - -#include -#include - -static const char * const kDivider = - "----------------------------------------------------------------------"; - -/*! \brief Creates a new ConsoleListener object with the given verbosity level. - - All output from said listener is sent to standard output via printf(). - - \param level All update messages with verbosity levels below this value - will be ignored. If level is \c VERBOSITY_NONE, no output - whatsoever (including errors and warnings) will be - generated. -*/ -ConsoleListener::ConsoleListener(VerbosityLevel level) - : fLevel(level) -{ -} - -void -ConsoleListener::OnStart(const char *sourceDirectory, const char *outputFile, - const char *udfVolumeName, uint16 udfRevision) const -{ - if (Level() > VERBOSITY_NONE) { - printf("%s\n", kDivider); - printf("Source directory: `%s'\n", sourceDirectory); - printf("Output file: `%s'\n", outputFile); - printf("UDF Volume Name: `%s'\n", udfVolumeName); - printf("UDF Revision: %01x.%01x%01x\n", - (udfRevision & 0x0f00) >> 8, - (udfRevision & 0x00f0) >> 4, - (udfRevision & 0x000f)); - printf("%s\n", kDivider); - } -} - -void -ConsoleListener::OnError(const char *message) const -{ - if (Level() > VERBOSITY_NONE) - printf("ERROR: %s\n", message); -} - -void -ConsoleListener::OnWarning(const char *message) const -{ - if (Level() > VERBOSITY_NONE) - printf("WARNING: %s\n", message); -} - -void -ConsoleListener::OnUpdate(VerbosityLevel level, const char *message) const -{ - if (Level() > VERBOSITY_NONE && level <= Level()) { - switch (level) { - case VERBOSITY_MEDIUM: - printf(" "); - break; - case VERBOSITY_HIGH: - printf(" "); - break; - default: - break; - } - printf("%s\n", message); - } -} - -void -ConsoleListener::OnCompletion(status_t result, const Statistics &statistics) const -{ - if (Level() > VERBOSITY_NONE) { - if (result == B_OK) { - uint64 directories = statistics.Directories(); - uint64 files = statistics.Files(); - uint64 symlinks = statistics.Symlinks(); - printf("Finished\n"); - printf("- Build time: %s\n", statistics.ElapsedTimeString().c_str()); - printf("- Directories: %Ld director%s in %s\n", - directories, directories == 1 ? "y" : "ies", - statistics.DirectoryBytesString().c_str()); - printf("- Files: %Ld file%s in %s\n", - files, files == 1 ? "" : "s", - statistics.FileBytesString().c_str()); - if (symlinks > 0) - printf("- Symlinks: No symlink support yet; %Ld symlink%s ommitted\n", symlinks, - symlinks == 1 ? "" : "s"); - printf("- Image size: %s\n", statistics.ImageSizeString().c_str()); - } else { - printf("----------------------------------------------------------------------\n"); - printf("Build failed with error: 0x%lx, `%s'\n", result, - strerror(result)); - printf("----------------------------------------------------------------------\n"); - } - } -} diff --git a/src/bin/makeudfimage/ConsoleListener.h b/src/bin/makeudfimage/ConsoleListener.h deleted file mode 100644 index eec0f322aa..0000000000 --- a/src/bin/makeudfimage/ConsoleListener.h +++ /dev/null @@ -1,34 +0,0 @@ -//---------------------------------------------------------------------- -// This software is part of the OpenBeOS distribution and is covered -// by the MIT License. -// -// Copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net -//---------------------------------------------------------------------- - -/*! \file ConsoleListener.h - - Declarations for a console-based implementation of ProgressListener - interface. -*/ - -#ifndef _CONSOLE_LISTENER_H -#define _CONSOLE_LISTENER_H - -#include "ProgressListener.h" - -class ConsoleListener : public ProgressListener { -public: - ConsoleListener(VerbosityLevel level); - virtual void OnStart(const char *sourceDirectory, const char *outputFile, - const char *udfVolumeName, uint16 udfRevision) const; - virtual void OnError(const char *message) const; - virtual void OnWarning(const char *message) const; - virtual void OnUpdate(VerbosityLevel level, const char *message) const; - virtual void OnCompletion(status_t result, const Statistics &statistics) const; - - VerbosityLevel Level() const { return fLevel; } -private: - VerbosityLevel fLevel; -}; - -#endif // _CONSOLE_LISTENER_H diff --git a/src/bin/makeudfimage/DataStream.h b/src/bin/makeudfimage/DataStream.h deleted file mode 100644 index 382d10665f..0000000000 --- a/src/bin/makeudfimage/DataStream.h +++ /dev/null @@ -1,38 +0,0 @@ -//---------------------------------------------------------------------- -// This software is part of the OpenBeOS distribution and is covered -// by the MIT License. -// -// Copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net -//---------------------------------------------------------------------- - -/*! \file DataStream.h -*/ - -#ifndef _DATA_STREAM_H -#define _DATA_STREAM_H - -#include - -class DataStream : public BPositionIO { -public: - virtual status_t InitCheck() const = 0; - - virtual ssize_t Read(void *buffer, size_t size) = 0; - virtual ssize_t ReadAt(off_t pos, void *buffer, size_t size) = 0; - - virtual ssize_t Write(const void *buffer, size_t size) = 0; - virtual ssize_t WriteAt(off_t pos, const void *buffer, size_t size) = 0; - - virtual ssize_t Write(BDataIO &data, size_t size) = 0; - virtual ssize_t WriteAt(off_t pos, BDataIO &data, size_t size) = 0; - - virtual ssize_t Zero(size_t size) = 0; - virtual ssize_t ZeroAt(off_t pos, size_t size) = 0; - - virtual off_t Seek(off_t position, uint32 seek_mode) = 0; - virtual off_t Position() const = 0; - - virtual status_t SetSize(off_t size) = 0; -}; - -#endif // _DATA_STREAM_H diff --git a/src/bin/makeudfimage/EmbeddedStream.cpp b/src/bin/makeudfimage/EmbeddedStream.cpp deleted file mode 100644 index cd3a5d3042..0000000000 --- a/src/bin/makeudfimage/EmbeddedStream.cpp +++ /dev/null @@ -1,51 +0,0 @@ -//---------------------------------------------------------------------- -// This software is part of the OpenBeOS distribution and is covered -// by the MIT License. -// -// Copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net -//---------------------------------------------------------------------- - -/*! \file EmbeddedStream.cpp -*/ - -#include "EmbeddedStream.h" - -#include -#include - -EmbeddedStream::EmbeddedStream(DataStream &stream, off_t offset, size_t size) - : SimulatedStream(stream) - , fOffset(offset) - , fSize(size) -{ -} - -/*! \brief Returns the largest extent in the underlying data stream - corresponding to the extent starting at byte position \a pos of - byte length \a size in the output parameter \a extent. - - NOTE: If the position is at or beyond the end of the stream, the - function will return B_OK, but the value of extent.size will be 0. -*/ -status_t -EmbeddedStream::_GetExtent(off_t pos, size_t size, data_extent &extent) -{ - if (pos >= fSize) { - // end of stream - extent.offset = fOffset + fSize; - extent.size = 0; - } else { - // valid position - extent.offset = fOffset + pos; - extent.size = fSize - pos; - } - return B_OK; -} - -/*! \brief Returns the current size of the stream. -*/ -off_t -EmbeddedStream::_Size() -{ - return fSize; -} diff --git a/src/bin/makeudfimage/EmbeddedStream.h b/src/bin/makeudfimage/EmbeddedStream.h deleted file mode 100644 index d3f0dc048f..0000000000 --- a/src/bin/makeudfimage/EmbeddedStream.h +++ /dev/null @@ -1,32 +0,0 @@ -//---------------------------------------------------------------------- -// This software is part of the OpenBeOS distribution and is covered -// by the MIT License. -// -// Copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net -//---------------------------------------------------------------------- - -/*! \file EmbeddedStream.h -*/ - -#ifndef _EMBEDDED_STREAM_H -#define _EMBEDDED_STREAM_H - -#include "SimulatedStream.h" - -/*! \brief SimulatedStream implementation that takes a single, - not-neccessarily-block-aligned extent. -*/ -class EmbeddedStream : public SimulatedStream { -public: - EmbeddedStream(DataStream &stream, off_t offset, size_t size); - -protected: - virtual status_t _GetExtent(off_t pos, size_t size, data_extent &extent); - virtual off_t _Size(); - -private: - off_t fOffset; - size_t fSize; -}; - -#endif // _EMBEDDED_STREAM_H diff --git a/src/bin/makeudfimage/ExtentStream.cpp b/src/bin/makeudfimage/ExtentStream.cpp deleted file mode 100644 index 38c44b0f03..0000000000 --- a/src/bin/makeudfimage/ExtentStream.cpp +++ /dev/null @@ -1,77 +0,0 @@ -//---------------------------------------------------------------------- -// This software is part of the OpenBeOS distribution and is covered -// by the MIT License. -// -// Copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net -//---------------------------------------------------------------------- - -/*! \file ExtentStream.cpp -*/ - -#include "ExtentStream.h" - -#include -#include - -ExtentStream::ExtentStream(DataStream &stream, - const std::list &extentList, - uint32 blockSize) - : SimulatedStream(stream) - , fExtentList(extentList) - , fBlockSize(blockSize) - , fSize(0) -{ - for (std::list::const_iterator i = fExtentList.begin(); - i != fExtentList.end(); - i++) - { - fSize += i->length(); - } -} - -/*! \brief Returns the largest extent in the underlying data stream - corresponding to the extent starting at byte position \a pos of - byte length \a size in the output parameter \a extent. - - NOTE: If the position is at or beyond the end of the stream, the - function will return B_OK, but the value of extent.size will be 0. -*/ -status_t -ExtentStream::_GetExtent(off_t pos, size_t size, data_extent &extent) -{ - status_t error = pos >= 0 ? B_OK : B_BAD_VALUE; - if (!error) { - off_t finalOffset = 0; - off_t streamPos = 0; - for (std::list::const_iterator i = fExtentList.begin(); - i != fExtentList.end(); - i++) - { - off_t offset = i->location() * fBlockSize; - finalOffset = offset + i->length(); - if (streamPos <= pos && pos < streamPos+i->length()) { - // Found it - off_t difference = pos - streamPos; - extent.offset = offset + difference; - extent.size = i->length() - difference; - if (extent.size > size) - extent.size = size; - return B_OK; - } else { - streamPos += i->length(); - } - } - // Didn't find it, so pos is past the end of the stream - extent.offset = finalOffset; - extent.size = 0; - } - return error; -} - -/*! \brief Returns the current size of the stream. -*/ -off_t -ExtentStream::_Size() -{ - return fSize; -} diff --git a/src/bin/makeudfimage/ExtentStream.h b/src/bin/makeudfimage/ExtentStream.h deleted file mode 100644 index 78f102438b..0000000000 --- a/src/bin/makeudfimage/ExtentStream.h +++ /dev/null @@ -1,36 +0,0 @@ -//---------------------------------------------------------------------- -// This software is part of the OpenBeOS distribution and is covered -// by the MIT License. -// -// Copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net -//---------------------------------------------------------------------- - -/*! \file ExtentStream.h -*/ - -#ifndef _EXTENT_STREAM_H -#define _EXTENT_STREAM_H - -#include - -#include "SimulatedStream.h" -#include "UdfStructures.h" - -/*! \brief SimulatedStream implementation that takes a list of - block-aligned data extents. -*/ -class ExtentStream : public SimulatedStream { -public: - ExtentStream(DataStream &stream, const std::list &extentList, uint32 blockSize); - -protected: - virtual status_t _GetExtent(off_t pos, size_t size, data_extent &extent); - virtual off_t _Size(); - -private: - const std::list &fExtentList; - const uint32 fBlockSize; - off_t fSize; -}; - -#endif // _EXTENT_STREAM_H diff --git a/src/bin/makeudfimage/FileStream.cpp b/src/bin/makeudfimage/FileStream.cpp deleted file mode 100644 index 4a1521e42c..0000000000 --- a/src/bin/makeudfimage/FileStream.cpp +++ /dev/null @@ -1,30 +0,0 @@ -//---------------------------------------------------------------------- -// This software is part of the OpenBeOS distribution and is covered -// by the MIT License. -// -// Copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net -//---------------------------------------------------------------------- - -/*! \file FileStream.cpp -*/ - -#include "FileStream.h" - -#include -#include - -FileStream::FileStream(const char *path, uint32 open_mode) - : PositionIOStream(fFile) - , fFile(path, open_mode) -{ -} - -status_t -FileStream::InitCheck() const -{ - status_t error = PositionIOStream::InitCheck(); - if (!error) - error = fFile.InitCheck(); - return error; -} - diff --git a/src/bin/makeudfimage/FileStream.h b/src/bin/makeudfimage/FileStream.h deleted file mode 100644 index 87f1726705..0000000000 --- a/src/bin/makeudfimage/FileStream.h +++ /dev/null @@ -1,30 +0,0 @@ -//---------------------------------------------------------------------- -// This software is part of the OpenBeOS distribution and is covered -// by the MIT License. -// -// Copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net -//---------------------------------------------------------------------- - -/*! \file FileStream.h -*/ - -#ifndef _FILE_STREAM_H -#define _FILE_STREAM_H - -#include - -#include "PositionIOStream.h" - -/*! \brief DataStream implementation that writes directly to a file. -*/ -class FileStream : public PositionIOStream { -public: - FileStream(const char *path, uint32 open_mode); - virtual status_t InitCheck() const; - void Flush() { fFile.Sync(); } - -private: - BFile fFile; -}; - -#endif // _FILE_STREAM_H diff --git a/src/bin/makeudfimage/Jamfile b/src/bin/makeudfimage/Jamfile deleted file mode 100644 index eaa67b374b..0000000000 --- a/src/bin/makeudfimage/Jamfile +++ /dev/null @@ -1,42 +0,0 @@ -SubDir HAIKU_TOP src bin makeudfimage ; - -UsePrivateHeaders [ FDirName kernel util ] ; # For kernel_cpp.h -SubDirHdrs [ FDirName $(HAIKU_TOP) src add-ons kernel file_systems udf ] ; - -{ - local defines = [ FDefines USER ] ; - SubDirCcFlags $(defines) ; - SubDirC++Flags $(defines) ; -} - -BinCommand makeudfimage - : makeudfimage.cpp - Allocator.cpp - Attribute.cpp - ConsoleListener.cpp - EmbeddedStream.cpp - ExtentStream.cpp - FileStream.cpp - MemoryStream.cpp - PhysicalPartitionAllocator.cpp - PositionIOStream.cpp - Shell.cpp - SimulatedStream.cpp - Statistics.cpp - UdfBuilder.cpp - - # Common Udf source files - DString.cpp - UdfDebug.cpp - UdfString.cpp - UdfStructures.cpp - Utils.cpp - - : stdc++.r4 - be - -; - -SEARCH on [ FGristFiles DString.cpp UdfDebug.cpp UdfString.cpp UdfStructures.cpp Utils.cpp ] - = [ FDirName $(HAIKU_TOP) src add-ons kernel file_systems udf ] ; - diff --git a/src/bin/makeudfimage/MemoryStream.cpp b/src/bin/makeudfimage/MemoryStream.cpp deleted file mode 100644 index 8f3b360f2e..0000000000 --- a/src/bin/makeudfimage/MemoryStream.cpp +++ /dev/null @@ -1,31 +0,0 @@ -//---------------------------------------------------------------------- -// This software is part of the OpenBeOS distribution and is covered -// by the MIT License. -// -// Copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net -//---------------------------------------------------------------------- - -/*! \file MemoryStream.cpp -*/ - -#include "MemoryStream.h" - -#include -#include - -MemoryStream::MemoryStream(void *buffer, size_t length) - : PositionIOStream(fMemory) - , fMemory(buffer, length) - , fInitStatus(buffer ? B_OK : B_NO_INIT) -{ -} - -status_t -MemoryStream::InitCheck() const -{ - status_t error = PositionIOStream::InitCheck(); - if (!error) - error = fInitStatus; - return error; -} - diff --git a/src/bin/makeudfimage/MemoryStream.h b/src/bin/makeudfimage/MemoryStream.h deleted file mode 100644 index 12063de9eb..0000000000 --- a/src/bin/makeudfimage/MemoryStream.h +++ /dev/null @@ -1,30 +0,0 @@ -//---------------------------------------------------------------------- -// This software is part of the OpenBeOS distribution and is covered -// by the MIT License. -// -// Copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net -//---------------------------------------------------------------------- - -/*! \file MemoryStream.h -*/ - -#ifndef _MEMORY_STREAM_H -#define _MEMORY_STREAM_H - -#include - -#include "PositionIOStream.h" - -/*! \brief DataStream implementation that writes directly to a chunk of memory. -*/ -class MemoryStream : public PositionIOStream { -public: - MemoryStream(void *buffer, size_t length); - virtual status_t InitCheck() const; - -private: - BMemoryIO fMemory; - status_t fInitStatus; -}; - -#endif // _MEMORY_STREAM_H diff --git a/src/bin/makeudfimage/PhysicalPartitionAllocator.cpp b/src/bin/makeudfimage/PhysicalPartitionAllocator.cpp deleted file mode 100644 index 7d7c9e8aa7..0000000000 --- a/src/bin/makeudfimage/PhysicalPartitionAllocator.cpp +++ /dev/null @@ -1,142 +0,0 @@ -//---------------------------------------------------------------------- -// This software is part of the OpenBeOS distribution and is covered -// by the MIT License. -// -// Copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net -//---------------------------------------------------------------------- - -/*! \file PartitionAllocator.h - - Udf physical partition allocator (implementation). -*/ - -#include "PhysicalPartitionAllocator.h" - -extent_address PhysicalPartitionAllocator::dummyExtent; - -PhysicalPartitionAllocator::PhysicalPartitionAllocator(uint16 number, - uint32 offset, - Allocator &allocator) - : fNumber(number) - , fOffset(offset) - , fAllocator(allocator) -{ - -} - -/*! \brief Allocates the next available block. - - \param block Output parameter into which the number of the - allocated block (in the partition) is stored. - \param physicalBlock Output parameter into which the number of the - allocated block (on the physical volume) is - stored. - - \return - - B_OK: Success. - - error code: Failure, no blocks available. -*/ -status_t -PhysicalPartitionAllocator::GetNextBlock(uint32 &block, uint32 &physicalBlock) -{ - status_t error = fAllocator.GetNextBlock(physicalBlock, fOffset); - if (!error) - block = physicalBlock-fOffset; - return error; -} - -/*! \brief Allocates the next available extent of given length. - - \param length The desired length (in bytes) of the extent. - \param contiguous If false, signals that an extent of shorter length will - be accepted. This allows for small chunks of - unallocated space to be consumed, provided a - contiguous chunk is not needed. - \param extent Output parameter into which the extent as allocated - in the partition is stored. Note that the length - field of the extent may be shorter than the length - parameter passed to this function is \a contiguous is - false. - \param physicalExtent Output parameter into which the extent as allocated - on the physical volume is stored. Note that the length - field of the extent may be shorter than the length - parameter passed to this function is \a contiguous is - false. - - \return - - B_OK: Success. - - error code: Failure. -*/ -status_t -PhysicalPartitionAllocator::GetNextExtent(uint32 length, - bool contiguous, - long_address &extent, - extent_address &physicalExtent) -{ - status_t error = fAllocator.GetNextExtent(length, contiguous, physicalExtent, fOffset); - if (!error) { - extent.set_partition(PartitionNumber()); - extent.set_block(physicalExtent.location()-fOffset); - extent.set_length(physicalExtent.length()); - } - return error; -} - -/*! \brief Allocates enough extents to add up to length bytes and stores said - extents in the given address lists. - - \param length The desired length (in bytes) to be allocated. - \param extents Output parameter into which the extents as allocated - in the partition are stored. - \param physicalExtent Output parameter into which the extents as allocated - on the physical volume are stored. - - \return - - B_OK: Success. - - error code: Failure. -*/ -status_t -PhysicalPartitionAllocator::GetNextExtents(off_t length, std::list &extents, - std::list &physicalExtents) -{ - DEBUG_INIT_ETC("PhysicalPartitionAllocator", ("length: %lld", length)); - extents.empty(); - physicalExtents.empty(); - - // Allocate extents until we're done or we hit an error - status_t error = B_OK; - while (error == B_OK) { - long_address extent; - extent_address physicalExtent; - uint32 chunkLength = length <= ULONG_MAX ? uint32(length) : ULONG_MAX; - error = GetNextExtent(chunkLength, false, extent, physicalExtent); - if (!error) { - extents.push_back(extent); - physicalExtents.push_back(physicalExtent); - if (physicalExtent.length() > chunkLength) { - // This should never happen, but just to be safe - PRINT(("ERROR: allocated extent length longer than requested " - " extent length (allocated: %ld, requested: %ld)\n", - physicalExtent.length(), chunkLength)); - error = B_ERROR; - } else { - // ToDo: Might want to add some checks for 0 length allocations here - length -= physicalExtent.length(); - if (length == 0) { - // All done - break; - } - } - } - } - RETURN(error); -} - -/*! \brief Returns the length of the partition in blocks. -*/ -uint32 -PhysicalPartitionAllocator::Length() const -{ - uint32 length = fAllocator.Length(); - return fOffset >= length ? 0 : length-fOffset; -} diff --git a/src/bin/makeudfimage/PhysicalPartitionAllocator.h b/src/bin/makeudfimage/PhysicalPartitionAllocator.h deleted file mode 100644 index a659fcfbdc..0000000000 --- a/src/bin/makeudfimage/PhysicalPartitionAllocator.h +++ /dev/null @@ -1,43 +0,0 @@ -//---------------------------------------------------------------------- -// This software is part of the OpenBeOS distribution and is covered -// by the MIT License. -// -// Copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net -//---------------------------------------------------------------------- - -/*! \file PhysicalPartitionAllocator.h - - Udf physical partition allocator (declarations). -*/ - -#ifndef _PHYSICAL_PARTITION_ALLOCATOR_H -#define _PHYSICAL_PARTITION_ALLOCATOR_H - -#include - -#include "Allocator.h" -#include "UdfStructures.h" - -/*! \brief Allocates blocks and extents from a Udf physical partition. -*/ -class PhysicalPartitionAllocator { -public: - PhysicalPartitionAllocator(uint16 number, uint32 offset, Allocator &allocator); - - status_t GetNextBlock(uint32 &block, uint32 &physicalBlock); - status_t GetNextExtent(uint32 length, bool contiguous, long_address &extent, - extent_address &physicalExtent = dummyExtent); - status_t GetNextExtents(off_t length, std::list &extents, - std::list &physicalExtents); - - - uint16 PartitionNumber() const { return fNumber; } - uint32 Length() const; -private: - static extent_address dummyExtent; - uint16 fNumber; //!< The partition number of this partition - uint32 fOffset; //!< The offset of the start of this partition in physical space - Allocator &fAllocator; -}; - -#endif // _PHYSICAL_PARTITION_ALLOCATOR_H diff --git a/src/bin/makeudfimage/PositionIOStream.cpp b/src/bin/makeudfimage/PositionIOStream.cpp deleted file mode 100644 index 5b3b12bea4..0000000000 --- a/src/bin/makeudfimage/PositionIOStream.cpp +++ /dev/null @@ -1,207 +0,0 @@ -//---------------------------------------------------------------------- -// This software is part of the OpenBeOS distribution and is covered -// by the MIT License. -// -// Copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net -//---------------------------------------------------------------------- - -/*! \file PositionIOStream.cpp -*/ - -#include "PositionIOStream.h" - -#include -#include - -PositionIOStream::PositionIOStream(BPositionIO &stream) - : fStream(stream) -{ -} - -ssize_t -PositionIOStream::Read(void *buffer, size_t size) -{ - return fStream.Read(buffer, size); -} - -ssize_t -PositionIOStream::ReadAt(off_t pos, void *buffer, size_t size) -{ - return fStream.ReadAt(pos, buffer, size); -} - -ssize_t -PositionIOStream::Write(const void *buffer, size_t size) -{ - return fStream.Write(buffer, size); -} - -ssize_t -PositionIOStream::WriteAt(off_t pos, const void *buffer, size_t size) -{ - return fStream.WriteAt(pos, buffer, size); -} - -/*! \brief Writes \a size bytes worth of data from \a data at the current - position in the file, incrementing the file's position marker as it goes. -*/ -ssize_t -PositionIOStream::Write(BDataIO &data, size_t size) -{ - status_t error = kBufferSize > 0 ? B_OK : B_BAD_VALUE; - size_t bytes = 0; - if (!error) { - void *buffer = malloc(kBufferSize); - error = buffer ? B_OK : B_NO_MEMORY; - if (!error) { - // Fudge the buffer size from here out if the requested - // number of bytes to write is smaller than the buffer - size_t bufferSize = (size < kBufferSize ? size : kBufferSize); - // Zero - memset(buffer, 0, bufferSize); - // Write - while (bytes < size) { - ssize_t bytesRead = data.Read(buffer, bufferSize); - if (bytesRead >= 0) { - ssize_t bytesWritten = fStream.Write(buffer, bytesRead); - if (bytesWritten >= 0) { - bytes += bytesWritten; - } else { - error = status_t(bytesWritten); - break; - } - } else { - error = status_t(bytesRead); - break; - } - } - } - free(buffer); - } - return error ? ssize_t(error) : ssize_t(bytes); -} - -/*! \brief Writes \a size bytes worth of data from \a data at position - \a pos in the file without incrementing the file's position marker. -*/ -ssize_t -PositionIOStream::WriteAt(off_t pos, BDataIO &data, size_t size) -{ - status_t error = kBufferSize > 0 ? B_OK : B_BAD_VALUE; - size_t bytes = 0; - if (!error) { - void *buffer = malloc(kBufferSize); - error = buffer ? B_OK : B_NO_MEMORY; - if (!error) { - // Fudge the buffer size from here out if the requested - // number of bytes to write is smaller than the buffer - size_t bufferSize = (size < kBufferSize ? size : kBufferSize); - // Zero - memset(buffer, 0, bufferSize); - // Write - while (bytes < size) { - ssize_t bytesRead = data.Read(buffer, bufferSize); - if (bytesRead >= 0) { - ssize_t bytesWritten = fStream.WriteAt(pos, buffer, bytesRead); - if (bytesWritten >= 0) { - bytes += bytesWritten; - pos += bytesWritten; - } else { - error = status_t(bytesWritten); - break; - } - } else { - error = status_t(bytesRead); - break; - } - } - } - free(buffer); - } - return error ? ssize_t(error) : ssize_t(bytes); -} - -/*! \brief Writes \a size bytes worth of zeros at the current position - in the file, incrementing the file's position marker as it goes. -*/ -ssize_t -PositionIOStream::Zero(size_t size) -{ - status_t error = kBufferSize > 0 ? B_OK : B_BAD_VALUE; - size_t bytes = 0; - if (!error) { - void *buffer = malloc(kBufferSize); - error = buffer ? B_OK : B_NO_MEMORY; - if (!error) { - // Fudge the buffer size from here out if the requested - // number of bytes to write is smaller than the buffer - size_t bufferSize = (size < kBufferSize ? size : kBufferSize); - // Zero - memset(buffer, 0, bufferSize); - // Write - while (bytes < size) { - ssize_t bytesWritten = fStream.Write(buffer, bufferSize); - if (bytesWritten >= 0) { - bytes += bytesWritten; - } else { - error = status_t(bytesWritten); - break; - } - } - } - free(buffer); - } - return error ? ssize_t(error) : ssize_t(bytes); -} - -/*! \brief Writes \a size bytes worth of zeros at position \a pos - in the file without incrementing the file's position marker. -*/ -ssize_t -PositionIOStream::ZeroAt(off_t pos, size_t size) -{ - status_t error = kBufferSize > 0 ? B_OK : B_BAD_VALUE; - size_t bytes = 0; - if (!error) { - void *buffer = malloc(kBufferSize); - error = buffer ? B_OK : B_NO_MEMORY; - if (!error) { - // Fudge the buffer size from here out if the requested - // number of bytes to write is smaller than the buffer - size_t bufferSize = (size < kBufferSize ? size : kBufferSize); - // Zero - memset(buffer, 0, bufferSize); - // Write - while (bytes < size) { - ssize_t bytesWritten = fStream.WriteAt(pos, buffer, bufferSize); - if (bytesWritten >= 0) { - bytes += bytesWritten; - pos += bytesWritten; - } else { - error = status_t(bytesWritten); - break; - } - } - } - free(buffer); - } - return error ? ssize_t(error) : ssize_t(bytes); -} - -off_t -PositionIOStream::Seek(off_t position, uint32 seek_mode) -{ - return fStream.Seek(position, seek_mode); -} - -off_t -PositionIOStream::Position() const -{ - return fStream.Position(); -} - -status_t -PositionIOStream::SetSize(off_t size) -{ - return fStream.SetSize(size); -} diff --git a/src/bin/makeudfimage/PositionIOStream.h b/src/bin/makeudfimage/PositionIOStream.h deleted file mode 100644 index de8bfadbe9..0000000000 --- a/src/bin/makeudfimage/PositionIOStream.h +++ /dev/null @@ -1,47 +0,0 @@ -//---------------------------------------------------------------------- -// This software is part of the OpenBeOS distribution and is covered -// by the MIT License. -// -// Copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net -//---------------------------------------------------------------------- - -/*! \file PositionIOStream.h -*/ - -#ifndef _POSITION_IO_STREAM_H -#define _POSITION_IO_STREAM_H - -#include - -#include "DataStream.h" - -/*! \brief DataStream implementation that writes to a BPositionIO. -*/ -class PositionIOStream : public DataStream { -public: - PositionIOStream(BPositionIO &stream); - virtual status_t InitCheck() const { return B_OK; } - - static const size_t kBufferSize = 32 * 1024; - - virtual ssize_t Read(void *buffer, size_t size); - virtual ssize_t ReadAt(off_t pos, void *buffer, size_t size); - - virtual ssize_t Write(const void *buffer, size_t size); - virtual ssize_t WriteAt(off_t pos, const void *buffer, size_t size); - - virtual ssize_t Write(BDataIO &data, size_t size); - virtual ssize_t WriteAt(off_t pos, BDataIO &data, size_t size); - - virtual ssize_t Zero(size_t size); - virtual ssize_t ZeroAt(off_t pos, size_t size); - - virtual off_t Seek(off_t position, uint32 seek_mode); - virtual off_t Position() const; - - virtual status_t SetSize(off_t size); -private: - BPositionIO &fStream; -}; - -#endif // _POSITION_IO_STREAM_H diff --git a/src/bin/makeudfimage/ProgressListener.h b/src/bin/makeudfimage/ProgressListener.h deleted file mode 100644 index e8999f5eb6..0000000000 --- a/src/bin/makeudfimage/ProgressListener.h +++ /dev/null @@ -1,36 +0,0 @@ -//---------------------------------------------------------------------- -// This software is part of the OpenBeOS distribution and is covered -// by the MIT License. -// -// Copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net -//---------------------------------------------------------------------- - -/*! \file ProgressListener.h - - Interface for receiving progress information updates from an - executing UdfBuilder object. -*/ - -#ifndef _PROGRESS_LISTENER_H -#define _PROGRESS_LISTENER_H - -#include "Statistics.h" - -enum VerbosityLevel { - VERBOSITY_NONE, - VERBOSITY_LOW, - VERBOSITY_MEDIUM, - VERBOSITY_HIGH, -}; - -class ProgressListener { -public: - virtual void OnStart(const char *sourceDirectory, const char *outputFile, - const char *udfVolumeName, uint16 udfRevision) const = 0; - virtual void OnError(const char *message) const = 0; - virtual void OnWarning(const char *message) const = 0; - virtual void OnUpdate(VerbosityLevel level, const char *message) const = 0; - virtual void OnCompletion(status_t result, const Statistics &statistics) const = 0; -}; - -#endif // _PROGRESS_LISTENER_H diff --git a/src/bin/makeudfimage/Shell.cpp b/src/bin/makeudfimage/Shell.cpp deleted file mode 100644 index 8cc41a9443..0000000000 --- a/src/bin/makeudfimage/Shell.cpp +++ /dev/null @@ -1,173 +0,0 @@ -//---------------------------------------------------------------------- -// This software is part of the OpenBeOS distribution and is covered -// by the MIT License. -// -// Copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net -//---------------------------------------------------------------------- - -/*! \file Shell.cpp - - Command-line shell for makeudfimage -*/ - -#include "Shell.h" - -#include - -#include "ConsoleListener.h" -#include "UdfDebug.h" -#include "UdfBuilder.h" - -Shell::Shell() - // The following settings are essentially default values - // for all the command-line options (except for the last - // three vars). - : fVerbosityLevel(VERBOSITY_LOW) - , fBlockSize(2048) - , fDoUdf(true) - , fDoIso(false) - , fSourceDirectory("") - , fOutputFile("") - , fUdfVolumeName("") - , fUdfRevision(0x0201) - , fTruncate(true) -{ -} - -status_t -Shell::Run(int argc, char *argv[]) -{ - DEBUG_INIT("Shell"); - status_t error = _ProcessArguments(argc, argv); - if (!error) { - if (fUdfVolumeName == "") - fUdfVolumeName = "(Unnamed UDF Volume)"; - ConsoleListener listener(fVerbosityLevel); - UdfBuilder builder(fOutputFile.c_str(), fBlockSize, fDoUdf, - fUdfVolumeName.c_str(), fUdfRevision, fDoIso, "ISO_VOLUME", - fSourceDirectory.c_str(), listener, fTruncate); - error = builder.InitCheck(); - if (!error) - error = builder.Build(); - } - - if (error) - _PrintHelp(); - - RETURN(error); -} - -status_t -Shell::_ProcessArguments(int argc, char *argv[]) { - DEBUG_INIT_ETC("Shell", ("argc: %d", argc)); - - // Throw all the arguments into a handy list - std::list argumentList; - for (int i = 1; i < argc; i++) - argumentList.push_back(std::string(argv[i])); - - bool foundSourceDirectory = false; - bool foundOutputFile = false; - bool foundUdfVolumeName = false; - - // Now bust out some processing - int argumentCount = argumentList.size(); - int index = 0; - for(std::list::iterator i = argumentList.begin(); - i != argumentList.end(); - ) - { - std::string &arg = *i; - if (arg == "-h" || arg == "--help") { - _PrintTitle(); - RETURN(B_ERROR); - } else if (arg == "-v0" || arg == "--quiet") { - fVerbosityLevel = VERBOSITY_NONE; - } else if (arg == "-v1") { - fVerbosityLevel = VERBOSITY_LOW; - } else if (arg == "-v2") { - fVerbosityLevel = VERBOSITY_MEDIUM; - } else if (arg == "-v3") { - fVerbosityLevel = VERBOSITY_HIGH; - } else if (arg == "-r" || arg == "--revision") { - i++; - index++; - if (*i == "1.50") - fUdfRevision = 0x0150; - else if (*i == "2.01") - fUdfRevision = 0x0201; - else { - printf("ERROR: invalid UDF revision `%s'; please specify `1.50' " - "or `2.01'\n", i->c_str()); - RETURN(B_ERROR); - } - } else if (arg == "-t" || arg == "--no-truncate") { - fTruncate = 0; - } else { - if (index == argumentCount-3) { - // Take this argument as the source dir - fSourceDirectory = arg; - foundSourceDirectory = true; - } else if (index == argumentCount-2) { - // Take this argument as the output filename - fOutputFile = arg; - foundOutputFile = true; - } else if (index == argumentCount-1) { - // Take this argument as the udf volume name - fUdfVolumeName = arg; - foundUdfVolumeName = true; - } else { - printf("ERROR: invalid argument `%s'\n", arg.c_str()); - printf("\n"); - RETURN(B_ERROR); - } - } - i++; - index++; - } - - status_t error = B_OK; - if (!foundSourceDirectory) { - printf("ERROR: no source directory specified\n"); - error = B_ERROR; - } - if (!foundOutputFile) { - printf("ERROR: no output file specified\n"); - error = B_ERROR; - } - if (!foundUdfVolumeName) { - printf("ERROR: no volume name specified\n"); - error = B_ERROR; - } - - if (error) - printf("\n"); - RETURN(error); -} - -void -Shell::_PrintHelp() { - printf("usage: makeudfimage [options] \n"); - printf("example: makeudfimage /boot/home/mail mail.udf \"Mail Backup\"\n"); - printf("\n"); - printf("VALID OPTIONS:\n"); - printf(" -h, --help Displays this help text.\n"); - printf(" --quiet Turns off console output.\n"); - printf(" -r, --revision Selects the UDF revision to use. Supported\n"); - printf(" revisions are 1.50 and 2.01. Defaults to 2.01.\n"); - printf(" -t, --no-trunc Don't truncate output file if it already\n"); - printf(" exists.\n"); - printf("\n"); -} - -#define MAKEUDFIMAGE_VERSION "1.0.0" -#ifndef MAKEUDFIMAGE_VERSION -# define MAKEUDFIMAGE_VERSION ("development version " __DATE__ ", " __TIME__) -#endif - -void -Shell::_PrintTitle() { - printf("makeudfimage %s\n", MAKEUDFIMAGE_VERSION); - printf("Copyright © 2004 Tyler Dauwalder\n"); - printf("\n"); -} diff --git a/src/bin/makeudfimage/Shell.h b/src/bin/makeudfimage/Shell.h deleted file mode 100644 index da3d0b5438..0000000000 --- a/src/bin/makeudfimage/Shell.h +++ /dev/null @@ -1,41 +0,0 @@ -//---------------------------------------------------------------------- -// This software is part of the OpenBeOS distribution and is covered -// by the MIT License. -// -// Copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net -//---------------------------------------------------------------------- - -/*! \file Shell.h -*/ - -#ifndef _SHELL_H -#define _SHELL_H - -#include -#include - -#include "ProgressListener.h" - -class Shell { -public: - Shell(); - status_t Run(int argc, char *argv[]); - -private: - status_t _ProcessArguments(int argc, char *argv[]); - void _PrintHelp(); - void _PrintTitle(); - - VerbosityLevel fVerbosityLevel; - uint32 fBlockSize; - bool fDoUdf; - bool fDoIso; - std::string fSourceDirectory; - std::string fOutputFile; - std::string fUdfVolumeName; - uint16 fUdfRevision; - bool fTruncate; -}; - - -#endif // _SHELL_H diff --git a/src/bin/makeudfimage/SimulatedStream.cpp b/src/bin/makeudfimage/SimulatedStream.cpp deleted file mode 100644 index 2cf327edaa..0000000000 --- a/src/bin/makeudfimage/SimulatedStream.cpp +++ /dev/null @@ -1,297 +0,0 @@ -//---------------------------------------------------------------------- -// This software is part of the OpenBeOS distribution and is covered -// by the MIT License. -// -// Copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net -//---------------------------------------------------------------------- - -/*! \file SimulatedStream.cpp -*/ - -#include "SimulatedStream.h" - -#include -#include -#include -#include "UdfDebug.h" - -SimulatedStream::SimulatedStream(DataStream &stream) - : fPosition(0) - , fStream(stream) -{ -} - -status_t -SimulatedStream::InitCheck() const -{ - return fStream.InitCheck(); -} - -ssize_t -SimulatedStream::Read(void *_buffer, size_t size) -{ - uint8 *buffer = reinterpret_cast(_buffer); - status_t error = buffer ? B_OK : B_BAD_VALUE; - ssize_t bytesTotal = 0; - while (error == B_OK && size > 0) { - data_extent extent; - error = _GetExtent(fPosition, size, extent); - if (!error) { - if (extent.size > 0) { - ssize_t bytes = fStream.ReadAt(extent.offset, buffer, extent.size); - if (bytes >= 0) { - size -= bytes; - fPosition += bytes; - buffer += bytes; - bytesTotal += bytes; - } else { - error = status_t(bytes); - } - } else { - // end of simulated stream - break; - } - } - } - return !error ? bytesTotal : ssize_t(error); -} - -ssize_t -SimulatedStream::ReadAt(off_t pos, void *_buffer, size_t size) -{ - uint8 *buffer = reinterpret_cast(_buffer); - status_t error = buffer ? B_OK : B_BAD_VALUE; - ssize_t bytesTotal = 0; - while (error == B_OK && size > 0) { - data_extent extent; - error = _GetExtent(pos, size, extent); - if (!error) { - if (extent.size > 0) { - ssize_t bytes = fStream.ReadAt(extent.offset, buffer, extent.size); - if (bytes >= 0) { - size -= bytes; - pos += bytes; - buffer += bytes; - bytesTotal += bytes; - } else { - error = status_t(bytes); - } - } else { - // end of simulated stream - break; - } - } - } - return !error ? bytesTotal : ssize_t(error); -} - -/*! \brief Writes \a size bytes worth of data from \a buffer at the current - position in the stream, incrementing the stream's position marker as it goes. -*/ -ssize_t -SimulatedStream::Write(const void *_buffer, size_t size) -{ - const uint8 *buffer = reinterpret_cast(_buffer); - status_t error = buffer ? B_OK : B_BAD_VALUE; - ssize_t bytesTotal = 0; - while (error == B_OK && size > 0) { - data_extent extent; - error = _GetExtent(fPosition, size, extent); - if (!error) { - if (extent.size > 0) { - ssize_t bytes = fStream.WriteAt(extent.offset, buffer, extent.size); - if (bytes >= 0) { - size -= bytes; - fPosition += bytes; - buffer += bytes; - bytesTotal += bytes; - } else { - error = status_t(bytes); - } - } else { - // end of simulated stream - break; - } - } - } - return !error ? bytesTotal : ssize_t(error); -} - -/*! \brief Writes \a size bytes worth of data from \a buffer at position - \a pos in the stream without incrementing the stream's position marker. -*/ -ssize_t -SimulatedStream::WriteAt(off_t pos, const void *_buffer, size_t size) -{ - const uint8 *buffer = reinterpret_cast(_buffer); - status_t error = buffer ? B_OK : B_BAD_VALUE; - ssize_t bytesTotal = 0; - while (error == B_OK && size > 0) { - data_extent extent; - error = _GetExtent(pos, size, extent); - if (!error) { - if (extent.size > 0) { - ssize_t bytes = fStream.WriteAt(extent.offset, buffer, extent.size); - if (bytes >= 0) { - size -= bytes; - pos += bytes; - buffer += bytes; - bytesTotal += bytes; - } else { - error = status_t(bytes); - } - } else { - // end of simulated stream - break; - } - } - } - return !error ? bytesTotal : ssize_t(error); -} - -/*! \brief Writes \a size bytes worth of data from \a data at the current - position in the stream, incrementing the stream's position marker as it goes. -*/ -ssize_t -SimulatedStream::Write(BDataIO &data, size_t size) -{ - DEBUG_INIT_ETC("SimulatedStream", ("size: %ld", size)); - status_t error = B_OK; - ssize_t bytesTotal = 0; - while (error == B_OK && size > 0) { - data_extent extent; - error = _GetExtent(fPosition, size, extent); - if (!error) { - if (extent.size > 0) { - PRINT(("writing to underlying stream (offset: %llu, size: %ld)\n", extent.offset, extent.size)); - ssize_t bytes = fStream.WriteAt(extent.offset, data, extent.size); - if (bytes >= 0) { - size -= bytes; - fPosition += bytes; - bytesTotal += bytes; - } else { - error = status_t(bytes); - } - } else { - // end of simulated stream - break; - } - } - } - RETURN(!error ? bytesTotal : ssize_t(error)); -} - -/*! \brief Writes \a size bytes worth of data from \a data at position - \a pos in the stream without incrementing the stream's position marker. -*/ -ssize_t -SimulatedStream::WriteAt(off_t pos, BDataIO &data, size_t size) -{ - status_t error = B_OK; - ssize_t bytesTotal = 0; - while (error == B_OK && size > 0) { - data_extent extent; - error = _GetExtent(pos, size, extent); - if (!error) { - if (extent.size > 0) { - ssize_t bytes = fStream.WriteAt(extent.offset, data, extent.size); - if (bytes >= 0) { - size -= bytes; - pos += bytes; - bytesTotal += bytes; - } else { - error = status_t(bytes); - } - } else { - // end of simulated stream - break; - } - } - } - return !error ? bytesTotal : ssize_t(error); -} - -/*! \brief Writes \a size bytes worth of zeros at the current position - in the stream, incrementing the stream's position marker as it goes. -*/ -ssize_t -SimulatedStream::Zero(size_t size) -{ - status_t error = B_OK; - ssize_t bytesTotal = 0; - while (error == B_OK && size > 0) { - data_extent extent; - error = _GetExtent(fPosition, size, extent); - if (!error) { - if (extent.size > 0) { - ssize_t bytes = fStream.ZeroAt(extent.offset, extent.size); - if (bytes >= 0) { - size -= bytes; - fPosition += bytes; - bytesTotal += bytes; - } else { - error = status_t(bytes); - } - } else { - // end of simulated stream - break; - } - } - } - return !error ? bytesTotal : ssize_t(error); -} - -/*! \brief Writes \a size bytes worth of zeros at position \a pos - in the stream without incrementing the stream's position marker. -*/ -ssize_t -SimulatedStream::ZeroAt(off_t pos, size_t size) -{ - status_t error = B_OK; - ssize_t bytesTotal = 0; - while (error == B_OK && size > 0) { - data_extent extent; - error = _GetExtent(pos, size, extent); - if (!error) { - if (extent.size > 0) { - ssize_t bytes = fStream.ZeroAt(extent.offset, extent.size); - if (bytes >= 0) { - size -= bytes; - pos += bytes; - bytesTotal += bytes; - } else { - error = status_t(bytes); - } - } else { - // end of simulated stream - break; - } - } - } - return !error ? bytesTotal : ssize_t(error); -} - -off_t -SimulatedStream::Seek(off_t pos, uint32 seek_mode) -{ - off_t size = _Size(); - switch (seek_mode) { - case SEEK_SET: - fPosition = pos; - break; - case SEEK_CUR: - fPosition += pos; - break; - case SEEK_END: - fPosition = size + pos; - break; - default: - break; - } - // Range check - if (fPosition < 0) - fPosition = 0; - else if (fPosition > size && SetSize(fPosition) != B_OK) - fPosition = size; - return fPosition; -} diff --git a/src/bin/makeudfimage/SimulatedStream.h b/src/bin/makeudfimage/SimulatedStream.h deleted file mode 100644 index c1042febcd..0000000000 --- a/src/bin/makeudfimage/SimulatedStream.h +++ /dev/null @@ -1,77 +0,0 @@ -//---------------------------------------------------------------------- -// This software is part of the OpenBeOS distribution and is covered -// by the MIT License. -// -// Copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net -//---------------------------------------------------------------------- - -/*! \file SimulatedStream.h -*/ - -#ifndef _SIMULATED_STREAM_H -#define _SIMULATED_STREAM_H - -#include "DataStream.h" - -/*! \brief Abstract DataStream wrapper around another DataStream and a sequence of - extents in said stream that allows for easy write access to said sequence - of extents as though they were a continuous chunk of data. - - NOTE: The SimulatedStream object never modifies the data stream position - of the underlying data stream; all read/write/zero calls use the underlying - stream's ReadAt()/WriteAt()/ZeroAt() functions. -*/ -class SimulatedStream : public DataStream { -public: - SimulatedStream(DataStream &stream); - virtual status_t InitCheck() const; - - virtual ssize_t Read(void *buffer, size_t size); - virtual ssize_t ReadAt(off_t pos, void *buffer, size_t size); - - virtual ssize_t Write(const void *buffer, size_t size); - virtual ssize_t WriteAt(off_t pos, const void *buffer, size_t size); - - virtual ssize_t Write(BDataIO &data, size_t size); - virtual ssize_t WriteAt(off_t pos, BDataIO &data, size_t size); - - virtual ssize_t Zero(size_t size); - virtual ssize_t ZeroAt(off_t pos, size_t size); - - virtual off_t Seek(off_t pos, uint32 seek_mode); - virtual off_t Position() const { return fPosition; } - - virtual status_t SetSize(off_t size) { return B_ERROR; } - -protected: - struct data_extent { - data_extent(off_t offset = 0, size_t size = 0) - : offset(offset) - , size(size) - { - } - - off_t offset; - size_t size; - }; - - /*! \brief Should be implemented to return (via the output parameter - \a extent) the largest extent in the underlying data stream corresponding - to the extent in the simulated data stream starting at byte position - \a pos of byte length \a size. - - NOTE: If the position is at or beyond the end of the simulated stream, the - function should return B_OK, and the value of extent.size should be 0. - */ - virtual status_t _GetExtent(off_t pos, size_t size, data_extent &extent) = 0; - - /*! \brief Should be implemented to return the current size of the stream. - */ - virtual off_t _Size() = 0; - -private: - off_t fPosition; - DataStream &fStream; -}; - -#endif // _SIMULATED_STREAM_H diff --git a/src/bin/makeudfimage/Statistics.cpp b/src/bin/makeudfimage/Statistics.cpp deleted file mode 100644 index a94f9c8669..0000000000 --- a/src/bin/makeudfimage/Statistics.cpp +++ /dev/null @@ -1,158 +0,0 @@ -//---------------------------------------------------------------------- -// This software is part of the OpenBeOS distribution and is covered -// by the MIT License. -// -// Copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net -//---------------------------------------------------------------------- - -/*! \file Statistics.h - - BDataIO wrapper around a given attribute for a file. (implementation) -*/ - -#include "Statistics.h" - -#include - -/*! \brief Returns a string describing the given number of bytes - in the most appropriate units (i.e. bytes, KB, MB, etc.). -*/ -std::string -bytes_to_string(uint64 bytes) -{ - const uint64 kb = 1024; // kilo - const uint64 mb = 1024 * kb; // mega - const uint64 gb = 1024 * mb; // giga - const uint64 tb = 1024 * gb; // tera - const uint64 pb = 1024 * tb; // peta - const uint64 eb = 1024 * pb; // exa - std::string units; - uint64 divisor = 1; - if (bytes >= eb) { - units = "EB"; - divisor = eb; - } else if (bytes >= pb) { - units = "PB"; - divisor = pb; - } else if (bytes >= tb) { - units = "TB"; - divisor = tb; - } else if (bytes >= gb) { - units = "GB"; - divisor = gb; - } else if (bytes >= mb) { - units = "MB"; - divisor = mb; - } else if (bytes >= kb) { - units = "KB"; - divisor = kb; - } else { - units = "bytes"; - divisor = 1; - } - double scaledValue = double(bytes) / double(divisor); - char scaledString[10]; - // Should really only need 7 chars + NULL... - sprintf(scaledString, divisor == 1 ? "%.0f " : "%.1f ", scaledValue); - return std::string(scaledString) + units; -} - -/*! \brief Creates a new statistics object and sets the start time - for the duration timer. -*/ -Statistics::Statistics() - : fStartTime(real_time_clock()) - , fDirectories(0) - , fFiles(0) - , fSymlinks(0) - , fAttributes(0) - , fDirectoryBytes(0) - , fFileBytes(0) - , fImageSize(0) -{ -} - -/*! \brief Resets all statistics fields, including the start time of - the duration timer. -*/ -void -Statistics::Reset() -{ - Statistics null; - *this = null; -} - - -/*! \brief Returns a string describing the amount of time - elapsed since the object was created.. -*/ -std::string -Statistics::ElapsedTimeString() const -{ - time_t time = ElapsedTime(); - std::string result; - char buffer[256]; - // seconds - uint32 seconds = time % 60; - sprintf(buffer, "%ld second%s", seconds, seconds == 1 ? "" : "s"); - result = buffer; - time /= 60; - if (time > 0) { - // minutes - uint32 minutes = time % 60; - sprintf(buffer, "%ld minute%s", minutes, minutes == 1 ? "" : "s"); - result = std::string(buffer) + ", " + result; - time /= 60; - if (time > 0) { - // hours - uint32 hours = time % 24; - sprintf(buffer, "%ld hour%s", hours, hours == 1 ? "" : "s"); - result = std::string(buffer) + ", " + result; - time /= 24; - if (time > 0) { - // days - uint32 days = time % 365; - sprintf(buffer, "%ld day%s", days, days == 1 ? "" : "s"); - result = std::string(buffer) + ", " + result; - time /= 365; - if (time > 0) { - // years - sprintf(buffer, "%ld year%s", time, time == 1 ? "" : "s"); - result = std::string(buffer) + ", " + result; - time /= 60; - } - } - } - } - return result; -} - -/*! \brief Returns a string describing the number of bytes - allocated to directory data and metadata, displayed in the - appropriate units (i.e. bytes, KB, MB, etc.). -*/ -std::string -Statistics::DirectoryBytesString() const -{ - return bytes_to_string(DirectoryBytes()); -} - -/*! \brief Returns a string describing the number of bytes - allocated to file data and metadata, displayed in the - appropriate units (i.e. bytes, KB, MB, etc.). -*/ -std::string -Statistics::FileBytesString() const -{ - return bytes_to_string(FileBytes()); -} - -/*! \brief Returns a string describing the total image size, - displayed in the appropriate units (i.e. bytes, KB, MB, etc.). -*/ -std::string -Statistics::ImageSizeString() const -{ - return bytes_to_string(ImageSize()); -} - diff --git a/src/bin/makeudfimage/Statistics.h b/src/bin/makeudfimage/Statistics.h deleted file mode 100644 index 73f36b304e..0000000000 --- a/src/bin/makeudfimage/Statistics.h +++ /dev/null @@ -1,64 +0,0 @@ -//---------------------------------------------------------------------- -// This software is part of the OpenBeOS distribution and is covered -// by the MIT License. -// -// Copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net -//---------------------------------------------------------------------- - -/*! \file Statistics.h - - BDataIO wrapper around a given attribute for a file. (declarations) -*/ - -#ifndef _STATISTICS_H -#define _STATISTICS_H - -#include -#include -#include - -std::string bytes_to_string(uint64 bytes); - -class Statistics { -public: - Statistics(); - void Reset(); - - time_t StartTime() const { return fStartTime; } - time_t ElapsedTime() const { return real_time_clock() - fStartTime; } - std::string ElapsedTimeString() const; - - void AddDirectory() { fDirectories++; } - void AddFile() { fFiles++; } - void AddSymlink() { fSymlinks++; } - void AddAttribute() { fAttributes++; } - - void AddDirectoryBytes(uint64 count) { fDirectoryBytes += count; } - void AddFileBytes(uint64 count) { fFileBytes += count; } - - void SetImageSize(uint64 size) { fImageSize = size; } - - uint64 Directories() const { return fDirectories; } - uint64 Files() const { return fFiles; } - uint64 Symlinks() const { return fSymlinks; } - uint64 Attributes() const { return fAttributes; } - - uint64 DirectoryBytes() const { return fDirectoryBytes; } - uint64 FileBytes() const { return fFileBytes; } - std::string DirectoryBytesString() const; - std::string FileBytesString() const; - - uint64 ImageSize() const { return fImageSize; } - std::string ImageSizeString() const; -private: - time_t fStartTime; - uint64 fDirectories; - uint64 fFiles; - uint64 fSymlinks; - uint64 fAttributes; - uint64 fDirectoryBytes; - uint64 fFileBytes; - uint64 fImageSize; -}; - -#endif // _STATISTICS_H diff --git a/src/bin/makeudfimage/UdfBuilder.cpp b/src/bin/makeudfimage/UdfBuilder.cpp deleted file mode 100644 index f88cd9f235..0000000000 --- a/src/bin/makeudfimage/UdfBuilder.cpp +++ /dev/null @@ -1,1557 +0,0 @@ -//---------------------------------------------------------------------- -// This software is part of the OpenBeOS distribution and is covered -// by the MIT License. -// -// Copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net -//---------------------------------------------------------------------- - -/*! \file UdfBuilder.cpp - - Main UDF image building class implementation. -*/ - -#include "UdfBuilder.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "DString.h" -#include "ExtentStream.h" -#include "MemoryChunk.h" -#include "UdfDebug.h" -#include "Utils.h" - -using Udf::bool_to_string; -using Udf::check_size_error; - -//! Application identifier entity_id -static const Udf::entity_id kApplicationId(0, "*OpenBeOS makeudfimage"); - -static const Udf::logical_block_address kNullLogicalBlock(0, 0); -static const Udf::extent_address kNullExtent(0, 0); -static const Udf::long_address kNullAddress(0, 0, 0, 0); - -/*! \brief Returns the number of the block in which the byte offset specified - by \a pos resides in the data space specified by the extents in \a dataSpace. - - Used to figure out the value for Udf::file_id_descriptor::tag::location fields. - - \param block Output parameter into which the block number of interest is stored. -*/ -static -status_t -block_for_offset(off_t pos, std::list &dataSpace, uint32 blockSize, - uint32 &block) -{ - status_t error = pos >= 0 ? B_OK : B_BAD_VALUE; - if (!error) { - off_t streamPos = 0; - for (std::list::const_iterator i = dataSpace.begin(); - i != dataSpace.end(); - i++) - { - if (streamPos <= pos && pos < streamPos+i->length()) { - // Found it - off_t difference = pos - streamPos; - block = i->block() + difference / blockSize; - return B_OK; - } else { - streamPos += i->length(); - } - } - // Didn't find it, so pos is past the end of the data space - error = B_ERROR; - } - return error; -} - -/*! \brief Creates a new UdfBuilder object. - - \param udfRevision The UDF revision to write, formatted as in the UDF - domain id suffix, i.e. UDF 2.50 is represented by 0x0250. -*/ -UdfBuilder::UdfBuilder(const char *outputFile, uint32 blockSize, bool doUdf, - const char *udfVolumeName, uint16 udfRevision, bool doIso, - const char *isoVolumeName, const char *rootDirectory, - const ProgressListener &listener, bool truncate) - : fInitStatus(B_NO_INIT) - , fOutputFile(outputFile, B_READ_WRITE | B_CREATE_FILE | (truncate ? B_ERASE_FILE : 0)) - , fOutputFilename(outputFile) - , fBlockSize(blockSize) - , fBlockShift(0) - , fDoUdf(doUdf) - , fUdfVolumeName(udfVolumeName) - , fUdfRevision(udfRevision) - , fUdfDescriptorVersion(udfRevision <= 0x0150 ? 2 : 3) - , fUdfDomainId(udfRevision == 0x0150 ? Udf::kDomainId150 : Udf::kDomainId201) - , fDoIso(doIso) - , fIsoVolumeName(isoVolumeName) - , fRootDirectory(rootDirectory ? rootDirectory : "") - , fRootDirectoryName(rootDirectory) - , fListener(listener) - , fAllocator(blockSize) - , fPartitionAllocator(0, 257, fAllocator) - , fStatistics() - , fBuildTime(0) // set at start of Build() - , fBuildTimeStamp() // ditto - , fNextUniqueId(16) // Starts at 16 thanks to MacOS... See UDF-2.50 3.2.1 - , f32BitIdsNoLongerUnique(false) // Set to true once fNextUniqueId requires > 32bits -{ - 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) { - _PrintError("Error opening output file: 0x%lx, `%s'", error, - strerror(error)); - } - // Check the allocator - if (!error) { - error = _Allocator().InitCheck(); - if (error) { - _PrintError("Error creating block allocator: 0x%lx, `%s'", error, - strerror(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) - _PrintError("Invalid block size: %ld", blockSize); - } - // Check that at least one type of filesystem has - // been requested - if (!error) { - error = _DoUdf() || _DoIso() ? B_OK : B_BAD_VALUE; - if (error) - _PrintError("No filesystems requested."); - } - // Check the volume names - if (!error) { - if (_UdfVolumeName().Utf8Length() == 0) - _UdfVolumeName().SetTo("(Unnamed UDF Volume)"); - if (_IsoVolumeName().Utf8Length() == 0) - _IsoVolumeName().SetTo("UNNAMED_ISO"); - if (_DoUdf()) { - error = _UdfVolumeName().Cs0Length() <= 128 ? B_OK : B_ERROR; - if (error) { - _PrintError("Udf volume name too long (%ld bytes, max " - "length is 128 bytes.", - _UdfVolumeName().Cs0Length()); - } - } - if (!error && _DoIso()) { - error = _IsoVolumeName().Utf8Length() <= 32 ? B_OK : B_ERROR; - // ToDo: Should also check for illegal characters - if (error) { - _PrintError("Iso volume name too long (%ld bytes, max " - "length is 32 bytes.", - _IsoVolumeName().Cs0Length()); - } - } - } - // Check the udf revision - if (!error) { - error = _UdfRevision() == 0x0150 || _UdfRevision() == 0x0201 - ? B_OK : B_ERROR; - if (error) { - _PrintError("Invalid UDF revision 0x%04x", _UdfRevision()); - } - } - // Check the root directory - if (!error) { - error = _RootDirectory().InitCheck(); - if (error) { - _PrintError("Error initializing root directory entry: 0x%lx, `%s'", - error, strerror(error)); - } - } - - if (!error) { - fInitStatus = B_OK; - } -} - -status_t -UdfBuilder::InitCheck() const -{ - return fInitStatus; -} - -/*! \brief Builds the disc image. -*/ -status_t -UdfBuilder::Build() -{ - DEBUG_INIT("UdfBuilder"); - status_t error = InitCheck(); - if (error) - RETURN(error); - - // Note the time at which we're starting - fStatistics.Reset(); - _SetBuildTime(_Stats().StartTime()); - - // Udf variables - uint16 partitionNumber = 0; - Udf::anchor_volume_descriptor anchor256; - Udf::anchor_volume_descriptor anchorN; - Udf::extent_address primaryVdsExtent; - Udf::extent_address reserveVdsExtent; - Udf::primary_volume_descriptor primary; - Udf::partition_descriptor partition; - Udf::unallocated_space_descriptor freespace; - Udf::logical_volume_descriptor logical; - Udf::implementation_use_descriptor implementationUse; - Udf::long_address filesetAddress; - Udf::extent_address filesetExtent; - Udf::extent_address integrityExtent; - Udf::file_set_descriptor fileset; - node_data rootNode; - - // Iso variables -// Udf::extent_address rootDirentExtent; - - - _OutputFile().Seek(0, SEEK_SET); - fListener.OnStart(fRootDirectoryName.c_str(), fOutputFilename.c_str(), - _UdfVolumeName().Utf8(), _UdfRevision()); - - _PrintUpdate(VERBOSITY_LOW, "Initializing volume"); - - // Reserve the first 32KB and zero them out. - if (!error) { - _PrintUpdate(VERBOSITY_MEDIUM, "udf: Writing reserved area"); - const int reservedAreaSize = 32 * 1024; - Udf::extent_address extent(0, reservedAreaSize); - _PrintUpdate(VERBOSITY_HIGH, "udf: Reserving space for reserved area"); - error = _Allocator().GetExtent(extent); - if (!error) { - _PrintUpdate(VERBOSITY_HIGH, "udf: (location: %ld, length: %ld)", - extent.location(), extent.length()); - 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_MEDIUM, "iso: Writing primary volume descriptor"); - - // 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()) { - Udf::extent_address extent; - // Bea - _PrintUpdate(VERBOSITY_MEDIUM, "udf: Writing bea descriptor"); - _PrintUpdate(VERBOSITY_HIGH, "udf: Reserving space for bea descriptor"); - Udf::volume_structure_descriptor_header bea(0, Udf::kVSDID_BEA, 1); - error = _Allocator().GetNextExtent(vrsBlockSize, true, extent); - if (!error) { - _PrintUpdate(VERBOSITY_HIGH, "udf: (location: %ld, length: %ld)", - extent.location(), extent.length()); - 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 - _PrintUpdate(VERBOSITY_MEDIUM, "udf: Writing nsr descriptor"); - Udf::volume_structure_descriptor_header nsr(0, _UdfRevision() <= 0x0150 - ? Udf::kVSDID_ECMA167_2 - : Udf::kVSDID_ECMA167_3, - 1); - if (!error) { - _PrintUpdate(VERBOSITY_HIGH, "udf: Reserving space for nsr descriptor"); - _Allocator().GetNextExtent(vrsBlockSize, true, extent); - } - if (!error) { - _PrintUpdate(VERBOSITY_HIGH, "udf: (location: %ld, length: %ld)", - extent.location(), extent.length()); - 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 - _PrintUpdate(VERBOSITY_MEDIUM, "udf: Writing tea descriptor"); - Udf::volume_structure_descriptor_header tea(0, Udf::kVSDID_TEA, 1); - if (!error) { - _PrintUpdate(VERBOSITY_HIGH, "udf: Reserving space for tea descriptor"); - error = _Allocator().GetNextExtent(vrsBlockSize, true, extent); - } - if (!error) { - _PrintUpdate(VERBOSITY_HIGH, "udf: (location: %ld, length: %ld)", - extent.location(), extent.length()); - 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)); - } - } - - // Write the udf anchor256 and volume descriptor sequences - if (!error && _DoUdf()) { - _PrintUpdate(VERBOSITY_MEDIUM, "udf: Writing anchor256"); - // reserve anchor256 - _PrintUpdate(VERBOSITY_HIGH, "udf: Reserving space for anchor256"); - error = _Allocator().GetBlock(256); - if (!error) - _PrintUpdate(VERBOSITY_HIGH, "udf: (location: %ld, length: %ld)", - 256, _BlockSize()); - // reserve primary vds (min length = 16 blocks, which is plenty for us) - if (!error) { - _PrintUpdate(VERBOSITY_HIGH, "udf: Reserving space for primary vds"); - error = _Allocator().GetNextExtent(off_t(16) << _BlockShift(), true, primaryVdsExtent); - if (!error) { - _PrintUpdate(VERBOSITY_HIGH, "udf: (location: %ld, length: %ld)", - primaryVdsExtent.location(), primaryVdsExtent.length()); - ssize_t bytes = _OutputFile().ZeroAt(off_t(primaryVdsExtent.location()) << _BlockShift(), - primaryVdsExtent.length()); - error = check_size_error(bytes, primaryVdsExtent.length()); - } - } - // reserve reserve vds. try to grab the 16 blocks preceding block 256. if - // that fails, just grab any 16. most commercial discs just put the reserve - // vds immediately following the primary vds, which seems a bit stupid to me, - // now that I think about it... - if (!error) { - _PrintUpdate(VERBOSITY_HIGH, "udf: Reserving space for reserve vds"); - reserveVdsExtent.set_location(256-16); - reserveVdsExtent.set_length(off_t(16) << _BlockShift()); - error = _Allocator().GetExtent(reserveVdsExtent); - if (error) - error = _Allocator().GetNextExtent(off_t(16) << _BlockShift(), true, reserveVdsExtent); - if (!error) { - _PrintUpdate(VERBOSITY_HIGH, "udf: (location: %ld, length: %ld)", - reserveVdsExtent.location(), reserveVdsExtent.length()); - ssize_t bytes = _OutputFile().ZeroAt(off_t(reserveVdsExtent.location()) << _BlockShift(), - reserveVdsExtent.length()); - error = check_size_error(bytes, reserveVdsExtent.length()); - } - } - // write anchor_256 - if (!error) { - anchor256.main_vds() = primaryVdsExtent; - anchor256.reserve_vds() = reserveVdsExtent; - Udf::descriptor_tag &tag = anchor256.tag(); - tag.set_id(Udf::TAGID_ANCHOR_VOLUME_DESCRIPTOR_POINTER); - tag.set_version(_UdfDescriptorVersion()); - tag.set_serial_number(0); - tag.set_location(256); - tag.set_checksums(anchor256); - _OutputFile().Seek(off_t(256) << _BlockShift(), SEEK_SET); - 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(anchor256)); - error = check_size_error(bytes, _BlockSize()-sizeof(anchor256)); - } - } - uint32 vdsNumber = 0; - // write primary_vd - if (!error) { - _PrintUpdate(VERBOSITY_MEDIUM, "udf: Writing primary volume descriptor"); - // build primary_vd - primary.set_vds_number(vdsNumber); - primary.set_primary_volume_descriptor_number(0); - uint32 nameLength = _UdfVolumeName().Cs0Length(); - if (nameLength > primary.volume_identifier().size()-1) { - _PrintWarning("udf: Truncating volume name as stored in primary " - "volume descriptor to 31 byte limit. This shouldn't matter, " - "as the complete name is %d bytes long, which is short enough " - "to fit completely in the logical volume descriptor.", - nameLength); - } - Udf::DString volumeIdField(_UdfVolumeName(), - primary.volume_identifier().size()); - memcpy(primary.volume_identifier().data, volumeIdField.String(), - primary.volume_identifier().size()); - primary.set_volume_sequence_number(1); - primary.set_max_volume_sequence_number(1); - primary.set_interchange_level(2); - primary.set_max_interchange_level(3); - primary.set_character_set_list(1); - primary.set_max_character_set_list(1); - // first 16 chars of volume set id must be unique. first 8 must be - // a hex representation of a timestamp - char timestamp[9]; - sprintf(timestamp, "%08lX", _BuildTime()); - std::string volumeSetId(timestamp); - volumeSetId = volumeSetId + "--------" + "(unnamed volume set)"; - Udf::DString volumeSetIdField(volumeSetId.c_str(), - primary.volume_set_identifier().size()); - memcpy(primary.volume_set_identifier().data, volumeSetIdField.String(), - primary.volume_set_identifier().size()); - primary.descriptor_character_set() = Udf::kCs0CharacterSet; - primary.explanatory_character_set() = Udf::kCs0CharacterSet; - primary.volume_abstract() = kNullExtent; - primary.volume_copyright_notice() = kNullExtent; - primary.application_id() = kApplicationId; - primary.recording_date_and_time() = _BuildTimeStamp(); - primary.implementation_id() = Udf::kImplementationId; - memset(primary.implementation_use().data, 0, - primary.implementation_use().size()); - primary.set_predecessor_volume_descriptor_sequence_location(0); - primary.set_flags(0); // ToDo: maybe 1 is more appropriate? - memset(primary.reserved().data, 0, primary.reserved().size()); - primary.tag().set_id(Udf::TAGID_PRIMARY_VOLUME_DESCRIPTOR); - primary.tag().set_version(_UdfDescriptorVersion()); - primary.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(primary); - // write primary_vd to primary vds - primary.tag().set_location(primaryVdsExtent.location()+vdsNumber); - primary.tag().set_checksums(primary); - ssize_t bytes = _OutputFile().WriteAt(off_t(primary.tag().location()) << _BlockShift(), - &primary, sizeof(primary)); - error = check_size_error(bytes, sizeof(primary)); - if (!error && bytes < ssize_t(_BlockSize())) { - ssize_t bytesLeft = _BlockSize() - bytes; - bytes = _OutputFile().ZeroAt((off_t(primary.tag().location()) << _BlockShift()) - + bytes, bytesLeft); - error = check_size_error(bytes, bytesLeft); - } - // write primary_vd to reserve vds - if (!error) { - primary.tag().set_location(reserveVdsExtent.location()+vdsNumber); - primary.tag().set_checksums(primary); - ssize_t bytes = _OutputFile().WriteAt(off_t(primary.tag().location()) << _BlockShift(), - &primary, sizeof(primary)); - error = check_size_error(bytes, sizeof(primary)); - if (!error && bytes < ssize_t(_BlockSize())) { - ssize_t bytesLeft = _BlockSize() - bytes; - bytes = _OutputFile().ZeroAt(off_t((primary.tag().location()) << _BlockShift()) - + bytes, bytesLeft); - error = check_size_error(bytes, bytesLeft); - } - } - } - - // write partition descriptor - if (!error) { - _PrintUpdate(VERBOSITY_MEDIUM, "udf: Writing partition descriptor"); - // build partition descriptor - vdsNumber++; - partition.set_vds_number(vdsNumber); - partition.set_partition_flags(1); - partition.set_partition_number(partitionNumber); - partition.partition_contents() = _UdfRevision() <= 0x0150 - ? Udf::kPartitionContentsId1xx - : Udf::kPartitionContentsId2xx; - memset(partition.partition_contents_use().data, 0, - partition.partition_contents_use().size()); - partition.set_access_type(Udf::ACCESS_READ_ONLY); - partition.set_start(_Allocator().Tail()); - partition.set_length(0); - // Can't set the length till we've built most of rest of the image, - // so we'll set it to 0 now and fix it once we know how big - // the partition really is. - partition.implementation_id() = Udf::kImplementationId; - memset(partition.implementation_use().data, 0, - partition.implementation_use().size()); - memset(partition.reserved().data, 0, - partition.reserved().size()); - partition.tag().set_id(Udf::TAGID_PARTITION_DESCRIPTOR); - partition.tag().set_version(_UdfDescriptorVersion()); - partition.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(partition); - // write partition descriptor to primary vds - partition.tag().set_location(primaryVdsExtent.location()+vdsNumber); - partition.tag().set_checksums(partition); - ssize_t bytes = _OutputFile().WriteAt(off_t(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((off_t(partition.tag().location()) << _BlockShift()) - + bytes, bytesLeft); - error = check_size_error(bytes, bytesLeft); - } - // write partition descriptor to reserve vds - if (!error) { - partition.tag().set_location(reserveVdsExtent.location()+vdsNumber); - partition.tag().set_checksums(partition); - ssize_t bytes = _OutputFile().WriteAt(off_t(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((off_t(partition.tag().location()) << _BlockShift()) - + bytes, bytesLeft); - error = check_size_error(bytes, bytesLeft); - } - } - } - - // write unallocated space descriptor - if (!error) { - _PrintUpdate(VERBOSITY_MEDIUM, "udf: Writing unallocated space descriptor"); - // build freespace descriptor - vdsNumber++; - freespace.set_vds_number(vdsNumber); - freespace.set_allocation_descriptor_count(0); - freespace.tag().set_id(Udf::TAGID_UNALLOCATED_SPACE_DESCRIPTOR); - freespace.tag().set_version(_UdfDescriptorVersion()); - freespace.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(freespace); - // write freespace descriptor to primary vds - freespace.tag().set_location(primaryVdsExtent.location()+vdsNumber); - freespace.tag().set_checksums(freespace); - ssize_t bytes = _OutputFile().WriteAt(off_t(freespace.tag().location()) << _BlockShift(), - &freespace, sizeof(freespace)); - error = check_size_error(bytes, sizeof(freespace)); - if (!error && bytes < ssize_t(_BlockSize())) { - ssize_t bytesLeft = _BlockSize() - bytes; - bytes = _OutputFile().ZeroAt((off_t(freespace.tag().location()) << _BlockShift()) - + bytes, bytesLeft); - error = check_size_error(bytes, bytesLeft); - } - // write freespace descriptor to reserve vds - if (!error) { - freespace.tag().set_location(reserveVdsExtent.location()+vdsNumber); - freespace.tag().set_checksums(freespace); - ssize_t bytes = _OutputFile().WriteAt(off_t(freespace.tag().location()) << _BlockShift(), - &freespace, sizeof(freespace)); - error = check_size_error(bytes, sizeof(freespace)); - if (!error && bytes < ssize_t(_BlockSize())) { - ssize_t bytesLeft = _BlockSize() - bytes; - bytes = _OutputFile().ZeroAt((off_t(freespace.tag().location()) << _BlockShift()) - + bytes, bytesLeft); - error = check_size_error(bytes, bytesLeft); - } - } - } - - // 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) { - Udf::DString volumeIdField(_UdfVolumeName(), - logical.logical_volume_identifier().size()); - memcpy(logical.logical_volume_identifier().data, volumeIdField.String(), - logical.logical_volume_identifier().size()); - logical.set_logical_block_size(_BlockSize()); - logical.domain_id() = _UdfDomainId(); - memset(logical.logical_volume_contents_use().data, 0, - logical.logical_volume_contents_use().size()); - // Allocate a block for the file set descriptor - _PrintUpdate(VERBOSITY_HIGH, "udf: Reserving space for file set descriptor"); - error = _PartitionAllocator().GetNextExtent(_BlockSize(), true, - filesetAddress, filesetExtent); - if (!error) { - _PrintUpdate(VERBOSITY_HIGH, "udf: (partition: %d, location: %ld, " - "length: %ld) => (location: %ld, length: %ld)", - filesetAddress.partition(), filesetAddress.block(), - filesetAddress.length(), filesetExtent.location(), - filesetExtent.length()); - } - } - 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(_UdfDescriptorVersion()); - 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(primaryVdsExtent.location()+vdsNumber); - logical.tag().set_checksums(logical, logicalSize); - ssize_t bytes = _OutputFile().WriteAt(off_t(logical.tag().location()) << _BlockShift(), - &logical, logicalSize); - error = check_size_error(bytes, logicalSize); - if (!error && bytes < ssize_t(_BlockSize())) { - ssize_t bytesLeft = _BlockSize() - bytes; - bytes = _OutputFile().ZeroAt((off_t(logical.tag().location()) << _BlockShift()) - + bytes, bytesLeft); - error = check_size_error(bytes, bytesLeft); - } - // write logical descriptor to reserve vds - if (!error) { - logical.tag().set_location(reserveVdsExtent.location()+vdsNumber); - logical.tag().set_checksums(logical, logicalSize); - ssize_t bytes = _OutputFile().WriteAt(off_t(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((off_t(logical.tag().location()) << _BlockShift()) - + bytes, bytesLeft); - error = check_size_error(bytes, bytesLeft); - } - } - } - } - - // write implementation use descriptor - if (!error) { - _PrintUpdate(VERBOSITY_MEDIUM, "udf: Writing implementation use descriptor"); - // build implementationUse descriptor - vdsNumber++; - implementationUse.set_vds_number(vdsNumber); - switch (_UdfRevision()) { - case 0x0150: - implementationUse.implementation_id() = Udf::kLogicalVolumeInfoId150; - break; - case 0x0201: - implementationUse.implementation_id() = Udf::kLogicalVolumeInfoId201; - break; - default: - _PrintError("Invalid udf revision: 0x04x", _UdfRevision()); - error = B_ERROR; - } - ssize_t bytes = 0; - if (!error) { - Udf::logical_volume_info &info = implementationUse.info(); - info.character_set() = Udf::kCs0CharacterSet; - Udf::DString logicalVolumeId(_UdfVolumeName(), - info.logical_volume_id().size()); - memcpy(info.logical_volume_id().data, logicalVolumeId.String(), - info.logical_volume_id().size()); - Udf::DString info1("Logical Volume Info #1", - info.logical_volume_info_1().size()); - memcpy(info.logical_volume_info_1().data, info1.String(), - info.logical_volume_info_1().size()); - Udf::DString info2("Logical Volume Info #2", - info.logical_volume_info_2().size()); - memcpy(info.logical_volume_info_2().data, info2.String(), - info.logical_volume_info_2().size()); - Udf::DString info3("Logical Volume Info #3", - info.logical_volume_info_3().size()); - memcpy(info.logical_volume_info_3().data, info3.String(), - info.logical_volume_info_3().size()); - info.implementation_id() = Udf::kImplementationId; - memset(info.implementation_use().data, 0, info.implementation_use().size()); - implementationUse.tag().set_id(Udf::TAGID_IMPLEMENTATION_USE_VOLUME_DESCRIPTOR); - implementationUse.tag().set_version(_UdfDescriptorVersion()); - implementationUse.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(implementationUse); - // write implementationUse descriptor to primary vds - implementationUse.tag().set_location(primaryVdsExtent.location()+vdsNumber); - implementationUse.tag().set_checksums(implementationUse); - bytes = _OutputFile().WriteAt(off_t(implementationUse.tag().location()) << _BlockShift(), - &implementationUse, sizeof(implementationUse)); - error = check_size_error(bytes, sizeof(implementationUse)); - } - if (!error && bytes < ssize_t(_BlockSize())) { - ssize_t bytesLeft = _BlockSize() - bytes; - bytes = _OutputFile().ZeroAt((off_t(implementationUse.tag().location()) << _BlockShift()) - + bytes, bytesLeft); - error = check_size_error(bytes, bytesLeft); - } - // write implementationUse descriptor to reserve vds - if (!error) { - implementationUse.tag().set_location(reserveVdsExtent.location()+vdsNumber); - implementationUse.tag().set_checksums(implementationUse); - ssize_t bytes = _OutputFile().WriteAt(off_t(implementationUse.tag().location()) << _BlockShift(), - &implementationUse, sizeof(implementationUse)); - error = check_size_error(bytes, sizeof(implementationUse)); - if (!error && bytes < ssize_t(_BlockSize())) { - ssize_t bytesLeft = _BlockSize() - bytes; - bytes = _OutputFile().ZeroAt((off_t(implementationUse.tag().location()) << _BlockShift()) - + bytes, bytesLeft); - error = check_size_error(bytes, bytesLeft); - } - } - } - - // write terminating descriptor - if (!error) { - vdsNumber++; - Udf::terminating_descriptor terminator; - terminator.tag().set_id(Udf::TAGID_TERMINATING_DESCRIPTOR); - terminator.tag().set_version(_UdfDescriptorVersion()); - terminator.tag().set_serial_number(0); - terminator.tag().set_location(integrityExtent.location()+1); - terminator.tag().set_checksums(terminator); - DUMP(terminator); - // write terminator to primary vds - terminator.tag().set_location(primaryVdsExtent.location()+vdsNumber); - terminator.tag().set_checksums(terminator); - ssize_t bytes = _OutputFile().WriteAt(off_t(terminator.tag().location()) << _BlockShift(), - &terminator, sizeof(terminator)); - error = check_size_error(bytes, sizeof(terminator)); - if (!error && bytes < ssize_t(_BlockSize())) { - ssize_t bytesLeft = _BlockSize() - bytes; - bytes = _OutputFile().ZeroAt((off_t(terminator.tag().location()) << _BlockShift()) - + bytes, bytesLeft); - error = check_size_error(bytes, bytesLeft); - } - // write terminator to reserve vds - if (!error) { - terminator.tag().set_location(reserveVdsExtent.location()+vdsNumber); - terminator.tag().set_checksums(terminator); - ssize_t bytes = _OutputFile().WriteAt(off_t(terminator.tag().location()) << _BlockShift(), - &terminator, sizeof(terminator)); - error = check_size_error(bytes, sizeof(terminator)); - if (!error && bytes < ssize_t(_BlockSize())) { - ssize_t bytesLeft = _BlockSize() - bytes; - bytes = _OutputFile().ZeroAt((off_t(terminator.tag().location()) << _BlockShift()) - + bytes, bytesLeft); - error = check_size_error(bytes, bytesLeft); - } - } - } - - // Error check - if (error) { - _PrintError("Error writing udf vds: 0x%lx, `%s'", - error, strerror(error)); - } - } - - // Write the file set descriptor - if (!error) { - _PrintUpdate(VERBOSITY_MEDIUM, "udf: Writing file set descriptor"); - fileset.recording_date_and_time() = _BuildTimeStamp(); - fileset.set_interchange_level(3); - fileset.set_max_interchange_level(3); - fileset.set_character_set_list(1); - fileset.set_max_character_set_list(1); - fileset.set_file_set_number(0); - fileset.set_file_set_descriptor_number(0); - fileset.logical_volume_id_character_set() = Udf::kCs0CharacterSet; - Udf::DString volumeIdField(_UdfVolumeName(), - fileset.logical_volume_id().size()); - memcpy(fileset.logical_volume_id().data, volumeIdField.String(), - fileset.logical_volume_id().size()); - fileset.file_set_id_character_set() = Udf::kCs0CharacterSet; - Udf::DString filesetIdField(_UdfVolumeName(), - fileset.file_set_id().size()); - memcpy(fileset.file_set_id().data, filesetIdField.String(), - fileset.file_set_id().size()); - memset(fileset.copyright_file_id().data, 0, - fileset.copyright_file_id().size()); - memset(fileset.abstract_file_id().data, 0, - fileset.abstract_file_id().size()); - fileset.root_directory_icb() = kNullAddress; - fileset.domain_id() = _UdfDomainId(); - fileset.next_extent() = kNullAddress; - fileset.system_stream_directory_icb() = kNullAddress; - memset(fileset.reserved().data, 0, - fileset.reserved().size()); - fileset.tag().set_id(Udf::TAGID_FILE_SET_DESCRIPTOR); - fileset.tag().set_version(_UdfDescriptorVersion()); - fileset.tag().set_serial_number(0); - fileset.tag().set_location(filesetAddress.block()); - fileset.tag().set_checksums(fileset); - DUMP(fileset); - // write fsd - ssize_t bytes = _OutputFile().WriteAt(off_t(filesetExtent.location()) << _BlockShift(), - &fileset, sizeof(fileset)); - error = check_size_error(bytes, sizeof(fileset)); - if (!error && bytes < ssize_t(_BlockSize())) { - ssize_t bytesLeft = _BlockSize() - bytes; - bytes = _OutputFile().ZeroAt((off_t(filesetExtent.location()) << _BlockShift()) - + bytes, bytesLeft); - error = check_size_error(bytes, bytesLeft); - } - } - - // Build the rest of the image - if (!error) { - struct stat rootStats; - error = _RootDirectory().GetStat(&rootStats); - if (!error) - error = _ProcessDirectory(_RootDirectory(), "/", rootStats, rootNode, - kNullAddress, true); - } - - if (!error) - _PrintUpdate(VERBOSITY_LOW, "Finalizing volume"); - - // Rewrite the fsd with the root dir icb - if (!error) { - _PrintUpdate(VERBOSITY_MEDIUM, "udf: Finalizing file set descriptor"); - fileset.root_directory_icb() = rootNode.icbAddress; - fileset.tag().set_checksums(fileset); - DUMP(fileset); - // write fsd - ssize_t bytes = _OutputFile().WriteAt(off_t(filesetExtent.location()) << _BlockShift(), - &fileset, sizeof(fileset)); - error = check_size_error(bytes, sizeof(fileset)); - if (!error && bytes < ssize_t(_BlockSize())) { - ssize_t bytesLeft = _BlockSize() - bytes; - bytes = _OutputFile().ZeroAt((off_t(filesetExtent.location()) << _BlockShift()) - + bytes, bytesLeft); - error = check_size_error(bytes, bytesLeft); - } - } - - // Set the final 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(primaryVdsExtent.location()+partition.vds_number()); - partition.tag().set_checksums(partition); - ssize_t bytes = _OutputFile().WriteAt(off_t(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((off_t(partition.tag().location()) << _BlockShift()) - + bytes, bytesLeft); - error = check_size_error(bytes, bytesLeft); - } - // write partition descriptor to reserve vds - if (!error) { - partition.tag().set_location(reserveVdsExtent.location()+partition.vds_number()); - partition.tag().set_checksums(partition); - ssize_t bytes = _OutputFile().WriteAt(off_t(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((off_t(partition.tag().location()) << _BlockShift()) - + bytes, bytesLeft); - error = check_size_error(bytes, bytesLeft); - } - } - // Error check - if (error) { - _PrintError("Error writing udf vds: 0x%lx, `%s'", - error, strerror(error)); - } - } - - // Write the integrity sequence - if (!error && _DoUdf()) { - _PrintUpdate(VERBOSITY_MEDIUM, "udf: Writing logical volume integrity sequence"); - Udf::MemoryChunk chunk(_BlockSize()); - error = chunk.InitCheck(); - // write closed integrity descriptor - if (!error) { - memset(chunk.Data(), 0, _BlockSize()); - Udf::logical_volume_integrity_descriptor *lvid = - reinterpret_cast(chunk.Data()); - lvid->recording_time() = Udf::timestamp(real_time_clock()); - // recording time must be later than all file access times - lvid->set_integrity_type(Udf::INTEGRITY_CLOSED); - lvid->next_integrity_extent() = kNullExtent; - memset(lvid->logical_volume_contents_use().data, 0, - lvid->logical_volume_contents_use().size()); - lvid->set_next_unique_id(_NextUniqueId()); - lvid->set_partition_count(1); - lvid->set_implementation_use_length( - Udf::logical_volume_integrity_descriptor::minimum_implementation_use_length); - lvid->free_space_table()[0] = 0; - lvid->size_table()[0] = _PartitionAllocator().Length(); - lvid->implementation_id() = Udf::kImplementationId; - lvid->set_file_count(_Stats().Files()); - lvid->set_directory_count(_Stats().Directories()); - lvid->set_minimum_udf_read_revision(_UdfRevision()); - lvid->set_minimum_udf_write_revision(_UdfRevision()); - lvid->set_maximum_udf_write_revision(_UdfRevision()); - lvid->tag().set_id(Udf::TAGID_LOGICAL_VOLUME_INTEGRITY_DESCRIPTOR); - lvid->tag().set_version(_UdfDescriptorVersion()); - lvid->tag().set_serial_number(0); - lvid->tag().set_location(integrityExtent.location()); - lvid->tag().set_checksums(*lvid, lvid->descriptor_size()); - PDUMP(lvid); - // write lvid - ssize_t bytes = _OutputFile().WriteAt(off_t(integrityExtent.location()) << _BlockShift(), - lvid, _BlockSize()); - error = check_size_error(bytes, _BlockSize()); - } - // write terminating descriptor - if (!error) { - memset(chunk.Data(), 0, _BlockSize()); - Udf::terminating_descriptor *terminator = - reinterpret_cast(chunk.Data()); - terminator->tag().set_id(Udf::TAGID_TERMINATING_DESCRIPTOR); - terminator->tag().set_version(_UdfDescriptorVersion()); - terminator->tag().set_serial_number(0); - terminator->tag().set_location(integrityExtent.location()+1); - terminator->tag().set_checksums(*terminator); - PDUMP(terminator); - // write terminator - ssize_t bytes = _OutputFile().WriteAt(off_t((integrityExtent.location()+1)) << _BlockShift(), - terminator, _BlockSize()); - error = check_size_error(bytes, _BlockSize()); - } - } - - // reserve and write anchorN - if (!error) { - _PrintUpdate(VERBOSITY_MEDIUM, "udf: Writing anchorN"); - _PrintUpdate(VERBOSITY_HIGH, "udf: Reserving space for anchorN"); - uint32 blockN = _Allocator().Tail(); - error = _Allocator().GetBlock(blockN); - if (!error) - _PrintUpdate(VERBOSITY_HIGH, "udf: (location: %ld, length: %ld)", - blockN, _BlockSize()); - if (!error) { - anchorN.main_vds() = primaryVdsExtent; - anchorN.reserve_vds() = reserveVdsExtent; - Udf::descriptor_tag &tag = anchorN.tag(); - tag.set_id(Udf::TAGID_ANCHOR_VOLUME_DESCRIPTOR_POINTER); - tag.set_version(_UdfDescriptorVersion()); - tag.set_serial_number(0); - tag.set_location(blockN); - tag.set_checksums(anchorN); - _OutputFile().Seek(off_t(blockN) << _BlockShift(), SEEK_SET); - ssize_t bytes = _OutputFile().Write(&anchorN, sizeof(anchorN)); - error = check_size_error(bytes, sizeof(anchorN)); - if (!error && bytes < ssize_t(_BlockSize())) { - bytes = _OutputFile().Zero(_BlockSize()-sizeof(anchorN)); - error = check_size_error(bytes, _BlockSize()-sizeof(anchorN)); - } - } - } - - // NOTE: After this point, no more blocks may be allocated without jacking - // up anchorN's position as the last block in the volume. So don't allocate - // any, damn it. - - // Pad the end of the file to an even multiple of the block - // size, if necessary - if (!error) { - _OutputFile().Seek(0, SEEK_END); - uint32 tail = _OutputFile().Position() % _BlockSize(); - if (tail > 0) { - uint32 padding = _BlockSize() - tail; - ssize_t bytes = _OutputFile().Zero(padding); - error = check_size_error(bytes, padding); - } - if (!error) - _Stats().SetImageSize(_OutputFile().Position()); - } - - if (!error) { - _PrintUpdate(VERBOSITY_LOW, "Flushing image data"); - _OutputFile().Flush(); - } - - fListener.OnCompletion(error, _Stats()); - RETURN(error); -} - -/*! \brief Returns the next unique id, then increments the id (the lower - 32-bits of which wrap to 16 instead of 0, per UDF-2.50 3.2.1.1). -*/ -uint64 -UdfBuilder::_NextUniqueId() -{ - uint64 result = fNextUniqueId++; - if ((fNextUniqueId & 0xffffffff) == 0) { - fNextUniqueId |= 0x10; - f32BitIdsNoLongerUnique = true; - } - return result; -} - -/*! \brief Sets the time at which image building began. -*/ -void -UdfBuilder::_SetBuildTime(time_t time) -{ - fBuildTime = time; - Udf::timestamp stamp(time); - fBuildTimeStamp = stamp; -} - -/*! \brief Uses vsprintf() to output the given format string and arguments - into the given message string. - - va_start() must be called prior to calling this function to obtain the - \a arguments parameter, but va_end() must *not* be called upon return, - as this function takes the liberty of doing so for you. -*/ -status_t -UdfBuilder::_FormatString(char *message, const char *formatString, va_list arguments) const -{ - status_t error = message && formatString ? B_OK : B_BAD_VALUE; - if (!error) { - vsprintf(message, formatString, arguments); - va_end(arguments); - } - return error; -} - -/*! \brief Outputs a printf()-style error message to the listener. -*/ -void -UdfBuilder::_PrintError(const char *formatString, ...) const -{ - if (!formatString) { - DEBUG_INIT_ETC("UdfBuilder", ("formatString: `%s'", formatString)); - PRINT(("ERROR: _PrintError() called with NULL format string!\n")); - return; - } - char message[kMaxUpdateStringLength]; - va_list arguments; - va_start(arguments, formatString); - status_t error = _FormatString(message, formatString, arguments); - if (!error) - fListener.OnError(message); -} - -/*! \brief Outputs a printf()-style warning message to the listener. -*/ -void -UdfBuilder::_PrintWarning(const char *formatString, ...) const -{ - if (!formatString) { - DEBUG_INIT_ETC("UdfBuilder", ("formatString: `%s'", formatString)); - PRINT(("ERROR: _PrintWarning() called with NULL format string!\n")); - return; - } - char message[kMaxUpdateStringLength]; - va_list arguments; - va_start(arguments, formatString); - status_t error = _FormatString(message, formatString, arguments); - if (!error) - fListener.OnWarning(message); -} - -/*! \brief Outputs a printf()-style update message to the listener - at the given verbosity level. -*/ -void -UdfBuilder::_PrintUpdate(VerbosityLevel level, const char *formatString, ...) const -{ - if (!formatString) { - DEBUG_INIT_ETC("UdfBuilder", ("level: %d, formatString: `%s'", - level, formatString)); - PRINT(("ERROR: _PrintUpdate() called with NULL format string!\n")); - return; - } - char message[kMaxUpdateStringLength]; - va_list arguments; - va_start(arguments, formatString); - status_t error = _FormatString(message, formatString, arguments); - if (!error) - fListener.OnUpdate(level, message); -} - -/*! \brief Processes the given directory and its children. - - \param entry The directory to process. - \param path Pathname of the directory with respect to the fileset - in construction. - \param node Output parameter into which the icb address and dataspace - information for the processed directory is placed. - \param isRootDirectory Used to signal that the directory being processed - is the root directory, since said directory has - a special unique id assigned to it. -*/ -status_t -UdfBuilder::_ProcessDirectory(BEntry &entry, const char *path, struct stat stats, - node_data &node, Udf::long_address parentIcbAddress, - bool isRootDirectory) -{ - DEBUG_INIT_ETC("UdfBuilder", ("path: `%s'", path)); - uint32 udfDataLength = 0; - uint64 udfUniqueId = isRootDirectory ? 0 : _NextUniqueId(); - // file entry id must be numerically lower than unique id's - // in all fids that reference it, thus we allocate it now. - status_t error = entry.InitCheck() == B_OK && path ? B_OK : B_BAD_VALUE; - if (!error) { - _PrintUpdate(VERBOSITY_LOW, "Adding `%s'", path); - BDirectory directory(&entry); - error = directory.InitCheck(); - if (!error) { - - // Max length of a udf file identifier Cs0 string - const uint32 maxUdfIdLength = _BlockSize() - (38); - - _PrintUpdate(VERBOSITY_MEDIUM, "Gathering statistics"); - - // Figure out how many file identifier characters we have - // for each filesystem - uint32 entries = 0; - //uint32 isoChars = 0; - while (error == B_OK) { - BEntry childEntry; - error = directory.GetNextEntry(&childEntry); - if (error == B_ENTRY_NOT_FOUND) { - error = B_OK; - break; - } - if (!error) - error = childEntry.InitCheck(); - if (!error) { - BPath childPath; - error = childEntry.GetPath(&childPath); - if (!error) - error = childPath.InitCheck(); - // Skip symlinks until we add symlink support; this - // allows graceful skipping of them later on instead - // of stopping with a fatal error - struct stat childStats; - if (!error) - error = childEntry.GetStat(&childStats); - if (!error && S_ISLNK(childStats.st_mode)) - continue; - if (!error) { - _PrintUpdate(VERBOSITY_MEDIUM, "found child: `%s'", childPath.Leaf()); - entries++; - // Determine udf char count - Udf::String name(childPath.Leaf()); - uint32 udfLength = name.Cs0Length(); - udfLength = maxUdfIdLength >= udfLength - ? udfLength : maxUdfIdLength; - Udf::file_id_descriptor id; - id.set_id_length(udfLength); - id.set_implementation_use_length(0); - udfDataLength += id.total_length(); - // Determine iso char count - // isoChars += ??? - } - } - } - -// entries = 0; -// udfChars = 0; - - // Include parent directory entry in data length calculation - if (!error) { - Udf::file_id_descriptor id; - id.set_id_length(0); - id.set_implementation_use_length(0); - udfDataLength += id.total_length(); - } - - _PrintUpdate(VERBOSITY_MEDIUM, "children: %ld", entries); - _PrintUpdate(VERBOSITY_MEDIUM, "udf: data length: %ld", udfDataLength); - - // Reserve iso dir entry space - - // Reserve udf icb space - Udf::long_address icbAddress; - Udf::extent_address icbExtent; - if (!error && _DoUdf()) { - _PrintUpdate(VERBOSITY_MEDIUM, "udf: Reserving space for icb"); - error = _PartitionAllocator().GetNextExtent(_BlockSize(), true, icbAddress, - icbExtent); - if (!error) { - _PrintUpdate(VERBOSITY_HIGH, "udf: (partition: %d, location: %ld, " - "length: %ld) => (location: %ld, length: %ld)", - icbAddress.partition(), icbAddress.block(), - icbAddress.length(), icbExtent.location(), - icbExtent.length()); - node.icbAddress = icbAddress; - } - } - - DataStream *udfData = NULL; - std::list udfDataExtents; - std::list &udfDataAddresses = node.udfData; - - // Reserve udf dir data space - if (!error && _DoUdf()) { - _PrintUpdate(VERBOSITY_MEDIUM, "udf: Reserving space for directory data"); - error = _PartitionAllocator().GetNextExtents(udfDataLength, udfDataAddresses, - udfDataExtents); - if (!error) { - int extents = udfDataAddresses.size(); - if (extents > 1) - _PrintUpdate(VERBOSITY_HIGH, "udf: Reserved %d extents", - extents); - std::list::iterator a; - std::list::iterator e; - for (a = udfDataAddresses.begin(), e = udfDataExtents.begin(); - a != udfDataAddresses.end() && e != udfDataExtents.end(); - a++, e++) - { - _PrintUpdate(VERBOSITY_HIGH, "udf: (partition: %d, location: %ld, " - "length: %ld) => (location: %ld, length: %ld)", - a->partition(), a->block(), a->length(), e->location(), - e->length()); - } - } - if (!error) { - udfData = new(nothrow) ExtentStream(_OutputFile(), udfDataExtents, _BlockSize()); - error = udfData ? B_OK : B_NO_MEMORY; - } - } - - uint32 udfAllocationDescriptorsLength = udfDataAddresses.size() - * sizeof(Udf::long_address); - - // Process attributes - uint16 attributeCount = 0; - - // Write iso parent directory - - // Write udf parent directory fid - if (!error && _DoUdf()) { - Udf::MemoryChunk chunk((38) + 4); - error = chunk.InitCheck(); - if (!error) { - memset(chunk.Data(), 0, (38) + 4); - Udf::file_id_descriptor *parent = - reinterpret_cast(chunk.Data()); - parent->set_version_number(1); - // Clear characteristics to false, then set - // those that need to be true - parent->set_characteristics(0); - parent->set_is_directory(true); - parent->set_is_parent(true); - parent->set_id_length(0); - parent->icb() = isRootDirectory ? icbAddress : parentIcbAddress; - if (!isRootDirectory) - parent->icb().set_unique_id(uint32(_NextUniqueId())); - parent->set_implementation_use_length(0); - parent->tag().set_id(Udf::TAGID_FILE_ID_DESCRIPTOR); - parent->tag().set_version(_UdfDescriptorVersion()); - parent->tag().set_serial_number(0); - uint32 block; - error = block_for_offset(udfData->Position(), udfDataAddresses, - _BlockSize(), block); - if (!error) { - parent->tag().set_location(block); - parent->tag().set_checksums(*parent, parent->descriptor_size()); - ssize_t bytes = udfData->Write(parent, parent->total_length()); - error = check_size_error(bytes, parent->total_length()); - } - } - } - - // Process children - uint16 childDirCount = 0; - if (!error) - error = directory.Rewind(); - while (error == B_OK) { - BEntry childEntry; - error = directory.GetNextEntry(&childEntry); - if (error == B_ENTRY_NOT_FOUND) { - error = B_OK; - break; - } - if (!error) - error = childEntry.InitCheck(); - if (!error) { - BPath childPath; - error = childEntry.GetPath(&childPath); - if (!error) - error = childPath.InitCheck(); - struct stat childStats; - if (!error) - error = childEntry.GetStat(&childStats); - if (!error) { - node_data childNode; - std::string childImagePath(path); - childImagePath += (childImagePath[childImagePath.length()-1] == '/' - ? "" : "/"); - childImagePath += childPath.Leaf(); - // Process child - if (S_ISREG(childStats.st_mode)) { - // Regular file - error = _ProcessFile(childEntry, childImagePath.c_str(), - childStats, childNode); - } else if (S_ISDIR(childStats.st_mode)) { - // Directory - error = _ProcessDirectory(childEntry, childImagePath.c_str(), - childStats, childNode, icbAddress); - if (!error) - childDirCount++; - } else if (S_ISLNK(childStats.st_mode)) { - // Symlink - // For now, skip it - _Stats().AddSymlink(); - _PrintWarning("No symlink support yet; skipping symlink: `%s'", - childImagePath.c_str()); - continue; - } - - // Write iso direntry - - // Write udf fid - if (!error) { - Udf::String udfName(childPath.Leaf()); - uint32 udfNameLength = udfName.Cs0Length(); - uint32 idLength = (38) - + udfNameLength; - Udf::MemoryChunk chunk(idLength + 4); - error = chunk.InitCheck(); - if (!error) { - memset(chunk.Data(), 0, idLength + 4); - Udf::file_id_descriptor *id = - reinterpret_cast(chunk.Data()); - id->set_version_number(1); - // Clear characteristics to false, then set - // those that need to be true - id->set_characteristics(0); - id->set_is_directory(S_ISDIR(childStats.st_mode)); - id->set_is_parent(false); - id->set_id_length(udfNameLength); - id->icb() = childNode.icbAddress; - id->icb().set_unique_id(uint32(_NextUniqueId())); - id->set_implementation_use_length(0); - memcpy(id->id(), udfName.Cs0(), udfNameLength); - id->tag().set_id(Udf::TAGID_FILE_ID_DESCRIPTOR); - id->tag().set_version(_UdfDescriptorVersion()); - id->tag().set_serial_number(0); - uint32 block; - error = block_for_offset(udfData->Position(), udfDataAddresses, - _BlockSize(), block); - if (!error) { - id->tag().set_location(block); - id->tag().set_checksums(*id, id->descriptor_size()); - PDUMP(id); - PRINT(("pos: %Ld\n", udfData->Position())); - ssize_t bytes = udfData->Write(id, id->total_length()); - PRINT(("pos: %Ld\n", udfData->Position())); - error = check_size_error(bytes, id->total_length()); - } - } - } - } - } - } - - // Build and write udf icb - Udf::MemoryChunk chunk(_BlockSize()); - if (!error) - error = chunk.InitCheck(); - if (!error) { - memset(chunk.Data(), 0, _BlockSize()); - uint8 fileType = Udf::ICB_TYPE_DIRECTORY; - uint16 linkCount = 1 + attributeCount + childDirCount; - if (_UdfRevision() <= 0x0150) { - error = _WriteFileEntry( - reinterpret_cast(chunk.Data()), - fileType, linkCount, udfDataLength, udfDataLength, - stats, udfUniqueId, udfAllocationDescriptorsLength, - Udf::TAGID_FILE_ENTRY, - icbAddress, icbExtent, udfDataAddresses - ); - } else { - error = _WriteFileEntry( - reinterpret_cast(chunk.Data()), - fileType, linkCount, udfDataLength, udfDataLength, - stats, udfUniqueId, udfAllocationDescriptorsLength, - Udf::TAGID_EXTENDED_FILE_ENTRY, - icbAddress, icbExtent, udfDataAddresses - ); - } - } - - delete udfData; - udfData = NULL; - } - } - - if (!error) { - _Stats().AddDirectory(); - uint32 totalLength = udfDataLength + _BlockSize(); - _Stats().AddDirectoryBytes(totalLength); - } - RETURN(error); -} - -status_t -UdfBuilder::_ProcessFile(BEntry &entry, const char *path, struct stat stats, - node_data &node) -{ - DEBUG_INIT_ETC("UdfBuilder", ("path: `%s'", path)); - status_t error = entry.InitCheck() == B_OK && path ? B_OK : B_BAD_VALUE; - off_t udfDataLength = stats.st_size; - if (udfDataLength > ULONG_MAX && _DoIso()) { - _PrintError("File `%s' too large for iso9660 filesystem (filesize: %Lu bytes, max: %lu bytes)", - path, udfDataLength, ULONG_MAX); - error = B_ERROR; - } - if (!error) { - _PrintUpdate(VERBOSITY_LOW, "Adding `%s' (%s)", path, - bytes_to_string(stats.st_size).c_str()); - BFile file(&entry, B_READ_ONLY); - error = file.InitCheck(); - if (!error) { - // Reserve udf icb space - Udf::long_address icbAddress; - Udf::extent_address icbExtent; - if (!error && _DoUdf()) { - _PrintUpdate(VERBOSITY_MEDIUM, "udf: Reserving space for icb"); - error = _PartitionAllocator().GetNextExtent(_BlockSize(), true, icbAddress, - icbExtent); - if (!error) { - _PrintUpdate(VERBOSITY_HIGH, "udf: (partition: %d, location: %ld, " - "length: %ld) => (location: %ld, length: %ld)", - icbAddress.partition(), icbAddress.block(), - icbAddress.length(), icbExtent.location(), - icbExtent.length()); - node.icbAddress = icbAddress; - } - } - - DataStream *udfData = NULL; - std::list udfDataExtents; - std::list &udfDataAddresses = node.udfData; - - // Reserve iso/udf data space - if (!error) { - _PrintUpdate(VERBOSITY_MEDIUM, "Reserving space for file data"); - if (_DoIso()) { - // Reserve a contiguous extent, as iso requires - Udf::long_address address; - Udf::extent_address extent; - error = _PartitionAllocator().GetNextExtent(udfDataLength, true, address, extent); - if (!error) { - udfDataAddresses.empty(); // just in case - udfDataAddresses.push_back(address); - udfDataExtents.push_back(extent); - } - } else { - // Udf can handle multiple extents if necessary - error = _PartitionAllocator().GetNextExtents(udfDataLength, udfDataAddresses, - udfDataExtents); - } - if (!error) { - int extents = udfDataAddresses.size(); - if (extents > 1) - _PrintUpdate(VERBOSITY_HIGH, "udf: Reserved %d extents", - extents); - std::list::iterator a; - std::list::iterator e; - for (a = udfDataAddresses.begin(), e = udfDataExtents.begin(); - a != udfDataAddresses.end() && e != udfDataExtents.end(); - a++, e++) - { - _PrintUpdate(VERBOSITY_HIGH, "udf: (partition: %d, location: %ld, " - "length: %ld) => (location: %ld, length: %ld)", - a->partition(), a->block(), a->length(), e->location(), - e->length()); - } - } - if (!error) { - udfData = new(nothrow) ExtentStream(_OutputFile(), udfDataExtents, _BlockSize()); - error = udfData ? B_OK : B_NO_MEMORY; - } - } - - uint32 udfAllocationDescriptorsLength = udfDataAddresses.size() - * sizeof(Udf::long_address); - - // Process attributes - uint16 attributeCount = 0; - - // Write file data - if (!error) { - _PrintUpdate(VERBOSITY_MEDIUM, "Writing file data"); - ssize_t bytes = udfData->Write(file, udfDataLength); - error = check_size_error(bytes, udfDataLength); - } - - // Build and write udf icb - Udf::MemoryChunk chunk(_BlockSize()); - if (!error) - error = chunk.InitCheck(); - if (!error) { - memset(chunk.Data(), 0, _BlockSize()); - uint8 fileType = Udf::ICB_TYPE_REGULAR_FILE; - uint16 linkCount = 1 + attributeCount; - uint64 uniqueId = _NextUniqueId(); - if (_UdfRevision() <= 0x0150) { - error = _WriteFileEntry( - reinterpret_cast(chunk.Data()), - fileType, linkCount, udfDataLength, udfDataLength, - stats, uniqueId, udfAllocationDescriptorsLength, - Udf::TAGID_FILE_ENTRY, - icbAddress, icbExtent, udfDataAddresses - ); - } else { - error = _WriteFileEntry( - reinterpret_cast(chunk.Data()), - fileType, linkCount, udfDataLength, udfDataLength, - stats, uniqueId, udfAllocationDescriptorsLength, - Udf::TAGID_EXTENDED_FILE_ENTRY, - icbAddress, icbExtent, udfDataAddresses - ); - } - } - - delete udfData; - udfData = NULL; - } - } - - if (!error) { - _Stats().AddFile(); - off_t totalLength = udfDataLength + _BlockSize(); - _Stats().AddFileBytes(totalLength); - } - RETURN(error); -} - diff --git a/src/bin/makeudfimage/UdfBuilder.h b/src/bin/makeudfimage/UdfBuilder.h deleted file mode 100644 index a36cf744e5..0000000000 --- a/src/bin/makeudfimage/UdfBuilder.h +++ /dev/null @@ -1,208 +0,0 @@ -//---------------------------------------------------------------------- -// This software is part of the OpenBeOS distribution and is covered -// by the MIT License. -// -// Copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net -//---------------------------------------------------------------------- - -/*! \file UdfBuilder.h - - Main UDF image building class interface declarations. -*/ - -#ifndef _UDF_BUILDER_H -#define _UDF_BUILDER_H - -#include -#include -#include -#include -#include -#include - -#include "Allocator.h" -#include "FileStream.h" -#include "MemoryStream.h" -#include "PhysicalPartitionAllocator.h" -#include "ProgressListener.h" -#include "Statistics.h" -#include "UdfString.h" - -/*! \brief Handy struct into which all the interesting information about - a processed directory, file, or whatever is placed by the corresponding - UdfBuilder::_Process*() function. -*/ -struct node_data { - Udf::long_address icbAddress; //!< Udf icb address - std::list udfData; //!< Dataspace for node in Udf partition space - std::list isoData; //!< Dataspace for node in physical space -}; - -class UdfBuilder { -public: - UdfBuilder(const char *outputFile, uint32 blockSize, bool doUdf, - const char *udfVolumeName, uint16 udfRevision, bool doIso, - const char *isoVolumeName, - const char *rootDirectory, const ProgressListener &listener, - bool truncate); - status_t InitCheck() const; - status_t Build(); -private: - //! Maximum length of string generated by calls to any _Print*() functions - static const int kMaxUpdateStringLength = 1024; - - FileStream& _OutputFile() { return fOutputFile; } - uint32 _BlockSize() const { return fBlockSize; } - uint32 _BlockShift() const { return fBlockShift; } - bool _DoUdf() const { return fDoUdf; } - Udf::String& _UdfVolumeName() { return fUdfVolumeName; } - uint16 _UdfRevision() const { return fUdfRevision; } - uint16 _UdfDescriptorVersion() const { return fUdfDescriptorVersion; } - const Udf::entity_id& _UdfDomainId() const { return fUdfDomainId; } - bool _DoIso() const { return fDoIso; } - Udf::String& _IsoVolumeName() { return fIsoVolumeName; } - BEntry& _RootDirectory() { return fRootDirectory; } - Allocator& _Allocator() { return fAllocator; } - PhysicalPartitionAllocator& _PartitionAllocator() { return fPartitionAllocator; } - Statistics& _Stats() { return fStatistics; } - time_t _BuildTime() const { return fBuildTime; } - Udf::timestamp& _BuildTimeStamp() { return fBuildTimeStamp; } - uint64 _NextUniqueId(); - bool _32BitIdsNoLongerUnique() const { return f32BitIdsNoLongerUnique; } - - void _SetBuildTime(time_t time); - - 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 _ProcessDirectory(BEntry &entry, const char *path, struct stat stats, - node_data &node, Udf::long_address parentIcbAddress, - bool isRootDirectory = false); - status_t _ProcessFile(BEntry &entry, const char *path, struct stat stats, - node_data &node); - status_t _ProcessSymlink(BEntry &symlink); - status_t _ProcessAttributes(BNode &node); - - template - status_t _WriteFileEntry(FileEntry *icb, uint8 fileType, uint16 linkCount, - uint64 dataLength, uint64 objectSize, struct stat stats, - uint64 uniqueId, uint32 allocationDescriptorsLength, - Udf::tag_id fileEntryType, Udf::long_address icbAddress, - Udf::extent_address icbExtent, - std::list dataAddresses); - - status_t fInitStatus; - FileStream fOutputFile; - std::string fOutputFilename; - uint32 fBlockSize; - uint32 fBlockShift; - bool fDoUdf; - Udf::String fUdfVolumeName; - uint16 fUdfRevision; - uint16 fUdfDescriptorVersion; - const Udf::entity_id &fUdfDomainId; - bool fDoIso; - Udf::String fIsoVolumeName; - BEntry fRootDirectory; - std::string fRootDirectoryName; - const ProgressListener &fListener; - Allocator fAllocator; - PhysicalPartitionAllocator fPartitionAllocator; - Statistics fStatistics; - time_t fBuildTime; - Udf::timestamp fBuildTimeStamp; - uint64 fNextUniqueId; - bool f32BitIdsNoLongerUnique; -}; - -template -status_t -UdfBuilder::_WriteFileEntry(FileEntry *icb, uint8 fileType, uint16 linkCount, - uint64 dataLength, uint64 objectSize, struct stat stats, - uint64 uniqueId, uint32 allocationDescriptorsLength, - Udf::tag_id fileEntryType, Udf::long_address icbAddress, - Udf::extent_address icbExtent, - std::list dataAddresses) -{ - DEBUG_INIT_ETC("UdfBuilder", ("type: %s", icb->descriptor_name())); - status_t error = B_ERROR; - Udf::icb_entry_tag &itag = icb->icb_tag(); - itag.set_prior_recorded_number_of_direct_entries(0); - itag.set_strategy_type(Udf::ICB_STRATEGY_SINGLE); - memset(itag.strategy_parameters().data, 0, - itag.strategy_parameters().size()); - itag.set_entry_count(1); - itag.reserved() = 0; - itag.set_file_type(fileType); - itag.parent_icb_location() = kNullLogicalBlock; - Udf::icb_entry_tag::flags_accessor &iflags = itag.flags_access(); - // clear flags, then set those of interest - iflags.all_flags = 0; - iflags.flags.descriptor_flags = Udf::ICB_DESCRIPTOR_TYPE_LONG; - iflags.flags.archive = 1; - icb->set_uid(0xffffffff); - icb->set_gid(0xffffffff); - icb->set_permissions(Udf::OTHER_EXECUTE | Udf::OTHER_READ - | Udf::GROUP_EXECUTE | Udf::GROUP_READ - | Udf::USER_EXECUTE | Udf::USER_READ); - icb->set_file_link_count(linkCount); - icb->set_record_format(0); - icb->set_record_display_attributes(0); - icb->set_record_length(0); - icb->set_information_length(dataLength); - icb->set_object_size(objectSize); // EFE only - icb->set_logical_blocks_recorded(_Allocator().BlocksFor(dataLength)); - icb->access_date_and_time() = Udf::timestamp(stats.st_atime); - icb->modification_date_and_time() = Udf::timestamp(stats.st_mtime); - icb->creation_date_and_time() = Udf::timestamp(stats.st_crtime); // EFE only - icb->attribute_date_and_time() = icb->creation_date_and_time(); - icb->set_checkpoint(1); - icb->set_reserved(0); // EFE only - icb->extended_attribute_icb() = kNullAddress; - icb->stream_directory_icb() = kNullAddress; // EFE only - icb->implementation_id() = Udf::kImplementationId; - icb->set_unique_id(uniqueId); - icb->set_extended_attributes_length(0); - icb->set_allocation_descriptors_length(allocationDescriptorsLength); - icb->tag().set_id(fileEntryType); - icb->tag().set_version(_UdfDescriptorVersion()); - icb->tag().set_serial_number(0); - icb->tag().set_location(icbAddress.block()); - - // write allocation descriptors - std::list::iterator a; - MemoryStream descriptorStream(icb->allocation_descriptors(), - allocationDescriptorsLength); - error = descriptorStream.InitCheck(); - if (!error) { - for (a = dataAddresses.begin(); - a != dataAddresses.end() && error == B_OK; - a++) - { - PRINT(("Dumping address:\n")); - DUMP(*a); - Udf::long_address &address = *a; - ssize_t bytes = descriptorStream.Write(&address, sizeof(address)); - error = check_size_error(bytes, sizeof(address)); - } - } - icb->tag().set_checksums(*icb, icb->descriptor_size()); - PDUMP(icb); - - // Write udf icb - if (!error) { - _PrintUpdate(VERBOSITY_MEDIUM, "udf: Writing icb"); - // write icb - _OutputFile().Seek(off_t(icbExtent.location()) << _BlockShift(), SEEK_SET); - PRINT(("position, icbsize: %Ld, %ld\n", _OutputFile().Position(), sizeof(icb))); - ssize_t bytes = _OutputFile().Write(icb, _BlockSize()); - PRINT(("position: %Ld\n", _OutputFile().Position())); - error = check_size_error(bytes, _BlockSize()); - PRINT(("position: %Ld\n", _OutputFile().Position())); - } - RETURN(error); -} - -#endif // _UDF_BUILDER_H diff --git a/src/bin/makeudfimage/makeudfimage.cpp b/src/bin/makeudfimage/makeudfimage.cpp deleted file mode 100644 index ac12c17be2..0000000000 --- a/src/bin/makeudfimage/makeudfimage.cpp +++ /dev/null @@ -1,20 +0,0 @@ -//---------------------------------------------------------------------- -// This software is part of the OpenBeOS distribution and is covered -// by the MIT License. -// -// Copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net -//---------------------------------------------------------------------- - -/*! \file makeudfimage.cpp - - UDF image builder. -*/ - -#include "Shell.h" - -int main(int argc, char *argv[]) -{ - Shell shell; - shell.Run(argc, argv); - return 0; -} diff --git a/src/tests/Jamfile b/src/tests/Jamfile index 741a80ff33..a1acf2290b 100644 --- a/src/tests/Jamfile +++ b/src/tests/Jamfile @@ -25,7 +25,6 @@ if $(TARGET_PLATFORM) = libbe_test { SubInclude HAIKU_TOP src tests add-ons ; SubInclude HAIKU_TOP src tests apps ; -SubInclude HAIKU_TOP src tests bin ; SubInclude HAIKU_TOP src tests system ; SubInclude HAIKU_TOP src tests kits ; SubInclude HAIKU_TOP src tests libs ; diff --git a/src/tests/bin/Jamfile b/src/tests/bin/Jamfile deleted file mode 100644 index d472866662..0000000000 --- a/src/tests/bin/Jamfile +++ /dev/null @@ -1,3 +0,0 @@ -SubDir HAIKU_TOP src tests bin ; - -SubInclude HAIKU_TOP src tests bin makeudfimage ; diff --git a/src/tests/bin/makeudfimage/AllocatorTest.cpp b/src/tests/bin/makeudfimage/AllocatorTest.cpp deleted file mode 100644 index 013263fc01..0000000000 --- a/src/tests/bin/makeudfimage/AllocatorTest.cpp +++ /dev/null @@ -1,144 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "AllocatorTest.h" - -#include "Allocator.h" -#include "PhysicalPartitionAllocator.h" - -AllocatorTest::AllocatorTest(std::string name) - : BTestCase(name) -{ -} - -CppUnit::Test* -AllocatorTest::Suite() { - CppUnit::TestSuite *suite = new CppUnit::TestSuite("Yo"); - - // And our tests - suite->addTest(new CppUnit::TestCaller("Allocator::BlockSize Test", &AllocatorTest::BlockSizeTest)); - suite->addTest(new CppUnit::TestCaller("Allocator::Partition Full Test", &AllocatorTest::PartitionFullTest)); - - return suite; -} - -void -AllocatorTest::BlockSizeTest() { - { - Allocator allocator(0); - CHK(allocator.InitCheck() != B_OK); - NextSubTest(); - } - { - Allocator allocator(1); - CHK(allocator.InitCheck() == B_OK); - NextSubTest(); - } - { - Allocator allocator(2); - CHK(allocator.InitCheck() == B_OK); - NextSubTest(); - } - { - Allocator allocator(3); - CHK(allocator.InitCheck() != B_OK); - NextSubTest(); - } - { - Allocator allocator(256); - CHK(allocator.InitCheck() == B_OK); - NextSubTest(); - } - { - Allocator allocator(512); - CHK(allocator.InitCheck() == B_OK); - NextSubTest(); - } - { - Allocator allocator(1024); - CHK(allocator.InitCheck() == B_OK); - NextSubTest(); - } - { - Allocator allocator(1025); - CHK(allocator.InitCheck() != B_OK); - NextSubTest(); - } - { - Allocator allocator(2048); - CHK(allocator.InitCheck() == B_OK); - NextSubTest(); - } - { - Allocator allocator(4096); - CHK(allocator.InitCheck() == B_OK); - NextSubTest(); - } -} - -void -AllocatorTest::PartitionFullTest() { - { - extent_address extent; - const uint32 blockSize = 2048; - Allocator allocator(blockSize); - CHK(allocator.InitCheck() == B_OK); - CHK(allocator.GetNextExtent(blockSize*12, true, extent) == B_OK); // 0-11 - extent.set_location(14); - extent.set_length(1); - CHK(allocator.GetExtent(extent) == B_OK); // 14 - CHK(allocator.GetNextExtent(blockSize*3, true, extent) == B_OK); // 15-17 - CHK(allocator.GetNextExtent(1, true, extent) == B_OK); // 12 - CHK(allocator.GetBlock(12) != B_OK); - CHK(allocator.GetBlock(13) == B_OK); - } - NextSubTest(); - { - extent_address extent; - Allocator allocator(2048); - CHK(allocator.InitCheck() == B_OK); - CHK(allocator.GetNextExtent(ULONG_MAX-1, true, extent) == B_OK); - CHK(allocator.GetNextExtent(1, true, extent) != B_OK); - extent.set_location(256); - extent.set_length(1); - CHK(allocator.GetExtent(extent) != B_OK); - CHK(allocator.GetBlock(13) != B_OK); - } - NextSubTest(); - { - extent_address extent; - const uint32 blockSize = 2048; - Allocator allocator(blockSize); - CHK(allocator.InitCheck() == B_OK); - CHK(allocator.GetNextExtent(ULONG_MAX-blockSize*2, true, extent) == B_OK); - CHK(allocator.GetNextExtent(1, true, extent) == B_OK); - extent.set_location(256); - extent.set_length(1); - CHK(allocator.GetExtent(extent) != B_OK); - CHK(allocator.GetBlock(13) != B_OK); - PhysicalPartitionAllocator partition(0, 0, allocator); - std::list extents; - std::list physicalExtents; - CHK(partition.GetNextExtents(1, extents, physicalExtents) == B_OK); - } - NextSubTest(); - { - extent_address extent; - const uint32 blockSize = 2048; - Allocator allocator(blockSize); - CHK(allocator.InitCheck() == B_OK); - CHK(allocator.GetNextExtent(ULONG_MAX, true, extent) == B_OK); - PhysicalPartitionAllocator partition(0, 0, allocator); - std::list extents; - std::list physicalExtents; - CHK(partition.GetNextExtents(1, extents, physicalExtents) != B_OK); - } - NextSubTest(); -} - diff --git a/src/tests/bin/makeudfimage/AllocatorTest.h b/src/tests/bin/makeudfimage/AllocatorTest.h deleted file mode 100644 index 635462c631..0000000000 --- a/src/tests/bin/makeudfimage/AllocatorTest.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef _udf_allocator_test_h_ -#define _udf_allocator_test_h_ - -#include -#include - -class AllocatorTest : public BTestCase { -public: - AllocatorTest(std::string name = ""); - - static CppUnit::Test* Suite(); - - void BlockSizeTest(); - void PartitionFullTest(); -}; - -#endif // _udf_allocator_test_h_ diff --git a/src/tests/bin/makeudfimage/Jamfile b/src/tests/bin/makeudfimage/Jamfile deleted file mode 100644 index 364fba25ce..0000000000 --- a/src/tests/bin/makeudfimage/Jamfile +++ /dev/null @@ -1,32 +0,0 @@ -SubDir HAIKU_TOP src tests bin makeudfimage ; - -AddSubDirSupportedPlatforms libbe_test ; - -UsePublicHeaders add-ons/file_system ; # For fsproto.h -UsePrivateHeaders [ FDirName kernel util ] ; # For kernel_cpp.h -UsePrivateHeaders private shared ; -SubDirHdrs [ FDirName $(HAIKU_TOP) src add-ons kernel file_systems udf ] ; -SubDirHdrs [ FDirName $(HAIKU_TOP) src bin makeudfimage ] ; - -UnitTestLib libmakeudfimagetest.so - : MakeudfimageTestAddon.cpp - # test files - AllocatorTest.cpp - - # makeudfimage files - Allocator.cpp - PhysicalPartitionAllocator.cpp - - # udf files - UdfDebug.cpp - UdfString.cpp - UdfStructures.cpp - Utils.cpp - - : be [ TargetLibstdc++ ] -; - -SEARCH on [ FGristFiles Allocator.cpp PhysicalPartitionAllocator.cpp ] - = [ FDirName $(HAIKU_TOP) src bin makeudfimage ] ; -SEARCH on [ FGristFiles UdfDebug.cpp UdfString.cpp UdfStructures.cpp Utils.cpp ] #DString.cpp UdfDebug.cpp UdfString.cpp UdfStructures.cpp Utils.cpp ] - = [ FDirName $(HAIKU_TOP) src add-ons kernel file_systems udf ] ; diff --git a/src/tests/bin/makeudfimage/MakeudfimageTestAddon.cpp b/src/tests/bin/makeudfimage/MakeudfimageTestAddon.cpp deleted file mode 100644 index b923dbd399..0000000000 --- a/src/tests/bin/makeudfimage/MakeudfimageTestAddon.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include -#include - -#include "AllocatorTest.h" - -BTestSuite* getTestSuite() { - BTestSuite *suite = new BTestSuite("makeudfimage"); - suite->addTest("Udf::Allocator", AllocatorTest::Suite()); - return suite; -}