xref: /haiku/src/add-ons/kernel/file_systems/udf/Icb.h (revision 97901ec593ec4dd50ac115c1c35a6d72f6e489a5)
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