1//---------------------------------------------------------------------- 2// This software is part of the OpenBeOS distribution and is covered 3// by the OpenBeOS license. 4// 5// Copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net 6//---------------------------------------------------------------------- 7 8/*! \file UdfBuilder.h 9 10 Main UDF image building class interface declarations. 11*/ 12 13#ifndef _UDF_BUILDER_H 14#define _UDF_BUILDER_H 15 16#include <Entry.h> 17#include <list> 18#include <Node.h> 19#include <stdarg.h> 20#include <string> 21#include <SupportDefs.h> 22 23#include "Allocator.h" 24#include "FileStream.h" 25#include "MemoryStream.h" 26#include "PhysicalPartitionAllocator.h" 27#include "ProgressListener.h" 28#include "Statistics.h" 29#include "UdfString.h" 30 31/*! \brief Handy struct into which all the interesting information about 32 a processed directory, file, or whatever is placed by the corresponding 33 UdfBuilder::_Process*() function. 34*/ 35struct node_data { 36 Udf::long_address icbAddress; //!< Udf icb address 37 std::list<Udf::long_address> udfData; //!< Dataspace for node in Udf partition space 38 std::list<Udf::extent_address> isoData; //!< Dataspace for node in physical space 39}; 40 41class UdfBuilder { 42public: 43 UdfBuilder(const char *outputFile, uint32 blockSize, bool doUdf, 44 const char *udfVolumeName, uint16 udfRevision, bool doIso, 45 const char *isoVolumeName, 46 const char *rootDirectory, const ProgressListener &listener, 47 bool truncate); 48 status_t InitCheck() const; 49 status_t Build(); 50private: 51 //! Maximum length of string generated by calls to any _Print*() functions 52 static const int kMaxUpdateStringLength = 1024; 53 54 FileStream& _OutputFile() { return fOutputFile; } 55 uint32 _BlockSize() const { return fBlockSize; } 56 uint32 _BlockShift() const { return fBlockShift; } 57 bool _DoUdf() const { return fDoUdf; } 58 Udf::String& _UdfVolumeName() { return fUdfVolumeName; } 59 uint16 _UdfRevision() const { return fUdfRevision; } 60 uint16 _UdfDescriptorVersion() const { return fUdfDescriptorVersion; } 61 const Udf::entity_id& _UdfDomainId() const { return fUdfDomainId; } 62 bool _DoIso() const { return fDoIso; } 63 Udf::String& _IsoVolumeName() { return fIsoVolumeName; } 64 BEntry& _RootDirectory() { return fRootDirectory; } 65 Allocator& _Allocator() { return fAllocator; } 66 PhysicalPartitionAllocator& _PartitionAllocator() { return fPartitionAllocator; } 67 Statistics& _Stats() { return fStatistics; } 68 time_t _BuildTime() const { return fBuildTime; } 69 Udf::timestamp& _BuildTimeStamp() { return fBuildTimeStamp; } 70 uint64 _NextUniqueId(); 71 bool _32BitIdsNoLongerUnique() const { return f32BitIdsNoLongerUnique; } 72 73 void _SetBuildTime(time_t time); 74 75 status_t _FormatString(char *message, const char *formatString, va_list arguments) const; 76 void _PrintError(const char *formatString, ...) const; 77 void _PrintWarning(const char *formatString, ...) const; 78 void _PrintUpdate(VerbosityLevel level, const char *formatString, ...) const; 79 80 status_t _ProcessDirectory(BEntry &entry, const char *path, struct stat stats, 81 node_data &node, Udf::long_address parentIcbAddress, 82 bool isRootDirectory = false); 83 status_t _ProcessFile(BEntry &entry, const char *path, struct stat stats, 84 node_data &node); 85 status_t _ProcessSymlink(BEntry &symlink); 86 status_t _ProcessAttributes(BNode &node); 87 88 template <class FileEntry> 89 status_t _WriteFileEntry(FileEntry *icb, uint8 fileType, uint16 linkCount, 90 uint64 dataLength, uint64 objectSize, struct stat stats, 91 uint64 uniqueId, uint32 allocationDescriptorsLength, 92 Udf::tag_id fileEntryType, Udf::long_address icbAddress, 93 Udf::extent_address icbExtent, 94 std::list<Udf::long_address> dataAddresses); 95 96 status_t fInitStatus; 97 FileStream fOutputFile; 98 std::string fOutputFilename; 99 uint32 fBlockSize; 100 uint32 fBlockShift; 101 bool fDoUdf; 102 Udf::String fUdfVolumeName; 103 uint16 fUdfRevision; 104 uint16 fUdfDescriptorVersion; 105 const Udf::entity_id &fUdfDomainId; 106 bool fDoIso; 107 Udf::String fIsoVolumeName; 108 BEntry fRootDirectory; 109 std::string fRootDirectoryName; 110 const ProgressListener &fListener; 111 Allocator fAllocator; 112 PhysicalPartitionAllocator fPartitionAllocator; 113 Statistics fStatistics; 114 time_t fBuildTime; 115 Udf::timestamp fBuildTimeStamp; 116 uint64 fNextUniqueId; 117 bool f32BitIdsNoLongerUnique; 118}; 119 120template <class FileEntry> 121status_t 122UdfBuilder::_WriteFileEntry(FileEntry *icb, uint8 fileType, uint16 linkCount, 123 uint64 dataLength, uint64 objectSize, struct stat stats, 124 uint64 uniqueId, uint32 allocationDescriptorsLength, 125 Udf::tag_id fileEntryType, Udf::long_address icbAddress, 126 Udf::extent_address icbExtent, 127 std::list<Udf::long_address> dataAddresses) 128{ 129 DEBUG_INIT_ETC("UdfBuilder", ("type: %s", icb->descriptor_name())); 130 status_t error = B_ERROR; 131 Udf::icb_entry_tag &itag = icb->icb_tag(); 132 itag.set_prior_recorded_number_of_direct_entries(0); 133 itag.set_strategy_type(Udf::ICB_STRATEGY_SINGLE); 134 memset(itag.strategy_parameters().data, 0, 135 itag.strategy_parameters().size()); 136 itag.set_entry_count(1); 137 itag.reserved() = 0; 138 itag.set_file_type(fileType); 139 itag.parent_icb_location() = kNullLogicalBlock; 140 Udf::icb_entry_tag::flags_accessor &iflags = itag.flags_access(); 141 // clear flags, then set those of interest 142 iflags.all_flags = 0; 143 iflags.flags.descriptor_flags = Udf::ICB_DESCRIPTOR_TYPE_LONG; 144 iflags.flags.archive = 1; 145 icb->set_uid(0xffffffff); 146 icb->set_gid(0xffffffff); 147 icb->set_permissions(Udf::OTHER_EXECUTE | Udf::OTHER_READ 148 | Udf::GROUP_EXECUTE | Udf::GROUP_READ 149 | Udf::USER_EXECUTE | Udf::USER_READ); 150 icb->set_file_link_count(linkCount); 151 icb->set_record_format(0); 152 icb->set_record_display_attributes(0); 153 icb->set_record_length(0); 154 icb->set_information_length(dataLength); 155 icb->set_object_size(objectSize); // EFE only 156 icb->set_logical_blocks_recorded(_Allocator().BlocksFor(dataLength)); 157 icb->access_date_and_time() = Udf::timestamp(stats.st_atime); 158 icb->modification_date_and_time() = Udf::timestamp(stats.st_mtime); 159 icb->creation_date_and_time() = Udf::timestamp(stats.st_crtime); // EFE only 160 icb->attribute_date_and_time() = icb->creation_date_and_time(); 161 icb->set_checkpoint(1); 162 icb->set_reserved(0); // EFE only 163 icb->extended_attribute_icb() = kNullAddress; 164 icb->stream_directory_icb() = kNullAddress; // EFE only 165 icb->implementation_id() = Udf::kImplementationId; 166 icb->set_unique_id(uniqueId); 167 icb->set_extended_attributes_length(0); 168 icb->set_allocation_descriptors_length(allocationDescriptorsLength); 169 icb->tag().set_id(fileEntryType); 170 icb->tag().set_version(_UdfDescriptorVersion()); 171 icb->tag().set_serial_number(0); 172 icb->tag().set_location(icbAddress.block()); 173 174 // write allocation descriptors 175 std::list<Udf::long_address>::iterator a; 176 MemoryStream descriptorStream(icb->allocation_descriptors(), 177 allocationDescriptorsLength); 178 error = descriptorStream.InitCheck(); 179 if (!error) { 180 for (a = dataAddresses.begin(); 181 a != dataAddresses.end() && error == B_OK; 182 a++) 183 { 184 PRINT(("Dumping address:\n")); 185 DUMP(*a); 186 Udf::long_address &address = *a; 187 ssize_t bytes = descriptorStream.Write(&address, sizeof(address)); 188 error = check_size_error(bytes, sizeof(address)); 189 } 190 } 191 icb->tag().set_checksums(*icb, icb->descriptor_size()); 192 PDUMP(icb); 193 194 // Write udf icb 195 if (!error) { 196 _PrintUpdate(VERBOSITY_MEDIUM, "udf: Writing icb"); 197 // write icb 198 _OutputFile().Seek(off_t(icbExtent.location()) << _BlockShift(), SEEK_SET); 199 PRINT(("position, icbsize: %Ld, %ld\n", _OutputFile().Position(), sizeof(icb))); 200 ssize_t bytes = _OutputFile().Write(icb, _BlockSize()); 201 PRINT(("position: %Ld\n", _OutputFile().Position())); 202 error = check_size_error(bytes, _BlockSize()); 203 PRINT(("position: %Ld\n", _OutputFile().Position())); 204 } 205 RETURN(error); 206} 207 208#endif // _UDF_BUILDER_H 209