1/*
2 * Copyright 2011, J��r��me Duval, korli@users.berlios.de.
3 * Copyright 2008-2010, Axel D��rfler, axeld@pinc-software.de.
4 * This file may be used under the terms of the MIT License.
5 */
6#ifndef VOLUME_H
7#define VOLUME_H
8
9
10#include <lock.h>
11#include <string.h>
12
13#include "exfat.h"
14#include "SplayTree.h"
15
16
17struct node_key {
18	cluster_t cluster;
19	uint32 offset;
20};
21
22struct node {
23	struct node_key key;
24	ino_t ino;
25	ino_t parent;
26	SplayTreeLink<struct node> nodeTreeLink;
27	SplayTreeLink<struct node> inoTreeLink;
28};
29
30
31struct NodeTreeDefinition {
32	typedef struct node_key KeyType;
33	typedef	struct node NodeType;
34
35	static KeyType GetKey(const NodeType* node)
36	{
37		return node->key;
38	}
39
40	static SplayTreeLink<NodeType>* GetLink(NodeType* node)
41	{
42		return &node->nodeTreeLink;
43	}
44
45	static int Compare(KeyType key, const NodeType* node)
46	{
47		if (key.cluster == node->key.cluster) {
48			if (key.offset == node->key.offset)
49				return 0;
50			return key.offset < node->key.offset ? -1 : 1;
51		}
52		return key.cluster < node->key.cluster ? -1 : 1;
53	}
54};
55
56struct InoTreeDefinition {
57	typedef ino_t KeyType;
58	typedef	struct node NodeType;
59
60	static KeyType GetKey(const NodeType* node)
61	{
62		return node->ino;
63	}
64
65	static SplayTreeLink<NodeType>* GetLink(NodeType* node)
66	{
67		return &node->inoTreeLink;
68	}
69
70	static int Compare(KeyType key, const NodeType* node)
71	{
72		if (key != node->ino)
73			return key < node->ino ? -1 : 1;
74		return 0;
75	}
76};
77
78
79typedef SplayTree<NodeTreeDefinition> NodeTree;
80typedef SplayTree<InoTreeDefinition> InoTree;
81class Inode;
82struct InodesInoTreeDefinition;
83typedef IteratableSplayTree<InodesInoTreeDefinition> InodesInoTree;
84struct InodesClusterTreeDefinition;
85typedef IteratableSplayTree<InodesClusterTreeDefinition> InodesClusterTree;
86
87
88enum volume_flags {
89	VOLUME_READ_ONLY	= 0x0001
90};
91
92
93class Volume {
94public:
95								Volume(fs_volume* volume);
96								~Volume();
97
98			status_t			Mount(const char* device, uint32 flags);
99			status_t			Unmount();
100
101			bool				IsValidSuperBlock();
102			bool				IsReadOnly() const
103								{ return (fFlags & VOLUME_READ_ONLY) != 0; }
104
105			Inode*				RootNode() const { return fRootNode; }
106			int					Device() const { return fDevice; }
107
108			dev_t				ID() const
109								{ return fFSVolume ? fFSVolume->id : -1; }
110			fs_volume*			FSVolume() const { return fFSVolume; }
111			const char*			Name() const;
112			void				SetName(const char* name)
113								{ strlcpy(fName, name, sizeof(fName)); }
114
115			uint32				BlockSize() const { return fBlockSize; }
116			uint32				EntriesPerBlock() const
117								{ return fEntriesPerBlock; }
118			uint32				EntriesPerCluster()
119								{ return fEntriesPerBlock
120									<< SuperBlock().BlocksPerClusterShift(); }
121			size_t				ClusterSize() { return fBlockSize
122									<< SuperBlock().BlocksPerClusterShift(); }
123			exfat_super_block&	SuperBlock() { return fSuperBlock; }
124
125			status_t			LoadSuperBlock();
126
127			// cache access
128			void*				BlockCache() { return fBlockCache; }
129
130	static	status_t			Identify(int fd, exfat_super_block* superBlock);
131
132			status_t			ClusterToBlock(cluster_t cluster,
133									fsblock_t &block);
134			Inode *				FindInode(ino_t id);
135			Inode *				FindInode(cluster_t cluster);
136			cluster_t			NextCluster(cluster_t cluster);
137			ino_t				GetIno(cluster_t cluster, uint32 offset, ino_t parent);
138			struct node_key*	GetNode(ino_t ino, ino_t &parent);
139private:
140			ino_t				_NextID() { return fNextId++; }
141
142			mutex				fLock;
143			fs_volume*			fFSVolume;
144			int					fDevice;
145			exfat_super_block	fSuperBlock;
146			char				fName[32];
147
148			uint16				fFlags;
149			uint32				fBlockSize;
150			uint32				fEntriesPerBlock;
151			Inode*				fRootNode;
152			ino_t				fNextId;
153
154			void*				fBlockCache;
155			InodesInoTree*		fInodesInoTree;
156			InodesClusterTree*	fInodesClusterTree;
157			NodeTree			fNodeTree;
158			InoTree				fInoTree;
159};
160
161#endif	// VOLUME_H
162
163