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