1/*
2 * Copyright 2017, Ch��� V�� Gia Hy, cvghy116@gmail.com.
3 * Copyright 2011, J��r��me Duval, korli@users.berlios.de.
4 * Copyright 2008, Axel D��rfler, axeld@pinc-software.de.
5 * This file may be used under the terms of the MIT License.
6 */
7#ifndef INODE_H
8#define INODE_H
9
10
11#include "btrfs.h"
12#include "Volume.h"
13#include "Journal.h"
14#include "BTree.h"
15
16
17//#define TRACE_BTRFS
18#ifdef TRACE_BTRFS
19#	define TRACEI(x...) dprintf("\33[34mbtrfs:\33[0m " x)
20#else
21#	define TRACEI(x...) ;
22#endif
23
24
25//! Class used for in-memory representation of inodes
26class Inode {
27public:
28						Inode(Volume* volume, ino_t id);
29						Inode(Volume* volume, ino_t id,
30							const btrfs_inode& item);
31						~Inode();
32
33			status_t	InitCheck();
34
35			ino_t		ID() const { return fID; }
36
37			rw_lock*	Lock() { return& fLock; }
38
39			status_t	UpdateNodeFromDisk();
40
41			bool		IsDirectory() const
42							{ return S_ISDIR(Mode()); }
43			bool		IsFile() const
44							{ return S_ISREG(Mode()); }
45			bool		IsSymLink() const
46							{ return S_ISLNK(Mode()); }
47			status_t	CheckPermissions(int accessMode) const;
48
49			btrfs_inode&	Node() { return fNode; }
50			mode_t		Mode() const { return fNode.Mode(); }
51			off_t		Size() const { return fNode.Size(); }
52			uid_t		UserID() const { return fNode.UserID(); }
53			gid_t		GroupID() const { return fNode.GroupID(); }
54			void		GetChangeTime(struct timespec& timespec) const
55							{ fNode.GetChangeTime(timespec); }
56			void		GetModificationTime(struct timespec& timespec) const
57							{ fNode.GetModificationTime(timespec); }
58			void		GetCreationTime(struct timespec& timespec) const
59							{ fNode.GetCreationTime(timespec); }
60			void		GetAccessTime(struct timespec& timespec) const
61							{ fNode.GetCreationTime(timespec); }
62
63			Volume*		GetVolume() const { return fVolume; }
64
65			status_t	FindBlock(off_t logical, off_t& physical,
66							off_t* _length = NULL);
67			status_t	ReadAt(off_t pos, uint8* buffer, size_t* length);
68			status_t	FillGapWithZeros(off_t start, off_t end);
69
70			void*		FileCache() const { return fCache; }
71			void*		Map() const { return fMap; }
72
73			status_t	FindParent(ino_t* id);
74			uint64		FindNextIndex(BTree::Path* path) const;
75	static	Inode*		Create(Transaction& transaction, ino_t id,
76							Inode* parent, int32 mode, uint64 size = 0,
77							uint64 flags = 0);
78			status_t	Insert(Transaction& transaction, BTree::Path* path);
79			status_t	Remove(Transaction& transaction, BTree::Path* path);
80			status_t	MakeReference(Transaction& transaction, BTree::Path* path,
81							Inode* parent, const char* name, int32 mode);
82			status_t	Dereference(Transaction& transaction, BTree::Path* path,
83							ino_t parentID, const char* name);
84private:
85						Inode(Volume* volume);
86						Inode(const Inode&);
87						Inode& operator=(const Inode&);
88							// no implementation
89
90			uint64		_NumBlocks();
91private:
92
93			rw_lock		fLock;
94			::Volume*	fVolume;
95			ino_t		fID;
96			void*		fCache;
97			void*		fMap;
98			status_t	fInitStatus;
99			btrfs_inode fNode;
100};
101
102/*!The Vnode class provides a convenience layer upon get_vnode(), so that
103 * you don't have to call put_vnode() anymore, which may make code more
104 * readable in some cases
105 */
106class Vnode {
107public:
108	Vnode(Volume* volume, ino_t id)
109		:
110		fInode(NULL)
111	{
112		SetTo(volume, id);
113	}
114
115	Vnode()
116		:
117		fStatus(B_NO_INIT),
118		fInode(NULL)
119	{
120	}
121
122	~Vnode()
123	{
124		Unset();
125	}
126
127	status_t InitCheck()
128	{
129		return fStatus;
130	}
131
132	void Unset()
133	{
134		if (fInode != NULL) {
135			put_vnode(fInode->GetVolume()->FSVolume(), fInode->ID());
136			fInode = NULL;
137			fStatus = B_NO_INIT;
138		}
139	}
140
141	status_t SetTo(Volume* volume, ino_t id)
142	{
143		Unset();
144
145		return fStatus = get_vnode(volume->FSVolume(), id, (void**)&fInode);
146	}
147
148	status_t Get(Inode** _inode)
149	{
150		*_inode = fInode;
151		return fStatus;
152	}
153
154	void Keep()
155	{
156		TRACEI("Vnode::Keep()\n");
157		fInode = NULL;
158	}
159
160private:
161	status_t	fStatus;
162	Inode*		fInode;
163};
164
165
166#endif	// INODE_H
167