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