xref: /haiku/src/add-ons/kernel/file_systems/exfat/Inode.h (revision 040a81419dda83d1014e9dc94936a4cb3f027303)
1 /*
2  * Copyright 2011, Jérôme Duval, korli@users.berlios.de.
3  * Copyright 2008, Axel Dörfler, axeld@pinc-software.de.
4  * This file may be used under the terms of the MIT License.
5  */
6 #ifndef INODE_H
7 #define INODE_H
8 
9 
10 #include <fs_cache.h>
11 #include <lock.h>
12 #include <string.h>
13 
14 #include "DirectoryIterator.h"
15 #include "exfat.h"
16 #include "SplayTree.h"
17 #include "Volume.h"
18 
19 
20 //#define TRACE_EXFAT
21 #ifdef TRACE_EXFAT
22 #	define TRACEI(x...) dprintf("\33[34mexfat:\33[0m " x)
23 #else
24 #	define TRACEI(x...) ;
25 #endif
26 
27 
28 struct InodesTreeDefinition;
29 
30 
31 class Inode : EntryVisitor {
32 public:
33 						Inode(Volume* volume, cluster_t cluster,
34 							uint32 offset);
35 						Inode(Volume* volume, ino_t ino);
36 						~Inode();
37 
38 			status_t	InitCheck();
39 
40 			ino_t		ID() const { return fID; }
41 			ino_t		Parent() const { return fParent; }
42 			cluster_t	Cluster() const { return fCluster; }
43 			uint32		Offset() const { return fOffset; }
44 			cluster_t	StartCluster() const
45 							{ return fFileInfoEntry.file_info.StartCluster(); }
46 			bool		IsContiguous() const
47 							{ return fFileInfoEntry.file_info.IsContiguous(); }
48 			cluster_t	NextCluster(cluster_t cluster) const;
49 
50 			rw_lock*	Lock() { return &fLock; }
51 
52 			status_t	UpdateNodeFromDisk();
53 
54 			bool		IsDirectory() const
55 							{ return S_ISDIR(Mode()); }
56 			bool		IsFile() const
57 							{ return S_ISREG(Mode()); }
58 			bool		IsSymLink() const
59 							{ return S_ISLNK(Mode()); }
60 			status_t	CheckPermissions(int accessMode) const;
61 
62 			mode_t		Mode() const;
63 			off_t		Size() const { return fFileInfoEntry.file_info.Size(); }
64 			uid_t		UserID() const { return 0;/*fNode.UserID();*/ }
65 			gid_t		GroupID() const { return 0;/*fNode.GroupID();*/ }
66 			void		GetChangeTime(struct timespec &timespec) const
67 							{ GetModificationTime(timespec); }
68 			void		GetModificationTime(struct timespec &timespec) const
69 							{ _GetTimespec(fFileEntry.file.ModificationDate(),
70 								fFileEntry.file.ModificationTime(), timespec); }
71 			void		GetCreationTime(struct timespec &timespec) const
72 							{ _GetTimespec(fFileEntry.file.CreationDate(),
73 								fFileEntry.file.CreationTime(), timespec); }
74 			void		GetAccessTime(struct timespec &timespec) const
75 							{ _GetTimespec(fFileEntry.file.AccessDate(),
76 								fFileEntry.file.AccessTime(), timespec); }
77 
78 			Volume*		GetVolume() const { return fVolume; }
79 
80 			status_t	FindBlock(off_t logical, off_t& physical,
81 							off_t *_length = NULL);
82 			status_t	ReadAt(off_t pos, uint8 *buffer, size_t *length);
83 			status_t	FillGapWithZeros(off_t start, off_t end);
84 
85 			void*		FileCache() const { return fCache; }
86 			void*		Map() const { return fMap; }
87 
88 			bool		VisitFile(struct exfat_entry*);
89 			bool		VisitFileInfo(struct exfat_entry*);
90 
91 private:
92 			friend struct InodesInoTreeDefinition;
93 			friend struct InodesClusterTreeDefinition;
94 
95 						Inode(Volume* volume);
96 						Inode(const Inode&);
97 						Inode &operator=(const Inode&);
98 							// no implementation
99 
100 			void		_GetTimespec(uint16 date, uint16 time,
101 							struct timespec &timespec) const;
102 			void		_Init();
103 
104 			rw_lock		fLock;
105 			::Volume*	fVolume;
106 			ino_t		fID;
107 			ino_t		fParent;
108 			cluster_t 	fCluster;
109 			uint32		fOffset;
110 			uint32		fFlags;
111 			void*		fCache;
112 			void*		fMap;
113 			status_t	fInitStatus;
114 
115 			SplayTreeLink<Inode> fInoTreeLink;
116 			Inode*				fInoTreeNext;
117 			SplayTreeLink<Inode> fClusterTreeLink;
118 			Inode*				fClusterTreeNext;
119 
120 			struct exfat_entry	fFileEntry;
121 			struct exfat_entry	fFileInfoEntry;
122 };
123 
124 
125 // The Vnode class provides a convenience layer upon get_vnode(), so that
126 // you don't have to call put_vnode() anymore, which may make code more
127 // readable in some cases
128 
129 class Vnode {
130 public:
131 	Vnode(Volume* volume, ino_t id)
132 		:
133 		fInode(NULL)
134 	{
135 		SetTo(volume, id);
136 	}
137 
138 	Vnode()
139 		:
140 		fStatus(B_NO_INIT),
141 		fInode(NULL)
142 	{
143 	}
144 
145 	~Vnode()
146 	{
147 		Unset();
148 	}
149 
150 	status_t InitCheck()
151 	{
152 		return fStatus;
153 	}
154 
155 	void Unset()
156 	{
157 		if (fInode != NULL) {
158 			put_vnode(fInode->GetVolume()->FSVolume(), fInode->ID());
159 			fInode = NULL;
160 			fStatus = B_NO_INIT;
161 		}
162 	}
163 
164 	status_t SetTo(Volume* volume, ino_t id)
165 	{
166 		Unset();
167 
168 		return fStatus = get_vnode(volume->FSVolume(), id, (void**)&fInode);
169 	}
170 
171 	status_t Get(Inode** _inode)
172 	{
173 		*_inode = fInode;
174 		return fStatus;
175 	}
176 
177 	void Keep()
178 	{
179 		TRACEI("Vnode::Keep()\n");
180 		fInode = NULL;
181 	}
182 
183 private:
184 	status_t	fStatus;
185 	Inode*		fInode;
186 };
187 
188 
189 struct InodesInoTreeDefinition {
190 	typedef ino_t KeyType;
191 	typedef	Inode NodeType;
192 
193 	static KeyType GetKey(const NodeType* node)
194 	{
195 		return node->ID();
196 	}
197 
198 	static SplayTreeLink<NodeType>* GetLink(NodeType* node)
199 	{
200 		return &node->fInoTreeLink;
201 	}
202 
203 	static int Compare(KeyType key, const NodeType* node)
204 	{
205 		return key == node->ID() ? 0
206 			: (key < node->ID() ? -1 : 1);
207 	}
208 
209 	static NodeType** GetListLink(NodeType* node)
210 	{
211 		return &node->fInoTreeNext;
212 	}
213 };
214 
215 typedef IteratableSplayTree<InodesInoTreeDefinition> InodesInoTree;
216 
217 struct InodesClusterTreeDefinition {
218 	typedef cluster_t KeyType;
219 	typedef	Inode NodeType;
220 
221 	static KeyType GetKey(const NodeType* node)
222 	{
223 		return node->Cluster();
224 	}
225 
226 	static SplayTreeLink<NodeType>* GetLink(NodeType* node)
227 	{
228 		return &node->fClusterTreeLink;
229 	}
230 
231 	static int Compare(KeyType key, const NodeType* node)
232 	{
233 		return key == node->Cluster() ? 0
234 			: (key < node->Cluster() ? -1 : 1);
235 	}
236 
237 	static NodeType** GetListLink(NodeType* node)
238 	{
239 		return &node->fClusterTreeNext;
240 	}
241 };
242 
243 typedef IteratableSplayTree<InodesClusterTreeDefinition> InodesClusterTree;
244 
245 #endif	// INODE_H
246