//---------------------------------------------------------------------- // This software is part of the OpenBeOS distribution and is covered // by the OpenBeOS 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