1/*
2 * Copyright 2002-2014 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Tyler Dauwalder
7 *		Ingo Weinhold, bonefish@users.sf.net
8 */
9
10
11#include <Statable.h>
12
13#include <sys/stat.h>
14
15#include <compat/sys/stat.h>
16
17#include <Node.h>
18#include <NodeMonitor.h>
19#include <Volume.h>
20
21
22class BStatable::Private {
23public:
24	Private(const BStatable* object)
25		:
26		fObject(object)
27	{
28	}
29
30	status_t GetStatBeOS(struct stat_beos* stat)
31	{
32		return fObject->_GetStat(stat);
33	}
34
35private:
36	const BStatable*	fObject;
37};
38
39
40#if __GNUC__ > 3
41BStatable::~BStatable()
42{
43}
44#endif
45
46
47// Returns whether or not the current node is a file.
48bool
49BStatable::IsFile() const
50{
51	struct stat stat;
52	if (GetStat(&stat) == B_OK)
53		return S_ISREG(stat.st_mode);
54	else
55		return false;
56}
57
58
59// Returns whether or not the current node is a directory.
60bool
61BStatable::IsDirectory() const
62{
63	struct stat stat;
64	if (GetStat(&stat) == B_OK)
65		return S_ISDIR(stat.st_mode);
66	else
67		return false;
68}
69
70
71// Returns whether or not the current node is a symbolic link.
72bool
73BStatable::IsSymLink() const
74{
75	struct stat stat;
76	if (GetStat(&stat) == B_OK)
77		return S_ISLNK(stat.st_mode);
78	else
79		return false;
80}
81
82
83// Fills out ref with the node_ref of the node.
84status_t
85BStatable::GetNodeRef(node_ref* ref) const
86{
87	status_t result = (ref ? B_OK : B_BAD_VALUE);
88	struct stat stat = {};
89
90	if (result == B_OK)
91		result = GetStat(&stat);
92
93	if (result == B_OK) {
94		ref->device  = stat.st_dev;
95		ref->node = stat.st_ino;
96	}
97
98	return result;
99}
100
101
102// Fills out the node's UID into owner.
103status_t
104BStatable::GetOwner(uid_t* owner) const
105{
106	status_t result = (owner ? B_OK : B_BAD_VALUE);
107	struct stat stat = {};
108
109	if (result == B_OK)
110		result = GetStat(&stat);
111
112	if (result == B_OK)
113		*owner = stat.st_uid;
114
115	return result;
116}
117
118
119// Sets the node's UID to owner.
120status_t
121BStatable::SetOwner(uid_t owner)
122{
123	struct stat stat = {};
124	stat.st_uid = owner;
125
126	return set_stat(stat, B_STAT_UID);
127}
128
129
130// Fills out the node's GID into group.
131status_t
132BStatable::GetGroup(gid_t* group) const
133{
134	status_t result = (group ? B_OK : B_BAD_VALUE);
135	struct stat stat = {};
136
137	if (result == B_OK)
138		result = GetStat(&stat);
139
140	if (result == B_OK)
141		*group = stat.st_gid;
142
143	return result;
144}
145
146
147// Sets the node's GID to group.
148status_t
149BStatable::SetGroup(gid_t group)
150{
151	struct stat stat = {};
152	stat.st_gid = group;
153
154	return set_stat(stat, B_STAT_GID);
155}
156
157
158// Fills out permissions with the node's permissions.
159status_t
160BStatable::GetPermissions(mode_t* permissions) const
161{
162	status_t result = (permissions ? B_OK : B_BAD_VALUE);
163	struct stat stat = {};
164
165	if (result == B_OK)
166		result = GetStat(&stat);
167
168	if (result == B_OK)
169		*permissions = (stat.st_mode & S_IUMSK);
170
171	return result;
172}
173
174
175// Sets the node's permissions to permissions.
176status_t
177BStatable::SetPermissions(mode_t permissions)
178{
179	struct stat stat = {};
180	// the FS should do the correct masking -- only the S_IUMSK part is
181	// modifiable
182	stat.st_mode = permissions;
183
184	return set_stat(stat, B_STAT_MODE);
185}
186
187
188// Fills out the size of the node's data (not counting attributes) into size.
189status_t
190BStatable::GetSize(off_t* size) const
191{
192	status_t result = (size ? B_OK : B_BAD_VALUE);
193	struct stat stat = {};
194
195	if (result == B_OK)
196		result = GetStat(&stat);
197
198	if (result == B_OK)
199		*size = stat.st_size;
200
201	return result;
202}
203
204
205// Fills out mtime with the last modification time of the node.
206status_t
207BStatable::GetModificationTime(time_t* mtime) const
208{
209	status_t result = (mtime ? B_OK : B_BAD_VALUE);
210	struct stat stat = {};
211
212	if (result == B_OK)
213		result = GetStat(&stat);
214
215	if (result == B_OK)
216		*mtime = stat.st_mtime;
217
218	return result;
219}
220
221
222// Sets the node's last modification time to mtime.
223status_t
224BStatable::SetModificationTime(time_t mtime)
225{
226	struct stat stat = {};
227	stat.st_mtime = mtime;
228
229	return set_stat(stat, B_STAT_MODIFICATION_TIME);
230}
231
232
233// Fills out ctime with the creation time of the node
234status_t
235BStatable::GetCreationTime(time_t* ctime) const
236{
237	status_t result = (ctime ? B_OK : B_BAD_VALUE);
238	struct stat stat = {};
239
240	if (result == B_OK)
241		result = GetStat(&stat);
242
243	if (result == B_OK)
244		*ctime = stat.st_crtime;
245
246	return result;
247}
248
249
250// Sets the node's creation time to ctime.
251status_t
252BStatable::SetCreationTime(time_t ctime)
253{
254	struct stat stat = {};
255	stat.st_crtime = ctime;
256
257	return set_stat(stat, B_STAT_CREATION_TIME);
258}
259
260
261// Fills out atime with the access time of the node.
262status_t
263BStatable::GetAccessTime(time_t* atime) const
264{
265	status_t result = (atime ? B_OK : B_BAD_VALUE);
266	struct stat stat = {};
267
268	if (result == B_OK)
269		result = GetStat(&stat);
270
271	if (result == B_OK)
272		*atime = stat.st_atime;
273
274	return result;
275}
276
277
278// Sets the node's access time to atime.
279status_t
280BStatable::SetAccessTime(time_t atime)
281{
282	struct stat stat = {};
283	stat.st_atime = atime;
284
285	return set_stat(stat, B_STAT_ACCESS_TIME);
286}
287
288
289// Fills out vol with the the volume that the node lives on.
290status_t
291BStatable::GetVolume(BVolume* volume) const
292{
293	status_t result = (volume ? B_OK : B_BAD_VALUE);
294	struct stat stat = {};
295	if (result == B_OK)
296		result = GetStat(&stat);
297
298	if (result == B_OK)
299		result = volume->SetTo(stat.st_dev);
300
301	return result;
302}
303
304
305// _OhSoStatable1() -> GetStat()
306extern "C" status_t
307#if __GNUC__ == 2
308_OhSoStatable1__9BStatable(const BStatable* self, struct stat* stat)
309#else
310_ZN9BStatable14_OhSoStatable1Ev(const BStatable* self, struct stat* stat)
311#endif
312{
313	// No Perform() method -- we have to use the old GetStat() method instead.
314	struct stat_beos oldStat = {};
315	status_t result = BStatable::Private(self).GetStatBeOS(&oldStat);
316	if (result != B_OK)
317		return result;
318
319	convert_from_stat_beos(&oldStat, stat);
320
321	return B_OK;
322}
323
324
325void BStatable::_OhSoStatable2() {}
326void BStatable::_OhSoStatable3() {}
327