xref: /haiku/src/add-ons/kernel/file_systems/udf/Icb.h (revision 820dca4df6c7bf955c46e8f6521b9408f50b2900)
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 &timespec) const;
101 	void 						GetModificationTime(struct timespec &timespec) 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