1/*
2 * Copyright 2007, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * All rights reserved. Distributed under the terms of the MIT license.
4 */
5#ifndef NODE_H
6#define NODE_H
7
8#include <fs_interface.h>
9#include <NodeMonitor.h>
10
11#include "Attribute.h"
12#include "Entry.h"
13#include "String.h"
14
15class AllocationInfo;
16class AttributeIterator;
17class Directory;
18class Volume;
19
20// node type
21enum {
22	NODE_TYPE_DIRECTORY,
23	NODE_TYPE_FILE,
24	NODE_TYPE_SYMLINK,
25};
26
27// access modes
28enum {
29	ACCESS_R	= S_IROTH,
30	ACCESS_W	= S_IWOTH,
31	ACCESS_X	= S_IXOTH,
32};
33
34class Node : public DoublyLinkedListLinkImpl<Node> {
35public:
36	Node(Volume *volume, uint8 type);
37	virtual ~Node();
38
39	virtual status_t InitCheck() const;
40
41	Node*& HashLink()	{ return fHashLink; }
42
43	inline void SetVolume(Volume *volume)	{ fVolume = volume; }
44	inline Volume *GetVolume() const		{ return fVolume; }
45
46	inline ino_t GetID() const	{ return fID; }
47
48	status_t AddReference();
49	void RemoveReference();
50	int32 GetRefCount()	{ return fRefCount; }
51
52	virtual status_t Link(Entry *entry);
53	virtual status_t Unlink(Entry *entry);
54
55	inline bool IsDirectory() const	{ return S_ISDIR(fMode); }
56	inline bool IsFile() const		{ return S_ISREG(fMode); }
57	inline bool IsSymLink() const	{ return S_ISLNK(fMode); }
58
59	virtual status_t SetSize(off_t newSize) = 0;
60	virtual off_t GetSize() const = 0;
61
62	// stat data
63
64	inline void SetMode(mode_t mode)
65		{ fMode = (fMode & ~S_IUMSK) | (mode & S_IUMSK); }
66	inline mode_t GetMode() const	{ return fMode; }
67
68	inline void SetUID(uid_t uid)	{ fUID = uid; MarkModified(B_STAT_UID); }
69	inline uid_t GetUID() const		{ return fUID; }
70
71	inline void SetGID(uid_t gid)	{ fGID = gid; MarkModified(B_STAT_GID); }
72	inline uid_t GetGID() const		{ return fGID; }
73
74	inline void SetATime(time_t aTime)	{ fATime = aTime; }
75	inline time_t GetATime() const		{ return fATime; }
76
77	void SetMTime(time_t mTime);
78	inline time_t GetMTime() const		{ return fMTime; }
79
80	inline void SetCTime(time_t cTime)	{ fCTime = cTime; }
81	inline time_t GetCTime() const		{ return fCTime; }
82
83	inline void SetCrTime(time_t crTime)	{ fCrTime = crTime; }
84	inline time_t GetCrTime() const			{ return fCrTime; }
85
86	inline void MarkModified(uint32 flags)	{ fModified |= flags; }
87	inline uint32 MarkUnmodified();
88	inline bool IsModified() const			{ return fModified; }
89
90	status_t CheckPermissions(int mode) const;
91
92	bool IsKnownToVFS() const	{ return fIsKnownToVFS; }
93
94	// attributes
95	status_t CreateAttribute(const char *name, Attribute **attribute);
96	status_t DeleteAttribute(Attribute *attribute);
97	status_t AddAttribute(Attribute *attribute);
98	status_t RemoveAttribute(Attribute *attribute);
99
100	status_t FindAttribute(const char *name, Attribute **attribute) const;
101
102	status_t GetPreviousAttribute(Attribute **attribute) const;
103	status_t GetNextAttribute(Attribute **attribute) const;
104
105	Entry *GetFirstReferrer() const;
106	Entry *GetLastReferrer() const;
107	Entry *GetPreviousReferrer(Entry *entry) const;
108	Entry *GetNextReferrer(Entry *entry) const;
109
110	// debugging
111	virtual void GetAllocationInfo(AllocationInfo &info);
112
113private:
114	Node					*fHashLink;
115	Volume					*fVolume;
116	ino_t					fID;
117	int32					fRefCount;
118	mode_t					fMode;
119	uid_t					fUID;
120	uid_t					fGID;
121	time_t					fATime;
122	time_t					fMTime;
123	time_t					fCTime;
124	time_t					fCrTime;
125	uint32					fModified;
126	bool					fIsKnownToVFS;
127
128	// attribute management
129	DoublyLinkedList<Attribute>		fAttributes;
130
131protected:
132	// entries referring to this node
133	DoublyLinkedList<Entry, GetNodeReferrerLink>	fReferrers;
134};
135
136// MarkUnmodified
137inline
138uint32
139Node::MarkUnmodified()
140{
141	uint32 modified = fModified;
142	if (modified) {
143		fCTime = time(NULL);
144		SetMTime(fCTime);
145		fModified = 0;
146	}
147	return modified;
148}
149
150// open_mode_to_access
151inline static
152int
153open_mode_to_access(int openMode)
154{
155	switch (openMode & O_RWMASK) {
156		case O_RDONLY:
157			return ACCESS_R;
158		case O_WRONLY:
159			return ACCESS_W;
160		case O_RDWR:
161			return ACCESS_R | ACCESS_W;
162	}
163	return 0;
164}
165
166
167// NodeMTimeUpdater
168class NodeMTimeUpdater {
169public:
170	NodeMTimeUpdater(Node *node) : fNode(node) {}
171	~NodeMTimeUpdater()
172	{
173		if (fNode && fNode->IsModified())
174			fNode->MarkUnmodified();
175	}
176
177private:
178	Node	*fNode;
179};
180
181#endif	// NODE_H
182