1 /* 2 * Copyright 2008, Salvatore Benedetto, salvatore.benedetto@gmail.com. 3 * Copyright 2003, Tyler Dauwalder, tyler@dauwalder.net. 4 * Distributed under the terms of the MIT License. 5 */ 6 #ifndef _UDF_ICB_H 7 #define _UDF_ICB_H 8 9 /*! \file Icb.h */ 10 11 #include "UdfStructures.h" 12 13 #include <util/kernel_cpp.h> 14 #include <util/SinglyLinkedList.h> 15 16 #include "CachedBlock.h" 17 18 class DirectoryIterator; 19 class Icb; 20 class Volume; 21 22 /*! \brief Abstract interface to file entry structure members 23 that are not commonly accessible through file_icb_entry(). 24 25 This is necessary, since we can't use virtual functions in 26 the disk structure structs themselves, since we generally 27 don't create disk structure objects by calling new, but 28 rather just cast a chunk of memory read off disk to be 29 a pointer to the struct of interest (which works fine 30 for regular functions, but fails miserably for virtuals 31 due to the vtable not being setup properly). 32 */ 33 class AbstractFileEntry { 34 public: 35 virtual uint8* AllocationDescriptors() = 0; 36 virtual uint32 AllocationDescriptorsLength() = 0; 37 }; 38 39 40 template <class Descriptor> 41 class FileEntry : public AbstractFileEntry { 42 public: 43 FileEntry(CachedBlock *descriptorBlock = NULL); 44 void SetTo(CachedBlock *descriptorBlock); 45 virtual uint8* AllocationDescriptors(); 46 virtual uint32 AllocationDescriptorsLength(); 47 48 private: 49 Descriptor *_Descriptor(); 50 CachedBlock *fDescriptorBlock; 51 }; 52 53 54 class DirectoryIterator : public SinglyLinkedListLinkImpl<DirectoryIterator> { 55 public: 56 57 status_t GetNextEntry(char *name, uint32 *length, 58 ino_t *id); 59 60 Icb *Parent() { return fParent; } 61 const Icb *Parent() const { return fParent; } 62 63 void Rewind(); 64 65 private: 66 friend class Icb; 67 68 /* The following is called by Icb::GetDirectoryIterator() */ 69 DirectoryIterator(Icb *parent); 70 /* The following is called by Icb::~Icb() */ 71 void _Invalidate() { fParent = NULL; } 72 73 bool fAtBeginning; 74 Icb *fParent; 75 off_t fPosition; 76 }; 77 78 79 class Icb { 80 public: 81 Icb(Volume *volume, long_address address); 82 ~Icb(); 83 84 status_t InitCheck(); 85 ino_t Id() { return fId; } 86 87 // categorization 88 uint8 Type() { return _IcbTag().file_type(); } 89 bool IsFile() { return Type() == ICB_TYPE_REGULAR_FILE; } 90 bool IsDirectory() { return (Type() == ICB_TYPE_DIRECTORY 91 || Type() == ICB_TYPE_STREAM_DIRECTORY); } 92 93 uint32 Uid() { return _FileEntry()->uid(); } 94 uint32 Gid() { return 0; } 95 uint16 FileLinkCount() { return _FileEntry()->file_link_count(); } 96 uint64 Length() { return _FileEntry()->information_length(); } 97 mode_t Mode() { return (IsDirectory() ? S_IFDIR : S_IFREG) 98 | S_IRUSR | S_IRGRP | S_IROTH; } 99 time_t AccessTime(); 100 time_t ModificationTime(); 101 102 uint8 *AllocationDescriptors() 103 { return _AbstractEntry()->AllocationDescriptors(); } 104 uint32 AllocationDescriptorsSize() 105 { return _AbstractEntry()->AllocationDescriptorsLength(); } 106 107 status_t Read(off_t pos, void *buffer, size_t *length, 108 uint32 *block = NULL); 109 110 void * FileCache() { return fFileCache; } 111 void * FileMap() { return fFileMap; } 112 113 status_t GetFileMap(off_t offset, size_t size, 114 struct file_io_vec *vecs, size_t *count); 115 116 // for directories only 117 status_t GetDirectoryIterator(DirectoryIterator **iterator); 118 status_t Find(const char *filename, ino_t *id); 119 120 Volume *GetVolume() const { return fVolume; } 121 122 private: 123 AbstractFileEntry *_AbstractEntry() { return (_Tag().id() 124 == TAGID_EXTENDED_FILE_ENTRY) 125 ? (AbstractFileEntry *)&fExtendedEntry 126 : (AbstractFileEntry *)&fFileEntry; } 127 128 descriptor_tag &_Tag() { return ((icb_header *)fData.Block())->tag(); } 129 icb_entry_tag &_IcbTag() { return ((icb_header *)fData.Block())->icb_tag(); } 130 file_icb_entry *_FileEntry() { return (file_icb_entry *)fData.Block(); } 131 extended_file_icb_entry &_ExtendedEntry() { return *(extended_file_icb_entry *)fData.Block(); } 132 133 template<class DescriptorList> 134 status_t _GetFileMap(DescriptorList &list, off_t offset, 135 size_t size, struct file_io_vec *vecs, 136 size_t *count); 137 template<class DescriptorList> 138 status_t _Read(DescriptorList &list, off_t pos, 139 void *buffer, size_t *length, uint32 *block); 140 141 Volume *fVolume; 142 CachedBlock fData; 143 status_t fInitStatus; 144 ino_t fId; 145 SinglyLinkedList<DirectoryIterator> fIteratorList; 146 FileEntry<file_icb_entry> fFileEntry; 147 FileEntry<extended_file_icb_entry> fExtendedEntry; 148 void * fFileCache; 149 void * fFileMap; 150 }; 151 152 153 template <class Descriptor> 154 FileEntry<Descriptor>::FileEntry(CachedBlock *descriptorBlock) 155 : fDescriptorBlock(descriptorBlock) 156 { 157 } 158 159 160 template <class Descriptor> 161 void 162 FileEntry<Descriptor>::SetTo(CachedBlock *descriptorBlock) 163 { 164 fDescriptorBlock = descriptorBlock; 165 } 166 167 168 template <class Descriptor> 169 uint8* 170 FileEntry<Descriptor>::AllocationDescriptors() 171 { 172 Descriptor* descriptor = _Descriptor(); 173 return descriptor ? descriptor->allocation_descriptors() : NULL; 174 } 175 176 177 template <class Descriptor> 178 uint32 179 FileEntry<Descriptor>::AllocationDescriptorsLength() 180 { 181 Descriptor* descriptor = _Descriptor(); 182 return descriptor ? descriptor->allocation_descriptors_length() : 0; 183 } 184 185 186 template <class Descriptor> 187 Descriptor* 188 FileEntry<Descriptor>::_Descriptor() 189 { 190 return fDescriptorBlock 191 ? (Descriptor *)fDescriptorBlock->Block() : NULL; 192 } 193 194 #endif // _UDF_ICB_H 195