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