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 19class DirectoryIterator; 20class Icb; 21class 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*/ 34class AbstractFileEntry { 35public: 36 virtual uint8* AllocationDescriptors() = 0; 37 virtual uint32 AllocationDescriptorsLength() = 0; 38}; 39 40 41template <class Descriptor> 42class FileEntry : public AbstractFileEntry { 43public: 44 FileEntry(CachedBlock *descriptorBlock = NULL); 45 void SetTo(CachedBlock *descriptorBlock); 46 virtual uint8* AllocationDescriptors(); 47 virtual uint32 AllocationDescriptorsLength(); 48 49private: 50 Descriptor *_Descriptor(); 51 CachedBlock *fDescriptorBlock; 52}; 53 54 55class DirectoryIterator : public SinglyLinkedListLinkImpl<DirectoryIterator> { 56public: 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 66private: 67friend 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 80class Icb { 81public: 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 125private: 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 159template <class Descriptor> 160FileEntry<Descriptor>::FileEntry(CachedBlock *descriptorBlock) 161 : fDescriptorBlock(descriptorBlock) 162{ 163} 164 165 166template <class Descriptor> 167void 168FileEntry<Descriptor>::SetTo(CachedBlock *descriptorBlock) 169{ 170 fDescriptorBlock = descriptorBlock; 171} 172 173 174template <class Descriptor> 175uint8* 176FileEntry<Descriptor>::AllocationDescriptors() 177{ 178 Descriptor* descriptor = _Descriptor(); 179 return descriptor ? descriptor->allocation_descriptors() : NULL; 180} 181 182 183template <class Descriptor> 184uint32 185FileEntry<Descriptor>::AllocationDescriptorsLength() 186{ 187 Descriptor* descriptor = _Descriptor(); 188 return descriptor ? descriptor->allocation_descriptors_length() : 0; 189} 190 191 192template <class Descriptor> 193Descriptor* 194FileEntry<Descriptor>::_Descriptor() 195{ 196 return fDescriptorBlock 197 ? (Descriptor *)fDescriptorBlock->Block() : NULL; 198} 199 200#endif // _UDF_ICB_H 201