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
Parent()61 Icb *Parent() { return fParent; }
Parent()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() */
_Invalidate()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();
Id()86 ino_t Id() { return fId; }
87
88 // categorization
Type()89 uint8 Type() { return _IcbTag().file_type(); }
IsFile()90 bool IsFile() { return Type() == ICB_TYPE_REGULAR_FILE; }
IsDirectory()91 bool IsDirectory() { return (Type() == ICB_TYPE_DIRECTORY
92 || Type() == ICB_TYPE_STREAM_DIRECTORY); }
93
Uid()94 uint32 Uid() { return _FileEntry()->uid(); }
Gid()95 uint32 Gid() { return 0; }
FileLinkCount()96 uint16 FileLinkCount() { return _FileEntry()->file_link_count(); }
Length()97 uint64 Length() { return _FileEntry()->information_length(); }
Mode()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
AllocationDescriptors()103 uint8 *AllocationDescriptors()
104 { return _AbstractEntry()->AllocationDescriptors(); }
AllocationDescriptorsSize()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
FileCache()113 void * FileCache() { return fFileCache; }
FileMap()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
GetVolume()123 Volume *GetVolume() const { return fVolume; }
124
125 private:
_AbstractEntry()126 AbstractFileEntry *_AbstractEntry() const { return (_Tag().id()
127 == TAGID_EXTENDED_FILE_ENTRY)
128 ? (AbstractFileEntry *)&fExtendedEntry
129 : (AbstractFileEntry *)&fFileEntry; }
130
_Tag()131 descriptor_tag &_Tag() const { return ((icb_header *)fData.Block())->tag(); }
_IcbTag()132 icb_entry_tag &_IcbTag() const { return ((icb_header *)fData.Block())->icb_tag(); }
_FileEntry()133 file_icb_entry *_FileEntry() const
134 { return (file_icb_entry *)fData.Block(); }
_ExtendedEntry()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>
FileEntry(CachedBlock * descriptorBlock)160 FileEntry<Descriptor>::FileEntry(CachedBlock *descriptorBlock)
161 : fDescriptorBlock(descriptorBlock)
162 {
163 }
164
165
166 template <class Descriptor>
167 void
SetTo(CachedBlock * descriptorBlock)168 FileEntry<Descriptor>::SetTo(CachedBlock *descriptorBlock)
169 {
170 fDescriptorBlock = descriptorBlock;
171 }
172
173
174 template <class Descriptor>
175 uint8*
AllocationDescriptors()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
AllocationDescriptorsLength()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*
_Descriptor()194 FileEntry<Descriptor>::_Descriptor()
195 {
196 return fDescriptorBlock
197 ? (Descriptor *)fDescriptorBlock->Block() : NULL;
198 }
199
200 #endif // _UDF_ICB_H
201